網絡子係統22_隊列規則傳輸接口
// 調用路徑:
// 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;
}
最後更新:2017-04-03 15:22:11