第4章 接口以太网

2019-09-01 18:53

第4章 接口:以太网

4.1 引言

在第3章我们讨论了所有接口要用到的数据结构及对这些数据结构的初始化。在本章,我们说明以太网设备驱动程序在初始化后是如何接收和传输帧的。本章的第二部分是介绍配置网络设备的通用ioctl命令。第5章是SLIP和环回驱动程序。

我们不准备查看整个以太网驱动程序的源代码,因为它有大约1,000行C代码(其中有一半是一个特定接口卡的硬件细节),但我们要研究设备无关的以太网代码部分,及驱动程序是如何和内核其他部分交互的。 如果读者对一个驱动程序的源代码感兴趣,Net/3版本包括很多不同接口的源代码。要想研究接口的技术规范要求能理解设备专用的命令。图4.1所示的是Net/3提供的各种驱动程序,包括在本章我们要讨论的LANCE驱动程序。

网络设备驱动程序通过ifnet结构(图3.6)中的7个函数指针来访问。图4.2列出了指向我们的三个例子驱动程序的指针项。 输入函数不包含在图4.2中,因为它们是网络设备中断驱动的。中断服务例程的配置是硬件相关的并且超出了本书的范围。我们要识别处理设备中断的函数,但不是这些函数被调用的机制。

设备 DEC DEUNA接口 3Com以太网接口 Excelan EXOS 204接口 Interlan以太网通信控制器 Interlan NP100以太网通信控制器 Digital Q-BUS to NI适配器 CMC ENP-20以太网控制器 Excelan EXOS 202 (VME) & 203 (QBUS) ACC VERSAbus以太网控制器 AMD 7990 LANCE接口 NE2000以太网 Western Digital 8003以太网适配器 文件 vax/if/if_de.c vax/if/if_ec.c vax/if/if_ex.c vax/if/if_il.c vax/if/if_ix.c vax/if/if_qe.c tahoe/if/if_enp.c tahoe/if/if_ex.c tahoe/if/if_ace.c hp300/dev/if_le.c i386/isa/if_ne.c i386/isa/if_we.c 图4.1 Net/3中可用的以太网驱动程序

ifnet if_init if_output if_start if_done if_ioctl if_reset if_watchdog 以太网 leinit ether_output lestart leioctl lereset SLIP slouput slioctl 环回 looutput lcioctl 说明 硬件初始化 接收并对传输的帧进行排队 开始传输帧 输出完成(未用) 处理来自一个进程的ioctl命令 把设备复位到已知的状态 监视设备故障或收集统计信息 图4.2 例子驱动程序的接口函数

只有函数if_output和if_ioctl被一致地调用。而if_init、if_done和if_reset从来不被调用或仅从设备专用代码调用(例如leinit直接被leioctl调用)。函数if_start仅被函数ether_output调用。

4.2 代码介绍

以太网设备驱动程序和通用接口ioctl的代码包含在两个头文件和三个C文件中,它

4—1

们列于图4.3中。

文件 net/if_ether.h net/if.h net/if_thersubr.c hp300/dev/if_le.c net/if.c 说明 以太网结构 Ioctl命令定义 通用以太网函数 LANCE以太网驱动程序 ioctl处理 图4.3 在本章讨论的文件

全局变量

显示在图4.4中的全局变量包括协议输入队列、LANCE接口结构和以太网广播地址。

变量 arpintrq clnlintrq ipintrq le_softc etherbraodcastaddr 数据类型 struct ifqueue struct ifqueue struct ifqueue struct le_softc[] u_char[] 图4.4 本章介绍的全局变量

说明 ARP输入队列 CLNP输入队列 IP输入队列 LANCE以太网接口 以太网广播地址 le_softc是一个数组,因为这里可以有多个以太网接口。 统计

结构ifnet中为每个接口收集的统计如图4.5所示。 ifnet成员 if_collisions if_ibytes if_ierrors if_imcasts if_ipackets if_iqdrops if_lastchange if_noproto if_obytes if_oerrors if_omcasts if_opackets if_snd.ifq_drops if_snd.ifq_len 说明 在CSMA接口的冲突数 接收到的字节总数 接收到的有输入差错分组数 接收到的多播分组数 在接口接收到的分组数 被此接口丢失的输入分组数 上一次改变统计的时间 指定为不支持协议的分组数 发送的字节总数 接口上输出的差错数 发送的多播分组数 接口上发送的分组数 在输出期间丢失的分组数 输出队列中的分组数。 图4.5 结构ifnet中维护的统计

用于 SNMP ? ? ? ? ? ? ? ? ? ? ? ? 图4.6显示了一些netstat命令的输出例子,它包括一些ifnet结构中的统计信息。 第一列包含显示为一个字符串的if_name和if_unit。若接口是关闭的(不设置IFF_UP),一个星号显示在这个名字的旁边。在图4.6中,sl0、sl2和sl3是关闭的。

