首页 优秀范文 接口协议

接口协议赏析八篇

时间:2022-10-10 04:59:30

接口协议

接口协议第1篇

关键词:HART协议 DCS接口卡 应用

根据HART协议的DCS接口卡的硬件和软件设计,我们对其进行过研究分析,了解DCS-HART接口卡的功能和它的工作过程,让我们更好的知道DCS接口卡是怎样对现场仪表进行控制操作的。

一、HART协议

HART协议是远程传感器高速通道的开放协议,它采用的是半双工通信方式,在原有的模拟信号传输上进行数字信号的通信,这种将模拟信号转变为数字信号的系统得到了快速的发展,它设定了一系列的命令其中有通信命令、行为命令、特殊设备命令,这三种命令可以同时出现在一个设备中 。

二、DCS-HART接口卡的硬件设计

DCS-HART接口卡的工作程序,是由MPU对串行口2和DCS通讯,经过串行口1和现场仪表进行通讯,根据卡件的工作状态进行控制信号的输出来决定DC\DC器件向通讯线的供电。MODEM将MPU输出的数字信号转变为HART协议的物理层信号,从MODEM向通讯链路发送的波形和在链路上接收到的波形要进行放大、驱动。变压器使得DCS-HART接口卡和通讯链路发生了耦合作用,将HART协议产生的物理层信号进行叠加,加到要进行采样的电阻上,采样电阻是电压/电流的转换器件,它将HART协议产生的物理层信号转化成电压信号,而DC/DC器件主要是用于向通信链路进行隔离供电。

三、软件设计

1.能够保证DCS和现场仪表的通讯

HART协议对于通讯波特率的规定实际上只有1200bps,它不可能在一次中断完成命令的接受/发送,所以在HART仪表的通讯中断中,每次只接收/发送一个字节,根据接受/发送的状态进行字节的成帧,这样进行的中断需要耗费的时间仅有几百个微秒,每两个字节发送的时间间隔是9.167ms,这是两次通讯程序的中断时间间隔。

如果在DCS串行口中断执行时产生HART通讯中断,可以在DCS中断程序退出后进行HART程序的中断。如果在HART的串行口进行中断时有DCS通讯中断发生在结束HART中断后,再进行DCS中断。

2.有随时插随时用的功能

接口卡的这个功能可以分为两个含义:(一)接口卡可以随时对下位仪表的在线状态进行检测,并将检测结果报告给用户。(二)接口卡可以将下位仪表的数据进行读取或者是对下位仪表发送用户设置的参数。

用户他们不需要在DCS操作台上对每台仪表的信息进行组合,通电开始,卡件就会依次的对每台设备进行地址的查询,并收集每一台设备的管理信息,把这些收集到的信息保存到设备管理的缓冲区域中,方便DCS进行查询。根据下位机的在/离线状态实时数据就会在50ms一次中报告给DCS,所以用户想要观察到画面中的每一路现场仪表的在线状态可以在DCS的操作站台上进行查看[1]。

3.在DCS的结构上实现了对HART仪表的网络管理

DCS对于HART网络的管理存在不足之处,那就是在通讯结构上是进行的主从式通讯,通讯的层次相对较多,通讯的速率也比HART协议规定的1200bps快的多的多。

由于现场仪表的上/离线情况是突发性的,所以当接口卡检测到这种事情的发生后就会自动的将事件上报给DCS的室内操作台,而主从式的通讯结构是不能完成这样的上报事件的,由于这种事件的信息量不是很大,所以只需要很少的字节就可以将全部现场仪表的在线状态表达出来,所以,这种信息可以放到实时数据里发送给操作[2]。

为了使现现场仪表中的信息得以保存,操作台要4次的数据命令,才能使得每一层的信息得以更新,第4次收到的信息才是最新的现场仪表组态信息。

4.HART协议的通讯速度问题

HART协议发送一个字节需要9.167ms,在HART协议中一个很简单的命令就有十几个字节,而对于下位机的响应又有二十几个字节,要完成一次通讯命令要花去将近半秒钟的时间。所以轮询4台下位机要花去2s的时间,DCS和接口卡的实时数据通讯时间对于2s来说可以是忽略的,也就是说实时数据可以在两秒内进行一次更新,如果发生DCS下达命令,实时数据的更新就会增加时间。在完成对4台仪表5遍的实时数据检测,平均响应时间为最大的响应时间一半,也就是5s[3]。

四、小结

DCS接口卡中HART协议的应用,在一定的程度上减少对现场仪表的维护工作,还节约了材料。DCS接口卡初步的实现了对现场仪表的网络化管理,DCS-HART接口卡现场仪表的总线进行了功能的集成,对于DCS接口卡进行对现场仪表系统的完全控制可以慢慢的进行探索。

接口协议第2篇

关键词:PS/2接口;串行通讯;单片机;键盘;CD4052

1PS/2接口标准的发展过程

随着计算机工业的发展,作为计算机最常用输入设备的键盘也日新月异。1981年IBM推出了IBMPC/XT键盘及其接口标准。该标准定义了83键,采用5脚DIN连接器和简单的串行协议。实际上,第一套键盘扫描码集并没有主机到键盘的命令。为此,1984年IBM推出了IBMAT键盘接口标准。该标准定义了84~101键,采用5脚DIN连接器和双向串行通讯协议,此协议依照第二套键盘扫描码集设有8个主机到键盘的命令。到了1987年,IBM又推出了PS/2键盘接口标准。该标准仍旧定义了84~101键,但是采用6脚mini-DIN连接器,该连接器在封装上更小巧,仍然用双向串行通讯协议并且提供有可选择的第三套键盘扫描码集,同时支持17个主机到键盘的命令。现在,市面上的键盘都和PS/2及AT键盘兼容,只是功能不同而已。

2PS/2接口硬件

2.1物理连接器

一般,具有五脚连接器的键盘称之为AT键盘,而具有六脚mini-DIN连接器的键盘则称之为PS/2键盘。其实这两种连接器都只有四个脚有意义。它们分别是Clock(时钟脚)、Data数据脚、+5V(电源脚)和Ground(电源地)。在PS/2键盘与PC机的物理连接上只要保证这四根线一一对应就可以了。PS/2键盘靠PC的PS/2端口提供+5V电源,另外两个脚Clock(时钟脚)和Data数据脚都是集电极开路的,所以必须接大阻值的上拉电阻。它们平时保持高电平,有输出时才被拉到低电平,之后自动上浮到高电平。现在比较常用的连接器如图1所示。

2.2电气特性

PS/2通讯协议是一种双向同步串行通讯协议。通讯的两端通过Clock(时钟脚)同步,并通过Data(数据脚)交换数据。任何一方如果想抑制另外一方通讯时,只需要把Clock(时钟脚)拉到低电平。如果是PC机和PS/2键盘间的通讯,则PC机必须做主机,也就是说,PC机可以抑制PS/2键盘发送数据,而PS/2键盘则不会抑制PC机发送数据。一般两设备间传输数据的最大时钟频率是33kHz,大多数PS/2设备工作在10~20kHz。推荐值在15kHz左右,也就是说,Clock(时钟脚)高、低电平的持续时间都为40μs。每一数据帧包含11~12个位,具体含义如表1所列。

表1数据帧格式说明

1个起始位总是逻辑0

8个数据位(LSB)低位在前

1个奇偶校验位奇校验

1个停止位总是逻辑1

1个应答位仅用在主机对设备的通讯中

表中,如果数据位中1的个数为偶数,校验位就为1;如果数据位中1的个数为奇数,校验位就为0;总之,数据位中1的个数加上校验位中1的个数总为奇数,因此总进行奇校验。

2.3PS/2设备和PC机的通讯

PS/2设备的Clock(时钟脚)和Data数据脚都是集电极开路的,平时都是高电平。当PS/2设备等待发送数据时,它首先检查Clock(时钟脚)以确认其是否为高电平。如果是低电平,则认为是PC机抑制了通讯,此时它必须缓冲需要发送的数据直到重新获得总线的控制权(一般PS/2键盘有16个字节的缓冲区,而PS/2鼠标只有一个缓冲区仅存储最后一个要发送的数据)。如果Clock(时钟脚)为高电平,PS/2设备便开始将数据发送到PC机。一般都是由PS/2设备产生时钟信号。发送时一般都是按照数据帧格式顺序发送。其中数据位在Clock(时钟脚)为高电平时准备好,在Clock(时钟脚)的下降沿被PC机读入。PS/2设备到PC机的通讯时序如图2所示。

当时钟频率为15kHz时,从Clock(时钟脚)的上升沿到数据位转变时间至少要5μs。数据变化到Clock(时钟脚)下降沿的时间至少也有5μs,但不能大于25μs,这是由PS/2通讯协议的时序规定的。如果时钟频率是其它值,参数的内容应稍作调整。

上述讨论中传输的数据是指对特定键盘的编码或者对特定命令的编码。一般采用第二套扫描码集所规定的码值来编码。其中键盘码分为通码(Make)和断码(Break)。通码是按键接通时所发送的编码,用两位十六进制数来表示,断码通常是按键断开时所发送的编码,用四位十六进制数来表示。

3PS/2接口的嵌入式软件编程方法

PS/2设备主要用于产生同步时钟信号和读写数据。

3.1PS/2向PC机发送一个字节

从PS/2向PC机发送一个字节可按照下面的步骤进行:

(1)检测时钟线电平,如果时钟线为低,则延时50μs;

(2)检测判断时钟信号是否为高,为高,则向下执行,为低,则转到(1);

(3)检测数据线是否为高,如果为高则继续执行,如果为低,则放弃发送(此时PC机在向PS/2设备发送数据,所以PS/2设备要转移到接收程序处接收数据);

(4)延时20μs(如果此时正在发送起始位,则应延时40μs);

(5)输出起始位(0)到数据线上。这里要注意的是:在送出每一位后都要检测时钟线,以确保PC机没有抑制PS/2设备,如果有则中止发送;

(6)输出8个数据位到数据线上;

(7)输出校验位;

(8)输出停止位(1);

(9)延时30μs(如果在发送停止位时释放时钟信号则应延时50μs);

通过以下步骤可发送单个位:

(1)准备数据位(将需要发送的数据位放到数据线上);

(2)延时20μs;

(3)把时钟线拉低;

(4)延时40μs;

(5)释放时钟线;

(6)延时20μs。

3.2PS/2设备从PC机接收一个字节

由于PS/2设备能提供串行同步时钟,因此,如果PC机发送数据,则PC机要先把时钟线和数据线置为请求发送的状态。PC机通过下拉时钟线大于100μs来抑制通讯,并且通过下拉数据线发出请求发送数据的信号,然后释放时钟。当PS/2设备检测到需要接收的数据时,它会产生时钟信号并记录下面8个数据位和一个停止位。主机此时在时钟线变为低时准备数据到数据线,并在时钟上升沿锁存数据。而PS/2设备则要配合PC机才能读到准确的数据。具体连接步骤如下:

(1)等待时钟线为高电平。

