irpas技术客

linux 3.16.35 内核不支持 ethtool 获取 virtio 接口速率双工问题_longyu_wlz

网络投稿 5600

linux 3.16.35 内核不支持 ethtool 获取 virtio 接口速率双工 问题描述

linux-3.16.35 内核虚拟化环境中,管理口使用 virtio 网卡,执行 ethtool 获取信息,有如下信息:

[root] # ethtool enps0f0 Settings for enps0f0: Link detected: yes

获取的信息中缺少速率双工的状态,这说明此版本内核 virtio-net 驱动代码中 ethtool_ops xxx_get_settings 类别的接口没有实现。

内核代码中的相关信息

3.16.35 内核中 virtio-net 驱动 ethtool_ops 实现代码:

static const struct ethtool_ops virtnet_ethtool_ops = { .get_drvinfo = virtnet_get_drvinfo, .get_link = ethtool_op_get_link, .get_ringparam = virtnet_get_ringparam, .set_channels = virtnet_set_channels, .get_channels = virtnet_get_channels, };

确认 virtio-net 实现的 ethtool_ops 中未注册 get_settings 接口,故而不能获取到速率双工。

如何修复?

考虑到我们使用 virtio-net 作为管理口的场景中获取到的速率双工只用于展示,没有其它用途,决定自己实现一个非常简单的版本。 查看内核 git log 中的相关修改,发现有写固定值的实现,最新的实现通过读取后端信息来获取,相对复杂,最终决定使用如下代码解决此问题:

Index: virtio_net.c =================================================================== --- virtio_net.c +++ virtio_net.c @@ -1314,12 +1314,30 @@ channels->other_count = 0; } +static int virtnet_get_link_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + cmd->speed = SPEED_UNKNOWN; + cmd->autoneg = AUTONEG_DISABLE; + cmd->supported = SUPPORTED_10000baseT_Full; + cmd->port = PORT_OTHER; + cmd->duplex = DUPLEX_UNKNOWN; + + if (netif_running(dev)) { + ethtool_cmd_speed_set(cmd, SPEED_10000); + cmd->duplex = DUPLEX_FULL; + } + + return 0; +} + static const struct ethtool_ops virtnet_ethtool_ops = { .get_drvinfo = virtnet_get_drvinfo, .get_link = ethtool_op_get_link, .get_ringparam = virtnet_get_ringparam, .set_channels = virtnet_set_channels, .get_channels = virtnet_get_channels, + .get_settings = virtnet_get_link_settings, };

上述逻辑为当接口状态 RUNNING 的时候,返回 10G 速率与全双工,当接口状态 down 的时候,返回未知速率与半双工模式。 实现了一个 virtnet_get_link_settings 注册到 virtnet_ethtool_ops get_settings 虚函数中就能够正常获取 virtio-net 网卡的速率双工。

测试记录

重新编译然后加载 virtio_net 后的状态:

[root] # ethtool eth0 Settings for eth0: Supported ports: [ ] Supported link modes: 10000baseT/Full Supported pause frame use: No Supports auto-negotiation: No Advertised link modes: Not reported Advertised pause frame use: No Advertised auto-negotiation: No Speed: Unknown! Duplex: Unknown! (255) Port: Other PHYAD: 0 Transceiver: internal Auto-negotiation: off Link detected: no

接口 up 时获取的状态:

[root] # ethtool eth0 Settings for eth0: Supported ports: [ ] Supported link modes: 10000baseT/Full Supported pause frame use: No Supports auto-negotiation: No Advertised link modes: Not reported Advertised pause frame use: No Advertised auto-negotiation: No Speed: 10000Mb/s Duplex: Full Port: Other PHYAD: 0 Transceiver: internal Auto-negotiation: off Link detected: yes

接口 down 了后的状态:

[root] # ifconfig eth0 down [root] # ethtool eth0 Settings for eth0: Supported ports: [ ] Supported link modes: 10000baseT/Full Supported pause frame use: No Supports auto-negotiation: No Advertised link modes: Not reported Advertised pause frame use: No Advertised auto-negotiation: No Speed: Unknown! Duplex: Unknown! (255) Port: Other PHYAD: 0 Transceiver: internal Auto-negotiation: off Link detected: no

测试通过!

一点插曲

写的过程中纠结了下要返回的速率是千兆还是万兆的问题,认知中应该是千兆,但是阅读高版本的代码却发现返回的是万兆,经过一通搜索后确定 virtio-net 网卡的速率是万兆而非千兆。 修复了这个问题后发布给产品,产品对于获取到的速率是万兆也有疑问,于是澄清了下,果然很多人都认为 virtio-net 虚拟网卡的速率应该是千兆呀。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Linux #31635 #内核不支持 #ethtool #获取 #virtio #接口速率双工问题