图4.6 接口统计的样本

第二列显示的是if_mtu。在表头“Network”和“Address”底下的输出依赖于地址的类型。对于链路层地址,显示了结构sockaddr_dl的sdl_data的内容。对于IP地址显示了子网和单播地址。其余的列是if_ipackets,if_ierrors,if_opackets,if_oerrors和if_collisions。

? 在输出中冲突的分组大约有3%(942,798 / 23,234,729 = 3%)。

4—2

? 这个机器的SLIP输出队列从未满过,因为SLIP接口的输出没有差错。

? 在传输中LANCE硬件检测到12个以太网的输出差错。其中一些差错可能被视为冲突。

? 硬件检测出814个以太网的输入差错,例如分组太短或错误的检验和。

SNMP变量

图4.7所示的是SNMP接口表(ifTable)中的一个接口项对象(ifEntry),它包含在每个接口的ifnet结构中。

ISODE SNMP代理从if_type获得ifSpeed并为ifAdminStatus维护一个内部变量。代理的ifLastChange基于结构ifnet中的if_lastchange但与代理的启动时间相关,而不是与系统的启动时间相关。代理为ifSpecific返回一个空变量。

SNMP变量 ifIndex ifDescr ifType ifMtu ifSpeed ifPhysAddress ifAdminStatus ifOperStatus ifLastChange ifInOctets ifInUcastPkts ifInNUcastPkts ifInDiscards ifInErrors ifInUnknownProtos ifOutOctets ifOutUcastPkts ifOutNUcastPkts ifOUtDiscards ifOutErrors ifOutQLen ifSpecific 接口表,索引= 说明 ifnet成员 if_index 唯一地标识接口 if_name 接口的文本名称 if_type 接口的类型(例如以太网、SLIP等等) if_mtu 接口的MTU(字节) (看正文) 接口的正常速率(每秒比特) ac_enaddr 媒体地址(来自结构arpcom) (看正文) 接口的期望状态(IFF_UP标志) if_flags 接口的操作状态(IFF_UP标志) (看正文) 上一次统计改变时间 if_ibytes 输入的字节总数 if_ipackets – 输入的单播分组数 if_imcasts if_imcasts 输入的广播或多播分组数 if_iqdrops 因为实现的限制而丢弃的分组数 if_ierrors 差错的分组数 if_noproto 指定为未知协议的分组数 if_obytes 输出字节数 if_opackets – 输出的单播分组数 if_omcasts if_omcasts 输出的广播或多播分组数 if_snd.ifq_drops 因为实现的限制而丢失的输出分组数 if_oerrors 因为差错而丢失的输出分组数 if_snd.ifq_len 输出队列长度 n/a 媒体专用信息的SNMP对象ID(未实现) 图4.7 接口表ifTable的变量

4.3 以太网接口

Net/3以太网设备驱动程序都遵循同样的设计。对于大多数Unix设备驱动程序来说,都是这样,因为写一个新接口卡的驱动程序总是在一个已有的驱动程序的基础上修改而来的。在本节,我们简要地概述一下以太网的标准和一个以太网驱动程序的设计。我们用LANCE驱动程序来说明这个设计。 图4.8说明了一个IP分组的以太网封装。

图4.8 一个IP分组的以太网封装

以太网帧包括48 bit的目的地址和源地址,接下来是一个16 bit的类型字段,它标识这个帧所携带的数据的格式。对于IP分组,类型是0x0800(2048)。帧的最后是一个32 bit

4—3

的CRC(循环冗余检验),它用来检查帧中的差错。

我们所讨论的最初的以太网组帧的标准在1982年由Digital设备公司、Intel公司及施乐公司发布,并作为今天在TCP/IP网络中最常用的格式。另一个可选的格式是IEEE(电气电子工程师协会)规定的802.2和802.3标准。更多的IEEE标准详见[Stallings 1987]。

我们用48 bit的以太网地址作为硬件地址。IP地址到硬件地址之间的转换用ARP协议(RFC 826 [Plummer 1982]),这个协议在第21章讨论,而硬件地址到IP地址的转换用RARP协议(RFC 903 [Finlayson et al. 1984])。以太网地址有两种类型:单播和多播。一个单播地址描述一个单一的以太网接口,而一个多播地址描述一组以太网接口。一个以太网广播是一个所有接口都接收的多播。以太网单播地址由设备的厂商分配,也有一些设备的地址允许用软件改变。

一些DECNET协议要求标识一个多接口主机的硬件地址,因此DECNET必须能改变一个设备的以太网单播地址。

图4.9列举了以太网接口的数据结构和函数。

在图中有:用一个椭圆标识的一个函数(leintr)、用一个方框标识的数据结构(le_softc[0])、le_softc及用圆角方框标识的一组函数(ARP协议)。