(2)判断数据线是否为低,为高则错误退出,否则继续执行。

(3)读地址线上的数据内容,共8个bit,每读完一个位,都应检测时钟线是否被PC机拉低,如果被拉低则要中止接收。

(4)读地址线上的校验位内容,1个bit。

(5)读停止位。

(6)如果数据线上为0(即还是低电平),PS/2设备继续产生时钟,直到接收到1且产生出错信号为止(因为停止位是1,如果PS/2设备没有读到停止位,则表明此次传输出错)。

(7输出应答位。

(8)检测奇偶校验位,如果校验失败,则产生错误信号以表明此次传输出现错误。

(9)延时45μs,以便PC机进行下一次传输。

读数据线的步骤如下:

(1)延时20μs;

(2)把时钟线拉低

(3)延时40μs

(4)释放时钟线

(5)延时20μs

(6)读数据线。

下面的步骤可用于发出应答位;

(1)延时15μs;

(2)把数据线拉低;

(3)延时5μs;

(4)把时钟线拉低;

(5)延时40μs;

(6)释放时钟线;

(7)延时5μs;

(8)释放数据线。

4用于工控机的双键盘设计

工控机通常要接标准键盘,但是为了方便操作,常常需要外接一个专用键盘。此实例介绍了在工控PC机到PS/2总线上再接入一个自制专用键盘的应用方法。

该设计应能保证两个键盘单独工作,而且相互不能影响。因此,不能直接把专用键盘和标准键盘一起接到工控PC的PS/2口。鉴于这种情况,本设计使用模拟开关CD4052并通过时分复用工控PC的PS/2口,来使在同一个时刻只有一个键盘有效,从而解决上述问题。其硬件原理图如图3所示。其中P2口和P1口用于键盘扫描电路(图中未画出),P0.0为数据端,P0.1为时钟端,P0.2为模拟开关选通端。由于专用键盘不需要接收工控PC机的命令,所以软件中并不需要写这部分相应的代码。

通过软件可在专用键盘复位后把P0.2清0,以使模拟开关CD4052打开相应的通道。这时工控PC的标准键盘将开始工作。标准键盘可以完成工控PC刚启动时对外设检测的应答。复位后的专用键盘不停地扫描有没有按键,如果有键按下则识别按键,并且按照预先的设计进行编码,同时调用发送程序并通过PS/2口发送到工控PC。此时模拟开关关闭相应通道(将P0.2置1),专用键盘接入工控PCPS/2口的时钟线和数据线而工作,但标准键盘被模拟开关从PS/2的时钟线和数据线中断而不工作,这样,双键盘便可时分复用同一个工控PC机的PS/2口。相应的发送子程序如下:

#defineDATAP00用P0.0做数据线

#defineCLKP01用P0.1做时钟线

#defineINHIBITP02用P0.2做CD4052的INH端

#definePORTRP1用P1口做读入口

#definePORTWP2用P2口做写出口可以实现64个自定义键

voidsend(ucharx)/***functionforsendacharda-ta***/

{

uchari,temp,char_temp;

bitflag_check=1;

INHIBIT=1;//disablestandardkeyboard

delay_ms(3);

temp=x;

for(i=0;i<8;i++)//findthenumberof1inthisucharxisoddornot

{

char_temp=temp&0x01;

if(char_temp==0x01)

{

flag_check=!flag_check;

}

temp=temp>>1;

}

CLK=1;//send1toP1thenreadP1

while(!CLK)//ifCLKislowwait

{

;

}

CLK=1;DATA=1;//send1toP1thenreadP1

if(CLK==1)

{

delay_us(30);//

}

if(CLK==1&&DATA==1)//senddata

{

DATA=0;//startbit0

delay_us(10);

CLK=0;

delay_us(5);//

temp=x;

for(i=0;i<8;i++)//send8bitsLSBfirst

{

CLK=1;

delay_us(5);

char_temp=temp&0x01;

if(char_temp==0x01)

{

DATA=1;

}

else

{

DATA=0;

}

//DATA=(bit)(temp&0x01);

//LSB

delay_us(10);

CLK=0;

delay_us(5);

temp=temp>>1;

}

CLK=1;//sendcheckbit

delay_us(5);

DATA=flag_check;

delay_us(10);

CLK=0;

delay_us(5)

CLK=1;//sendstopbit

delay_us(5);

DATA=1;

delayus10

CLK=0

delay_us(5);

CLK=1;

delay_us(30);

CLK=1;DATA=1;//send1toP1thenreadP1

if(CLK==1&&DATA==0)

{

return;//pcissendingdatatomcu,goto

receivingfunction

}

INHIBIT=0;//enablestandardkeyboard

}

接口协议第3篇

关键词:协议栈;虚拟化;网络设备

中图分类号:TP316.8 文献标识码:A

The technology of Linux protocol stack virtualization

based on the ethernet switch

CHEN bing-bing*a,b,c, CHENG you-qingb,c

(a.Wuhan Research Institute of Post and Telecommunications, Wuhan 430074, China; b.State Key Laboratory of Optical Communication Technologies and Networks, Wuhan, 430074, China; c.Wuhan FiberHome Networks Co. , Ltd. , Wuhan 430074, China)

Abstract: The goal of network protocol stack virtualization is that virtualize multiple virtual protocol stacks based on one network device in order to implement the function of one network device virtualized into multiple. Since the network protocol stack of the Linux operation system itself don’t support this kind of technology, so this paper implement the technology of network protocol stack virtualization by means of modifying the IPV4 network protocol stack based on the 3.11.10 Linux operation system version. And then, it is proved on the device platform that the Ethernet switch, of which the protocol stack virtualization has been realized, has the function of isolating business flow

Key words: protocol stack;virtualization;network device

1 引言

随着网络规模的不断扩大,业务种类的不断丰富,网络对业务的隔离以及安全性、可靠性等属性提出了越来越高的要求[1]。此外,随着硬件能力的迅速提升,多框、集群、分布式路由交换系统的成熟,单台物理网络设备的业务处理能力已经达到了一个新的高度[2]。为了将单台物理设备的强大业务处理能力充分利用,弹性的适应当前的业务需求和未来的发展,网络设备的一虚多(即将一台物理设备虚拟成多个逻辑设备)成为了网络与通信界追求的目标[3]。Linux操作系统因其具有的开源、安全和稳定等优点,受到网络设备制造商的青睐,被广泛应用到网络设备的嵌入式开发中。

目前,国内外对Linux操作系统虚拟化的研究都着力于操作系统级的全局性资源隔离虚拟化,而缺少对网络协议栈虚拟化的深入研究。对于小规模以太网而言,全局性的资源隔离会对网络设备的进程资源造成不必要的浪费,增加了网络设备的负荷,影响网络数据包处理速率。

因此,本文在以太网交换机设备上研究了Linux嵌入式操作系统中虚拟协议栈技术,以实现业务流的隔离,提高单个以太网交换机设备的资源利用率[4]。

2 Linux网络协议栈的层次结构

网络协议栈是指TCP/IP协议栈,实现了一个网络中数据传输的过程:包括上层协议到底层协议,和由底层协议到上层协议。Linux网络协议栈的层次架构模型如图1所示,最上面一层为用户空间中的应用层,中间部分为内核空间中的网络协议栈部分,底层为物理设备[5]。在网络协议栈中用户空间和内核空间之间的数据通过套接字缓存(socket buffer) 来传递,相应的数据结构为sk_buffer。

图1 Linux网络协议栈层次架构

Linux网络协议栈的最上层是系统调用接口,为用户空间中的应用程序提供一种访问内核网络协议栈的接口。通过网络协议栈进行通信都需要对套接字进行操作,网络协议栈提供了两种调用接口给用户进程。一种是在sys_socketcall中会根据网络系统调用号调用具体的功能,另一种是通过普通文件操作来访问网络协议栈,将套接口的输入、输出操作当成典型的文件读写操作来进行。

套接字是一个与协议无关的接口层,它提供了一组通用接口来支持各种协议,它对用户层的应用程序屏蔽了与协议相关的实现细节,将应用程序发送的与协议无关的请求映射到与协议相关的实现。传输层负责数据的传输和数据的控制,提供端到端数据交换机制,传输层协议包括面向连接的TCP协议和面向无连接的UDP协议。网络层负责接收、发送或转发数据包,网络层的协议包括IP协议、ARP协议、RARP协议、ICMP协议和IGMP协议等。邻居子系统为三层协议地址与二层协议地址提供了的映射关系,此外还缓存了二层首部,以加速数据包的发送。在发送数据包的时候,先进行路由查找,如果找到对应的路由,再查看邻居表中是否存在相应的映射关系,如果不存在则新建对应的邻居项;然后再判断邻居项是否为可用状态,如果不可用则把数据报存至发送缓存队列后发送请求;在接收到请求应答后,将对应的邻居项置为可用,并将其缓存队列中的数据包发送出去;如果在指定时间内为收到响应包,则将对应邻居项置为无效状态。对于以太网交换机而言,邻居子系统提供了三层IP地址和二层MAC地址的映射,邻居表就是ARP表。

网络协议栈底部是一个与硬件无关的网络设备接口层,它将网络层的不同协议与各种网络设备连接在一起。设备无关接口层提供了一组通用函数供底层网络设备驱动程序和上层协议栈调用。当输出数据时协议栈不必关心底层的网络设备,而当输入数据时网络设备驱动同样也不必关心上层的协议栈。协议栈向设备发送数据包时都需调用dev_queue_xmit函数。该函数对sk_buffer进行排队,最终由底层设备驱动程序进行传输。而接收报文通常是调用netif_rx函数实现的。当底层设备驱动程序收到一个报文时,就会通过调用netif_rx函数将报文的sk_buffer上传至网络层。

以太网交换机设备上网络接口卡(NIC)的相关信息是由net_device结构来描述的,net_device包括了硬件信息成员变量、接口信息成员变量、设备操作接口变量和一些辅助成员变量。网络接口卡的IPv4地址等相关配置信息存放在in_device结构中,net_device中有一个指针指向in_device。每个网络接口卡都会有一个对应的net_device结构。当设备启动时调用register_netdevice函数注册到系统中,注册过的网络接口卡NIC可通过unregister_netdevice函数注销。net_device结构中包含了一个名为hard_start_xmit的接口,通常在初始化网络接口卡时设置该接口。当协议栈向网络接口卡发送数据包时,会通过设备无关接口调用到此接口[6]。

3 Linux协议栈虚拟化的实现框架

Linux协议栈虚拟化技术是属于控制平面的虚拟化,Linux协议栈虚拟化技术的实现分为以下四个部分:路由表的虚拟化、网络接口的虚拟化、与上层应用接口的虚拟化、套接字层的虚拟化。路由表的虚拟化通过对存储路由表项的数据结构的虚拟化扩展来实现,使每一个虚拟出来的协议栈都对应一份独立的路由转发表实例,虚拟协议栈的路由转发表实例之间互不干扰[7]。网络接口的虚拟化使网络接口卡在收发数据包的时候,可以区分出这个数据包是属于哪个虚拟协议栈,也使数据包在协议栈中传递的时候,可能选择正确的函数处理接口。以上两部分都是通过virtual_id标识来区分不同的虚拟协议栈,每个虚拟协议栈都自己唯一的virtual_id标识,virtual_id和虚拟协议栈是一一对应的。

图2 虚拟化协议栈架构

3.1 路由表的虚拟化

Linux协议栈中使用数据结构fib_table来描述路由表信息,所有的fib_table结构链接在全局散列表fib_table_hash中。fib_table_hash存储在数据结构struct net中的struct netns_ipv4成员中。参数不同的fib_table_hash表示不同类型的路由表,例如fib_table_hash[RT_TABLE_LOCAL]表示设备本地地址的路由表。路由表的虚拟化是将指针数据结构struct hlist_head*fib_table_hash重定义为指向指针的数据结构struct hlist_head** fib_table_hash,使用不同virtual_id标识来区分不同虚拟协议栈的路由表转发实例,例如本地路由表就重定义为fib_table_hash[RT_TABLE_LOCAL][virtual_id]。

Linux协议栈中使用数据结构rtable来描述路由缓存,路由缓存链接在散列表rt_hash_bucket中,为了使路由缓存和虚拟路由表项实例一一对应,散列表rt_hash_bucket需要被重定义为virtual_id 个不同的散列表,即rt_hash_bucket[virtual_id]。

由于不同虚拟协议栈中的目的IP地址可以重用,所以相同的IP地址在邻居子系统的ARP表中对应的目的MAC地址是不同的。而ARP表查找函数的输入参数为net_device和目的IP地址,因此可以通过net_device来区分不同虚拟协议栈中IP地址对应的MAC地址。

3.2 网络接口的虚拟化

协议栈底层网络接口的虚拟化是通过协议栈的net_device结构实现的,需要在net_device数据结构中添加一个virtual_id标识,net_device数据结构中的virtual_id表示该net_device结构对应的网络接口卡属于该virtual_id对应的虚拟协议栈。

3.3 与上层应用接口的虚拟化

协议栈内部不同层次之间接口的虚拟化是通过在协议栈内部接口函数中添加参数virtual_id实现的,virtual_id表示了同一个接口函数中对不同虚拟协议栈进行操作时,选择的表项结构是不同的。比如网络设备状态变化时或者网络设备上IP配置变化时,路由子系统收到通知链的通知,需要对路由表和路由缓存进行添加、删除、修改等操作,接口函数中的virtual_id可以选择对应的路由表项实例进行操作。同样,OSPF、RIP、ISIS等路由协议在网络路由拓扑变化时,需要对路由表进行动态添加、修改、删除的函数,因此修改路由表的接口函数传入的参数struct fib_config结构中也需要增加virtual_id标识,用来标识将要操作的路由表转发实例。

3.4 套接字层的虚拟化

在保证虚拟协议栈业务隔离的前提下,为了兼顾设备内存资源利用率,协议栈接口允许一定的共享,比如多个虚拟协议栈中同种类型的业务流可以共享同一个socket接口。应用层的协议通过socket发送数据包的时候,需要在接收方的网络地址结构中添加相应的virtual_id标识,使应用层的报文通过socket进入协议栈之后可以区分不同的虚拟协议栈,在进行报文转发的时候也可以查找对应虚拟协议栈的路由表转发实例。应用层的协议用socket接收数据包的时候,也可以从接收的地址结构中取出virtual_id标识,区分数据包是由哪个虚拟协议栈送上来的。

4 Linux虚拟协议栈的关键操作

由于网络设备上的每个虚拟协议栈可以对应设备的多个虚拟网络接口卡NIC,所以可以通过网管配置命令将多个虚拟网络接口卡的net_device结构用同一个virtual_id标识,标识为同一个逻辑组,这个逻辑组收发的所有数据包都交给同一个虚拟协议栈处理。当网络设备的网络接口卡NIC收到数据包的时候,根据网络接口卡逻辑组的划分,在数据包的地址结构中添加上对应的virtual_id标识,如图3所示将存放其地址信息的sockaddr_in结构强制转换成sockaddr_in_virtual结构。当数据包在协议栈上下层之间传递的时候,就根据virtual_id标识查找对应的函数接口和路由表项转发实例[8]。当网络设备从出端口发送数据包的时候,数据包不再带有virtual_id标识,virtual_id标识只在设备内部有效,因此设备协议栈的虚拟化对对整个网络是透明的。

图3 sockaddr_in_virtual地址信息结构

5 Linux虚拟协议栈在以太网交换机上的实现

5.1 测试平台的搭建

搭建的测试环境拓扑结构如图4所示,三层交换机设备为烽火网络的S5800系列三层千兆路由交换机。将网络协议栈被改造后的Linux嵌入式操作系统download到三层交换机设备上,该交换机设备与四台电脑相连,PC1和PC2属于vlan1,PC3和PC4属于vlan2,PC1和PC3 的IP 地址相同,PC2和PC4的IP 地址相同。

在网管界面中输入配置命令行,将与PC1和PC2相连的交换机接口划分为同一个逻辑组,它们的net_device数据结构中virtual_id都被赋值为1,与PC3和PC4相连的交换机接口也划分为同一个逻辑组,它们的net_device数据结构中virtual_id都被赋值为2。因此, PC1和PC3发送到交换机的数据包分别被送往不同的虚拟协议栈,实现业务流的隔离。

图4 以太网交换机测试拓扑

5.2 测试结果分析

图5显示了在电脑PC1上ping PC2的实验结果,图6显示了在电脑PC3上ping PC4的实验结果,虽然PC1和PC2的IP地址相同,但是业务流之间互不影响,相互隔离。图7和图8显示了协议栈经过一虚多虚拟化后每个虚拟协议栈都有自己独立的路由转发表。

由上可知,经过网络协议栈虚拟化的虚拟设备可以承载不同的业务,或者服务于不同的用户群,达到业务隔离提升网络可靠性和安全性,降低用户成本,并可以实现多用户群管理隔离,有效简化运维。

图5 PC1 ping PC2实验结果

图6 PC3 ping PC4实验结果

图7 虚拟协议栈1的路由表 图8 虚拟协议栈2的路由表

6 结论

接口协议第4篇

PCookie 是 muxBind 底层设备驱动后返回的设备索引号,以便系统卸载网络服务子层时可解除该绑定。

Ifp 是网络服务子层 Attach至协议栈时返回的子网接口索引号,以便系统卸载该 Service 时可解除绑定。

6.2.3 Service 协议数据收发流程

Service 正确绑定至协议栈后,就可以接收SAR END驱动层传入的该协议类型数据报文并对其处理,根据处理的结果选择转发或丢弃;对于协议栈下发的报文,也可以方便地进行相应协议封装,再交给 END驱动发送。其收发流程框图如图 6-1 所示。

图6-1 Service 收发流程示意图

接收流程(虚线箭头所示):

1)SAR 模块收到报文,产生中断,进入接收中断处理例程

2)调用END_RCV_RTN_CALL将报文返回给协议栈(reserved 中存放协议类型)

