Chinaunix首页 | 论坛 | 博客
  • 博客访问: 224720
  • 博文数量: 52
  • 博客积分: 15
  • 博客等级: 民兵
  • 技术积分: 390
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-06 09:31
文章分类

全部博文(52)

文章存档

2015年(1)

2014年(44)

2013年(7)

我的朋友

分类: 嵌入式

2014-05-31 16:03:24

第四章 ARP:地址解析协议

虽然数据链路层的第一道关卡是MAC地址,但基于TCP/IP的网络主要使用IP地址来标识主机而不使用MAC地址。比如要连接到别人的电脑或拷贝共享文件,一般会说:“告诉我你电脑的IP”,而不是“告诉我你电脑的MAC”。从以太网帧结构知道,不知道对方网卡的MAC地址是无法正常通讯的,那主机是怎样从IP地址上自动获取到MAC地址呢?这就是这章要讲的“地址解析协议”,以下简称其英文缩写“ARP”。

41 ARP工作原理

从对方的IP地址获取MAC地址最简单的方法是静态映射,即手工建立IP地址和MAC地址的映射表。这种方法必须预先知道每个IP对应的网卡的MAC地址,并写到程序里,发送数据时先搜索这张表,找到IP地址对应的MAC地址。静态映射表内容如下:

表 4-1 静态映射表

IP地址

MAC地址

192.168.1.15

00-0B-6A-8E-3F-C2

192.168.6.82

00-1C-35-27-59-A8

静态映射表有一定的局限性,如:一台电脑换过网卡后,查找得出的MAC地址就不正确,会导致通讯不上;当对方电脑的IP地址改变后,虽然MAC地址没有变,但映射关系变了,静态映射表也必须手工改变。这样,维护一张静态映射表就很费劲。

为了避免手工维护映射表,设计人员使用ARP协议来实现地址的映射,由主机自己智能地维护一张动态映射表。具体是怎样实现地呢?通过图4-1可以形象的说明。假如MCU主机需要与IP为192.168.1.15的主机建立连接,但不知道其MAC地址,于是先在整个网络广播,查询内“192.168.1.15“对应的MAC地址,由于是广播(目的MAC地址是FF-FF-FF-FF-FF-FF),同一网络上的所有主机都收到了这个请求。但只有电脑A应答,因为它的IP就是192.168.1.15。MCU收到电脑A的应答后,将IP和MAC地址存放在动态映射表中,下次连接的时候就能直接查找动态表。

当然,动态映射表中,IP和MAC的映射关系并不是一成不变的,ARP还启动一个定时器,当映射关系存在一定的时间(如1分钟)后,会被清除掉,下次发送数据时还是需要通过ARP请求获取它们的对应关系。这个过程称为ARP表老化。

clip_image002

图4-1 ARP 工作原理

42 ARP分组结构

ARP分组是封装在以太网帧中的数据段中,当以太网帧首部的TYPE段为0806H时,表示后边的数据是ARP分组。如图4-2。

clip_image004

图4-2 ARP 分组的封装

ARP分组的具体结构如图4-3。

0 8 16 24 31

硬件类型

协议类型

硬件长度

协议长度

操作

发送方MAC地址(6字节中的0-3字节)

发送方MAC地址(4-5字节)

发送方IP地址(0-1字节)

发送方IP地址(2-3字节)

接收方MAC地址(0-1字节)

接收方MAC地址(2-5字节)

接收方IP地址(0-3字节)

     

图4-3 ARP 分组的格式

硬件类型:16位,定义运行ARP的物理网络。对以太网来说固定为0001H。还有0002H为实验以太网,0003H为业余无线电,0004H为令牌网等等。

协议类型:16位,定义发送方提供的高层协议类型。对IPV4来说,固定为0800H。

硬件长度:8位,定义物理地址(MAC地址)的长度,以字节为单位,对以太网来说,固定为06H。

协议长度:8位,定义逻辑地址(IP地址)的长度,以字节为单位,对应以太网的IPV4,长度固定为04H。

操作:16位,定义ARP分组是请求还是应答。请求则为01H,应答为02H。

