static int mq_dump(struct Qdisc *sch, struct sk_buff *skb) { struct net_device *dev = qdisc_dev(sch); struct Qdisc *qdisc; unsigned int ntx; sch->q.qlen = 0; memset(&sch->bstats, 0, sizeof(sch->bstats)); memset(&sch->qstats, 0, sizeof(sch->qstats)); for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { qdisc = netdev_get_tx_queue(dev, ntx)->qdisc_sleeping; spin_lock_bh(qdisc_lock(qdisc)); sch->q.qlen += qdisc->q.qlen; sch->bstats.bytes += qdisc->bstats.bytes; sch->bstats.packets += qdisc->bstats.packets; sch->qstats.qlen += qdisc->qstats.qlen; sch->qstats.backlog += qdisc->qstats.backlog; sch->qstats.drops += qdisc->qstats.drops; sch->qstats.requeues += qdisc->qstats.requeues; sch->qstats.overlimits += qdisc->qstats.overlimits; spin_unlock_bh(qdisc_lock(qdisc)); } return 0; }
/** * the caller needs to hold netdev_get_tx_queue(local->mdev, X)->lock */ void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local, struct sta_info *sta, u16 tid, u8 requeue) { int agg_queue = sta->tid_to_tx_q[tid]; struct ieee80211_hw *hw = &local->hw; /* return the qdisc to the pool */ clear_bit(agg_queue, local->queue_pool); sta->tid_to_tx_q[tid] = ieee80211_num_queues(hw); if (requeue) { ieee80211_requeue(local, agg_queue); } else { struct netdev_queue *txq; spinlock_t *root_lock; struct Qdisc *q; txq = netdev_get_tx_queue(local->mdev, agg_queue); q = rcu_dereference(txq->qdisc); root_lock = qdisc_lock(q); spin_lock_bh(root_lock); qdisc_reset(q); spin_unlock_bh(root_lock); } }
static bool some_qdisc_is_busy(struct net_device *dev) { unsigned int i; for (i = 0; i < dev->num_tx_queues; i++) { struct netdev_queue *dev_queue; spinlock_t *root_lock; struct Qdisc *q; int val; dev_queue = netdev_get_tx_queue(dev, i); q = dev_queue->qdisc_sleeping; root_lock = qdisc_lock(q); spin_lock_bh(root_lock); val = (test_bit(__QDISC_STATE_RUNNING, &q->state) || test_bit(__QDISC_STATE_SCHED, &q->state)); spin_unlock_bh(root_lock); if (val) return true; } return false; }
static inline struct sk_buff *__skb_dequeue_bad_txq(struct Qdisc *q) { const struct netdev_queue *txq = q->dev_queue; spinlock_t *lock = NULL; struct sk_buff *skb; if (q->flags & TCQ_F_NOLOCK) { lock = qdisc_lock(q); spin_lock(lock); } skb = skb_peek(&q->skb_bad_txq); if (skb) { /* check the reason of requeuing without tx lock first */ txq = skb_get_tx_queue(txq->dev, skb); if (!netif_xmit_frozen_or_stopped(txq)) { skb = __skb_dequeue(&q->skb_bad_txq); if (qdisc_is_percpu_stats(q)) { qdisc_qstats_cpu_backlog_dec(q, skb); qdisc_qstats_cpu_qlen_dec(q); } else { qdisc_qstats_backlog_dec(q, skb); q->q.qlen--; } } else { skb = NULL; } } if (lock) spin_unlock(lock); return skb; }
/* * NOTE: Called under qdisc_lock(q) with locally disabled BH. * * __QDISC_STATE_RUNNING guarantees only one CPU can process * this qdisc at a time. qdisc_lock(q) serializes queue accesses for * this queue. * * netif_tx_lock serializes accesses to device driver. * * qdisc_lock(q) and netif_tx_lock are mutually exclusive, * if one is grabbed, another must be free. * * Note, that this procedure can be called by a watchdog timer * * Returns to the caller: * 0 - queue is empty or throttled. * >0 - queue is not empty. * */ static inline int qdisc_restart(struct Qdisc *q) { struct netdev_queue *txq; int ret = NETDEV_TX_BUSY; struct net_device *dev; spinlock_t *root_lock; struct sk_buff *skb; /* Dequeue packet */ //从队列上取下一个要发送的数据包. if (unlikely((skb = dequeue_skb(q)) == NULL)) return 0; root_lock = qdisc_lock(q); /* And release qdisc */ spin_unlock(root_lock); dev = qdisc_dev(q); txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); HARD_TX_LOCK(dev, txq, smp_processor_id()); //调用dev_hard_start_xmit吧数据包通过实际的链路发送出去... if (!netif_tx_queue_stopped(txq) && !netif_tx_queue_frozen(txq)) ret = dev_hard_start_xmit(skb, dev, txq); HARD_TX_UNLOCK(dev, txq); spin_lock(root_lock); switch (ret) { case NETDEV_TX_OK: /* Driver sent out skb successfully */ ret = qdisc_qlen(q); break; case NETDEV_TX_LOCKED: /* Driver try lock failed */ ret = handle_dev_cpu_collision(skb, txq, q); break; default: /* Driver returned NETDEV_TX_BUSY - requeue skb */ if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit())) printk(KERN_WARNING "BUG %s code %d qlen %d\n", dev->name, ret, q->q.qlen); ret = dev_requeue_skb(skb, q); break; } if (ret && (netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq))) ret = 0; return ret; }
static void dev_deactivate_queue(struct net_device *dev, struct netdev_queue *dev_queue, void *_qdisc_default) { struct Qdisc *qdisc_default = _qdisc_default; struct Qdisc *qdisc; qdisc = dev_queue->qdisc; if (qdisc) { spin_lock_bh(qdisc_lock(qdisc)); if (!(qdisc->flags & TCQ_F_BUILTIN)) set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state); rcu_assign_pointer(dev_queue->qdisc, qdisc_default); qdisc_reset(qdisc); spin_unlock_bh(qdisc_lock(qdisc)); } }
static inline void qdisc_enqueue_skb_bad_txq(struct Qdisc *q, struct sk_buff *skb) { spinlock_t *lock = NULL; if (q->flags & TCQ_F_NOLOCK) { lock = qdisc_lock(q); spin_lock(lock); } __skb_queue_tail(&q->skb_bad_txq, skb); if (lock) spin_unlock(lock); }
static void sfq_perturbation(unsigned long arg) { struct Qdisc *sch = (struct Qdisc *)arg; struct sfq_sched_data *q = qdisc_priv(sch); spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch)); spin_lock(root_lock); q->perturbation = prandom_u32(); if (!q->filter_list && q->tail) sfq_rehash(sch); spin_unlock(root_lock); if (q->perturb_period) mod_timer(&q->perturb_timer, jiffies + q->perturb_period); }
static void pie_timer(unsigned long arg) { struct Qdisc *sch = (struct Qdisc *)arg; struct pie_sched_data *q = qdisc_priv(sch); spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch)); spin_lock(root_lock); calculate_probability(sch, &q->params, &q->vars); /* reset the timer to fire after 'tupdate'. tupdate is in jiffies. */ if (q->params.tupdate) mod_timer(&q->adapt_timer, jiffies + q->params.tupdate); spin_unlock(root_lock); }
/* * NOTE: Called under qdisc_lock(q) with locally disabled BH. * * __QDISC_STATE_RUNNING guarantees only one CPU can process * this qdisc at a time. qdisc_lock(q) serializes queue accesses for * this queue. * * netif_tx_lock serializes accesses to device driver. * * qdisc_lock(q) and netif_tx_lock are mutually exclusive, * if one is grabbed, another must be free. * * Note, that this procedure can be called by a watchdog timer * * Returns to the caller: * 0 - queue is empty or throttled. * >0 - queue is not empty. * */ static inline int qdisc_restart(struct Qdisc *q) { struct netdev_queue *txq; struct net_device *dev; spinlock_t *root_lock; struct sk_buff *skb; /* Dequeue packet */ skb = dequeue_skb(q); if (unlikely(!skb)) return 0; WARN_ON_ONCE(skb_dst_is_noref(skb)); root_lock = qdisc_lock(q); dev = qdisc_dev(q); txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); return sch_direct_xmit(skb, q, dev, txq, root_lock); }
/* * NOTE: Called under qdisc_lock(q) with locally disabled BH. * * __QDISC___STATE_RUNNING guarantees only one CPU can process * this qdisc at a time. qdisc_lock(q) serializes queue accesses for * this queue. * * netif_tx_lock serializes accesses to device driver. * * qdisc_lock(q) and netif_tx_lock are mutually exclusive, * if one is grabbed, another must be free. * * Note, that this procedure can be called by a watchdog timer * * Returns to the caller: * 0 - queue is empty or throttled. * >0 - queue is not empty. * */ static inline int qdisc_restart(struct Qdisc *q, int *packets) { struct netdev_queue *txq; struct net_device *dev; spinlock_t *root_lock; struct sk_buff *skb; bool validate; /* Dequeue packet */ skb = dequeue_skb(q, &validate, packets); if (unlikely(!skb)) return 0; root_lock = qdisc_lock(q); dev = qdisc_dev(q); txq = skb_get_tx_queue(dev, skb); return sch_direct_xmit(skb, q, dev, txq, root_lock, validate); }
static inline int dev_requeue_skb_locked(struct sk_buff *skb, struct Qdisc *q) { spinlock_t *lock = qdisc_lock(q); spin_lock(lock); while (skb) { struct sk_buff *next = skb->next; __skb_queue_tail(&q->gso_skb, skb); qdisc_qstats_cpu_requeues_inc(q); qdisc_qstats_cpu_backlog_inc(q, skb); qdisc_qstats_cpu_qlen_inc(q); skb = next; } spin_unlock(lock); __netif_schedule(q); return 0; }
/* Attach toplevel qdisc to device queue. */ struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, struct Qdisc *qdisc) { struct Qdisc *oqdisc = dev_queue->qdisc_sleeping; spinlock_t *root_lock; root_lock = qdisc_lock(oqdisc); spin_lock_bh(root_lock); /* Prune old scheduler */ if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) qdisc_reset(oqdisc); /* ... and graft new one */ if (qdisc == NULL) qdisc = &noop_qdisc; dev_queue->qdisc_sleeping = qdisc; rcu_assign_pointer(dev_queue->qdisc, &noop_qdisc); spin_unlock_bh(root_lock); return oqdisc; }
static inline void qdisc_enqueue_skb_bad_txq(struct Qdisc *q, struct sk_buff *skb) { spinlock_t *lock = NULL; if (q->flags & TCQ_F_NOLOCK) { lock = qdisc_lock(q); spin_lock(lock); } __skb_queue_tail(&q->skb_bad_txq, skb); if (qdisc_is_percpu_stats(q)) { qdisc_qstats_cpu_backlog_inc(q, skb); qdisc_qstats_cpu_qlen_inc(q); } else { qdisc_qstats_backlog_inc(q, skb); q->q.qlen++; } if (lock) spin_unlock(lock); }
/* * NOTE: Called under qdisc_lock(q) with locally disabled BH. * * __QDISC_STATE_RUNNING guarantees only one CPU can process * this qdisc at a time. qdisc_lock(q) serializes queue accesses for * this queue. * * netif_tx_lock serializes accesses to device driver. * * qdisc_lock(q) and netif_tx_lock are mutually exclusive, * if one is grabbed, another must be free. * * Note, that this procedure can be called by a watchdog timer * * Returns to the caller: * 0 - queue is empty or throttled. * >0 - queue is not empty. * */ static inline int qdisc_restart(struct Qdisc *q) { struct netdev_queue *txq; struct net_device *dev; spinlock_t *root_lock; struct sk_buff *skb; int ret; struct ve_struct *old_ve; /* Dequeue packet */ skb = dequeue_skb(q); if (unlikely(!skb)) return 0; old_ve = set_exec_env(skb->owner_env); root_lock = qdisc_lock(q); dev = qdisc_dev(q); txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); ret = sch_direct_xmit(skb, q, dev, txq, root_lock); (void)set_exec_env(old_ve); return ret; }
static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num) { struct net_device *dev; struct sk_buff *skb_orig, *skb, *skb_shared; struct Qdisc *q; struct netdev_queue *txq; spinlock_t *root_lock; int users, index; int retval = -EINVAL; unsigned int orig_queue_index; index = entry->skb->imq_flags & IMQ_F_IFMASK; if (unlikely(index > numdevs - 1)) { if (net_ratelimit()) printk(KERN_WARNING "IMQ: invalid device specified, highest is %u\n", numdevs - 1); retval = -EINVAL; goto out; } /* check for imq device by index from cache */ dev = imq_devs_cache[index]; if (unlikely(!dev)) { char buf[8]; /* get device by name and cache result */ snprintf(buf, sizeof(buf), "imq%d", index); dev = dev_get_by_name(&init_net, buf); if (unlikely(!dev)) { /* not found ?!*/ BUG(); retval = -ENODEV; goto out; } imq_devs_cache[index] = dev; dev_put(dev); } if (unlikely(!(dev->flags & IFF_UP))) { entry->skb->imq_flags = 0; nf_reinject(entry, NF_ACCEPT); retval = 0; goto out; } dev->last_rx = jiffies; skb = entry->skb; skb_orig = NULL; /* skb has owner? => make clone */ if (unlikely(skb->destructor)) { skb_orig = skb; skb = skb_clone(skb, GFP_ATOMIC); if (unlikely(!skb)) { retval = -ENOMEM; goto out; } entry->skb = skb; } skb->nf_queue_entry = entry; dev->stats.rx_bytes += skb->len; dev->stats.rx_packets++; if (!skb->dev) { /* skb->dev == NULL causes problems, try the find cause. */ if (net_ratelimit()) { dev_warn(&dev->dev, "received packet with skb->dev == NULL\n"); dump_stack(); } skb->dev = dev; } /* Disables softirqs for lock below */ rcu_read_lock_bh(); /* Multi-queue selection */ orig_queue_index = skb_get_queue_mapping(skb); txq = imq_select_queue(dev, skb); q = rcu_dereference(txq->qdisc); if (unlikely(!q->enqueue)) goto packet_not_eaten_by_imq_dev; root_lock = qdisc_lock(q); spin_lock(root_lock); users = atomic_read(&skb->users); skb_shared = skb_get(skb); /* increase reference count by one */ skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will overwrite it */ qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */ if (likely(atomic_read(&skb_shared->users) == users + 1)) { kfree_skb(skb_shared); /* decrease reference count by one */ skb->destructor = &imq_skb_destructor; /* cloned? */ if (unlikely(skb_orig)) kfree_skb(skb_orig); /* free original */ spin_unlock(root_lock); rcu_read_unlock_bh(); /* schedule qdisc dequeue */ __netif_schedule(q); retval = 0; goto out; } else { skb_restore_cb(skb_shared); /* restore skb->cb */ skb->nf_queue_entry = NULL; /* qdisc dropped packet and decreased skb reference count of * skb, so we don't really want to and try refree as that would * actually destroy the skb. */ spin_unlock(root_lock); goto packet_not_eaten_by_imq_dev; } packet_not_eaten_by_imq_dev: skb_set_queue_mapping(skb, orig_queue_index); rcu_read_unlock_bh(); /* cloned? restore original */ if (unlikely(skb_orig)) { kfree_skb(skb); entry->skb = skb_orig; } retval = -1; out: return retval; }
/* * NOTE: Called under qdisc_lock(q) with locally disabled BH. * * __QDISC_STATE_RUNNING guarantees only one CPU can process * this qdisc at a time. qdisc_lock(q) serializes queue accesses for * this queue. * * netif_tx_lock serializes accesses to device driver. * * qdisc_lock(q) and netif_tx_lock are mutually exclusive, * if one is grabbed, another must be free. * * Note, that this procedure can be called by a watchdog timer * * Returns to the caller: * 0 - queue is empty or throttled. * >0 - queue is not empty. * */ static inline int qdisc_restart(struct Qdisc *q) { struct netdev_queue *txq; int ret = NETDEV_TX_BUSY; struct net_device *dev; spinlock_t *root_lock; struct sk_buff *skb; /* Dequeue packet */ if (unlikely((skb = dequeue_skb(q)) == NULL)) return 0; root_lock = qdisc_lock(q); /* And release qdisc */ spin_unlock(root_lock); dev = qdisc_dev(q); txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); HARD_TX_LOCK(dev, txq, smp_processor_id()); if (!netif_tx_queue_stopped(txq) && !netif_tx_queue_frozen(txq)) ret = dev_hard_start_xmit(skb, dev, txq); HARD_TX_UNLOCK(dev, txq); spin_lock(root_lock); switch (ret) { case NETDEV_TX_OK: /* Driver sent out skb successfully */ ret = qdisc_qlen(q); break; case NETDEV_TX_LOCKED: /* Driver try lock failed */ ret = handle_dev_cpu_collision(skb, txq, q); break; default: /* Driver returned NETDEV_TX_BUSY - requeue skb */ if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit())) printk(KERN_WARNING "BUG %s code %d qlen %d\n", dev->name, ret, q->q.qlen); //[ENODEV] No such device. An attempt was made to apply an inappropriate function to a device if (ret == -ENODEV) { printk(KERN_EMERG "%s: STOP QUEUE. Reason = %d (-ENODEV) (net\\sched\\sch_generic.c 170)\n", dev->name, ret); if (strnicmp((char *)&dev->name, "eth0", 4) == 0) { //Stop upper layers calling the device hard_start_xmit routine. //Used for flow control when transmit resources are unavailable. ret = dev_requeue_skb(skb, q); netif_stop_queue(dev); } } else ret = dev_requeue_skb(skb, q); break; } if (ret && (netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq))) ret = 0; return ret; }
/* Note that dequeue_skb can possibly return a SKB list (via skb->next). * A requeued skb (via q->gso_skb) can also be a SKB list. */ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, int *packets) { const struct netdev_queue *txq = q->dev_queue; struct sk_buff *skb = NULL; *packets = 1; if (unlikely(!skb_queue_empty(&q->gso_skb))) { spinlock_t *lock = NULL; if (q->flags & TCQ_F_NOLOCK) { lock = qdisc_lock(q); spin_lock(lock); } skb = skb_peek(&q->gso_skb); /* skb may be null if another cpu pulls gso_skb off in between * empty check and lock. */ if (!skb) { if (lock) spin_unlock(lock); goto validate; } /* skb in gso_skb were already validated */ *validate = false; if (xfrm_offload(skb)) *validate = true; /* check the reason of requeuing without tx lock first */ txq = skb_get_tx_queue(txq->dev, skb); if (!netif_xmit_frozen_or_stopped(txq)) { skb = __skb_dequeue(&q->gso_skb); if (qdisc_is_percpu_stats(q)) { qdisc_qstats_cpu_backlog_dec(q, skb); qdisc_qstats_cpu_qlen_dec(q); } else { qdisc_qstats_backlog_dec(q, skb); q->q.qlen--; } } else { skb = NULL; } if (lock) spin_unlock(lock); goto trace; } validate: *validate = true; if ((q->flags & TCQ_F_ONETXQUEUE) && netif_xmit_frozen_or_stopped(txq)) return skb; skb = qdisc_dequeue_skb_bad_txq(q); if (unlikely(skb)) goto bulk; skb = q->dequeue(q); if (skb) { bulk: if (qdisc_may_bulk(q)) try_bulk_dequeue_skb(q, skb, txq, packets); else try_bulk_dequeue_skb_slow(q, skb, packets); } trace: trace_qdisc_dequeue(q, txq, *packets, skb); return skb; }