图4.9左上角显示的是OSI无连接网络层(clnl)协议、IP和ARP的输入队列。对于clnlintrq我们不打算讲更多,将它包含进来是为了强调ether_input要将以太网帧分路到多个协议队列中。

在技术上,OSI使用无连接网络协议(CLNP而不是CLNL),但我们使用的是Net/3中的术语。CLNP的官方标准是ISO 8473。[Stallings 1993]对这个标准进行了概述。

接口结构le_softc在图4.9的中间。我们感兴趣的是这个结构中的ifnet和arpcom,其他是LANCE硬件的专用部分。我们在图3.6显示了结构ifnet,在图3.26显示了结构arpcom。

leintr函数

我们从以太网帧的接收开始。现在,我们假设硬件已初始化并且系统已完成配置,当接口产生一个中断时,leintr被调用。在正常操作中,一个以太网接口接收发送到它的单播地址和以太网广播地址的帧。当一个完整的帧可用,接口就产生一个中断并且内核调用leintr。

图4.9 以太网设备驱动程序

在第12章,我们会看见可能要配置多个以太网接口来接收以太网多播帧(不同于广播)。

有些接口可以配置为运行在混杂方式(promiscuous mode),在这种方式下接口接收所有出现在网络上的帧。在卷1中讨论的tcpdump程序可以使用BPF (BSD分组过滤程序)来利用这种特性。

leintr检测硬件并且如果有一个帧到达就调用leread把这个帧从接口转移到一个mbuf链中(用m_devget)。如果硬件报告一个帧已传输完或发现一个差错(如一个有错误的检验和),则leintr更新相应的接口统计,复位这个硬件,并调用lestart来传输另一个帧。

所有以太网设备驱动程序将它们接收到的帧传给ether_input做进一步的处理。设备驱动程序构造的mbuf链不包括以太网首部,以太网首部作为一个独立的参数传递给ether_input。结构ether_header显示在图4.10中。 38-42 以太网CRC并不总可用。它由接口硬件来计算与检验,接口硬件丢弃到达的CRC差错帧。以太网设备驱动程序负责ether_type的网络和主机字节序间的转换。在驱动程

4—4

序外它总是主机字节序。

图4.10 结构ether_header

leread函数

函数leread(图4.11)的开始是由leintr传给它的一个连续的内存缓冲区并且构造了一个ther_header结构和一个mbuf链。这个链表存储来自以太网帧的数据。leread还将输入帧传给BPF。

图4.11 函数leread

528-539 函数leintr给leread传了三个参数:unit,它标识接收到此帧的特定接

口卡;buf,它指向接收到的帧;len,它是帧的字节数(包括首部和CRC)。

函数将et指向这个缓存的开始,并且将以太网字节序转换成主机字节序,来构造结构ether_header。

540-551 将len减去以太网首部和CRC的大小得到数据的字节数。短分组(Runt packet)是一个长度太短的非法以太网帧,它被记录、统计并被丢弃。

552-557 接下来,目的地址被检测,判断是不是以太网广播或多播地址。以太网广播地址是一个以太网多播地址的特例;它的每一比特都被设置了。etherbroadcastaddr是一个数组,定义如下:

u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 这是C语言中定义一个48 bit值的方便的方法。这个技术仅在我们假设字符是8 bit值时才起作用——ANSI C并不保证这一点。

bcmp比较etherbroadcastaddr和ether_dhost,若相同,则设置标志M_BCAST。 一个以太网多播地址由这个地址的首字节的低位比特来标识,如图4.12所示。

图4.12 检测一个以太网多播地址

在第12章我们会看到并不是所有以太网多播帧都是IP多播数据报并且IP必须进一步检测这个分组。 如果这个地址的多播比特被置位,在mbuf首部中设置M_MCAST。检测的顺序是重要的:首先ether_input将整个48 bit地址和以太网广播地址比较,若不同则检测这个标识以太网多播地址的首字节的低位比特(习题4.1)。

558-573 如果接口带有BPF,调用bpf_tap把这个帧直接传给BPF。我们会看见对于SLIP和环回接口,要构造一个特定的BPF帧,因为这些网络没有一个链路层首部(不像以太网)。 当一个接口带有BPF,它可以配置为运行在混淆模式并且接收网络上出现的所有以太网帧,而不是通常硬件接收帧的子集。如果分组发送给一个不与此接口地址匹配的单播地址,则被leread丢弃。 574-585 m_devget(2.6节)将数据从传给leread的缓存中复制到一个它分配的mbuf链中。传给m_devget的第一个参数指向以太网首部后的第一个字节,它是此帧中的第一个数据字节。如果m_devget内存用完,leread立即返回。另外广播和多播标志被设置在链表中的第一个mbuf中,ether_input处理这个分组。

4—5


第4章 接口以太网.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:材料分析测试方法作业题

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: