E-mail:for_rest@foxmail.com 老衲五木出品
会把所有网卡芯片的结构体链成一个链表进行管理,有一个 netif_list 的全局变量指向该链
表的头部。next 字段就是用于链表用。
ip_addr、netmask、gw 三个字段用于发送和处理数据包用,分别表示 IP 地址、子网掩
码和网关地址。前两个字段在数据包发送时有重要作用,第三个字段似乎没什么用。IP 地
址和网卡设备必须一一对应。如果你连什么叫 IP 地址、子网掩码和它们的作用都不晓得,
那你有必要去看看 TCP/IP 协议详解卷 1 第三章。
input 字段指向一个函数,这个函数将网卡设备接收到的数据包提交给 IP 层,使用时将
input 指针指向该函数即可,后面将详细讨论这个问题。该函数的两个参数是 pbuf 类型和 netif
类型的,返回参数是 err_t 类型。其中 pbuf 代表接收到的数据包。
output 字段向一个函数,这个函数和具体网络接口设备驱动密切相关,它用于 IP 层将
一个数据包发送到网络接口上。用户需要根据实际网卡编写该函数,并将 output 字段指向
该函数。该函数的三个参数是 pbuf 类型、netif 类型和 ip_addr 类型,返回参数是 err_t 类型。
其中 pbuf 代表要发送的数据包。ipaddr 代表网卡需要将该数据包发送到的地址,该地址应
该是接收实际的链路层帧的主机的 IP 地址,而不一定为数据包最终需要到达的 IP 地址。
例如,当要发送 IP 信息包到一个并不在本地网络里的主机上时,链路层帧会被发送到网络
里的一个路由器上。在这种情况下,给 output 函数的 IP 地址将是这个路由器的地址。
linkoutput 字段和上面的 output 基本上是起相同的作用,但是这个函数是在 ARP 模块中
被调用的,这里不赘述了。注意这个函数只有两个参数。实际上 output 字段函数的实现最
终还是调用 linkoutput 字段函数将数据包发送出去的。
state 字段可以指向用户关心的关于设备的一些信息,用户可以自由发挥,也可以不用。
hwaddr_len 和 hwaddr[]表示 MAC 地址长度和 MAC 地址,一般 MAC 地址长度为 6。
mtu 字段表示该网络一次可以传送的最大字节数,对于以太网一般设为 1500,不多说。
flags 字段是网卡状态信息标志位,是很重要的控制字段,它包括网卡功能使能、广播
使能、ARP 使能等等重要控制位。
name[]字段用于保存每一个网络网络接口的名字。用两个字符的名字来标识网络接口使
用的设备驱动的种类,名字由设备驱动来设置并且应该反映通过网络接口表示的硬件的种
类。比如蓝牙设备(bluetooth)的网络接口名字可以是 bt,而 IEEE 802.11b WLAN 设备的
名字就可以是 wl,当然设置什么名字用户是可以自由发挥的,这并不影响用户对网络接口
的使用。当然,如果两个网络接口具有相同的网络名字,我们就用 num 字段来区分相同类
别的不同网络接口。
到这里,你可能一头雾水,太抽象的东西太容易让人纠结。好吧,我们举个例子来看
看一个以太网网卡接口结构是这样被初始化,还有数据包是如何接收和发送的。先来看初始
化过程,源码:
static struct netif enc28j60; (1)
struct ip_addr ipaddr, netmask, gw; (2)
IP4_ADDR(&gw, 192,168,0,1); (3)
IP4_ADDR(&ipaddr, 192,168,0,60); (4)
IP4_ADDR(&netmask, 255,255,255,0); (5)
netif_init(); (6)
netif_add(&enc28j60, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input); (7)
netif_set_default(&enc28j60); (8)
netif_set_up(&enc28j60); (9)