3)MUX层询问该报文的协议类型

4)SAR驱动层将 reserved 中的类型返回给MUX层

5)MUX层根据协议类型将报文提交给相应的 Service.

6)Service 解封装后,调用 do_protocol_with_type将报文提交给协议栈

发送流程(实线箭头所示):

1)协议栈通过MUX层发送报文

2)MUX 层将报文传给预先绑定的 Service

3)Service 对数据进行封装后,return False,将数据返回 MUX 层

4)MUX 层将数据发送到 SAR 模块相应的 PVC 接口

5)SAR 模块相应的 PVC 接口发送该报文。

6.3 RFC1483协议报文处理

由于 RFC1483数据报文的封装格式比较简单,我们将该类型报文的封装、解封装例程放在 END 驱动中实现,以提高系统对该类型报文的处理效率。

6.3.1 RFC1483 报文封装格式

RFC1483 标准描述了ATM网络上承载无连接网络互连业务(即路由和桥接的协议数据单元)的两种不同方法。第一种方法允许在一条 ATM 虚电路上复用多个协议,这是需要在所传送的 PDU 前加上 IEEE802.2 逻辑链路控制信头,以此来表示所传递的 PDU 的协议,这种方法称为 LLC 封装; 第二种方法是一个高层协议由一条ATM虚电路来承载,这种方法成为基于 VC 的复用。

6.3.1.1 LLC 封装

在 LLC 封装中,路由协议通过在 PDU 前加一个IEEE802.2 LLC 信头来进行标识, IEEE802.2 LLC 信头后接 IEEE802.1a 子网络附属点(SNAP)信头。在 LLC 类型 1 的操作中,LLC 信头包括 3 个字节,如下:

在用于路由协议的LLC 封装中,LLC信头编码有两种格式:一种为 0xFE-FE-03, 用于说明后接的是 ISO 路由协议的 PDU;另一种为 0xAA-AA-03,用于说明后接的是非 ISO 路由协议。控制字段编码为 0x03,用于说明后接的是无编号信息的命令 PDU。

对于 ISO 路由协议PDU,其AAL5 CPCS-PDU 净荷字段的格式为

对于非 ISO 路由PDU (如 IP 协议),其封装格式为

(其中,如果是 IP 报文的话,Ethernet Type 值为 0x0800)

对于桥接协议报文,在 LLC 封装的 SNAP 信头中应标识出桥接媒体的类型。与非 ISO 路由协议的封装一样,LLC信头编码值 0xAA-AA-03 表示存在 SNAP 信头, SNAP 信头中的OUI值是 802.1组织编码 0x00-80-C2,桥接媒体的实际类型由2字节的 PID 来标识。此外, PID还标识是否在封装的桥接 PDU 中保留源帧校验序列(FCS)。以最常见的以太网/802.3为例,用于封装 802.3 PDU的AAL5 CPCS-PDU净荷帧格式如下

6.3.1.1 基于VC 的复用

在基于 VC 的复用中,不同的协议报文可以通过不同的 VC 通道传递,因此在 AAL5的CPCP-PDU 净荷上就不再包含明确标识所承载协议的信息了,使得处理开销最小。

路由协议的 PDU 在 AAL5 CPCS-PDU 的净荷中直接承载。

桥接协议的 PDU 和LLC封装格式描述相同,但仅包含 PID 字段后的内容。其 AAL5 CPCS-PDU 净荷字段格式如下所示:

6.3.2 RFC1483 报文的封装处理

上层协议在调用 muxSend 之前,会先调用 endAddressForm 函数进行二层数据封装,我们在这个函数里实现IP 报文到Ethernet类型报文的数据封装。SarEndSend函数里会调用 ATMSRV_Encap 进行 Ethernet 报文到 AAL5 相应协议类型的封装。

6.3.3 RFC1483 报文解封装处理

在中断接收处理函数里,会调用 ATMSRV_Decap 解除ATM协议封装,同时将二层协议类型存于 mBlkPktHdr.reserved 中,由 endPacketDataGet通知 MUX。

