引 言
近年来,人们都把TCP/IP协议栈作必要裁减后移植到8位或16位微处理器上,完成嵌入式异型网关的构建(如北京英贝多EM2002系列网关,海华信网络通等),从而使不同类型的数据包可以通过透明传输接入到现有的IP网络,自此开辟了网络测控的新纪元。
嵌入式网关的运行必然遇到IP地址的设置问题。传统的方案是在设备出厂前直接烧写在Flash中,或利用串口本地设置,或在已知IP的前提下利用以太网口设置。上述方案繁琐和不灵活,希望有一种灵活、便捷、全新的IP设置方案。通过对网络各层协议的分析,实现一种在数据链路层完成对嵌入式网关IP远程设置方案。该方案的优点集中表现在出厂无须固化IP、远程动态设置、穿透子网、集中管理等。
1 技术对比
目前,实现嵌入式网关的设置模式主要有图1所示的两种:一是本地化,二是网络化,但具体实现方法不同。为了描述方便,把用于设置的PC机定义为上位机,嵌入式网关定义为下位机。
(1)直接烧写法
直接烧写是在程序中给定1P、MAC地址端口号等参数,编译后烧写在Flash中。该方法明显不够灵活,每次修改都须重新编译、重新下载。
(2)串口法
串口法是通过串口通信修改存储在EEPROM中的IP地址等网络参数。该方案较前一种有一定的灵活性,但由于RS 232的传输距离和网络扩展难的限制,往往只能应用在一对一的本地设置
(3)已知lP远程修改法
该方法可以达到网络化管理的目的,但设备须在出厂前一一预设不同的IP地址才能完成建立在传输层之上的网络通信。一般此时设置的IP不满足具体网络环境的要求,即意味着此次设置是一次不必要的重复劳动。
综合上述方案的优缺点,提出在数据链路层架构协议,在网络底层完成数据通信的方案,弥补了出厂前必须固化IP的不足,实现了在项目实施后统一对设备网络化管理。该方案的优点还表现在由于其回避TCP/IP包,这样在一个节点可修改位于不同子网中的任意嵌入式网关的IP地址。该方案的实质是省去了TCP、IP报头,直接根据MAC地址完成目标主机的识别和通信。
2 实现原理
2.1 数据链路层帧格式的分析
由于网络设备运行于Ethernet(以太网),所以这里所涉及的数据链路层协议是指Ethernet的数据链路层协议。IEEE 802项目将数据链路层分为LLc(逻辑链路控制)层和MAC(介质访问控制)层。LLC层包含数据帧中和终端用户相关的部分,如逻辑地址、控制信息和数据;MAC层解决了共享介质的竞争问题,包含同步、标识、流量和差错控制。IEEE802.3制定了支持LAN标准CSMA/CD访问控制模式的Ethernet标准,其帧格式下:
2.2 帧格式的定义
通过对数据链路层帧格式的分析,不难发现在数据链路层包含了能惟一标识一台主机的MAC地址。不需要ARP协议做IP和MAC地址映射,进而实现未知目的IP的链路层通信。
为了满足实现对嵌人式网关的远程设置要求,可根据Ethernet协议标准定义帧格式,且命名为RSF帧(Remote Set Frame):
目的MAC地址,6字节;
源MAC地址,6字节;
帧类型(RSF=0801 IP=0800 ARP=0806 RARF=8035),2字节;
OP操作选项(RSF query=01,RSF setIp=02,RSFreplyr=03),2字节;
目的port,2字节;
发送端MAC地址,6字节;
发送端IP地址,4字节;
目的MAC地址,6字节;
目的IP地址,4字节;
设置结果,1字节。
该帧格式的定义类似于TCP/IP协议栈中的ARP协议帧,包含了以太网头14个字节。帧类型,在该字段802项目定义的有效长的值与以太网的有效类型值无一相同,这样可以区分这两种帧的格式,这里设定该帧类型为0801,以区别于已定义的帧类型;OP操作码,RSF query=01表示服务器发送的数据包用于查询网络中的嵌入式网络设备的MAc地址,RsF setlp=02表示服务器发送的数据包用于设置嵌入式网络设备的IP地址,RsF reply=03用于设置信息的返回;端口号是目的端预设置的端口号:剩下的20字节为发送端和目的端的IP和MAC地址。
3 具体实现
根据上述帧格式的定义和图2所示的系统流程,分别在上位机和下位机添加相应的接口和功能模块来实现。
上位机发出查询下位机MAc地址的请求指令,下位机接收后响应请求,返回本地MAC地址;上位机为查询到的不同MAc地址分配不同的IP地址之后发送设置IP请求;下位机接收后响应请求,并截取数据包中的信息来完成本地设置;最后上位机根据设置返回的状态决定是否重新设置。其中给查询到的MAc地址分配相应的IP地址,分为手工和自动方法。手工方法是由用户根据自己的需要设置IP地址;自动方法是根据ip pool(ip池)原理来实现IP的自动分配。
3.1上位机部分
由于该方案旨在利用数据链路层协议来解决对嵌入式网关的IP远程设置问题,就必然要求上位机编程要绕过位于第4层与第5层问的套接字编程接口(socket)。幸运的是,位于第2与第3层间的NDIs(网络驱动器接口)提供了访问网络底层的能力。其优点在于屏蔽了下层各种网卡的差别,为上层提供了一个完备NDIS库,可以完成原始数据包的捕获,数据包的过滤,以及原始数据包的发送等强大的功能。另外,意大利的Fulvio Riss0、LorisDegioanni等专家开发了一个Windows平台下免费公共的网络访问系统,并提供Winpcap开发包,方便地提供了一个访问网络底层的接口。
寻找到访问网络底层的编程接口后,只需要定义相应的数据包结构,并调用库中发包函数就能完成原始数据包的接收和发送功能。这里只给出关键的数据结构的定义代码。
以太网头的数据结构:
Typedef structtag DLCHeader {
unsigned char DesMAC[6]; //以太网目的地址
unsigned char srcMAC[6]; //以太网源地址
unsigned short Etherype; //帧类型
);
RSF帧结构:
typedef struct tagRSFFrame
{unsigned short opcode; //操作码
unsigned short Prot //目标端口号
unsigned char Send_HW_Addr[6];//发送端以太网地址
unsigned long Send_Prot_Addr; //发送端IP地址
unsigned char Targ_HW_Addr[6];//目的以太网地址
unsigned long Targ_Prot_Addr; //目的lP地址
unsigned char ReturnValue //设置结果
};
RSF包结构:
typedef struct tagRSFPacket{
DLCHEADER dlcHeader;
RSFFRAME rsfFrame;
};
3.2 下位机部分
嵌入式网关的实现关键在于TCP/IP协议栈的实现。目前主要有TCP/IP的软移植(如ulP TCP/IP的移植)、硬移植(主要由专业芯片实现)和嵌入式系统自带TCP/IP协议栈。如果是利用嵌入式系统来实现嵌人式网关,就必须对操作系统内核驱动作相应的改动。这里只重点介绍TCP/IP在微处理器上软移植的情况。在这种情况,只要在数据链路层模块中添加帧的识别和处理功能模块,就可以获得数据帧中的IP地址等数据,并对本地IP进行设置。具体设置是调用对EEPROM的读写程序模块来完成的,关键代码如下:
void eth_rcve(UCHAR xdata*inbuf)//数据链路层接收模块
{ ……
switch(etb->frame-type)
{ ……
case RSF_PACKET://在原协议栈中添加自定义协议调用修改本地IP模块; break;
case ARP_PACKET:调用ARP处理模块; break;
……
}
}
void eth_send(UCHAR xdata*outbuf,UCHAR*hwaddr,UINT ptype,UINT Ien)//数据链路层发送模块
{……}
结语
通用计算机数据链路层自定义帧的实现,可应用于解决嵌入式网络设备的远程设置问题,改进了过去嵌入式网络设备IP地址使用直接烧写或串口本地配置等方法。该方案的特点是绕开了套接字编程,直接将上位机与下位机的通信建立在数据链路层的基础之上。相对于依靠上层协议通信,在数据链路层直接通信,可以避开上层协议的约束,从而达到对网络数据更直接和灵活处理的目的。