- static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
-
struct net_device *dev,
-
struct netdev_queue *txq)
-
{
-
spinlock_t *root_lock = qdisc_lock(q);
-
bool contended = qdisc_is_running(q);
-
int rc;
-
-
/*
-
* Heuristic to force contended enqueues to serialize on a
-
* separate lock before trying to get qdisc main lock.
-
* This permits __QDISC_STATE_RUNNING owner to get the lock more often
-
* and dequeue packets faster.
-
*/
-
if (unlikely(contended))
-
spin_lock(&q->busylock);
-
-
spin_lock(root_lock);
-
if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {
- /* 该quque的状态为非活动的,drop该数据包 */
-
kfree_skb(skb);
-
rc = NET_XMIT_DROP;
-
} else if ((q->flags & TCQ_F_CAN_BYPASS) && !qdisc_qlen(q) &&
-
qdisc_run_begin(q)) {
/*
这部分代码,从注释上看,似乎选中的queue是一个保留的工作queue。
想来也是非正常路径,暂时保留不看。
*/
-
/*
-
* This is a work-conserving queue; there are no old skbs
-
* waiting to be sent out; and the qdisc is not running -
-
* xmit the skb directly.
-
*/
-
if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE))
-
skb_dst_force(skb);
-
__qdisc_update_bstats(q, skb->len);
-
if (sch_direct_xmit(skb, q, dev, txq, root_lock)) {
-
if (unlikely(contended)) {
-
spin_unlock(&q->busylock);
-
contended = false;
-
}
-
__qdisc_run(q);
-
} else
-
qdisc_run_end(q);
-
-
rc = NET_XMIT_SUCCESS;
-
} else {
/* 正常路径 */
/* 确保dst被引用,防止被其他模块释放 */
-
skb_dst_force(skb);
- /* 将数据包加入到queue中 */
-
rc = qdisc_enqueue_root(skb, q);
/* 如果queue不是运行状态,将其置为运行状态 */
-
if (qdisc_run_begin(q)) {
-
if (unlikely(contended)) {
-
spin_unlock(&q->busylock);
-
contended = false;
-
}
-
__qdisc_run(q);
-
}
-
}
-
spin_unlock(root_lock);
-
if (unlikely(contended))
-
spin_unlock(&q->busylock);
-
return rc;
-
}