7增加 NAT 支持

目前已经有很多for vxworks 的第三方 NAT 协议产品, 而且 windriver 公司自己也推出了Tornado 开发平台下的 NAT 组件, 但价位实在太高。 由于该协议本身实现的难度不大,而且有 linux 或 BSD 的相关模块可供参考和移植,所以我们决定自己实现这个协议。难点主要在于NAT收发处理函数的绑定, NAT 端口地址转换hash表的建立及查找算法的实现。

7.1  NAT 模块主处理流程

主要包括LAN口和WAN口的IP地址转换。如图 7-1 所示。

图7-1 NAT 主处理流程示意图

7.2 NAT 模块初始化

7.2.1 NAT 数据结构初始化

1) nat_session结构,记录每一连接的连接信息:

struct nat_session

{

UCHAR ip_proto;

//协议类型

struct in_addr src_addr, dst_addr, new_addr; //源地址,目标地址,转换后地址

/* Port numbers are in host UCHAR order: */

union

{

/* For TCP _and_ UDP: */

struct { UINT16 src_port, dst_port, new_port; } tcp; //端口

/* For ICMP: */

struct { UINT16 src_ident, new_ident; } icmp;

//identification

} U;

enum nat_session_state state;

//连接状态

unsigned long

timestamp;

//时间戳

NAT_ALG

*alg;

//应用层网关函数指针

int

alg_use;

//标志,是否需要应用层网关

NAT_SESSION *parent;

//ftp中指向控制连接session的指针

NAT_SESSION *next_hash;

//Hash表下一表项

};

2)nat_interface接口结构

struct nat_interface

{

NAT_INTERFACE *next;

//指向下一个接口结构

struct in_addr ipaddress;

//接口地址(转换地址)

/* Pointer to table of session structures, and hash table: */

NAT_SESSION *sessions;

//指向session结构表

NAT_SESSION **hashtable;

//指向hash结构表

int next_session;

/* Pointer to table of fragment structures */

NAT_FRAGMENT *fragments;

//指向fragment结构表

int frag_queued;

//记录保存有多少个分片队列

/* Stats - counts of sessions */

//各种计数器

UINT32 tcp_out, udp_out;

UINT32 icmp_q_out, icmp_err_out, icmp_err_in;

UINT32 discard_in, discard_out, refused_in, del_early;

};

7.2.2 NAT 收发处理函数的绑定

仔细分析 vxworks 协议栈代码后,觉得使用 _ipFilterHook 绑定 NAT 接收报文处理函数的方式比较可行,该钩子函数在协议栈接收到数据报文时被调用,函数输入输出格式如下:

BOOL NatIpFilterHookRtn

(

struct ifnet rcvifnet,

/* 数据接收的接口*/

struct mbuf **m,

/* 数据报文地址 */

struct ip **ip,

/* IP 头部地址 */

int hlen

/* IP 头的长度 */

)

返回值: 为 FALSE时表示报文处理正常,协议栈可继续转发或处理

为TRUE 时指示系统丢弃该报文

由于无法找到协议栈输出报文的钩子,我们打算把输出报文 NAT 转换放在 _ipFilterHook 的 LAN 口钩子中处理,即在 LAN口报文进入协议栈之前就更改源IP和端口地址。但这样做的缺点是:此时系统还没有检索过该报文的路由目的接口,需要人为增加查找路由表算法,当发现是发往指定 WAN 口时再行转换,处理的效率较低。

为充分利用协议栈的报文路由处理功能,决定采用更改协议栈代码的方式,在 ip_output 函数适当位置处人为增加一个钩子 _func_natOutput,重新编译 vxworks 协议栈库函数。 这样,NAT 模块初始化时即可将NAT输出报文处理函数绑定至该钩子。函数的输入输出关系格式如下:

int NatOutput

(

struct mbuf** m0,

/* 数据报文地址 */

struct ip **ip,

/* IP 头部地址 */

struct in_ifaddr* ia /* 报文目的接口 */

)

返回值: OK 或 ERROR (ERROR 时将丢弃并释放该报文)

7.3

NAT模块主要算法

7.3.1 NAT 端口地址转换HASH算法

NAPT 转换表查找算法可分为按端口查找和按地址查找两种。在实际的 ADSL接入环境中,局端很少会为一个连接分配多个 IP,因此我们采用按端口查找的算法来简单实现。

1) session 结构数组的初始化

NAT初始化时根据系统支持的最大转换数目建立一个按端口分布的 nat_session结构数组(nat_session 节点的定义见7.2.1), 同时建立一个指向nat_session 的空 hash 表。Hash节点结构如下:

typedef struct nat_hash_bucket_

{

struct nat_hash_bucket_ *next;

//指向下一个节点

struct nat_hash_bucket_ *prev;

//指向前一个节点

unsigned nat_session *pSession; //指向nat链表中相应的节点

}nat_hash_bucket;

2) 新建 session

get_free_session 在session静态表(结构数组)中获得一个free session,并将其从Hash表中unlink出来。查找的依据为时间戳, 顺序遍历session表,直到找到第一个超时的session。若未找到,则覆盖当前指针指向的session。

填充该 session 结构,返回该session 所对应的端口号。根据 TCP/UDP 报文的源 IP 和源端口号计算出 hash 头,增加到 hash 头所对应的链表后。其中,hash 头的算法如下:

LOCAL UINT16 ipnat_hash_fn(ipaddrtype addr1,

ipaddrtype addr2,

UINT16 port1,

UINT16 port2)

{

UINT16 bucket;

bucket = addr1 >> 16;

bucket ^= addr1 & 0xffff;

bucket ^= port1;

bucket ^= addr2 >> 16;

bucket ^= addr2 & 0xffff;

bucket ^= port2;

bucket = bucket % IPNAT_HASHLEN;

return(bucket);

}

转换后的 TCP/IP 报文源IP变为 WAN口IP,源端口变为session 索引值,这样做的优点是:外部返回的报文可以通过TCP/IP报文的目的端口号直接定位到 session 数组中,查找的速度最快。

3) 查找 session

通过 TCP/UDP 报文的源 IP 和源端口号计算出 hash 头,然后遍历该头所对应的链表,直到找到相匹配的hash 节点。

4) 删除 session

收到 TCP/UDP 连接关闭请求后,根据目的端口号找到 session 数组,释放该 session, 并将其从 Hash 表中 unlink 出来。

7.3.2 TCP/UDP 协议端口地址转换

setup_tcpudp_outgoing 为从内部网络出去的TCP/UDP连接建立一个session,记录下连接的源地址、端口,目标地址、端口,转换后的地址、端口,协议类型以及连接建立时间等信息。

translate_outgoing_tcpudp 核心函数,根据 session 的对应记录,转换数据包的IP地址、端口,同时重新调整IP校验和及TCP/UDP校验和,其中,校验和调整主要用到了adjust_chksum函数。算法如下:

void adjust_chksum(ulong *chkSum, ushort oldW, ushort newW)

