二、以太网接口接收数据帧
当接口接收到发送给该接口的单播地址和广播地址的帧,帧可用时,触发一个中断,并且内核调用驱动函数函数leintr()。
leintr()函数内部根据硬件寄存器的值,判断是什么中断,如果是LE_RINT状态,调用lerint处理接收的数据,如果是LE_TINT,调用lexint做输出数据处理。
其他的状态,程序会更新接口的统计,并调用lereset重设接口寄存器的值和状态。
以太网接口接收数据中断,触发调用函数lerint(),该函数主要处理接收到的数据,并丢弃错误的数据,同时更新统计值,有效数据通过调用函数leread交到enther_input函数做后续处理。
leread的输入参数包括数据内容buf,长度len。以太网的头部(ether_header结构存放)存放再buf的首部。
leread获取到以太网的数据的头部,判断ether_type类型,并要区别802和以太网包的不同格式,获取数据的长度和内容。判断是否广播数据和多播数据,并置flag,如果给接口有bpf回调,同时调用。
最后leread调用m_devget函数获取一个mbuf,并把数据放入mbuf,但以太网的首部未放入,而时通过ether_input函数的参数带入。
/******************************************************/
/*
* Pull packet off interface. Off is nonzero if packet
* has trailing header; m_devget will then force this header
* information to be at the front, but we still have to drop
* the type and length which are at the front of any trailer data.
*/
m = m_devget((char *)(et + 1), len, off, &le->sc_if, 0);
if (m == 0)
return;
m->m_flags |= flags;
ether_input(&le->sc_if, et, m);
/******************************************************/
ether_input主要完成对广播和多播包的识别以及链路层数据的分发处理。
(1)通过以太网地址识别包的类型,并置mbuf的m_flags标记。
(2)通过以太网头部的ether_type分发不同类型的数据包。
对于ETHERTYPE_IP包,调用schednetisr(NETISR_IP)软中断,并选择ipintrp队列输入数据。
对ETHERTYPE_ARP包,调用schednetisr(NETISR_ARP)软中断,并选择arpintrp队列输入数据。
对ETHERTYPE_NS包,调用schednetisr(NETISR_NS)软中断,并选择nsintrp队列输入数据。
对其他的包可能时ISO封装的802包做相应的处理。
函数的最后根据选择的队列,将数据入队。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mythfish/archive/2008/10/22/3126080.aspx