diff options
Diffstat (limited to 'include/net/sch_generic.h')
| -rw-r--r-- | include/net/sch_generic.h | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index dad558bc06fa..3c8728aaab4e 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
| @@ -23,11 +23,17 @@ struct qdisc_rate_table { | |||
| 23 | }; | 23 | }; |
| 24 | 24 | ||
| 25 | enum qdisc_state_t { | 25 | enum qdisc_state_t { |
| 26 | __QDISC_STATE_RUNNING, | ||
| 27 | __QDISC_STATE_SCHED, | 26 | __QDISC_STATE_SCHED, |
| 28 | __QDISC_STATE_DEACTIVATED, | 27 | __QDISC_STATE_DEACTIVATED, |
| 29 | }; | 28 | }; |
| 30 | 29 | ||
| 30 | /* | ||
| 31 | * following bits are only changed while qdisc lock is held | ||
| 32 | */ | ||
| 33 | enum qdisc___state_t { | ||
| 34 | __QDISC___STATE_RUNNING, | ||
| 35 | }; | ||
| 36 | |||
| 31 | struct qdisc_size_table { | 37 | struct qdisc_size_table { |
| 32 | struct list_head list; | 38 | struct list_head list; |
| 33 | struct tc_sizespec szopts; | 39 | struct tc_sizespec szopts; |
| @@ -72,9 +78,27 @@ struct Qdisc { | |||
| 72 | unsigned long state; | 78 | unsigned long state; |
| 73 | struct sk_buff_head q; | 79 | struct sk_buff_head q; |
| 74 | struct gnet_stats_basic_packed bstats; | 80 | struct gnet_stats_basic_packed bstats; |
| 81 | unsigned long __state; | ||
| 75 | struct gnet_stats_queue qstats; | 82 | struct gnet_stats_queue qstats; |
| 83 | struct rcu_head rcu_head; | ||
| 84 | spinlock_t busylock; | ||
| 76 | }; | 85 | }; |
| 77 | 86 | ||
| 87 | static inline bool qdisc_is_running(struct Qdisc *qdisc) | ||
| 88 | { | ||
| 89 | return test_bit(__QDISC___STATE_RUNNING, &qdisc->__state); | ||
| 90 | } | ||
| 91 | |||
| 92 | static inline bool qdisc_run_begin(struct Qdisc *qdisc) | ||
| 93 | { | ||
| 94 | return !__test_and_set_bit(__QDISC___STATE_RUNNING, &qdisc->__state); | ||
| 95 | } | ||
| 96 | |||
| 97 | static inline void qdisc_run_end(struct Qdisc *qdisc) | ||
| 98 | { | ||
| 99 | __clear_bit(__QDISC___STATE_RUNNING, &qdisc->__state); | ||
| 100 | } | ||
| 101 | |||
| 78 | struct Qdisc_class_ops { | 102 | struct Qdisc_class_ops { |
| 79 | /* Child qdisc manipulation */ | 103 | /* Child qdisc manipulation */ |
| 80 | struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *); | 104 | struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *); |
| @@ -312,12 +336,24 @@ extern void qdisc_calculate_pkt_len(struct sk_buff *skb, | |||
| 312 | extern void tcf_destroy(struct tcf_proto *tp); | 336 | extern void tcf_destroy(struct tcf_proto *tp); |
| 313 | extern void tcf_destroy_chain(struct tcf_proto **fl); | 337 | extern void tcf_destroy_chain(struct tcf_proto **fl); |
| 314 | 338 | ||
| 315 | /* Reset all TX qdiscs of a device. */ | 339 | /* Reset all TX qdiscs greater then index of a device. */ |
| 340 | static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i) | ||
| 341 | { | ||
| 342 | struct Qdisc *qdisc; | ||
| 343 | |||
| 344 | for (; i < dev->num_tx_queues; i++) { | ||
| 345 | qdisc = netdev_get_tx_queue(dev, i)->qdisc; | ||
| 346 | if (qdisc) { | ||
| 347 | spin_lock_bh(qdisc_lock(qdisc)); | ||
| 348 | qdisc_reset(qdisc); | ||
| 349 | spin_unlock_bh(qdisc_lock(qdisc)); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 316 | static inline void qdisc_reset_all_tx(struct net_device *dev) | 354 | static inline void qdisc_reset_all_tx(struct net_device *dev) |
| 317 | { | 355 | { |
| 318 | unsigned int i; | 356 | qdisc_reset_all_tx_gt(dev, 0); |
| 319 | for (i = 0; i < dev->num_tx_queues; i++) | ||
| 320 | qdisc_reset(netdev_get_tx_queue(dev, i)->qdisc); | ||
| 321 | } | 357 | } |
| 322 | 358 | ||
| 323 | /* Are all TX queues of the device empty? */ | 359 | /* Are all TX queues of the device empty? */ |
| @@ -427,6 +463,25 @@ static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) | |||
| 427 | return __qdisc_dequeue_head(sch, &sch->q); | 463 | return __qdisc_dequeue_head(sch, &sch->q); |
| 428 | } | 464 | } |
| 429 | 465 | ||
| 466 | static inline unsigned int __qdisc_queue_drop_head(struct Qdisc *sch, | ||
| 467 | struct sk_buff_head *list) | ||
| 468 | { | ||
| 469 | struct sk_buff *skb = __qdisc_dequeue_head(sch, list); | ||
| 470 | |||
| 471 | if (likely(skb != NULL)) { | ||
| 472 | unsigned int len = qdisc_pkt_len(skb); | ||
| 473 | kfree_skb(skb); | ||
| 474 | return len; | ||
| 475 | } | ||
| 476 | |||
| 477 | return 0; | ||
| 478 | } | ||
| 479 | |||
| 480 | static inline unsigned int qdisc_queue_drop_head(struct Qdisc *sch) | ||
| 481 | { | ||
| 482 | return __qdisc_queue_drop_head(sch, &sch->q); | ||
| 483 | } | ||
| 484 | |||
| 430 | static inline struct sk_buff *__qdisc_dequeue_tail(struct Qdisc *sch, | 485 | static inline struct sk_buff *__qdisc_dequeue_tail(struct Qdisc *sch, |
| 431 | struct sk_buff_head *list) | 486 | struct sk_buff_head *list) |
| 432 | { | 487 | { |
| @@ -551,9 +606,16 @@ static inline u32 qdisc_l2t(struct qdisc_rate_table* rtab, unsigned int pktlen) | |||
| 551 | } | 606 | } |
| 552 | 607 | ||
| 553 | #ifdef CONFIG_NET_CLS_ACT | 608 | #ifdef CONFIG_NET_CLS_ACT |
| 554 | static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask) | 609 | static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask, |
| 610 | int action) | ||
| 555 | { | 611 | { |
| 556 | struct sk_buff *n = skb_clone(skb, gfp_mask); | 612 | struct sk_buff *n; |
| 613 | |||
| 614 | if ((action == TC_ACT_STOLEN || action == TC_ACT_QUEUED) && | ||
| 615 | !skb_shared(skb)) | ||
| 616 | n = skb_get(skb); | ||
| 617 | else | ||
| 618 | n = skb_clone(skb, gfp_mask); | ||
| 557 | 619 | ||
| 558 | if (n) { | 620 | if (n) { |
| 559 | n->tc_verd = SET_TC_VERD(n->tc_verd, 0); | 621 | n->tc_verd = SET_TC_VERD(n->tc_verd, 0); |
