heidsoft / devops

devops 经验总结实践与产品化
81 stars 44 forks source link

linux NIC Link is Up 10 Gbps, Flow Control: RX/TX #83

Open heidsoft opened 1 year ago

heidsoft commented 1 year ago

https://github.com/ntop/PF_RING/issues/293

/**
 * ixgb_watchdog - Timer Call-back
 * @data: pointer to netdev cast into an unsigned long
 **/

static void
ixgb_watchdog(struct timer_list *t)
{
    struct ixgb_adapter *adapter = from_timer(adapter, t, watchdog_timer);
    struct net_device *netdev = adapter->netdev;
    struct ixgb_desc_ring *txdr = &adapter->tx_ring;

    ixgb_check_for_link(&adapter->hw);

    if (ixgb_check_for_bad_link(&adapter->hw)) {
        /* force the reset path */
        netif_stop_queue(netdev);
    }

    if (adapter->hw.link_up) {
        if (!netif_carrier_ok(netdev)) {
            netdev_info(netdev,
                    "NIC Link is Up 10 Gbps Full Duplex, Flow Control: %s\n",
                    (adapter->hw.fc.type == ixgb_fc_full) ?
                    "RX/TX" :
                    (adapter->hw.fc.type == ixgb_fc_rx_pause) ?
                     "RX" :
                    (adapter->hw.fc.type == ixgb_fc_tx_pause) ?
                    "TX" : "None");
            adapter->link_speed = 10000;
            adapter->link_duplex = FULL_DUPLEX;
            netif_carrier_on(netdev);
        }
    } else {
        if (netif_carrier_ok(netdev)) {
            adapter->link_speed = 0;
            adapter->link_duplex = 0;
            netdev_info(netdev, "NIC Link is Down\n");
            netif_carrier_off(netdev);
        }
    }

    ixgb_update_stats(adapter);

    if (!netif_carrier_ok(netdev)) {
        if (IXGB_DESC_UNUSED(txdr) + 1 < txdr->count) {
            /* We've lost link, so the controller stops DMA,
             * but we've got queued Tx work that's never going
             * to get done, so reset controller to flush Tx.
             * (Do the reset outside of interrupt context). */
            schedule_work(&adapter->tx_timeout_task);
            /* return immediately since reset is imminent */
            return;
        }
    }

    /* Force detection of hung controller every watchdog period */
    adapter->detect_tx_hung = true;

    /* generate an interrupt to force clean up of any stragglers */
    IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);

    /* Reset the timer */
    mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
}

这段代码是一个名为“ixgb_watchdog”的定时器回调函数,用于监视网络设备的连接状态和传输情况。

以下是对这段代码的逐行解释:

  1. 函数参数是一个指向timer_list结构的指针,这个结构在Linux内核中用于实现定时器。

  2. 使用from_timer宏从定时器中获取ixgb_adapter结构的实例,该结构包含了网络设备的各种状态信息。

  3. 获取net_deviceixgb_desc_ring结构的实例,分别表示网络设备和发送描述符环。

  4. 调用ixgb_check_for_link函数检查网络设备的链接状态。

  5. 如果ixgb_check_for_bad_link函数返回真,则停止网络设备的数据队列,这通常表示网络连接出现问题。

  6. 如果网络设备的链接状态为上(link_up),则检查网络设备的载波状态。如果载波状态为下(carrier_ok),则设置网络设备的链接速度为10000Mbps、全双工,并开启载波。同时,打印一条信息,告知用户网络链接已经上,并展示流控的状态。

  7. 如果网络设备的链接状态为下,则检查网络设备的载波状态。如果载波状态为上,则设置网络设备的链接速度为0Mbps、双工状态为0,并关闭载波。同时,打印一条信息,告知用户网络链接已经下。

  8. 更新网络设备的统计信息。

  9. 如果网络设备的载波状态为下,且发送描述符环的未使用数加1小于总数,则调度一个工作队列任务来处理发送超时。然后立即返回,因为重置即将发生。

  10. 设置detect_tx_hung为真,以便在每个监视周期强制检测挂起的控制器。

  11. 生成一个中断来强制清理任何滞后的任务。

  12. 重置定时器,以便在2个时钟节(HZ)后再次调用这个函数。

netif_carrier_ok是Linux内核网络子系统中的一个函数,用于检查网络设备(如以太网卡)是否已连接到网络并且可以传输数据。

更具体地说,netif_carrier_ok函数会检查网络设备的carrier状态,这是一个表示设备是否已连接到网络并且可以正常工作的状态标志。如果设备已连接并且可以正常工作,netif_carrier_ok函数将返回非零值;如果设备未连接或无法正常工作,函数将返回零。

这个函数的主要用途是让网络驱动程序可以在尝试发送数据之前检查设备的状态,以避免在设备未连接或无法工作的情况下浪费资源。

heidsoft commented 1 year ago

https://time.geekbang.org/discuss/detail/77236 https://serverfault.com/questions/585442/eth0-nic-link-is-down-repeating-message-in-kernel-log https://bbs.archlinux.org/viewtopic.php?id=246307

heidsoft commented 1 year ago

https://www.intel.com/content/www/us/en/support/articles/000005480/ethernet-products.html#build_e1e https://blog.csdn.net/qq_31985307/article/details/120277739