- 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;
- }