Linux механизм сторожевого таймера сетевого устройства - PullRequest
0 голосов
/ 16 марта 2020

Я изучаю Linux драйвер сетевого устройства с Linux 4.12.14, и вот что я узнал:

  1. В драйвере устройства он устанавливает некоторые переменные, когда устройство открыто:
    dev->watchdog_timeo = TX_TIMEOUT;
    ...
    .ndo_tx_timeout     = el3_tx_timeout,
    
  2. Linux ядро ​​активирует таймер при открытии устройства:

    static void dev_watchdog(unsigned long arg)
    {
        struct net_device *dev = (struct net_device *)arg;
    
        netif_tx_lock(dev);
        if (!qdisc_tx_is_noop(dev)) {
            if (netif_device_present(dev) &&
                netif_running(dev) &&
                netif_carrier_ok(dev)) {
                int some_queue_timedout = 0;
                unsigned int i;
                unsigned long trans_start;
    
                for (i = 0; i < dev->num_tx_queues; i++) {
                    struct netdev_queue *txq;
    
                    txq = netdev_get_tx_queue(dev, i);
                    trans_start = txq->trans_start;
                    if (netif_xmit_stopped(txq) &&
                        time_after(jiffies, (trans_start +
                                 dev->watchdog_timeo))) {
                        some_queue_timedout = 1;
                        txq->trans_timeout++;
                        break;
                    }
                }
    
                if (some_queue_timedout) {
                    WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out\n",
                           dev->name, netdev_drivername(dev), i);
                    dev->netdev_ops->ndo_tx_timeout(dev);
                }
                if (!mod_timer(&dev->watchdog_timer,
                           round_jiffies(jiffies +
                                 dev->watchdog_timeo)))
                    dev_hold(dev);
            }
        }
        netif_tx_unlock(dev);
    
        dev_put(dev);
    }
    

    Итак, после того, как ядро ​​передает skb, оно обновляет txq-> trans_start:

    static inline netdev_tx_t netdev_start_xmit(struct sk_buff *skb, struct net_device *dev,
                            struct netdev_queue *txq, bool more)
    {
        const struct net_device_ops *ops = dev->netdev_ops;
        int rc;
    
        rc = __netdev_start_xmit(ops, skb, dev, more);
        if (rc == NETDEV_TX_OK)
            txq_trans_update(txq);
    
        return rc;
    }
    

    И функция обновления txq-> trans_start:

    static inline void txq_trans_update(struct netdev_queue *txq)
    {
        if (txq->xmit_lock_owner != -1)
            txq->trans_start = jiffies;
    }
    

Однако я нигде не нашел обновлений "txq-> trans_start "снова, поэтому мой вопрос: Почему успешная передача не приводит к превышению времени ожидания сторожевого таймера?

...