{

*chkSum -= oldW & 0xffff;

if ((*lChkSum)

{

(*chkSum) --;

(*chkSum) &= 0xffff;

}

(*chkSum) += newW & 0xffff;

if ((*chkSum) & 0x10000)

{

(*chkSum) ++;

(*chkSum) &= 0xffff;

}

}

8 设计总结

本系统的优点是,仅需采用一块 CPU 即可同时实现 ADSL接入和路由两项功能,硬件资源利用率高,而且,两种功能在同一套系统平台中可以有机结合,避免因中间插入多余转换接口导致包处理效率降低。

文中所述的仅实现了一个最简单的 ADSL 共享接入方式,并不能完全满足实际使用中的种种需求,还需要补充其它如协议报文处理、ICMP报文处理、应用层网关处理等功能。 此外,在实际测试中,感觉 NAT 地址转换Hash 表的算法还不够理想:在新建一个节点时需要重新遍历整个 nat_session 数组,这将导致在连接数较多的情况下再新建一条连接非常困难,系统效率急剧降低。

在这次开发设计前期,由于对操作系统的架构不够熟悉,在设备驱动编写方面没有经验,导致编写的驱动层次感很差,不利于维护和后期扩展。走了很多弯路之后,总结出经验:开发前期的调研工作非常必要,在着手写代码之前应该多花些时间了解开发平台、熟悉整个系统的架构、模块在系统之间的地位及模块间的接口关系。磨刀不误砍柴工,总体规划充分之后才能编写出效率高、易维护、易扩展的模块代码出来。

参考文档

ITU-T Recommendation I.363.5 AAL Specification: Type 5 AAL, March 1993

IETF RFC1483. Multiprotocol Encapsulation Over ATM Adaptation Layer5, July.1993

IETF RFC1577. Classical IP and ARP over ATM, January 1994

IETF RFC2364

IETF RFC2516

IETF RFC791 IP

IETF RFC768 UDP

IETF RFC793 TCP

IETF RFC792 ICMP

IETF RFC826 ARP

IETF RFC1631 NAT

Vxworks network services standard。

接口协议第5篇

关键词:VoIP;公用信道;服务器

中图分类号:TP393文献标识码:A文章编号:1009-3044(2008)24-1185-04

在VoIP通信过程中,服务器要为每个客户端创建一个信道来维持与其通信。这种用于和客户端保持通信的信道称为协议信道。如图1所示,传统的VoIP服务器都是由上层控制模块来直接控制协议信道,由于上层控制模块和底层协议信道相关,无法实现对不同类型协议信道的控制,因此传统VoIP服务器只能够支持单一的协议。如果能够设计出可同时支持多种协议的服务器,那么它就可以对各种协议进行处理和转换,从而解决不同VoIP协议的互通问题。

1 公用信道的思想

为了解决分布异构问题,人们提出了中间件的概念。中间件是位于平台(硬件和操作系统)和具体应用之间的通用服务,这些服务具有标准的程序接口和协议。中间件能够屏蔽操作系统和网络协议的差异,为应用程序提供多种通讯机制,并提供相应的平台以满足不同领域的需要。因此,中间件为应用程序提供了一个相对稳定的高层应用环境。这里借鉴了中间件的思想,在底层协议信道和上层控制模块之间添加一类特殊的信道,称为公用信道。图2描述了增加公用信道以后服务器控制协议信道的方式。通过公用信道将上层控制模块和底层协议信道相分离。公用信道提供了一系列的接口,上层控制模块只需通过这些接口就可以控制公用信道,从而达到管理和控制整个会话过程的目的,而不必关注底层协议信道具体使用的是哪种VoIP协议。

2 公用信道接口

2.1 会话模型

不同VoIP协议虽然在信令、媒体传输方式上存在不同,但服务器建立会话的过程都大致分为以下几个阶段:

呼叫开始:当服务器收到客户端的呼叫请求后,建立主叫用户信道。然后查找被叫用户地址,创建与被叫用户通信的信道。

呼叫被叫:在主被叫信道建立之后,开始向被叫用户发送能够呼叫请求消息,并等待被叫用户应答。

通话:服务器收到被叫用户应答后,就开始转发主被叫用户的语音数据。

呼叫结束:当收到主叫或被叫用户的挂机请求后,服务器分别拆除主被叫信道,结束通话。

公用信道可以根据服务器建立会话的过程,抽象出一系列与会话相关(呼叫、应答、挂机)的接口,以便上层控制模块使用这些接口来管理和调度公用信道,从而控制整个会话过程。

2.2 接口的多态性

多态性提供了接口和实现的分离,也就是说把做什么和怎么做分开来。多态性不但能改善代码的接口,提高其可读性,而且能创建可扩展的程序。

由于公用信道位于各协议信道之上,公用信道的这些接口的实现是和底层协议信道相关的。根据底层VoIP协议的不同,这些接口的实现方法有很大的差别。因此可采用多态性的思想来设计公用信道接口。由公用信道中定义上层控制模块调用的接口,而这些接口的实现交给底层各协议信道来完成。

在会话过程中,控制模块只需调用这些接口来控制会话,程序会根据底层信道类型的不同,调用相应的函数,公用信道因此表现出不同的行为。这样公用信道就屏蔽了底层协议信道的差异性,从而解决了不同VoIP协议的互通问题。

这种方式还具有良好的扩展性。当需要增加对一种新协议的支持,只需在底层实现公用信道定义的这些接口,而不必对公用信道和上层控制模块做任何改动。

2.3 多态性的实现

由于公用信道接口在实现上的多态性,这里使用结构体com_channel_tech来封装公用信道的接口。该结构体中包含了很多函数指针,这些函数指针指向接口的具体实现。根据底层协议信道类型的不同,底层使用不同的函数来填充com_channel_tech中的各个字段以实现这些接口。当上层控制模块调用某一接口时,系统根据会根据com_channel_tech的具体类型(底层使用的协议)调用相应的函数。这样我们就屏蔽了底层协议信道的差异性,为上层控制模块的调用提供了统一的接口。上层只需调用这些接口,就可以实现对公用信道的统一管理和调度,而不必关注在底层采用的是哪种协议。

例如,当接收到SIP请求,创建公用信道时,上层控制模块只需直接调用com_request接口,从而间接调用结构体com_channel_tech中request函数指针所指的sip_request函数。而对于IAX协议,相应的函数就换成了iax_request函数。

3 协议映射

3.1 公用帧

为了便于上层控制模块管理会话,公用信道中只使用一种协议来传输信令和语音,这种协议称为公用协议。以公用协议格式封装的帧称为公用帧(COM帧)。从客户端发送到协议信道的各种协议帧,必须首先转换成COM帧后才能送入公用信道,然后由控制模块对其进一步处理。从公用信道发往客户端的COM帧,需要根据底层协议信道的类型,进行相应的帧格式转换后才能发送。

由于公用信道既要处理信令又要转发语音数据,所以COM帧分为信令帧和语音帧两种类型。信令帧主要用于控制会话的进程,而语音帧用于传输实际的语音数据。采用结构体com_frame来表示COM帧:

struct com_frame {

int frametype;

int subclass;

int datalen;

int samples;

void *data;

struct timeval delivery;

};

其中frametype字段用于说明COM帧的类型属于信令帧(COM_FRAME_CONTROL)还是语音帧(COM_FRAME_VOICE)。

对于信令帧,只有subclass字段有意义,该字段用于说明信令帧表示的具体控制信息。

对于语音帧,subclass字段代表该语音帧使用的编码格式;datalen表示语音帧长度;samples表示采样点数;delivery表示发送时间戳;指针data指向实际的语音数据。

3.2 信令帧的映射

底层信道的各种协议帧在送入公用信道之前需要转化成COM帧。从公用信道中出来的COM帧需要转化成协议信道能处理的帧。不同协议帧之间的转换过程称为协议映射。协议映射关系的制定是实现VoIP互通的前提和保证。

3.3 语音帧的映射

为了保证语音在转发时不会失真,COM帧在传输语音时必须包含以下信息:语音编码格式、语音数据长度、采样点数、发送时间戳以及实际的语音数据。因此,其它协议帧在转化成COM帧时,必须完成以上内容的转换。

1)IAX帧映射到COM帧:对于IAX协议,语音是通过Mini帧来传输的,在开始发送语音和固定时间间隔内发送Full帧来同步语音帧。由于Mini帧只包含16位的时间戳和语音数据,协议信道需要将先前从Full帧中获得的语音编码格式subclass和32位的时间戳记录下来。这样,语音数据的编码格式可以从对应的协议信道获得。语音数据长度可由Mini帧帧长减去帧头长度得出。采样点数是根据数据长度和编码格式计算得出。时间戳由Full帧的高16位和Mini帧的16位组合而成。原始语音数据直接存入到COM帧的data字段。IAX帧的其他信息与转发语音无关,均保存在协议信道之中。

2)RTP帧映射到COM帧:对于SIP协议的客户端,语音数据通常是通过RTP帧来传送的。从RTP帧转化成COM帧,时间戳可以直接从RTP帧头的timestamp字段取得,语音编码格式从PT字段中得到,语音数据长度可由帧长减去帧头长度计算得出,采样点数也是根据数据长度和编码格式计算得出,而原始的语音数据直接存入到相应字段。

4 语音传输方式

在呼叫建立之后,客户端开始语音通信。语音传输方式有两种:一种是P2P方式,另一种是服务器转发方式(Server Relay)。

4.1 P2P方式

P2P方式是指语音数据直接从一个客户端发送到另一个客户端。P2P传输方式具有降低网络时延、减轻服务器负荷等优点。但不是任何客户端之间都可以建立P2P连接的。除了通信双方需要知道彼此的地址外,P2P还要具备如下条件:

1)通信双方采用相同的信令和语音传输方式。也就是说客户端采用的是相同的VoIP协议。

2)如果通信的一方或双方的网络中存在NAT,语音数据要能够穿越对方的NAT。

3)通信双方要能够理解对方所发送的语音数据。也就是说,发送语音数据的编码格式要能够为对方所支持。

对于满足上述条件的会话,服务器在建立呼叫后会调用com_bridge函数,尝试为客户端之间建立P2P连接。如果建立P2P成功,服务器就释放与客户端通信的信道,由客户端之间直接进行语音通信。

4.2 服务器转发方式

对于不满足建立P2P条件的客户端之间的会话,需要由服务器转发双方的语音数据,也就是说客户端先将语音数据发送给服务器,由服务器转发到另一个客户端。根据会话类型的不同,服务器的转发方式又分为以下两种。

1)经过公用信道的转发

对于不同客户端的语音通信,语音数据需要进行协议类型、语音编码格式的转换,这些都是由公用信道负责完成的。因此,语音数据要送入公用信道处理。图3描述了SIP和IAX客户端进行语音通信的过程。下面以SIP客户端向IAX客户端发送语音通信为例,来说明语音数据的传输路径。SIP客户端的语音以RTP帧的形式发送到服务器的RTP信道中,被转换成COM帧后送入到所在的公用信道。公用信道将其发送给与IAX客户端对应的公用信道。然后调用相应的接口函数将COM帧转换成IAX帧后,发送至IAX客户端。

2)不经公用信道的转发

对于同类型客户端的通信,由于语音数据不需要进行协议、编码格式的转换,可以将其直接发送到对方的协议信道中。所以可以优化上面的传输路径。图4描述了IAX客户端之间进行语音通信的过程,一方的语音数据以Mini帧格式发送到服务器,然后由IAX信道直接将该Mini帧发送到对方的IAX信道。这样语音数据就不必经过双方的公用信道,也不需要对帧类型进行转换,因而提高了语音数据的传输效率,减少了时延。

5 公用信道的通信

5.1 收发COM帧

每个公用信道都维护着一个readq队列,该队列是由COM帧组成的。协议信道发给公用信道的COM帧都是先送入该队列中。当服务器监听到某个公用信道有COM帧时,调用接口函数com_read,从该公用信道的readq队列中读取COM帧进行处理。

对于要发送给客户端的COM帧,直接调用公用信道提供的接口函数com_write即可。该函数的实现是由底层完成的,根据底层协议信道类型的不同,先将COM帧转化成对应的协议帧,然后调用套接字函数sendto将其发往客户端。

5.2 IO多路转接

如前所述,会话建立后上层控制模块要同时管理和控制主被叫两个公用信道,监听主被叫信道的readq队列是否有COM帧到来。如果采用传统的IO阻塞技术,那么线程就可能长时间阻塞在一个信道上,而另一个信道虽然有很多数据却不能得到及时处理。在这种情况下,我们使用IO多路转接技术来同时监听多个信道。

所谓IO多路转接技术,是先构造一张有关描述符(公用信道)的列表,然后调用poll函数,同时监听这些信道,直到这些信道中的一个已准备好进行IO(有数据发生)时,该函数立即返回。在返回时,它会告诉进程哪个信道有数据发生。poll函数的定义如下:

#include

int poll(struct pollfd fdarray[],nfds_t nfds,int timeout);

参数:fdarray 数组中的每一个元素对应一个描述符(公用信道)

nfds描述符的个数

timeout 监听(等待)时间

返回值:准备就绪的描述符,若超时则返回0,若出错返回-1

5.3 管道机制

COM帧是由底层的发送线程送至公用信道的readq队列中,而监听公用信道是由上层控制模块的线程来完成的。由于发送COM帧和监听COM帧是由服务器的不同线程控制,因此需要建立管道机制来解决线程间的通信问题。

在每个公用信道创建的时候,定义了一个alterpipe[2]的数组,用于建立通知管道。其中alterpipe[0]对应于管道的读端口,alterpipe[1]作为管道的写端口。在开始呼叫后,服务器会调用poll函数来监听公用信道的读端口alterpipe[0]。

当有数据送入到readq队列,底层发送线程控制该信道对应管道的写端口alterpipe[1]向读端口alterpipe[0]发送一个通知信号(通常是一个字符)。当读端口接收到该信号后,poll函数就立即返回,并告诉系统哪个信道有数据请求处理。服务器就从该信道对应的readq队列中读取出COM帧。这个过程可由图5来描述。

6 互通实例

下面就以IAX与SIP互通为例,说明互通过程中协议的映射过程。这里以SIP客户端发起呼叫和先挂机为例,呼叫的具体流程如图6所示,图中省略了一些次要消息的交互过程。

6.1 呼叫建立

主叫方SIP协议信道收到呼叫请求后,立即建立主叫公用信道。并分析被叫号码,根据被叫客户端的类型,建立相应的被叫公用信道以及到被叫客户端的协议信道。这样,双方就可以开始建立呼叫。SIP客户端呼叫IAX客户端的信令过程描述如图5所示:

