igb网卡的 link状态

本文详细解释了ethtool中的link状态、kernel中ethtool操作、ifconfig中的running状态以及网卡驱动如何处理SFP光模块链接问题。讨论了netif_running、netif_carrier_ok等概念,以及在驱动加载和ifconfig逻辑中的作用。
摘要由CSDN通过智能技术生成

1. Ethtool中的link状态

这里我们以igb网络为例,来说明ethtool中的link状态:

1.1 Net-tools中ethtool

首先从ethtool中, 发出一个ETHTOOL_GLINK的消息到kernel中:

0

1.2 Kernel中ethtool

net/core/dev_ioctl.c->dev_ethtool 系统ioctl的入口

0

0

这里可以看到,link状态取决于:  netif_running  && ethtool_ops->get_link

1.2.1 netif_running()

0

__LINK_STATE_START是怎么来的?,搜索代码可以找到_dev_open中有如下代码:

0

 _dev_open则是在调用ifconfig up 的流程中调用的,所以 netif_running类似于管理状态的概念,

执行ifconfig up ,则dev-state->__LINK_STATE_START被标记,ifconfig down, dev-state->__LINK_STATE_START标记被清除

0

1.2.2 ethtool_ops->get_link

这里进入igb网卡的流程…

0

0

这里有一个netif_carrier_ok(netdev): 这里最终是网卡link_up状态中设置的,见后面。

get_link_status: 针对不同的前端media模式, 对link状态的读取不同。

1.2.3 igb_has_link

bool igb_has_link(struct igb_adapter *adapter)

0

这里对于copper,link状态在外部,由外部上报LSC中断,系统觉得是准确的,所以这里如果外部中断已经上报了,不需要再去读取link状态了。

如下是对应copper和!copper 2种链路方式的读取,最终将读取到网卡的link状态

0

这里netif_carrier_on 在哪个流程里调用呢??  -- 这里是在网卡驱动的link检查流程中设置的:

1.2.4 link LSC 中断上报

igb_msix_other(int irq, void *data) //这里是other中断

0

1.2.5 igb_watchdog_task

//在网卡probe加载后,启动timer,timer中启动的work_queue

igb_watchdog_task

   link = igb_has_link(adapter); //读取Link状态     

   if (link) //检查到link 状态

        if (!netif_carrier_ok(netdev)) //如果原来没有link up

            printk() // dmesg打印出link up的信息

            netif_carrier_on(netdev); //设置网卡的link up信息

       

0

---   这里igb是一个特例,不是直接判断carrier_ok的值, 可以参考ixgbe。

综上:

ethtool link状态为:  ifconfig up &&  ethtool->get_link的状态(网卡硬件的物理状态)

netif_carrier_ok:  保存当前网卡的物理link状态到netdev中。

2. ifconfig中running

0

net-tool 中: 可以看到状态: IFF_RUNNING…

0

Kernel 中

0

netif_oper_up

0

这个状态在哪里设置的呢?

igb_watchdog_task

    link:  netif_carrier_on(netdev);

        linkwatch_fire_event(dev); //通知其它进程关注事件

linkwatch_fire_event

--> linkwatch_schedule_work

--> schedule: linkwatch_work

    --> rfc2863_policy(dev); //这个状态是为MIB状态

        --> IF_OPER_UP  -- 最终这里将状态设置起来

综上:

Ifconfig Running 状态为网卡link事件通过一系列的通知链,最终设置的一个mib状态, 只是ifconfig 将这个状态读取出来。

3. 一体机光转电口卡link 失败

问题描述:

使用的网卡为: E1000_DEV_ID_82580_FIBER 0x150F

在插上SFP光电转化口后启动(或者动态加载驱动):

1.  在插出/插入SFP光模块上的网线的时候, 能够监测到link事件。

2.  在有些环境中,可以将SFP 带着网线一起拔出,这时link事件检查不到。继续插上也检查不到。

3.  在有些环境,只有将SFP上网线拔出后(能够监测到link事件)才能够拔出SFP, 再插上SFP,再接上网线后,无法Link。

对比未插上SFP光模块启动的时候:  拔插网线/光模块都没有问题。

问题分析:

1.  在驱动加载的时候,这2种情况下, 驱动对硬件前端的识别情况不同:

插入SFP光转电:  前端media_type 识别为: e1000_media_type_copper ,对前端的处理Porwerup

igb_power_up_phy_copper(&adapter->hw);

在这种模式下,网卡驱动通过i2c对外界MDI来做negonation。

未插入SFP时候: media_type识别为: internal_serdes, 在这种模式下

igb_power_up_serdes_link_82575(&adapter->hw);

因为本地网卡MAC已经是FIRBBER, 所以协商的话直接设置本地PCS寄存器就可以了

带SFP加载驱动, 识别为copper, copper的前端为SPF光模块,通过MDI线连接。 在当前的环境中, 拔出SFP后,系统没有监测到media_type的变化, 中断未上报,只报了一些对i2c_read ERR的日志。

检查系统中其实是有check_swap的流程中的,只是在读eeprom的时候,当前网卡都没有走入case中,未将该状态设置起来:

0

该状态将在watch_dog_task中将检查,其核心是检查:

#define E1000_CONNSW   0x00034  /* Copper/Fiber switch control - RW */

检查到media_chagen后, 会调用网卡的reset流程,在该流程中,重新读取media的状态。

注: 在测试从 serdes -> copper 模式的时候,reset的流程总是发生crash, 考虑到在serdes模式下,热插拔是正常的, 就不检查这个流程了。 所以最终的修改如下:

0

其实这个问题就是: 光模块暴拔的问题…

//这里的判断表示: 如果不是fiber口,media_type 不是copper(fiber插入光转电口), 可以自动dect link变化,不需要下面增加的dect link流程.

如果发现当前控制器状态为:  SERDESD  -- 表示希望看到SERDESD 出现, 表面当前Fiber未发生link 变化。

0

4 ifconfig 逻辑

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

return (-1);

ife->flags = ifr.ifr_flags;

然后判断 flags:输出 runing状态

if (ptr->flags & IFF_RUNNING)

strcat(flags,_("RUNNING,"));

if (ptr->flags & IFF_UP)

strcat(flags,_("UP,"));

内核dev.c获取flag 返回给ioctl

unsigned int dev_get_flags(const struct net_device *dev)

{

unsigned int flags;

flags = (dev->flags & ~(IFF_PROMISC |

IFF_ALLMULTI |

IFF_RUNNING |

IFF_LOWER_UP |

IFF_DORMANT)) |

(dev->gflags & (IFF_PROMISC |

IFF_ALLMULTI));

if (netif_running(dev)) {

if (netif_oper_up(dev))

flags |= IFF_RUNNING;

if (netif_carrier_ok(dev))

flags |= IFF_LOWER_UP;

if (netif_dormant(dev))

flags |= IFF_DORMANT;

}

return flags;

}

static inline bool netif_oper_up(const struct net_device *dev)

{

return (dev->operstate == IF_OPER_UP ||

dev->operstate == IF_OPER_UNKNOWN /* backward compat */);

}

static inline bool netif_carrier_ok(const struct net_device *dev)

{

return !test_bit(__LINK_STATE_NOCARRIER, &dev->state);

}

5, ifconfig up

dev_open->__dev_open

6. kni 获取link

0

kni ea1000_phy_has_link_generic ret_val=0 phy_status=31049 success=0

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luopandeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值