// 调用路径:
// 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;
}