1)SIP客户端向服务器的SIP信道发送INVITE消息;2)SIP信道收到INVITE消息,立即创建主叫公用信道,并向SIP客户端发送100 Trying消息,确认收到呼叫请求,服务器正在处理中;3)SIP信道将INVITE消息翻译成COM_CONTROL_INVITE消息,并发送到主叫公用信道中;4)当公用信道收到该消息后,立即创建一个新线程,接入到上层控制模块,分析被叫号码,查找被叫地址,并根据被叫客户端类型分别创建被叫公用信道和被叫IAX信道,以便与IAX客户端通信;5)被叫公用信道将COM_CONTROL_INVITE消息转换成NEW消息发送给IAX信道;6)IAX信道将该消息发送给IAX客户端;7)IAX客户端发送ACCEPT消息确认建立连接;8)IAX客户端发送RINGING消息,表示其正在振铃中;9)IAX信道将RINGING消息转化成COM_CONTROL_RINGING消息,发送给被叫公用信道;10)被叫公用信道将该消息转发给主叫公用信道;11)主叫公用信道将COM_CONTROL_RINGING消息翻译成180 Ringing消息,发送给SIP信道;12)SIP信道将该消息发送给SIP客户端;13)IAX客户端发送ANSWER,表示被叫端已经应答。ANSWER消息按与Ringing消息类似传送过程转化成200 OK消息发送给SIP客户端。呼叫建立完成,双方开始语音通信。

6.2 语音转发

SIP协议采用的是RTP传输语数据音,而且收发语音的端口不同于SIP协议端口(2N,2N+1,N为随机整数);IAX是信令和语音是共享端口的,使用Mini帧传输语音。同前面的信令映射方法类似,语音帧也需要经过RTP/Mini帧 COM帧 Mini/RTP帧的转化过程。

6.3 呼叫释放

呼叫结束的过程如图6所示:28)SIP客户端向服务器的SIP信道发送BYE消息,请求结束会话;29)SIP信道收到BYE消息,立即向SIP客户端发送ACK消息,确认收到结束;30)SIP信道将BYE消息翻译成COM_CONTROL_HANGUP消息,并发送给主叫公用信道中;31)主叫公用信道将COM_CONTROL_HANGUP消息发送给被叫公用信道,并释放主叫公用信道和SIP信道;32)被叫公用信道向IAX信道发送HANGUP消息;33)IAX信道向IAX客户端发送HANGUP消息;34)IAX客户端向IAX信道发送ACK消息,表示已收到释放请求。服务器释放被叫公用信道和IAX信道。

参考文献:

[1] 张登银,孙精科.VoIP技术分析与系统设计[M].北京:人民邮电出版社,2003.

[2] Abbasi T, Prasad S, Seddigh N., Lambadaris I. A Comparative study of the SIP and IAX VoIP protocols.Electrical and Computer Engineering,2005.Canadian Conference on1-4 May 2005 Page(s):179-183.

[3] 糜正琨.IP网络电话技术[M].北京:人民邮电出版社,2000.

接口协议第6篇

关键词:数字电视,图文信息,接口

 

1引言

数字电视图文信息服务系统建立的目的主要是为了更好的给用户提供所需的关于医疗卫生、教育教学、农产品价格和供求等相关信息,对信息资源做到集中管理、共享访问,最终形成一个有一定规模的图文信息服务系统。论文参考,图文信息。为了使各部分模块之间能够顺畅的衔接,本文介绍了数字电视图文信息服务系统接口的设计方案。

2图文信息服务系统外部接口的设计

2.1与门户的接口

图文资源中心作为一个独立的平台,与门户登陆系统之间通过接口传送机顶盒登陆数据信息,如图1所示。

图1 门户系统接口结构图

门户系统接口:功能是获得当前机顶盒的MAC地址。论文参考,图文信息。

接口协议:通信采集用HTTP协议,通信的数据格式采用XML1.0标准。

2.2与合作方网站的接口

对于开放站点数据库的合作方,由于不同的合作方其数据库结构也不尽相同,因此在图文采集子系统的数据迁移模块中,分析合作方数据库结构的协议需要与开放站点做接口。

传输数据:合作方向资源中心提供的信息数据。

接口协议:合作方数据源的数据格式协议。论文参考,图文信息。与开发站点数据库的通信采集JDBC2.0标准;与XML格式数据源通信,数据格式采用XML1.0标准。

2.3短信平台接口

此接口留待扩展,当用户选择接收手机短信时,有新的留言信息会有手机短信提示,可和现有的短信平台对接,实现图文的短信增值。

传输数据:留言发件人、留言标题、留言正文。

接口协议:与留言系统数据库的通信采集JDBC2.0标准;与短信平台接口数据格式符合短信平台的协议。

2.4与中小学教育信息系统(PSTIM)接口

2.4.1数据同步

数据同步部分主要功能是基于TCP协议建立socket连接的方式,将中小学教育信息系统中的年级、年级所学科目、年级所学科目版本、知识点、教学周等信息传递过来,并将此信息转化为图文栏目层次的数据关系,通过此关系可以对学习资料图文信息进行组织。在图文中PSTIM传递而来的数据将组成为图文中一个子系统进行管理。

1.接口结构图

图2PSTIM门户系统接口结构图

2.协议和规范:

TCP协议:从PSTIM中获取数据采用的协议。

JDBC:数据转入图文数据库中遵守的规范。

HTTP:接口程序与图文数据库通信采用的协议。

3.接口实现:

接口实现分为五个模块(类):中间表、socket通信模块、传输数据分析模块、数据结构转化模块、图文库操作模块。论文参考,图文信息。

1) 中间表:

图3 接口图文与中小学教育数据结构图

2) Socket通信模块:

采用成熟的基于TCP协议的socket通信的代码搭建。根据双方沟通和《教学管理系统与EPG等系统的接口协议.》文档,接口同步程序作为socket通信的客户端。论文参考,图文信息。根据配置的IP和PORT向服务端发送数据请求。论文参考,图文信息。服务端数据发生变化由系统外通知,数据通信请求由手动方式触发。

3) 传输数据分析模块:

传输数据分析类根据文档《教学管理系统与EPG等系统的接口协议》制定数据传输协议编写。

4) 数据结构转化模块:

数据结构转化完毕后在栏目表中层次结构为:中小学教育信息系统->年级->年级所学科目->年级所学科目版本->知识点->图文学习资料。转化完毕在图文中中小教学系统传递而来的数据作为一个图文中一个子系统进行管理。

数据同步完毕后在接口图文与中小学教育表中层次结构为年级->年级所学科目->年级所学科目版本->知识点。

5) 图文库操作模块:

该模块主要由操作栏目和操作接口图文与中小学教育两个表。功能分为:

a) 对这两个表进行插入、修改、更新操作。

b) 获得同步数据在图文中所属的rootid。

c) 删除栏目(删除其下所有子栏目和信息)。

3总结

数字电视图文信息服务系统为数字电视增值业务的发展提供了更为广阔的平台,设计适合信息服务平台各类信息模块联接的接口,是图文信息服务系统中的重中之重。本文所设计的方案,满足了各模块之间的信息交互,为数字电视增值业务的发展奠定了坚实的技术基础。

参考文献:

[1]邓晓燕.广播电视台图文信息频道制播系统的升级和改版初探[J]. 技术与市场,2009,(04).

接口协议第7篇

关键词:蓝牙技术硬件实现链路管理与控制跳频

蓝牙技术是一项新兴的技术。它的主要目的是在全世界建立一个短距离的无线通信标准。它使用2.4GHz~2.5GHz的ISM(IndustrionScientifcMedical)频段来传送话音和数据。运用成熟、实用、先进的无线技术来代替电缆,它提供了低成本、低功耗的无线接口,使所有固定和移动设备通过微微网PAN(PersonalAreaNetwork)连接起来,诸如:计算机系统、家庭影院系统、无绳电话系统、通信设备等,相互通信,实现资源共享。蓝牙技术支持多种电子设备之间的短距离无线通信,这种通信不需要任何线缆,亦不需要用户直接手工干涉;每当一个嵌入了蓝牙技术的设备发觉另一同样嵌入蓝牙技术的设备,它们就能自动同步,相互通信,实现资源共享。

1蓝牙的结构体系

蓝牙协议栈的体系结构如图1所示。它是由底层硬件模块,中间层和高端应用层三大部分组成。

1.1蓝牙的底层模块

底层模块是蓝牙技术的核心模块,所有嵌入蓝牙技术的设备都必须包括底层模块。它主要由链路管理层LMP(LinkManagerProtocol)、基带层BB(BaseBand)和射频RF(RodioFraquency)组成。其功能是:无线连接层(RF)通过2.4GHz无需申请的ISM频段,实现数据流的过滤和传输;它主要定义了工作在此频段的蓝牙接收机应满足的需求;其带层(BB)提供了两种不同的物理链路(同步面向连接路SCOSynchronousConnectionOriented和异步无连接链路ACLAsynchronousConnectionLess),负责跳频和蓝牙数据及信息帧的传输,且对所有类型的数据包提供了不同层次的前向纠错码FEC(FrequencyErrorCorrection)或循环沉余度差错校验CTC(CyclicRedundancyCheck);LMP层负责两个或多个设备链路的建立和拆除及链路的安全和控制,如鉴权和加密、控制和协商基带包的大小等,它为上层软件模块提供了不同的访问入口;蓝牙主机控制器接口HCI(HostCntrollerInterface)由基带控制器、连接管理器、控制和事件寄存器等组成。它是蓝牙协议中软硬件之间的接口,提供了一个调用下层BB、LM、状态和控制寄存器等硬件的统一命令,上、下两个模块接口之间的消息和数据的传递必须通过HCI的解释才能进行。HCI层以上的协议软件实体运行在主机上,而HCI以下的功能由蓝牙设备来完成,二者之间通过传输层进行交互。

1.2中间协议层

中间协议层由逻辑链路控制与适配协议L2CAP(LogicalLinkControlandAdaptationProtocol)、服务发现协议SDP(ServiceDiscoveryProtocol)、串口仿真协议或称线缆替换协议(RFCOM)和二进制电话控制协议TCS(TelephonyControlprotocolSpectocol)组成。L2CAP是蓝牙协议栈的核心组成部分,也是其它协议实现的基础。它位于基带之上,向上层提供面向连接和无连接的数据服务。它主要完成数据的拆装、服务质量控制、协议的复用、分组的分割和重组(SegmentationAndReassembly)及组提取等功能。L2CAP允许高达64KB的数据分组。SDP是一个基于客户/服务器结构的协议。它工作在L2CAP层之上,为上层应用程序提供一种机制来发现可用的服务及其属性,而服务属性包括服务的类型及该服务所需的机制或协议信息。RFCOMM是一个仿真有线链路的无线数据仿真协议,符合ETSI标准的TS07.10串口仿真协议。它在蓝牙基带上仿真RS-232的控制和数据信号,为原先使用串行连接的上层业务提供传送能力。TCS是一个基于ITU-TQ.931建议的采用面向比特的协议,它定义了用于蓝牙设备之间建立语音和数据呼叫的控制信令(CallControlSignalling),并负责处理蓝廾设备组的移动管理过程。

1.3高端应用层

