《TCP/IP详解 卷2:实现》 —3.3 ifnet结构

举报
华章计算机 发表于 2019/11/21 11:13:13 2019/11/21
【摘要】 本节书摘来自华章计算机《TCP/IP详解 卷2:实现》一书中第3章,第3.3节,作者是[美]加里R.赖特(Gary R.Wright),W. 理查德史蒂文斯(W.Richard Stevens),陆雪莹 蒋慧 等译 谢希仁 校。

3.3   ifnet结构

结构ifnet中包含所有接口的通用信息。在系统初始化期间,分别为每个网络设备分配一个独立的ifnet结构。每个ifnet结构有一个列表,它包含这个设备的一个或多个协议地址。图3-5说明了一个接口和它的地址之间的关系。

在图3-5中的接口显示了3个存放在ifaddr结构中的协议地址。虽然有些网络接口(如SLIP)仅支持一个协议,但有些接口(如以太网)支持多个协议并需要多个地址。例如,一个系统可能使用一个以太网接口同时用于Internet和OSI两个协议。一个类型字段标识每个以太网帧的内容,并且因为Internet和OSI协议使用不同的编址方式,以太网接口必须有一个Internet地址和一个OSI地址。所有地址用一个链表链接起来(图3-5右侧的箭头),并且每个结构包含一个回指指针指向相关的ifnet结构(图3-5左侧的箭头)。

image.png

可能一个网络接口支持同一协议的多个地址。例如,在Net/3中可能为一个以太网接口分配两个Internet地址。

这个特点第一次是出现在Net/2中。当为一个网络重编地址时,一个接口有两个IP地址是有用的。在过渡期间,接口可以接收老地址和新地址的分组。

结构ifnet比较大,我们分五个部分来说明:

实现信息。

硬件信息。

接口统计。

函数指针。

输出队列。

图3-6所示的是包含在结构ifnet中的实现信息。

image.png

图3-6   ifnet结构:实现信息

80-82   if_next把所有接口的ifnet结构链接成一个链表。函数if_attach在系统初始化期间构造这个链表。if_addrlist指向这个接口的ifaddr结构列表(图3-16)。每个ifaddr结构存储一个要用这个接口通信的协议的地址信息。

1. 通用接口信息

83-86   if_name是一个短字符串,用于标识接口的类型,而if_unit标识多个相同类型的实例。例如,一个系统有两个SLIP接口,每个都有一个if_name,包含两字节的“s1”和一个if_unit。if_unit对第一个接口为0,对第二个接口为1。if_index在内核中唯一地标识这个接口,这在sysctl系统调用(见19.14节)以及路由域中要用到。

有时一个接口并不被一个协议地址唯一地标识。例如,几个SLIP连接可以有同样的本地IP地址。在这种情况下,if_index明确地指明这个接口。

if_flags表明接口的操作状态和属性。一个进程能检查所有的标志,但不能改变图3-7“内核专用”列中做了记号的标志。这些标志用4.4节讨论的命令SIOCGIFFLAGS和SIOCSIFFLAGS来访问。

      image.png

图3-7   if_flags值

IFF_BROADCAST和IFF_POINTOPOINT标志是互斥的。

宏IFF_CANTCHANGE是对所有在“内核专用”列中做了记号的标志进行按位“或”操作。

设备专用标志(IFF_LINKx)对于一个依赖这个设备的进程可能是可修改的,也可能是不可修改的。例如,图3-29显示了这些标志是如何被SLIP驱动程序定义的。

2. 接口时钟

87   if_timer以秒为单位记录时间,直到内核为此接口调用函数if_watchdog为止。这个函数用于设备驱动程序定时收集接口统计,或用于复位运行不正确的硬件。

3. BSD分组过滤器

88-89    下面两个成员if_pcount和if_bpf支持BSD分组过滤器(BPF)。通过BPF,一个进程能接收由此接口传输或接收的分组的备份。当我们讨论设备驱动程序时,还要讨论分组是如何通过BPF的。BPF在第31章讨论。

ifnet结构的下一个部分显示在图3-8中,它用来描述接口的硬件特性。

image.png

图3-8   ifnet结构:接口特性

Net/3和本书使用第138~143行的#define语句定义的短语来表示ifnet的成员。

4. 接口特性

90-92   if_type指明接口支持的硬件地址类型。图3-9列出了net/if_types.h中几个公共的if_type值。

