mii-tool的限制/mii-tool和千兆网络
mii-tool的限制mii-tool不支持1000M以上的网卡,这里我们先做个实验,先看看100M网卡能不能正确显示:
[root@localhost /]# mii-tool -v eth0
eth0: negotiated 100baseTx-FD, link ok product info: vendor 00:40:63, model 50 rev 10 basic mode: autonegotiation enabled basic status: autonegotiation complete, link ok capabilities: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD advertising: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD flow-control link partner: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD #这里显示100M网卡
[root@localhost /]# ethtool eth0
Settings for eth0: Supported ports: [ TP MII ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full Supports auto-negotiation: Yes Advertised link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full Advertised auto-negotiation: Yes Speed: 100Mb/s Duplex: Full Port: MII PHYAD: 1 Transceiver: internal Auto-negotiation: on Supports Wake-on: pumbg Wake-on: d Current message level: 0x00000001 (1) Link detected: yes #这里也显示是100M网卡
正常对于100M以下的网卡都能够用这俩个命令来查看,但是对于100M以上网卡的,mii-tool就会出现问题
mii-tool -v eth0
eth0: negotiated 100baseTx-FD, link ok product info: vendor 00:aa:00, model 56 rev 0 basic mode: autonegotiation enabled basic status: autonegotiation complete, link ok capabilities: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD advertising: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD flow-control link partner: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD #这里显示100M网卡,实际上我是1000M的接口
ethtool eth0
Settings for eth0: Supported ports: [ TP ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Supports auto-negotiation: Yes Advertised link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full Advertised auto-negotiation: Yes Speed: 1000Mb/s Duplex: Full Port: Twisted Pair PHYAD: 0 Transceiver: internal Auto-negotiation: on Supports Wake-on: umbg Wake-on: d Current message level: 0x00000007 (7) Link detected: yes #这里却正确的显示1000M网卡
这里简单分析一下mii-tool的显示部份的实现:
1、首先在主函数中打开套接字,循环调用处理函数: int main(int argc, char **argv) { int i; char s[6]; /* Open a basic socket. */ if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) perror("socket"); exit(-1); }
for (i = 0; i
sprintf(s, "eth%d", i); do_one_xcvr(skfd, s, 1); }
return 0;
} do_one_xcvr的主要功能是调用ioctl取得网卡的phy_id,然后进一步处理: int do_one_xcvr(int skfd, char *ifname, int maybe) { struct mii_data *mii = (struct mii_data *)&ifr.ifr_data; /* Get the vitals from the interface. */ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(skfd, SIOCGMIIPHY, &ifr) { if (!maybe || (errno != ENODEV)) { fprintf(stderr, "SIOCGMIIPHY on '%s' failed: %sn", ifname, strerror(errno)); } return 1; }
show_basic_mii(skfd, mii->phy_id);
}
关于SIOCGMIIPHY等宏的定义,很容易就能够找到了,这里不分析了……
show_basic_mii是整个核心了: int show_basic_mii(int sock, int phy_id) { char buf[100]; int i, mii_val[32]; int bmcr, bmsr, advert, lkpar; /* Some bits in the BMSR are latched, but we can't rely on being the only reader, so only the current values are meaningful */ mdio_read(sock, MII_BMSR); for (i = 0; i mii_val = mdio_read(sock, i);
if (mii_val[MII_BMCR] == 0xffff) {
fprintf(stderr, " No MII transceiver present!.n"); return -1; }
/* Descriptive rename. */
bmcr = mii_val[MII_BMCR]; bmsr = mii_val[MII_BMSR]; advert = mii_val[MII_ANAR]; lkpar = mii_val[MII_ANLPAR];
sprintf(buf, "%s: ", ifr.ifr_name);
if (bmcr & MII_BMCR_AN_ENA) { if (bmsr & MII_BMSR_AN_COMPLETE) { if (advert & lkpar) { strcat(buf, (lkpar & MII_AN_ACK) ? "negotiated" : "no autonegotiation,"); strcat(buf, media_list(advert & lkpar, 1)); strcat(buf, ", "); } else { strcat(buf, "autonegotiation failed, "); } } else if (bmcr & MII_BMCR_RESTART) { strcat(buf, "autonegotiation restarted, "); } } else { sprintf(buf+strlen(buf), "%s Mbit, %s duplex, ", (bmcr & MII_BMCR_100MBIT) ? "100" : "10", (bmcr & MII_BMCR_DUPLEX) ? "full" : "half"); } strcat(buf, (bmsr & MII_BMSR_LINK_VALID) ? "link ok" : "no link");
printf("%sn", buf);
return 0;
} 能够看到,主要是通过mdio_read来读取相关信息的,之后就是判断比较和输出了,而输出网卡物一类型的时候,用到了media_list,先来看看mdio_read: static int mdio_read(int skfd, int location) { struct mii_data *mii = (struct mii_data *)&ifr.ifr_data; mii->reg_num = location; if (ioctl(skfd, SIOCGMIIREG, &ifr) fprintf(stderr, "SIOCGMIIREG on %s failed: %sn", ifr.ifr_name, strerror(errno)); return -1; } return mii->val_out; } 同样,也是用ioctl……^o^,再来看看media_list,他主要根据mdio_read返回来的相关值读取一个事先封装好的结构数组: static char *media_list(int mask, int best) { static char buf[100]; int i; *buf = ''; mask >>= 5; for (i = 4; i >= 0; i--) { if (mask & (1 strcat(buf, " "); strcat(buf, media.name); if (best) break; } } if (mask & (1 strcat(buf, " flow-control"); return buf; } 最后来看看media的定义的赋值: const struct { char *name; u_short value; } media[] = { /* The order through 100baseT4 matches bits in the BMSR */ { "10baseT-HD", MII_AN_10BASET_HD }, { "10baseT-FD", MII_AN_10BASET_FD }, { "100baseTx-HD", MII_AN_100BASETX_HD }, { "100baseTx-FD", MII_AN_100BASETX_FD }, { "100baseT4", MII_AN_100BASET4 }, { "100baseTx", MII_AN_100BASETX_FD | MII_AN_100BASETX_HD }, { "10baseT", MII_AN_10BASET_FD | MII_AN_10BASET_HD }, };
这里没有定义100M以上的接口,所以,mii-tool不支持1000M
|