高端应用层位于蓝牙协议栈的最上部分。一个完整的蓝牙协议栈按其功能又可划分为四层:核心协议层(BB、LMP、LCAP、SDP)、线缆替换协议层(RFCOMM)、电话控制协议层(TCS-BIN)、选用协议层(PPP、TCP、TP、UDP、OBEX、IrMC、WAP、WAE)。而高端应用层是由选用协议层组成。选用协议层中的PPP(Point-to-PointProtocol)是点到点协议,由封装、链路控制协议、网络控制协议组成,定义了串行点到点链路应当如何传输因特网协议数据,它要用于LAN接入、拨号网络及传真等应用规范;TCP/IP(传输控制协议/网络层协议)、UDP(UserDatagramProtocol对象交换协议)是三种已有的协议,它定义了因特网与网络相关的通信及其他类型计算机设备和设备之间的通信。蓝牙采用或共享这些已有的协议去实现与连接因特网的设备通信,这样,既可提高效率,又可在一定程度上保证蓝牙技术和其它通信技术的互操作性;OBEX(ObjectExchangeProtocol)是对象交换协议,它支持设备间的数据交换,采用客户/服务器模式提供与HTTP(超文本传输协议)相同的基本功能。该协议作为一个开放性标准还定义了可用于交换的电子商务卡、个人日程表、消息和便条等格式;WAP(WirelessApplicationProtocol)是无线应用协议,它的目的是要在数字蜂窝电话和其它小型无线设备上实现因特网业务。它支持移动电话浏览网页、收取电子邮件和其它基于因特网的协议。WAE(WirelessApplicationEnvironment)是无线应用环境,它提供用于WAP电话和个人数字助理PDA所需的各种应用软件。

2蓝牙硬件的实现

蓝牙的技术规范除了包括协议部分外还包括蓝牙的应用部分(即应用模型)。在实现蓝牙的时候,一般是将蓝牙分成两部分来考虑,其一是软件实现部分,它位于HCI的上面,包括蓝牙协议栈上层的L2CAP、RFCOMM、SDP和TCS以及蓝牙的一些应用;其二是硬件实现部分,它位于HCI的下面,亦即上面提到的底层硬件模块,它已在图1中标示出。下面讨论蓝牙硬件模块的结构与性能。

蓝牙硬件模块由蓝牙协议栈的无线收发器(RF)、其带控制器(BB)和链路管理层(LMP)组成。目前大多数生产厂家都是利用片上系统技术SOC(System-On-Chip)将这三层功能模块集嵌在同一块芯片上。图2为单芯片蓝牙硬件模块结构图。它由微处理器(CPU)、无线收发器(RF)、基带控制器(BB)、静态随机存储器(SRAM)、闪存(Flash程序存储器)、通用异步收发器(UAST)、通用串行接口(USB)、语音编/解码器(CODEC)及蓝牙测试模块组成。下面分别叙述各部分的组成及功能。

(1)蓝牙基带控制器

蓝牙基带控制器是蓝牙硬件模块的关键模块。它主要由链路控制序列发生器、可编程程序列发生器、内部语音处理器、共享RAM裁器及定时链管理、加密/解密处理等功能单元组成。其主要功能:在微处理器模块控制下,实现蓝牙基带部分的所实时处理功能,包括负责对接收bit流进行符号定时提取的恢复;分组头及净荷的循环沉余度校验(CRC);分组头及净荷的前向纠错码(FEC)处理和发送处理;加密和解密处理等。且能提供从基带控制器到其它芯片的接口(诸如数据路径RAM客户接口、微处理器接口、脉码调制接口(PCM)等。

(2)无线收发器模块

无线收发器是蓝牙设备的核心,任何蓝牙设备都要有无线收发器。它与用于广播的普通无线收发器的不同之处在于体积小、功率小(目前生产的蓝牙无线收发器的最大输出功率只有100mW、2.5mW、1mW三种)。它由锁相环、发送模块和接收模块等组成。发送部分包括一个倍频器,且直接使用压控振荡器调制(VCO);接收部分包括混频器、中频器放大器、鉴频器以及低噪音放大器等。无线收发器的主要功能是调制/解调、帧定时恢复和跳频功能同时完成发送和接收操作。发送操作包括载波的产生、载波调制、功率控制及自动增益控制AGC;接收操作包括频率调谐至正确的载波频率及信号强度控制等。

(3)微处理器(CPU)

CPU负责蓝牙比特流调制和解调所的所有比特级处理,且还负责控制收发器和专用的语言编码和解码器。

(4)Flash存储器和SRAM

Flash存储器用于存放基带和链路管理层中的所有软件部分。SRAM作为CPU的运行空间,在作时把Flash中的软件调用SRAM中。

(5)语音编/解码器CODEC(CoderDecoder)

语音编/解码器CODEC由ADC(数模转换器)、模数转换口(ADC)、数字接口、编码模块等组成。主要功能:提供语音编码和解码功能,提供CVSD(ContinuousVariableSlopeDeltaModulation)即连续可变斜率增量调制及对数PCM(PulseCodedModulation)即脉码调制两种编码方式。

(6)蓝牙测试模块

它是由DUT(DeviceUnderTest)即被测试模块与测试设备及计量设备组成。一般测试设备被测试设备构成一个微微网,测试设备是主节点,DUT是从节点。测试设备对整个测试过程进行控制,其主要功能提供无线层和基带层的认证和一致性规范,同时还管理产品的生产和售后测试。

(7)UART(UniversalAsynchronousKeceiverTransunitter)通用异步收发器和USB(UniversalSerialBus)通用串行接口。

功能:提供到HCI(HostConfrollerInterface)即主机控制器接口传输层的物理连接,是高层与物理模块进行通信的通道。

3TR0700单芯片介绍

RT0700单芯片是Transilica公司的蓝牙产品,其结构如图3所示。它把无线收发器与基带都集成到一块CMOS芯片上,替代传统的串行语音和通用串行接口电缆,为语音和数据业务提供无线连接。

3.1结构及工作原理

RT0700单芯片由收发器、基带、语音编/解码器(CODEC)、带有4个可配置的8bit接口的8051微处理器、两个串行口双高性能的通用异步收发器(UART)、4KB的静态随机存储器(SRAM)、64KB的Flash程序存储器等组成。

收发器由低噪放大器(LNA)、电平控制器(PA)、混频器、鉴频器、控制寄存器、发送滤波器、振荡器等组成。其工作原理是:来自接收天线上的信号经低噪放大器(LNA)放大后,送至多级滤波器,多级滤波器具有预选择功能,它把LAN的输出信号限制在2.4GHz的ISM频段内,去除负频率成分,输出适合进行下变频处理的信号。I、Q混频器把蓝牙频段的信号移频至低中频(IF)传输的调制信号。复合滤波器负责从下变频信号中滤除无用信号和噪声。鉴频器使用过采样技术从IF信号中取出蓝牙低调制指数信号;发送器由发送滤波器、频率合成器、功率放大器、振荡器、天线等组成。其工作原理是:发送滤波器是一个高斯数字滤波器,它对发送环Tx输入的数据进行数字过滤;振荡器的功能是驱动一个外部的晶体振荡器或者接受一个外部的时钟信号,向频率合成器提供一个低噪声的参考频率。功率放大器的主要功能是对频率合成器的输出功率放大到1mW左右,且对频率合成器起缓冲作用,减少负载变化对合成器的影响;发送天线:当使用差分输入的LNA时,它可以是一个低噪声的平衡双极天线;8051微处理器是一个8位的微处理器,它的主要功能是管理和实现蓝牙协议栈。它具有一增强的指令集、二级数据指针、扩展的SRAM和双UART。在TR0700中对一些重复性的操作诸如分组的组装和拆解、加密、地址编码/解码、纠错和同步等都由硬件来实现,这样能降低处理器的开销,有效地提高响应性能。TR0700除了8051微处理器本身所带有的一些特殊功能寄存器(SFR)外,还定义了一些新的特殊功能寄存器(SFR),它还引入了一些特殊的中断,如一个带有特殊保护的外部中断INT3等。RT0700的基带操作有三种模式可供选择:数据/地址、端口、测试。

3.2基本功能及应用

接口协议第8篇

pcookie 是 muxbind 底层设备驱动后返回的设备索引号,以便系统卸载网络服务子层时可解除该绑定。

ifp 是网络服务子层 attach至协议栈时返回的子网接口索引号,以便系统卸载该 service 时可解除绑定。

6.2.3   service 协议数据收发流程

service 正确绑定至协议栈后,就可以接收sar end驱动层传入的该协议类型数据报文并对其处理,根据处理的结果选择转发或丢弃;对于协议栈下发的报文,也可以方便地进行相应协议封装,再交给 end驱动发送。其收发流程框图如图 6-1 所示。

图6-1 service 收发流程示意图

接收流程(虚线箭头所示):

1)sar 模块收到报文,产生中断,进入接收中断处理例程

2)调用end_rcv_rtn_call将报文返回给协议栈(reserved 中存放协议类型)

3)mux层询问该报文的协议类型

4)sar驱动层将 reserved 中的类型返回给mux层

5)mux层根据协议类型将报文提交给相应的 service.

6)service 解封装后,调用 do_protocol_with_type将报文提交给协议栈

发送流程(实线箭头所示):

1)协议栈通过mux层发送报文

2)mux 层将报文传给预先绑定的 service

3)service 对数据进行封装后,return false,将数据返回 mux 层

4)mux 层将数据发送到 sar 模块相应的 pvc 接口

5)sar 模块相应的 pvc 接口发送该报文。

6.3  rfc1483协议报文处理

由于 rfc1483数据报文的封装格式比较简单,我们将该类型报文的封装、解封装例程放在 end 驱动中实现,以提高系统对该类型报文的处理效率。

6.3.1  rfc1483 报文封装格式

rfc1483 标准描述了atm网络上承载无连接网络互连业务(即路由和桥接的协议数据单元)的两种不同方法。第一种方法允许在一条 atm 虚电路上复用多个协议,这是需要在所传送的 pdu 前加上 ieee802.2 逻辑链路控制信头,以此来表示所传递的 pdu 的协议,这种方法称为 llc 封装; 第二种方法是一个高层协议由一条atm虚电路来承载,这种方法成为基于 vc 的复用。

6.3.1.1  llc 封装

在 llc 封装中,路由协议通过在 pdu 前加一个ieee802.2 llc 信头来进行标识, ieee802.2 llc 信头后接 ieee802.1a 子网络附属点(snap)信头。在 llc 类型 1 的操作中,llc 信头包括 3 个字节,如下:

dsap

ssap

ctrl

在用于路由协议的llc 封装中,llc信头编码有两种格式:一种为 0xfe-fe-03, 用于说明后接的是 iso 路由协议的 pdu;另一种为 0xaa-aa-03,用于说明后接的是非 iso 路由协议。控制字段编码为 0x03,用于说明后接的是无编号信息的命令 pdu。

对于 iso 路由协议pdu,其aal5 cpcs-pdu 净荷字段的格式为

llc  0xfe-fe-03

iso pdu (up to 2^16 - 4 octets)

对于非 iso 路由pdu (如 ip 协议),其封装格式为

