mii-tool的限制/mii-tool与千兆网络

来源:互联网 发布:联合国数据库 编辑:程序博客网 时间:2024/05/21 06:43

mii-tool的限制/mii-tool与千兆网络

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)) < 0) {

perror("socket");

exit(-1);

}

 

for (i = 0; i < MAX_ETH; 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) < 0)

{

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 < 8; 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) < 0) {

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<<i)) {

strcat(buf, " ");

strcat(buf, media.name);

if (best) break;

}

}

if (mask & (1<<5))

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