欢迎光临
我们一直在努力

做phy是检查什么linux下查看网卡phy,Linux下网卡phy状态检测与控制

https://blog.csdn.net/vc66vcc/article/details/51193010

最近在一个项目中,集成一个交换机芯片的时候,遇到一些麻烦,发现交换机的性能总是上

不去,100M的交换机,实际交换能力只有10M。跟做硬件的同事一起,花了几周时间调试,

才找到问题。原来是接到交换机芯片上的几个子系统,用的Micrel 8041PHY芯片,默认关闭

了硬件流控,导致交换机无法通过流控来控制网络数据交换,结果使得其性能下降。而交换

机每个端口的PHY与子系统的PHY都使用的Auto Negotiation来协商链接状态,子系统默认不

支持流控,交换机也关闭了流控。

解决方法实际上很简单,就是在子系统端打开PHY的流控,其实也就是寄存器的一个位而已,

却花了我们几周时间。究其原因,都是由于大部分PHY芯片默认都打开流控,所以导致我们

一开始没怀疑到这上面,而且也没有引出交换机的控制口查看其状态。

子系统是跑的嵌入式Linux系统,所以在这几周的调试过程中,着重查看了Linux Kernel中

PHY的驱动,以及相关的一些系统调用。有些心得,记录下来。

Linux系统提供了两类ioctl系统调用SIOCETHTOOL和SIOCXMIIXXX,用于控制或者获取网卡

PHY的状态。这两类系统调用的实现取决于PHY驱动中对应ioctl的实现,一般的PHY驱动都

会实现至少其中的一类。下面以获取网卡的Link状态来说明这两类系统调用的使用。

0. Create socket handler

由于这两类调用都要使用socket handler,我们先建立一个socket handler用于下面的系统

调用。

/*————————————————————————–*/

/**

@brief    Detect eth link status from ETHTOOL API and MII reg.

@param    ifname — interface name.

@return   Return true if link is up, return false if link is down,

or return -1 if errors occur.

This function will first try to get eth link status from ETHTOOL API.

If it fails, it will try to get eth link status from MII reg.

*/

/*————————————————————————–*/

int get_netlink_status(char *ifname)

if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {

nl_err("socket error
");

return -1;

}

link_status = detect_ethtool(skfd, ifname);

if (link_status < 0)

link_status = detect_mii(skfd, ifname);

close(skfd);

return link_status;

}

1. SIOCETHTOOL ioctl

下面是SIOCETHTOLL系统调用的用法。

/*————————————————————————–*/

/**

@brief    Detect eth link status from ETHTOOL API.

@param    skfd   — socket handler.

@param    ifname — interface name.

@return   Return true if link is up, return false if link is down,

or return -1 if errors occur.

*/

/*————————————————————————–*/

int detect_ethtool(int skfd, char *ifname)

return (edata.data ? 1 : 0);

}

对应内核代码[linux/net/core/dev.c]中dev_ioctl()函数,对应的SIOCETHTOOL,又调用了

[linux/net/core/ethtool.c]中的实现,而dev_ethtool()函数,而这个函数最终又会调用

相应if驱动的ethtool_ops结构体中注册的函数来实现寄存器的操作。当然,不同的PHY驱动

对此有不同的操作,甚至有些PHY驱动根本没有注册这个结构体,这时,我们就要尝试下面

的方法了。

2. SIOCxMIIxxx ioctl

下面是SIOCxMIIxxx系统调用的用法。

/*————————————————————————–*/

/**

@brief    Detect eth link status from MII status reg.

@param    skfd   — socket handler.

@param    ifname — interface name.

@return   Return true if link is up, return false if link is down,

or return -1 if errors occur.

*/

/*————————————————————————–*/

static int detect_mii(int skfd, char *ifname)

mii_val = (struct mii_ioctl_data *)(&ifr.ifr_data);

mii_val->reg_num = MII_BMSR;

if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0)

if ((!(mii_val->val_out & BMSR_RFAULT)) &&

(mii_val->val_out & BMSR_LSTATUS) &&

(!(mii_val->val_out & BMSR_JCD))) {

return 1;

} else {

return 0;

}

}

对应内核代码[linux/net/core/dev.c]中dev_ioctl()函数,对应的SIOCxMIIxxx,又调用了

dev_ifsioc()函数,这个函数最终调用PHY驱动中注册的do_ioctl()函数来实现PHY寄存器的

读写。

赞(0)
未经允许不得转载:上海聚慕医疗器械有限公司 » 做phy是检查什么linux下查看网卡phy,Linux下网卡phy状态检测与控制

登录

找回密码

注册