接口层包含在本地网上发送和接收分组的硬件与软件。
我们用设备驱动程序来表示与硬件及网络接口通信的软件,网络接口是指在一个特定网络上硬件与设备驱动器之间的接口。
Net/3接口层试图在网络协议和连接到一个系统的网络设备的驱动器间提供一个与硬件无关的编程接口。这个接口层为全部的
设备提供下面支持。
1.一套精心定义的接口函数。
2.一套标准的统计与控制标志。
3.一个与设备无关的存储协议地址的方法。
4.一个标准的输出分组的排队方法。
这个不要求接口层提供可靠地分组传输,仅须要提供最大努力的服务。
更高协议层必须弥补这样的可靠性缺陷。
ifnet结构
结构ifnet结构中包括全部接口的通用信息。在系统初始化期间。分配为每一个网络设备分配一个独立的ifnet结构,每一个ifnet结构
有一个列表。它包括这个设备一个或多个协议地址。下图说明了一个接口和它地址之前的关系。
上图的接口显示了3个存放在ifaddr结构中的协议地址。
尽管一些网络接口,比如slip,仅支持一个协议,而其它接口。如
以太网,支持多个协议并须要多个地址。
比如。一个系统可能使用一个以太网接口同一时候同于Internet和OSI两个协议。一个
类型字段标识每一个以太网帧的内容,而且由于Internet和OSI协议使用不同的编址方式。以太网接口必须有一个Internet地址
和一个OSI地址。
下图是包括在结构ifnet中的实现信息。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvVE9ERDkxMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
ifnet结构中的下一部分显示在下图,它用来描写叙述接口的硬件特征。
接口统计信息由下图中下一组ifnet接口成员来收集。它们被增加来支持接口的标准SNMP MIB-II变量
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvVE9ERDkxMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
结构ifnet的下一部分,显示在下图,它包括指向标准接口层函数的指针,他们把设备专用的细节从网络层分离出来。每一个接口
实现这些适用于特定设备的函数。
以后会分析以太网、环回接口的设备专用函数,内核通过ifnet接口中的这些指针直接调用它们,比如,ifp指向一个ifnet结构。
(*if->if_start)(ifp)
调用这个接口的设备驱动程序的if_start函数。
结构ifnet的最后一个成员是接口的输出队列。
队列作为一个mbuf链的链表来实现。
ifaddr结构
每一个接口维护一个ifaddr结构的链表,由于一些数据链路。如以太网,支持多于一个的协议。一个单独的ifaddr结构描写叙述每一个
分配给接口的地址,通常每一个协议一个地址。支持多地址的还有一个原因是非常多协议。包含TCP/IP,支持为每一个物理接口指派
多个地址。
ifnet和ifaddr的关系例如以下:
sockaddr结构
一个接口的编址信息不只包括一个主机地址,在通用的sockeaddr结构中维护主机地址、广播地址和网络掩码。
通过使用
一个通用的结构,将硬件与协议专用的地址细节相对于接口层隐藏起来。下图说明了这些结构的组织。
sa_len指示地址的长度。sa_family指示地址的类型。sa_data。包括一个协议相关格式的地址。
ifnet和ifaddr的专用化
结构ifnet和ifaddr包括适用于全部网络接口和协议地址的通用信息。为了容纳其它设备和协议专用信息,每一个设备定义了而且
每一个协议分配了一个专用化版本号的ifnet和ifaddr结构。这些专用化的结构总是包括一个ifnet或ifaddr结构作为它们的第一个成员,
这样无需考虑其它专用信息就能訪问这些公共信息。
下图是专用化ifnet结构的组织。
每一个设备的结构以一个ifnet開始,接下来诠释设备相关的数据。环回接口仅仅声明了一个ifnet,由于它不要求不论什么设备相关的
数据。
每一个协议把每一个接口的地址信息存储在一个专用化的ifaddr结构列表中。以太网协议使用一个in_ifaddr结构。而OSI协议使用
一个iso_ifaddr结构。另外,当接口被初始化时,内核为每一个接口分配一个链路层地址。它在内核中标识这个接口。
下图是一个
包括链路层地址、internet地址和OSI地址的接口地址列表。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvVE9ERDkxMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
内核通过分配一个iifaddr结构和两个sockaddr_dl结构(一个是链路层地址本身,一个是地址掩码)来构造一个链路层地址。
结构sockaddr_dl可被OSI、ARP和路由算法訪问。
下图是一个初始化后的以太网sockaddr_dl.
第一个sockaddr_dl初始化各中值。
第二个是一个比特掩码,用来选择出如今第一个结构中的文本内容。上图为le0.
网络初始化概述
全部我们说明的结构在内核初始化时分配和互相链接起来的。
有些设备,比如slip和环回接口,全然用软件来实现。这些伪设
备用存储在全局pdevinit数组中的一个pdevinit结构来表示,在内核配置期间构造了这个数组。
以下概要地说明下以太网的初始化过程:
作为cpu_startup的一部分,内核查找不论什么连接的网络设备。
这个过程的细节超出了本书的范围,一旦一个设备被识别。一个
设备专用的初始化函数就被调用(LANCE以太网设备为leattach函数)。以下的操作被运行:
1.创建le_softc结构
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvVE9ERDkxMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
2.从设备复制硬件地址到结构中。
3.初始化ifnet结构。设置ifnet的例如以下成员:if_unit,if_name,if_mtu。if_init,if_reset,if_ioctl,if_output。if_start,if_flags。
if_attach函数
为这个接口创建一个链路层ifaddr
第二个是ifnet_addrs。它指向一个