// 调用路径: // 1.dev_queue_xmit->qdisc_run // 2.net_tx_action->qdisc_run // 对于dev->tx_queue_len !=0 的设备,都会有一个与之关联的队列规则,按照队列规则,调用dev->hard_start_xmit 1.1 static inline void qdisc_run(struct net_device *dev) { //设备传输队列没有被关闭,即__LINK_STATE_XOFF没有被设置 //结合规则队列完成传输 while (!netif_queue_stopped(dev) && qdisc_restart(dev) < 0); } // 结合设备关联的队列规则,完成数据传输 // 调用路径:qdisc_run->qdisc_restart // 返回值: =0 - queue is empty. // >0 - queue is not empty, but throttled. // <0 - queue is not empty. Device is throttled, if dev->tbusy != 0. // 函数流程: // 1.使用队列规则出队skb // 2.对dev->xmit_lock加锁 // 3.检测死锁与冲突; // 3.1 死锁:锁已被占用,占用者为本cpu,释放skb,返回 // 3.2 冲突:锁被占用,非本cpu,重入队skb,重调度设备 // 4.设置锁的拥有者为本cpu // 5.对dev->queue_lock解锁 // 6.向ETH_P_ALL类型l3协议传递此skb // 7.通过驱动程序hard_start_xmit完成传输 // 8.对dev->queue_lock加锁 // 9.对dev->xmit_lock解锁 1.2 int qdisc_restart(struct net_device *dev) { //与设备相关的队列规则 struct Qdisc *q = dev->qdisc; struct sk_buff *skb; //从规则队列出队skb if ((skb = q->dequeue(q)) != NULL) { //驱动特性:NETIF_F_LLTX,表明驱动在被调用hard_start_xmit时不需要上锁 unsigned nolock = (dev->features & NETIF_F_LLTX); if (!nolock) {//需要上锁 if (!spin_trylock(&dev->xmit_lock)) {//锁已经被获取 collision: //死锁: // 锁被占用,但是拥有者为本cpu,将skb丢掉,直接返回-1 if (dev->xmit_lock_owner == smp_processor_id()) { kfree_skb(skb); return -1; } //冲突: // 将skb重新入队 goto requeue; } //获取锁,将锁的拥有者设置为本cpu dev->xmit_lock_owner = smp_processor_id(); } { spin_unlock(&dev->queue_lock); if (!netif_queue_stopped(dev)) {//设备可以进行传输 int ret; //netdev_nit表示ETH_P_ALL类型l3协议的个数 if (netdev_nit) dev_queue_xmit_nit(skb, dev); //由驱动程序完成传输 ret = dev->hard_start_xmit(skb, dev); if (ret == NETDEV_TX_OK) { if (!nolock) { dev->xmit_lock_owner = -1; spin_unlock(&dev->xmit_lock); } spin_lock(&dev->queue_lock); return -1; } if (ret == NETDEV_TX_LOCKED && nolock) { spin_lock(&dev->queue_lock); goto collision; } } if (!nolock) { dev->xmit_lock_owner = -1; spin_unlock(&dev->xmit_lock); } spin_lock(&dev->queue_lock); q = dev->qdisc; } requeue: //将skb重新入队 q->ops->requeue(skb, q); //调度设备 netif_schedule(dev); return 1; } //返回规则队列中剩余的skb个数 return q->q.qlen; }