在linux中执行ifconfig XYZ命令会得到一大堆信息,唯独没有XYZ网络接口的速率,双工状态等信息,这合理吗?如果用惯了windows,那么就会觉得这个命令的输出确实少了一些什么,可是windows的ipconfig能得到这些信息吗?同样的也不能,windows网卡的速率双工信息是在“控制面板->网络连接”中选择具体网卡然后双击后看到的,并且此时只能看到速率,要查看双工信息则必须点击“属性”然后点击最上面网卡名称旁边的“配置”,之后点击“高级”选项卡,然后慢慢找吧,看起来很混乱,实际上也很混乱,速率/双工信息到底是网卡的配置属性还是内秉属性?本地连接状态下面的属性中包含有网卡的内秉属性和配置属性两种,内秉属性可以理解成是链路层和物理层的属性,而配置属性可以理解成网络层的属性,看起来很合理,这么说来,linux的ifconfig输出倒是有点乱了,既有网卡物理地址信息又存在ip地址信息,还有一些别的信息,确实,linux的ifconfig就是有点乱,如果你在一个网卡上配置了多个ip地址,那么用ifconfig命令是看不到的,而只能看到你最后配置的那个主ip地址,因此ifconfig命令的输出并不是很合理,如果想得到更合理的输出,请使用ip命令。我感觉ifconfig命令就是一个大杂烩,它几乎是万能的,却又极其不容易使用,现在的问题很明确,那就是设置一下网卡的速率和双工模式,请问用ifconfig怎么设置,很搞笑的是,ifconfig虽然默认不显示这些和网卡mac并列的内秉信息,但是却可以设置它们,比如用media选项,参数分别是10base2,10baseT,AUI等等,不像在windows中直接点击网卡的配置,然后点击高级选项卡,之后就可以自由设置这些参数了。linux的ifconfig虽然不太适合设置这些参数,但是它却拥有一个强大的工具来搞定这一切,这就是mii-tool和ethtool,这里并不区分这二者,它们实现的功能是很类似的。
MII的全称是Media Independent Interface,字面意思上就是媒体无关的接口,因此它是独立于具体设备的,仔细想想标准化的东西都是独立于具体设备的。虽然如此,很多以太网卡设备并不支持这些参数的配置,因此当你执行mii-tool的时候,会得到Operation not supported的提示,这是很合理的,因为这些参数的设置以极其功能并不是软件意义上的,而是硬件意义上,如果网卡上根本就没有相关的寄存器换句话说网卡根本就没有智能到支持自动协商双工模式的地步,你又如何去设置双工模式呢,或者你如何能让两个人同时渡过独木桥呢?实际上诸如双工模式的设置这种功能并不是必须的,因此对于软件来讲如果硬件没有实现那么完全不必去用软算法模拟之,对于上层应用来讲,底层的双工模式以及速率是完全透明的,这些概念只是功能意义上的,而不是接口意义上的。并不是所有的接口都能让你去随意设置速率和双工模式。可以这么认为,MII是一些比较智能的高速以太网卡为了彼此兼容或者说为了兼容弱者而设置的一个自协商机制。
可不要被上面说的吓坏以为mii-tool的代码有多么复杂,事实上它却很简单,该工具的源码很大的份额是在处理用户选项以及组合这些选项,除此之外就没有别的逻辑了,最终设置的时候i就是一个ioctl,内核会用vfs将这个ioctl路由到最终的设备,如果设备不支持mii,那么就直接返回一个“不支持”错误,然后返回,更简单的是,内核源代码本身的ioctl框架中就有一个SIOCETHTOOL标志来直接支持诸如速率和双工模式的协商方式配置,具体到设备的话就是简单的对特定的寄存器进行read和write操作,十分简单,既然如此,你就不要指望在内核源码的net_device结构体当中找到关于这些参数的字段了,它们不可能在这个如此抽象又如此重要的结构体中的,毕竟很多网络设备是没有这些概念的,因此它们最佳的位置应该在net_device的private字段中,我的意思是说它们在private中并不一定就是在private所代表的结构中,还很有可能藏在更加隐蔽的结构体的包含结构体之中,讨论这个已经没什么意义了。
想虚拟网卡之类的驱动程序有必要实现这些配置吗?根本就没有必要,因为虚拟网卡进出的数据根本就不是在“线路”上跑的,既然没有真正的“线路”那么这些关于线路的配置当然就是不需要的了,实际上速率和双工模式都是关于线路的配置,速率和模式和线路介质的导电性,信号衰减率,抗干扰系数都有关系,本机进出的虚拟网卡设置这些有意义吗?再次重申,这些东西不是“接口”意义上的,而是功能配置意义上的,它们也不是标准化的必须实现的,它们的存在是为了也仅仅是为了使得物理层更加有效率,在调用接口上完全和上面的N个层次戛然分离。
在Open×××中有一个--txqueuelen n重要的参数,它可以被理解成速率,只是它不是线路的速率而是和接口发送相关的,内核中的net_device中有一个tx_queue_len字段,表示在发送前,发送队列可以积压多少数据包,如果该值过于小,那么应用层发送过快的话,数据就会被drop掉,这也是值得关注的。还是以linux的tun设备为例,tun_net_xmit中有下列代码段:
if (!(tun->flags & TUN_ONE_QUEUE)) {
if (skb_queue_len(&tun->readq) >= TUN_READQ_SIZE)
netif_stop_queue(dev);
} else {
if (skb_queue_len(&tun->readq) >= dev->tx_queue_len)
goto drop;
}
skb_queue_tail(&tun->readq, skb);