发送方/接收方MAC地址:48位(针对以太网)。

发送方/接收方IP地址:32位(针对以太网)。

了解ARP的分组的格式后,就可以将图4-1 中ARP的工作原理用具体数据来表示,如图4-4。

clip_image006

图4-4 ARP 分组的图例

42 ARP的实现

uIP协议栈实现ARP的文件是Uip_arp.c,包含uip_arp_init(),uip_arp_timer(),uip_arp_update(),uip_arp_arpin(),uip_arp_out()5个函数。

4.2.1 ARP初始化

根据ARP分组的格式,uip头部结构定义如下,为了便于管理,它包含了以太网帧的头部uip_eth_hdr。

struct arp_hdr

{

struct uip_eth_hdr ethhdr; /*以太网首部,14字节*/

u16_t hwtype; /*硬件类型,0x0001*/

u16_t protocol; /*协议类型,0x0800*/

u8_t hwlen; /*硬件长度,0x06*/

u8_t protolen; /*协议长度,0x04*/

u16_t opcode; /*操作码,ARP请求:0x1;ARP应答:0x2*/

struct uip_eth_addr shwaddr; /*发送方MAC地址*/

u16_t sipaddr[2]; /*发送方IP地址*/

struct uip_eth_addr dhwaddr; /*接收方MAC地址*/

u16_t dipaddr[2]; /*接收方IP地址*/

};

前面说过,ARP协议的目的就是主机自动维护一张动态映射表,uIP对动态映射表的结构定义如下:

struct arp_entry

{

u16_t ipaddr[2]; /*IP地址*/

struct uip_eth_addr ethaddr; /*MAC地址*/

u8_t time; /*IP-MAC映射生成时间*/

};

表 4-2 uip的ARP动态映射表

IP地址

MAC地址

映射生成时间

192.168.1.15

00-0B-6A-8E-3F-C2

13

     

可以看到,它比静态映射表多了一项time,主要用来老化ARP表,存放的是一个时间计数arptime,这个计数默认是每10秒加1,写映射关系的时候取当前的arptime值存入time项。ARP动态映射表定义成一个全局变量arp_table ,在单片机的网路设计中,定义如下:static struct arp_entry xdata arp_table[UIP_ARPTAB_SIZE],其最多保存的映射关系是UIP_ARPTAB_SIZE个,默认值是8,可修改。

ARP的初始化函数uip_arp_init()就是将动态映射表arp_table里的IP地址项全部清零。使用的语句是:memset(arp_table[i].ipaddr, 0, 4);

4.2.2 ARP分组的处理

当收到的以太网帧的类型是0x0806时,调用void uip_arp_arpin(void)函数对收到的ARP分组进行处理。其实现流程图见图4-5。其中的更新动态映射表的功能由函数uip_arp_update()完成,流程图见4-6。

clip_image008

图4-5 ARP分组的处理流程图

clip_image010

图4-5 ARP更新动态映射表流程图

4.2.2 ARP动态映射表的老化

函数void uip_arp_timer(void)执行动态映射表的老化功能,这个函数每10秒被调用一次,进入该函数时,时间计数arptime加1,同时与动态映射表里的time项比较,当发现arptime - tabptr->time >= 120时,将该项的IP清零。也就是说,动态映射表里的映射关系在连续20分钟内没有刷新的话将失效。

4.2.2 ARP请求的自动发送

前面的介绍可以知道,本机IP层的发送函数只知道对方IP地址,而不知道对方的MAC地址,按分层的概念,它填充完IP头部的信息后就交给以太网帧处理。以太网帧的头部需要填充目的MAC地址,源MAC地址,类型。其中源MAC地址是本机MAC,类型是IP 0x0800,均已知。目的MAC呢?首先要查动态映射表,找到接收方IP对应的MAC地址填充。若此时动态映射表中没有映射关系,就必须按ARP请求的格式构造一个ARP请求分组发送给本地网路上的所有网络设备,获取到IP对应的MAC地址后才能正常发送。这些功能由void uip_arp_out(void)函数完成。

阅读(1501) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~