image.png

图3-9   if_type:数据链路类型

93-94   if_addrlen是数据链路地址的长度,而if_hdrlen是由硬件附加给任何分组的首部的长度。例如,以太网有一个长度为6字节的地址和一个长度为14字节的首部(图4-8)。

95   if_mtu是接口传输单元的最大值,即接口在一次输出操作中能传输的最大数据单元的字节数。这是控制网络和传输协议创建分组大小的重要参数。对于以太网来说,这个值是1500。

96-97   if_metric通常是0,其他更大的值不利于路由通过此接口。if_baudrate指定接口的传输速率,只有SLIP接口才设置它。

接口统计由图3-10中显示的下一组ifnet接口成员来收集。

5. 接口统计

98-111   这些统计大多数是不言自明的。当分组传输被共享媒体上其他传输中断时,if_collisions加1。if_noproto统计由于协议不被系统或接口支持而不能处理的分组数(例如:仅支持IP的系统接收到一个OSI分组)。当一个非IP分组到达一个SLIP接口的输出队列时,if_noproto加1。

image.png

图3-10   结构ifnet:接口统计

这些统计在Net/1中不属于ifnet结构,加入它们的目的是支持接口的标准SNMP MIB-II变量。

if_iqdrops仅被SLIP设备驱动程序访问。当IF_DROP被调用时,SLIP和其他网络驱动程序把if_snd.ifq_drops (图3-13)加1。在SNMP统计加入前,ifq_drops就已经存在于BSD软件中了。ISODE SNMP代理忽略if_iqdrops而使用if_snd.ifq_drops。

6. 改变时间戳

112-113   if_lastchange记录任何统计改变的最近时间。

Net/3和本书又一次使用第144~155行的#define语句定义的短名来指明ifnet的成员。

结构ifnet的下一个部分显示在图3-11中,它包含指向标准接口层函数的指针,它们把设备专用的细节从网络层分离出来。每个网络接口实现这些适用于特定设备的函数。

image.png

图3-11   结构ifnet:接口过程

7. 接口函数

114-129    在系统初始化时,每个设备驱动程序初始化它自己的ifnet结构,包括7个函数指针。图3-12说明了这些通用函数。

我们在Net/3中常会看到注释/* XXX */。它提醒读者这段代码是易混淆的,包括不明确的副作用,或者一个更难问题的快速解决方案。在这里,它指示if_done不在Net/3中使用。

image.png

图3-12   结构ifnet:函数指针

在第4章我们要查看以太网、SLIP和环回接口的设备专用函数,内核通过ifnet结构中的这些指针直接调用它们。例如,如果ifp指向一个ifnet结构,

(*ifp->if_start)(ifp)

则调用这个接口的设备驱动程序的if_start函数。

结构ifnet中剩下的最后一个成员是接口的输出队列,如图3-13所示。

130-137   if_snd是接口输出分组队列,每个接口有它自己的ifnet结构,即它自己的输出队列。ifq_head指向队列的第一个分组(下一个要输出的分组),ifq_tail指向队列最后一个分组,if_len是当前队列中分组的数目,而ifq_maxlen是队列中允许的缓存最大个数。除非驱动程序修改它,这个最大值被设置为50(来源于全局整数ifqmaxlen,它在编译期间根据IFQ_MAXLEN初始化而来)。队列作为一个mbuf链的链表来实现。ifq_drops统计因为队列满而丢弃的分组数。图3-14列出了那些访问队列的宏和函数。

image.png

图3-13   结构ifnet:输出队列

  image.png

图3-14   fiqueue例程

前5个例程是定义在net/if.h中的宏,最后一个例程if_qflush是定义在net/if.c中的函数。这些宏经常出现在下面这样的程序语句中:

image.png

这段代码试图把一个分组加到队列中。如果队列满,IF_DROP把ifq_drops加1,并且分组被丢弃。可靠协议如TCP会重传丢弃的分组。使用不可靠协议(如UDP)的应用程序必须自己检测和处理重传。

访问队列的语句被splimp和splx括起来,阻止网络中断,并且防止在不确定状态时网络中断服务例程访问此队列。

在splx之前调用m_freem,是因为这段mbuf代码有一个临界区运行在splimp级别上。若在m_freem前调用splx,在m_freem中进入另一个临界区(2.5节)是浪费效率的。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。