diff options
Diffstat (limited to 'include/net/sch_generic.h')
-rw-r--r-- | include/net/sch_generic.h | 150 |
1 files changed, 125 insertions, 25 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index becf86aa4ac6..e2ab13687fb9 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -71,6 +71,7 @@ struct Qdisc { | |||
71 | * qdisc_tree_decrease_qlen() should stop. | 71 | * qdisc_tree_decrease_qlen() should stop. |
72 | */ | 72 | */ |
73 | #define TCQ_F_INVISIBLE 0x80 /* invisible by default in dump */ | 73 | #define TCQ_F_INVISIBLE 0x80 /* invisible by default in dump */ |
74 | #define TCQ_F_NOLOCK 0x100 /* qdisc does not require locking */ | ||
74 | #define TCQ_F_OFFLOADED 0x200 /* qdisc is offloaded to HW */ | 75 | #define TCQ_F_OFFLOADED 0x200 /* qdisc is offloaded to HW */ |
75 | u32 limit; | 76 | u32 limit; |
76 | const struct Qdisc_ops *ops; | 77 | const struct Qdisc_ops *ops; |
@@ -88,14 +89,14 @@ struct Qdisc { | |||
88 | /* | 89 | /* |
89 | * For performance sake on SMP, we put highly modified fields at the end | 90 | * For performance sake on SMP, we put highly modified fields at the end |
90 | */ | 91 | */ |
91 | struct sk_buff *gso_skb ____cacheline_aligned_in_smp; | 92 | struct sk_buff_head gso_skb ____cacheline_aligned_in_smp; |
92 | struct qdisc_skb_head q; | 93 | struct qdisc_skb_head q; |
93 | struct gnet_stats_basic_packed bstats; | 94 | struct gnet_stats_basic_packed bstats; |
94 | seqcount_t running; | 95 | seqcount_t running; |
95 | struct gnet_stats_queue qstats; | 96 | struct gnet_stats_queue qstats; |
96 | unsigned long state; | 97 | unsigned long state; |
97 | struct Qdisc *next_sched; | 98 | struct Qdisc *next_sched; |
98 | struct sk_buff *skb_bad_txq; | 99 | struct sk_buff_head skb_bad_txq; |
99 | int padded; | 100 | int padded; |
100 | refcount_t refcnt; | 101 | refcount_t refcnt; |
101 | 102 | ||
@@ -150,19 +151,23 @@ struct Qdisc_class_ops { | |||
150 | /* Child qdisc manipulation */ | 151 | /* Child qdisc manipulation */ |
151 | struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *); | 152 | struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *); |
152 | int (*graft)(struct Qdisc *, unsigned long cl, | 153 | int (*graft)(struct Qdisc *, unsigned long cl, |
153 | struct Qdisc *, struct Qdisc **); | 154 | struct Qdisc *, struct Qdisc **, |
155 | struct netlink_ext_ack *extack); | ||
154 | struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl); | 156 | struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl); |
155 | void (*qlen_notify)(struct Qdisc *, unsigned long); | 157 | void (*qlen_notify)(struct Qdisc *, unsigned long); |
156 | 158 | ||
157 | /* Class manipulation routines */ | 159 | /* Class manipulation routines */ |
158 | unsigned long (*find)(struct Qdisc *, u32 classid); | 160 | unsigned long (*find)(struct Qdisc *, u32 classid); |
159 | int (*change)(struct Qdisc *, u32, u32, | 161 | int (*change)(struct Qdisc *, u32, u32, |
160 | struct nlattr **, unsigned long *); | 162 | struct nlattr **, unsigned long *, |
163 | struct netlink_ext_ack *); | ||
161 | int (*delete)(struct Qdisc *, unsigned long); | 164 | int (*delete)(struct Qdisc *, unsigned long); |
162 | void (*walk)(struct Qdisc *, struct qdisc_walker * arg); | 165 | void (*walk)(struct Qdisc *, struct qdisc_walker * arg); |
163 | 166 | ||
164 | /* Filter manipulation */ | 167 | /* Filter manipulation */ |
165 | struct tcf_block * (*tcf_block)(struct Qdisc *, unsigned long); | 168 | struct tcf_block * (*tcf_block)(struct Qdisc *sch, |
169 | unsigned long arg, | ||
170 | struct netlink_ext_ack *extack); | ||
166 | unsigned long (*bind_tcf)(struct Qdisc *, unsigned long, | 171 | unsigned long (*bind_tcf)(struct Qdisc *, unsigned long, |
167 | u32 classid); | 172 | u32 classid); |
168 | void (*unbind_tcf)(struct Qdisc *, unsigned long); | 173 | void (*unbind_tcf)(struct Qdisc *, unsigned long); |
@@ -187,15 +192,26 @@ struct Qdisc_ops { | |||
187 | struct sk_buff * (*dequeue)(struct Qdisc *); | 192 | struct sk_buff * (*dequeue)(struct Qdisc *); |
188 | struct sk_buff * (*peek)(struct Qdisc *); | 193 | struct sk_buff * (*peek)(struct Qdisc *); |
189 | 194 | ||
190 | int (*init)(struct Qdisc *, struct nlattr *arg); | 195 | int (*init)(struct Qdisc *sch, struct nlattr *arg, |
196 | struct netlink_ext_ack *extack); | ||
191 | void (*reset)(struct Qdisc *); | 197 | void (*reset)(struct Qdisc *); |
192 | void (*destroy)(struct Qdisc *); | 198 | void (*destroy)(struct Qdisc *); |
193 | int (*change)(struct Qdisc *, struct nlattr *arg); | 199 | int (*change)(struct Qdisc *sch, |
194 | void (*attach)(struct Qdisc *); | 200 | struct nlattr *arg, |
201 | struct netlink_ext_ack *extack); | ||
202 | void (*attach)(struct Qdisc *sch); | ||
203 | int (*change_tx_queue_len)(struct Qdisc *, unsigned int); | ||
195 | 204 | ||
196 | int (*dump)(struct Qdisc *, struct sk_buff *); | 205 | int (*dump)(struct Qdisc *, struct sk_buff *); |
197 | int (*dump_stats)(struct Qdisc *, struct gnet_dump *); | 206 | int (*dump_stats)(struct Qdisc *, struct gnet_dump *); |
198 | 207 | ||
208 | void (*ingress_block_set)(struct Qdisc *sch, | ||
209 | u32 block_index); | ||
210 | void (*egress_block_set)(struct Qdisc *sch, | ||
211 | u32 block_index); | ||
212 | u32 (*ingress_block_get)(struct Qdisc *sch); | ||
213 | u32 (*egress_block_get)(struct Qdisc *sch); | ||
214 | |||
199 | struct module *owner; | 215 | struct module *owner; |
200 | }; | 216 | }; |
201 | 217 | ||
@@ -218,14 +234,18 @@ struct tcf_proto_ops { | |||
218 | const struct tcf_proto *, | 234 | const struct tcf_proto *, |
219 | struct tcf_result *); | 235 | struct tcf_result *); |
220 | int (*init)(struct tcf_proto*); | 236 | int (*init)(struct tcf_proto*); |
221 | void (*destroy)(struct tcf_proto*); | 237 | void (*destroy)(struct tcf_proto *tp, |
238 | struct netlink_ext_ack *extack); | ||
222 | 239 | ||
223 | void* (*get)(struct tcf_proto*, u32 handle); | 240 | void* (*get)(struct tcf_proto*, u32 handle); |
224 | int (*change)(struct net *net, struct sk_buff *, | 241 | int (*change)(struct net *net, struct sk_buff *, |
225 | struct tcf_proto*, unsigned long, | 242 | struct tcf_proto*, unsigned long, |
226 | u32 handle, struct nlattr **, | 243 | u32 handle, struct nlattr **, |
227 | void **, bool); | 244 | void **, bool, |
228 | int (*delete)(struct tcf_proto*, void *, bool*); | 245 | struct netlink_ext_ack *); |
246 | int (*delete)(struct tcf_proto *tp, void *arg, | ||
247 | bool *last, | ||
248 | struct netlink_ext_ack *); | ||
229 | void (*walk)(struct tcf_proto*, struct tcf_walker *arg); | 249 | void (*walk)(struct tcf_proto*, struct tcf_walker *arg); |
230 | void (*bind_class)(void *, u32, unsigned long); | 250 | void (*bind_class)(void *, u32, unsigned long); |
231 | 251 | ||
@@ -247,8 +267,6 @@ struct tcf_proto { | |||
247 | 267 | ||
248 | /* All the rest */ | 268 | /* All the rest */ |
249 | u32 prio; | 269 | u32 prio; |
250 | u32 classid; | ||
251 | struct Qdisc *q; | ||
252 | void *data; | 270 | void *data; |
253 | const struct tcf_proto_ops *ops; | 271 | const struct tcf_proto_ops *ops; |
254 | struct tcf_chain *chain; | 272 | struct tcf_chain *chain; |
@@ -267,8 +285,7 @@ typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv); | |||
267 | 285 | ||
268 | struct tcf_chain { | 286 | struct tcf_chain { |
269 | struct tcf_proto __rcu *filter_chain; | 287 | struct tcf_proto __rcu *filter_chain; |
270 | tcf_chain_head_change_t *chain_head_change; | 288 | struct list_head filter_chain_list; |
271 | void *chain_head_change_priv; | ||
272 | struct list_head list; | 289 | struct list_head list; |
273 | struct tcf_block *block; | 290 | struct tcf_block *block; |
274 | u32 index; /* chain index */ | 291 | u32 index; /* chain index */ |
@@ -277,12 +294,33 @@ struct tcf_chain { | |||
277 | 294 | ||
278 | struct tcf_block { | 295 | struct tcf_block { |
279 | struct list_head chain_list; | 296 | struct list_head chain_list; |
297 | u32 index; /* block index for shared blocks */ | ||
298 | unsigned int refcnt; | ||
280 | struct net *net; | 299 | struct net *net; |
281 | struct Qdisc *q; | 300 | struct Qdisc *q; |
282 | struct list_head cb_list; | 301 | struct list_head cb_list; |
283 | struct work_struct work; | 302 | struct list_head owner_list; |
303 | bool keep_dst; | ||
304 | unsigned int offloadcnt; /* Number of oddloaded filters */ | ||
305 | unsigned int nooffloaddevcnt; /* Number of devs unable to do offload */ | ||
284 | }; | 306 | }; |
285 | 307 | ||
308 | static inline void tcf_block_offload_inc(struct tcf_block *block, u32 *flags) | ||
309 | { | ||
310 | if (*flags & TCA_CLS_FLAGS_IN_HW) | ||
311 | return; | ||
312 | *flags |= TCA_CLS_FLAGS_IN_HW; | ||
313 | block->offloadcnt++; | ||
314 | } | ||
315 | |||
316 | static inline void tcf_block_offload_dec(struct tcf_block *block, u32 *flags) | ||
317 | { | ||
318 | if (!(*flags & TCA_CLS_FLAGS_IN_HW)) | ||
319 | return; | ||
320 | *flags &= ~TCA_CLS_FLAGS_IN_HW; | ||
321 | block->offloadcnt--; | ||
322 | } | ||
323 | |||
286 | static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) | 324 | static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) |
287 | { | 325 | { |
288 | struct qdisc_skb_cb *qcb; | 326 | struct qdisc_skb_cb *qcb; |
@@ -291,11 +329,31 @@ static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) | |||
291 | BUILD_BUG_ON(sizeof(qcb->data) < sz); | 329 | BUILD_BUG_ON(sizeof(qcb->data) < sz); |
292 | } | 330 | } |
293 | 331 | ||
332 | static inline int qdisc_qlen_cpu(const struct Qdisc *q) | ||
333 | { | ||
334 | return this_cpu_ptr(q->cpu_qstats)->qlen; | ||
335 | } | ||
336 | |||
294 | static inline int qdisc_qlen(const struct Qdisc *q) | 337 | static inline int qdisc_qlen(const struct Qdisc *q) |
295 | { | 338 | { |
296 | return q->q.qlen; | 339 | return q->q.qlen; |
297 | } | 340 | } |
298 | 341 | ||
342 | static inline int qdisc_qlen_sum(const struct Qdisc *q) | ||
343 | { | ||
344 | __u32 qlen = 0; | ||
345 | int i; | ||
346 | |||
347 | if (q->flags & TCQ_F_NOLOCK) { | ||
348 | for_each_possible_cpu(i) | ||
349 | qlen += per_cpu_ptr(q->cpu_qstats, i)->qlen; | ||
350 | } else { | ||
351 | qlen = q->q.qlen; | ||
352 | } | ||
353 | |||
354 | return qlen; | ||
355 | } | ||
356 | |||
299 | static inline struct qdisc_skb_cb *qdisc_skb_cb(const struct sk_buff *skb) | 357 | static inline struct qdisc_skb_cb *qdisc_skb_cb(const struct sk_buff *skb) |
300 | { | 358 | { |
301 | return (struct qdisc_skb_cb *)skb->cb; | 359 | return (struct qdisc_skb_cb *)skb->cb; |
@@ -432,6 +490,7 @@ void qdisc_class_hash_remove(struct Qdisc_class_hash *, | |||
432 | void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *); | 490 | void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *); |
433 | void qdisc_class_hash_destroy(struct Qdisc_class_hash *); | 491 | void qdisc_class_hash_destroy(struct Qdisc_class_hash *); |
434 | 492 | ||
493 | int dev_qdisc_change_tx_queue_len(struct net_device *dev); | ||
435 | void dev_init_scheduler(struct net_device *dev); | 494 | void dev_init_scheduler(struct net_device *dev); |
436 | void dev_shutdown(struct net_device *dev); | 495 | void dev_shutdown(struct net_device *dev); |
437 | void dev_activate(struct net_device *dev); | 496 | void dev_activate(struct net_device *dev); |
@@ -444,10 +503,12 @@ void qdisc_destroy(struct Qdisc *qdisc); | |||
444 | void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n, | 503 | void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n, |
445 | unsigned int len); | 504 | unsigned int len); |
446 | struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, | 505 | struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, |
447 | const struct Qdisc_ops *ops); | 506 | const struct Qdisc_ops *ops, |
507 | struct netlink_ext_ack *extack); | ||
448 | void qdisc_free(struct Qdisc *qdisc); | 508 | void qdisc_free(struct Qdisc *qdisc); |
449 | struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, | 509 | struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, |
450 | const struct Qdisc_ops *ops, u32 parentid); | 510 | const struct Qdisc_ops *ops, u32 parentid, |
511 | struct netlink_ext_ack *extack); | ||
451 | void __qdisc_calculate_pkt_len(struct sk_buff *skb, | 512 | void __qdisc_calculate_pkt_len(struct sk_buff *skb, |
452 | const struct qdisc_size_table *stab); | 513 | const struct qdisc_size_table *stab); |
453 | int skb_do_redirect(struct sk_buff *); | 514 | int skb_do_redirect(struct sk_buff *); |
@@ -633,12 +694,39 @@ static inline void qdisc_qstats_backlog_dec(struct Qdisc *sch, | |||
633 | sch->qstats.backlog -= qdisc_pkt_len(skb); | 694 | sch->qstats.backlog -= qdisc_pkt_len(skb); |
634 | } | 695 | } |
635 | 696 | ||
697 | static inline void qdisc_qstats_cpu_backlog_dec(struct Qdisc *sch, | ||
698 | const struct sk_buff *skb) | ||
699 | { | ||
700 | this_cpu_sub(sch->cpu_qstats->backlog, qdisc_pkt_len(skb)); | ||
701 | } | ||
702 | |||
636 | static inline void qdisc_qstats_backlog_inc(struct Qdisc *sch, | 703 | static inline void qdisc_qstats_backlog_inc(struct Qdisc *sch, |
637 | const struct sk_buff *skb) | 704 | const struct sk_buff *skb) |
638 | { | 705 | { |
639 | sch->qstats.backlog += qdisc_pkt_len(skb); | 706 | sch->qstats.backlog += qdisc_pkt_len(skb); |
640 | } | 707 | } |
641 | 708 | ||
709 | static inline void qdisc_qstats_cpu_backlog_inc(struct Qdisc *sch, | ||
710 | const struct sk_buff *skb) | ||
711 | { | ||
712 | this_cpu_add(sch->cpu_qstats->backlog, qdisc_pkt_len(skb)); | ||
713 | } | ||
714 | |||
715 | static inline void qdisc_qstats_cpu_qlen_inc(struct Qdisc *sch) | ||
716 | { | ||
717 | this_cpu_inc(sch->cpu_qstats->qlen); | ||
718 | } | ||
719 | |||
720 | static inline void qdisc_qstats_cpu_qlen_dec(struct Qdisc *sch) | ||
721 | { | ||
722 | this_cpu_dec(sch->cpu_qstats->qlen); | ||
723 | } | ||
724 | |||
725 | static inline void qdisc_qstats_cpu_requeues_inc(struct Qdisc *sch) | ||
726 | { | ||
727 | this_cpu_inc(sch->cpu_qstats->requeues); | ||
728 | } | ||
729 | |||
642 | static inline void __qdisc_qstats_drop(struct Qdisc *sch, int count) | 730 | static inline void __qdisc_qstats_drop(struct Qdisc *sch, int count) |
643 | { | 731 | { |
644 | sch->qstats.drops += count; | 732 | sch->qstats.drops += count; |
@@ -769,26 +857,30 @@ static inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch) | |||
769 | /* generic pseudo peek method for non-work-conserving qdisc */ | 857 | /* generic pseudo peek method for non-work-conserving qdisc */ |
770 | static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch) | 858 | static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch) |
771 | { | 859 | { |
860 | struct sk_buff *skb = skb_peek(&sch->gso_skb); | ||
861 | |||
772 | /* we can reuse ->gso_skb because peek isn't called for root qdiscs */ | 862 | /* we can reuse ->gso_skb because peek isn't called for root qdiscs */ |
773 | if (!sch->gso_skb) { | 863 | if (!skb) { |
774 | sch->gso_skb = sch->dequeue(sch); | 864 | skb = sch->dequeue(sch); |
775 | if (sch->gso_skb) { | 865 | |
866 | if (skb) { | ||
867 | __skb_queue_head(&sch->gso_skb, skb); | ||
776 | /* it's still part of the queue */ | 868 | /* it's still part of the queue */ |
777 | qdisc_qstats_backlog_inc(sch, sch->gso_skb); | 869 | qdisc_qstats_backlog_inc(sch, skb); |
778 | sch->q.qlen++; | 870 | sch->q.qlen++; |
779 | } | 871 | } |
780 | } | 872 | } |
781 | 873 | ||
782 | return sch->gso_skb; | 874 | return skb; |
783 | } | 875 | } |
784 | 876 | ||
785 | /* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */ | 877 | /* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */ |
786 | static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch) | 878 | static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch) |
787 | { | 879 | { |
788 | struct sk_buff *skb = sch->gso_skb; | 880 | struct sk_buff *skb = skb_peek(&sch->gso_skb); |
789 | 881 | ||
790 | if (skb) { | 882 | if (skb) { |
791 | sch->gso_skb = NULL; | 883 | skb = __skb_dequeue(&sch->gso_skb); |
792 | qdisc_qstats_backlog_dec(sch, skb); | 884 | qdisc_qstats_backlog_dec(sch, skb); |
793 | sch->q.qlen--; | 885 | sch->q.qlen--; |
794 | } else { | 886 | } else { |
@@ -846,6 +938,14 @@ static inline void rtnl_qdisc_drop(struct sk_buff *skb, struct Qdisc *sch) | |||
846 | qdisc_qstats_drop(sch); | 938 | qdisc_qstats_drop(sch); |
847 | } | 939 | } |
848 | 940 | ||
941 | static inline int qdisc_drop_cpu(struct sk_buff *skb, struct Qdisc *sch, | ||
942 | struct sk_buff **to_free) | ||
943 | { | ||
944 | __qdisc_drop(skb, to_free); | ||
945 | qdisc_qstats_cpu_drop(sch); | ||
946 | |||
947 | return NET_XMIT_DROP; | ||
948 | } | ||
849 | 949 | ||
850 | static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch, | 950 | static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch, |
851 | struct sk_buff **to_free) | 951 | struct sk_buff **to_free) |