llc

0xaa-aa-03

oui

00-00-00

ethernet type(2字节)

非iso pdu (up to 2^16 - 4 octets)

 

(其中,如果是 ip 报文的话,ethernet type 值为 0x0800)

对于桥接协议报文,在 llc 封装的 snap 信头中应标识出桥接媒体的类型。与非 iso 路由协议的封装一样,llc信头编码值 0xaa-aa-03 表示存在 snap 信头, snap 信头中的oui值是 802.1组织编码 0x00-80-c2,桥接媒体的实际类型由2字节的 pid 来标识。此外, pid还标识是否在封装的桥接 pdu 中保留源帧校验序列(fcs)。以最常见的以太网/802.3为例,用于封装 802.3 pdu的aal5 cpcs-pdu净荷帧格式如下

llc  0xfe-fe-03

oui  0x00-80-c2

pid  0x00-01 or 0x00-07

pad  0x00-00

mac 目的地址

mac 源地址

mac 帧其它内容

帧校验(如果 pid是 00-01)

 

6.3.1.1  基于vc 的复用

在基于 vc 的复用中,不同的协议报文可以通过不同的 vc 通道传递,因此在 aal5的cpcp-pdu 净荷上就不再包含明确标识所承载协议的信息了,使得处理开销最小。

路由协议的 pdu 在 aal5 cpcs-pdu 的净荷中直接承载。

桥接协议的 pdu 和llc封装格式描述相同,但仅包含 pid 字段后的内容。其 aal5 cpcs-pdu 净荷字段格式如下所示:

pad  0x00-00

mac 目的地址

mac 源地址

mac 帧其它内容

帧校验(由vc 连接特性决定)

 

6.3.2  rfc1483 报文的封装处理

上层协议在调用 muxsend 之前,会先调用 endaddressform 函数进行二层数据封装,我们在这个函数里实现ip 报文到ethernet类型报文的数据封装。sarendsend函数里会调用 atmsrv_encap 进行 ethernet 报文到 aal5 相应协议类型的封装。

6.3.3  rfc1483 报文解封装处理

在中断接收处理函数里,会调用 atmsrv_decap 解除atm协议封装,同时将二层协议类型存于 mblkpkthdr.reserved 中,由 endpacketdataget通知 mux。

7增加 nat 支持

目前已经有很多for vxworks 的第三方 nat 协议产品, 而且 windriver 公司自己也推出了tornado 开发平台下的 nat 组件, 但价位实在太高。 由于该协议本身实现的难度不大,而且有 linux 或 bsd 的相关模块可供参考和移植,所以我们决定自己实现这个协议。难点主要在于nat收发处理函数的绑定, nat 端口地址转换hash表的建立及查找算法的实现。

7.1  nat 模块主处理流程

主要包括lan口和wan口的ip地址转换。如图 7-1 所示。

图7-1  nat 主处理流程示意图

7.2   nat 模块初始化

7.2.1   nat 数据结构初始化

1)  nat_session结构,记录每一连接的连接信息:

struct nat_session

{

    uchar ip_proto;                       //协议类型

    struct in_addr src_addr, dst_addr, new_addr;  //源地址,目标地址,转换后地址

    /* port numbers are in host uchar order: */

    union

    {

        /* for tcp _and_ udp: */

        struct { uint16 src_port, dst_port, new_port; } tcp;  //端口

        /* for icmp: */

        struct { uint16 src_ident, new_ident; } icmp;      //identification

    } u;

    enum nat_session_state state;               //连接状态

    unsigned long         timestamp;         //时间戳

    nat_alg      *alg;                   //应用层网关函数指针

    int          alg_use;                   //标志,是否需要应用层网关

    nat_session  *parent;                //ftp中指向控制连接session的指针

    nat_session  *next_hash;             //hash表下一表项

};

2)nat_interface接口结构

struct nat_interface

{

    nat_interface *next;                //指向下一个接口结构

    struct in_addr ipaddress;                  //接口地址(转换地址)

    /* pointer to table of session structures, and hash table: */

    nat_session *sessions;                //指向session结构表

    nat_session **hashtable;              //指向hash结构表

    int next_session;

    /* pointer to table of fragment structures */

    nat_fragment *fragments;             //指向fragment结构表

    int frag_queued;                         //记录保存有多少个分片队列

    /* stats - counts of sessions */              //各种计数器

    uint32 tcp_out, udp_out;

    uint32 icmp_q_out, icmp_err_out, icmp_err_in;

    uint32 discard_in, discard_out, refused_in, del_early;

};

7.2.2  nat 收发处理函数的绑定

仔细分析 vxworks 协议栈代码后,觉得使用 _ipfilterhook 绑定 nat 接收报文处理函数的方式比较可行,该钩子函数在协议栈接收到数据报文时被调用,函数输入输出格式如下:

bool natipfilterhookrtn

(

struct ifnet rcvifnet,     /* 数据接收的接口*/

struct mbuf **m,           /* 数据报文地址 */

struct ip **ip,            /* ip 头部地址 */

int hlen                   /* ip 头的长度 */

)

返回值: 为 false时表示报文处理正常,协议栈可继续转发或处理

为true 时指示系统丢弃该报文

由于无法找到协议栈输出报文的钩子,我们打算把输出报文 nat 转换放在 _ipfilterhook 的 lan 口钩子中处理,即在 lan口报文进入协议栈之前就更改源ip和端口地址。但这样做的缺点是:此时系统还没有检索过该报文的路由目的接口,需要人为增加查找路由表算法,当发现是发往指定 wan 口时再行转换,处理的效率较低。

为充分利用协议栈的报文路由处理功能,决定采用更改协议栈代码的方式,在 ip_output 函数适当位置处人为增加一个钩子 _func_natoutput,重新编译 vxworks 协议栈库函数。 这样,nat 模块初始化时即可将nat输出报文处理函数绑定至该钩子。函数的输入输出关系格式如下:

int natoutput

(

struct mbuf** m0,     /* 数据报文地址 */

struct ip **ip,       /* ip 头部地址 */

struct in_ifaddr* ia  /* 报文目的接口 */

)

返回值:  ok 或 error (error 时将丢弃并释放该报文)

 

7.3        nat模块主要算法

7.3.1  nat 端口地址转换hash算法

napt 转换表查找算法可分为按端口查找和按地址查找两种。在实际的 adsl接入环境中,局端很少会为一个连接分配多个 ip,因此我们采用按端口查找的算法来简单实现。

1) session 结构数组的初始化

nat初始化时根据系统支持的最大转换数目建立一个按端口分布的 nat_session结构数组(nat_session 节点的定义见7.2.1), 同时建立一个指向nat_session 的空 hash 表。hash节点结构如下:

typedef struct nat_hash_bucket_

{

     struct nat_hash_bucket_ *next;    //指向下一个节点

     struct nat_hash_bucket_ *prev;    //指向前一个节点

     unsigned nat_session   *psession; //指向nat链表中相应的节点

}nat_hash_bucket;

2) 新建 session

get_free_session 在session静态表(结构数组)中获得一个free session,并将其从hash表中unlink出来。查找的依据为时间戳, 顺序遍历session表,直到找到第一个超时的session。若未找到,则覆盖当前指针指向的session。

填充该 session 结构,返回该session 所对应的端口号。根据 tcp/udp 报文的源 ip 和源端口号计算出 hash 头,增加到 hash 头所对应的链表后。其中,hash 头的算法如下:

local uint16 ipnat_hash_fn(ipaddrtype addr1,

ipaddrtype addr2,

uint16 port1,

uint16 port2)

{

       uint16 bucket;

      

       bucket = addr1 >> 16;

       bucket ^= addr1 & 0xffff;

       bucket ^= port1;

       bucket ^= addr2 >> 16;

       bucket ^= addr2 & 0xffff;

       bucket ^= port2;

       bucket = bucket % ipnat_hashlen;

       return(bucket);

}

转换后的 tcp/ip 报文源ip变为 wan口ip,源端口变为session 索引值,这样做的优点是:外部返回的报文可以通过tcp/ip报文的目的端口号直接定位到 session 数组中,查找的速度最快。

3) 查找 session

通过 tcp/udp 报文的源 ip 和源端口号计算出 hash 头,然后遍历该头所对应的链表,直到找到相匹配的hash 节点。

4) 删除 session

收到 tcp/udp 连接关闭请求后,根据目的端口号找到 session 数组,释放该 session, 并将其从 hash 表中 unlink 出来。

7.3.2   tcp/udp 协议端口地址转换

setup_tcpudp_outgoing 为从内部网络出去的tcp/udp连接建立一个session,记录下连接的源地址、端口,目标地址、端口,转换后的地址、端口,协议类型以及连接建立时间等信息。

translate_outgoing_tcpudp 核心函数,根据 session 的对应记录,转换数据包的ip地址、端口,同时重新调整ip校验和及tcp/udp校验和,其中,校验和调整主要用到了adjust_chksum函数。算法如下:

void adjust_chksum(ulong *chksum, ushort oldw, ushort neww)

{

    *chksum -= oldw & 0xffff;

    if ((*lchksum) <= 0)

    {

        (*chksum) --;

        (*chksum) &= 0xffff;

    }

    (*chksum) += neww & 0xffff;

    if ((*chksum) & 0x10000)

    {

        (*chksum) ++;

        (*chksum) &= 0xffff;

    }

}

8 设计总结

本系统的优点是,仅需采用一块 cpu 即可同时实现 adsl接入和路由两项功能,硬件资源利用率高,而且,两种功能在同一套系统平台中可以有机结合,避免因中间插入多余转换接口导致包处理效率降低。

文中所述的仅实现了一个最简单的 adsl 共享接入方式,并不能完全满足实际使用中的种种需求,还需要补充其它如协议报文处理、icmp报文处理、应用层网关处理等功能。 此外,在实际测试中,感觉 nat 地址转换hash 表的算法还不够理想:在新建一个节点时需要重新遍历整个 nat_session 数组,这将导致在连接数较多的情况下再新建一条连接非常困难,系统效率急剧降低。

在这次开发设计前期,由于对操作系统的架构不够熟悉,在设备驱动编写方面没有经验,导致编写的驱动层次感很差,不利于维护和后期扩展。走了很多弯路之后,总结出经验:开发前期的调研工作非常必要,在着手写代码之前应该多花些时间了解开发平台、熟悉整个系统的架构、模块在系统之间的地位及模块间的接口关系。磨刀不误砍柴工,总体规划充分之后才能编写出效率高、易维护、易扩展的模块代码出来。

参考文档

itu-t recommendation i.363.5  aal specification:  type 5 aal, march 1993

ietf rfc1483. multiprotocol encapsulation over atm adaptation layer5, july.1993

ietf rfc1577. classical ip and arp over atm, january 1994

ietf rfc2364

ietf rfc2516

ietf rfc791 ip

ietf rfc768 udp

ietf rfc793 tcp

ietf rfc792 icmp

ietf rfc826 arp

ietf rfc1631 nat

vxworks network services standard。