上
层传给网卡驱动程序的待发送数据包是不包括以太网头的,以太网头需要在网卡驱动程序中进行构建。一个完整的以太网头包括源MAC地址,目的MAC地址,和
协议类型。这里问题的关键就是:如何获得目的MAC地址?即知道了目的IP地址后,如何将这个IP地址和一个MAC地址关联起来?通常处理这个问题是通过
地址解析协议(ARP)来>完成。
继续以前文的ping程序为例,主机172.16.48.2要向172.16.48.1发回显请求icmp包之前,会先向MAC地址ff:ff:ff:
ff:ff:ff广播一个ARP请求包,询问172.16.48.1的MAC地址。当172.16.48.1收到这个包时,会向172.16.48.2发
一个ARP应答包,告知自己的MAC地址。这样,48.2就可以为回显请求的ICMP包构建以太网头了。
然后,为了防止48.1的MAC地址会变化,每隔一定的时间,48.2都会向48.1发ARP请求包,询问48.1的MAC地址。
在网卡驱动程序中,代表网络接口的结构体struct net_device共有5个成员函数用于构建以太网头。它们分别是:
int (*rebuild_header)(struct sk_buff *skb );
该函数用来在传输数据包之前,完成ARP解析之后,重新建立硬件头。在我们的测试程序中,发现这个函数并没有被用到,设为 NULL也不影响驱动正常工作。
int (*hard_header)(... .../*省略*/);
该函数根据ARP协议得到的MAC地址构建以太网头。从测试情况来看,每次ARP应答包收到时,这个函数都会被调用,同时,在没有ARP应答包时,也会被调用几次,但不是每次发送包都被调用,有待深究。
int (*header_cache)(... .../*省略*/);
将ARP应答包中得到的结构填充hh_cache结构,从测试来看,它是作一个缓冲,每次有一个新的MAC地址得到时,将其作一个缓冲,保存下来。
int (*header_cache_update)(....../*省略*/);
目标主机的MAC址发生变化时,更新hh_cache结构,从而更新缓存。测试中没有测到这样的情况。
int (*hard_header_parse)(... .../*省略*/);
测试中没有用到,用途不明。
阅读(2268) | 评论(0) | 转发(0) |