.. | .. |
---|
10 | 10 | #include <linux/percpu.h> |
---|
11 | 11 | #include <linux/dynamic_queue_limits.h> |
---|
12 | 12 | #include <linux/list.h> |
---|
13 | | -#include <net/net_seq_lock.h> |
---|
14 | 13 | #include <linux/refcount.h> |
---|
15 | 14 | #include <linux/workqueue.h> |
---|
| 15 | +#include <linux/mutex.h> |
---|
| 16 | +#include <linux/rwsem.h> |
---|
| 17 | +#include <linux/atomic.h> |
---|
| 18 | +#include <linux/hashtable.h> |
---|
| 19 | +#include <linux/android_kabi.h> |
---|
16 | 20 | #include <net/gen_stats.h> |
---|
17 | 21 | #include <net/rtnetlink.h> |
---|
| 22 | +#include <net/flow_offload.h> |
---|
18 | 23 | |
---|
19 | 24 | struct Qdisc_ops; |
---|
20 | 25 | struct qdisc_walker; |
---|
21 | 26 | struct tcf_walker; |
---|
22 | 27 | struct module; |
---|
23 | | - |
---|
24 | | -typedef int tc_setup_cb_t(enum tc_setup_type type, |
---|
25 | | - void *type_data, void *cb_priv); |
---|
| 28 | +struct bpf_flow_keys; |
---|
26 | 29 | |
---|
27 | 30 | struct qdisc_rate_table { |
---|
28 | 31 | struct tc_ratespec rate; |
---|
.. | .. |
---|
34 | 37 | enum qdisc_state_t { |
---|
35 | 38 | __QDISC_STATE_SCHED, |
---|
36 | 39 | __QDISC_STATE_DEACTIVATED, |
---|
| 40 | + __QDISC_STATE_MISSED, |
---|
37 | 41 | }; |
---|
38 | 42 | |
---|
39 | 43 | struct qdisc_size_table { |
---|
.. | .. |
---|
48 | 52 | struct qdisc_skb_head { |
---|
49 | 53 | struct sk_buff *head; |
---|
50 | 54 | struct sk_buff *tail; |
---|
51 | | - union { |
---|
52 | | - u32 qlen; |
---|
53 | | - atomic_t atomic_qlen; |
---|
54 | | - }; |
---|
| 55 | + __u32 qlen; |
---|
55 | 56 | spinlock_t lock; |
---|
56 | 57 | }; |
---|
57 | 58 | |
---|
.. | .. |
---|
92 | 93 | struct net_rate_estimator __rcu *rate_est; |
---|
93 | 94 | struct gnet_stats_basic_cpu __percpu *cpu_bstats; |
---|
94 | 95 | struct gnet_stats_queue __percpu *cpu_qstats; |
---|
95 | | - int padded; |
---|
| 96 | + int pad; |
---|
96 | 97 | refcount_t refcnt; |
---|
97 | 98 | |
---|
98 | 99 | /* |
---|
.. | .. |
---|
101 | 102 | struct sk_buff_head gso_skb ____cacheline_aligned_in_smp; |
---|
102 | 103 | struct qdisc_skb_head q; |
---|
103 | 104 | struct gnet_stats_basic_packed bstats; |
---|
104 | | - net_seqlock_t running; |
---|
| 105 | + seqcount_t running; |
---|
105 | 106 | struct gnet_stats_queue qstats; |
---|
106 | 107 | unsigned long state; |
---|
107 | 108 | struct Qdisc *next_sched; |
---|
.. | .. |
---|
109 | 110 | |
---|
110 | 111 | spinlock_t busylock ____cacheline_aligned_in_smp; |
---|
111 | 112 | spinlock_t seqlock; |
---|
112 | | -#ifndef __GENKSYMS__ |
---|
| 113 | + |
---|
| 114 | + /* for NOLOCK qdisc, true if there are no enqueued skbs */ |
---|
| 115 | + bool empty; |
---|
113 | 116 | struct rcu_head rcu; |
---|
114 | | -#endif |
---|
| 117 | + |
---|
| 118 | + ANDROID_KABI_RESERVE(1); |
---|
| 119 | + |
---|
| 120 | + /* private data */ |
---|
| 121 | + long privdata[] ____cacheline_aligned; |
---|
115 | 122 | }; |
---|
116 | 123 | |
---|
117 | 124 | static inline void qdisc_refcount_inc(struct Qdisc *qdisc) |
---|
.. | .. |
---|
138 | 145 | { |
---|
139 | 146 | if (qdisc->flags & TCQ_F_NOLOCK) |
---|
140 | 147 | return spin_is_locked(&qdisc->seqlock); |
---|
141 | | -#ifdef CONFIG_PREEMPT_RT_BASE |
---|
142 | | - return spin_is_locked(&qdisc->running.lock) ? true : false; |
---|
143 | | -#else |
---|
144 | 148 | return (raw_read_seqcount(&qdisc->running) & 1) ? true : false; |
---|
145 | | -#endif |
---|
| 149 | +} |
---|
| 150 | + |
---|
| 151 | +static inline bool qdisc_is_percpu_stats(const struct Qdisc *q) |
---|
| 152 | +{ |
---|
| 153 | + return q->flags & TCQ_F_CPUSTATS; |
---|
| 154 | +} |
---|
| 155 | + |
---|
| 156 | +static inline bool qdisc_is_empty(const struct Qdisc *qdisc) |
---|
| 157 | +{ |
---|
| 158 | + if (qdisc_is_percpu_stats(qdisc)) |
---|
| 159 | + return READ_ONCE(qdisc->empty); |
---|
| 160 | + return !READ_ONCE(qdisc->q.qlen); |
---|
146 | 161 | } |
---|
147 | 162 | |
---|
148 | 163 | static inline bool qdisc_run_begin(struct Qdisc *qdisc) |
---|
149 | 164 | { |
---|
150 | 165 | if (qdisc->flags & TCQ_F_NOLOCK) { |
---|
| 166 | + if (spin_trylock(&qdisc->seqlock)) |
---|
| 167 | + goto nolock_empty; |
---|
| 168 | + |
---|
| 169 | + /* No need to insist if the MISSED flag was already set. |
---|
| 170 | + * Note that test_and_set_bit() also gives us memory ordering |
---|
| 171 | + * guarantees wrt potential earlier enqueue() and below |
---|
| 172 | + * spin_trylock(), both of which are necessary to prevent races |
---|
| 173 | + */ |
---|
| 174 | + if (test_and_set_bit(__QDISC_STATE_MISSED, &qdisc->state)) |
---|
| 175 | + return false; |
---|
| 176 | + |
---|
| 177 | + /* Try to take the lock again to make sure that we will either |
---|
| 178 | + * grab it or the CPU that still has it will see MISSED set |
---|
| 179 | + * when testing it in qdisc_run_end() |
---|
| 180 | + */ |
---|
151 | 181 | if (!spin_trylock(&qdisc->seqlock)) |
---|
152 | 182 | return false; |
---|
| 183 | + |
---|
| 184 | +nolock_empty: |
---|
| 185 | + WRITE_ONCE(qdisc->empty, false); |
---|
153 | 186 | } else if (qdisc_is_running(qdisc)) { |
---|
154 | 187 | return false; |
---|
155 | 188 | } |
---|
156 | | -#ifdef CONFIG_PREEMPT_RT_BASE |
---|
157 | | - if (try_write_seqlock(&qdisc->running)) |
---|
158 | | - return true; |
---|
159 | | - return false; |
---|
160 | | -#else |
---|
161 | 189 | /* Variant of write_seqcount_begin() telling lockdep a trylock |
---|
162 | 190 | * was attempted. |
---|
163 | 191 | */ |
---|
164 | 192 | raw_write_seqcount_begin(&qdisc->running); |
---|
165 | 193 | seqcount_acquire(&qdisc->running.dep_map, 0, 1, _RET_IP_); |
---|
166 | 194 | return true; |
---|
167 | | -#endif |
---|
168 | 195 | } |
---|
169 | 196 | |
---|
170 | 197 | static inline void qdisc_run_end(struct Qdisc *qdisc) |
---|
171 | 198 | { |
---|
172 | | -#ifdef CONFIG_PREEMPT_RT_BASE |
---|
173 | | - write_sequnlock(&qdisc->running); |
---|
174 | | -#else |
---|
175 | 199 | write_seqcount_end(&qdisc->running); |
---|
176 | | -#endif |
---|
177 | | - if (qdisc->flags & TCQ_F_NOLOCK) |
---|
| 200 | + if (qdisc->flags & TCQ_F_NOLOCK) { |
---|
178 | 201 | spin_unlock(&qdisc->seqlock); |
---|
| 202 | + |
---|
| 203 | + /* spin_unlock() only has store-release semantic. The unlock |
---|
| 204 | + * and test_bit() ordering is a store-load ordering, so a full |
---|
| 205 | + * memory barrier is needed here. |
---|
| 206 | + */ |
---|
| 207 | + smp_mb(); |
---|
| 208 | + |
---|
| 209 | + if (unlikely(test_bit(__QDISC_STATE_MISSED, |
---|
| 210 | + &qdisc->state))) { |
---|
| 211 | + clear_bit(__QDISC_STATE_MISSED, &qdisc->state); |
---|
| 212 | + __netif_schedule(qdisc); |
---|
| 213 | + } |
---|
| 214 | + } |
---|
179 | 215 | } |
---|
180 | 216 | |
---|
181 | 217 | static inline bool qdisc_may_bulk(const struct Qdisc *qdisc) |
---|
.. | .. |
---|
194 | 230 | } |
---|
195 | 231 | |
---|
196 | 232 | struct Qdisc_class_ops { |
---|
| 233 | + unsigned int flags; |
---|
197 | 234 | /* Child qdisc manipulation */ |
---|
198 | 235 | struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *); |
---|
199 | 236 | int (*graft)(struct Qdisc *, unsigned long cl, |
---|
.. | .. |
---|
223 | 260 | struct sk_buff *skb, struct tcmsg*); |
---|
224 | 261 | int (*dump_stats)(struct Qdisc *, unsigned long, |
---|
225 | 262 | struct gnet_dump *); |
---|
| 263 | + |
---|
| 264 | + ANDROID_KABI_RESERVE(1); |
---|
| 265 | +}; |
---|
| 266 | + |
---|
| 267 | +/* Qdisc_class_ops flag values */ |
---|
| 268 | + |
---|
| 269 | +/* Implements API that doesn't require rtnl lock */ |
---|
| 270 | +enum qdisc_class_ops_flags { |
---|
| 271 | + QDISC_CLASS_OPS_DOIT_UNLOCKED = 1, |
---|
226 | 272 | }; |
---|
227 | 273 | |
---|
228 | 274 | struct Qdisc_ops { |
---|
.. | .. |
---|
259 | 305 | u32 (*egress_block_get)(struct Qdisc *sch); |
---|
260 | 306 | |
---|
261 | 307 | struct module *owner; |
---|
| 308 | + |
---|
| 309 | + ANDROID_KABI_RESERVE(1); |
---|
262 | 310 | }; |
---|
263 | 311 | |
---|
264 | 312 | |
---|
.. | .. |
---|
270 | 318 | }; |
---|
271 | 319 | const struct tcf_proto *goto_tp; |
---|
272 | 320 | |
---|
273 | | - /* used by the TC_ACT_REINSERT action */ |
---|
| 321 | + /* used in the skb_tc_reinsert function */ |
---|
274 | 322 | struct { |
---|
275 | 323 | bool ingress; |
---|
276 | 324 | struct gnet_stats_queue *qstats; |
---|
.. | .. |
---|
288 | 336 | const struct tcf_proto *, |
---|
289 | 337 | struct tcf_result *); |
---|
290 | 338 | int (*init)(struct tcf_proto*); |
---|
291 | | - void (*destroy)(struct tcf_proto *tp, |
---|
| 339 | + void (*destroy)(struct tcf_proto *tp, bool rtnl_held, |
---|
292 | 340 | struct netlink_ext_ack *extack); |
---|
293 | 341 | |
---|
294 | 342 | void* (*get)(struct tcf_proto*, u32 handle); |
---|
| 343 | + void (*put)(struct tcf_proto *tp, void *f); |
---|
295 | 344 | int (*change)(struct net *net, struct sk_buff *, |
---|
296 | 345 | struct tcf_proto*, unsigned long, |
---|
297 | 346 | u32 handle, struct nlattr **, |
---|
298 | | - void **, bool, |
---|
| 347 | + void **, bool, bool, |
---|
299 | 348 | struct netlink_ext_ack *); |
---|
300 | 349 | int (*delete)(struct tcf_proto *tp, void *arg, |
---|
301 | | - bool *last, |
---|
| 350 | + bool *last, bool rtnl_held, |
---|
302 | 351 | struct netlink_ext_ack *); |
---|
303 | | - void (*walk)(struct tcf_proto*, struct tcf_walker *arg); |
---|
| 352 | + bool (*delete_empty)(struct tcf_proto *tp); |
---|
| 353 | + void (*walk)(struct tcf_proto *tp, |
---|
| 354 | + struct tcf_walker *arg, bool rtnl_held); |
---|
304 | 355 | int (*reoffload)(struct tcf_proto *tp, bool add, |
---|
305 | | - tc_setup_cb_t *cb, void *cb_priv, |
---|
| 356 | + flow_setup_cb_t *cb, void *cb_priv, |
---|
306 | 357 | struct netlink_ext_ack *extack); |
---|
| 358 | + void (*hw_add)(struct tcf_proto *tp, |
---|
| 359 | + void *type_data); |
---|
| 360 | + void (*hw_del)(struct tcf_proto *tp, |
---|
| 361 | + void *type_data); |
---|
307 | 362 | void (*bind_class)(void *, u32, unsigned long, |
---|
308 | 363 | void *, unsigned long); |
---|
309 | 364 | void * (*tmplt_create)(struct net *net, |
---|
.. | .. |
---|
314 | 369 | |
---|
315 | 370 | /* rtnetlink specific */ |
---|
316 | 371 | int (*dump)(struct net*, struct tcf_proto*, void *, |
---|
317 | | - struct sk_buff *skb, struct tcmsg*); |
---|
| 372 | + struct sk_buff *skb, struct tcmsg*, |
---|
| 373 | + bool); |
---|
| 374 | + int (*terse_dump)(struct net *net, |
---|
| 375 | + struct tcf_proto *tp, void *fh, |
---|
| 376 | + struct sk_buff *skb, |
---|
| 377 | + struct tcmsg *t, bool rtnl_held); |
---|
318 | 378 | int (*tmplt_dump)(struct sk_buff *skb, |
---|
319 | 379 | struct net *net, |
---|
320 | 380 | void *tmplt_priv); |
---|
321 | 381 | |
---|
322 | 382 | struct module *owner; |
---|
| 383 | + int flags; |
---|
| 384 | +}; |
---|
| 385 | + |
---|
| 386 | +/* Classifiers setting TCF_PROTO_OPS_DOIT_UNLOCKED in tcf_proto_ops->flags |
---|
| 387 | + * are expected to implement tcf_proto_ops->delete_empty(), otherwise race |
---|
| 388 | + * conditions can occur when filters are inserted/deleted simultaneously. |
---|
| 389 | + */ |
---|
| 390 | +enum tcf_proto_ops_flags { |
---|
| 391 | + TCF_PROTO_OPS_DOIT_UNLOCKED = 1, |
---|
323 | 392 | }; |
---|
324 | 393 | |
---|
325 | 394 | struct tcf_proto { |
---|
.. | .. |
---|
338 | 407 | void *data; |
---|
339 | 408 | const struct tcf_proto_ops *ops; |
---|
340 | 409 | struct tcf_chain *chain; |
---|
| 410 | + /* Lock protects tcf_proto shared state and can be used by unlocked |
---|
| 411 | + * classifiers to protect their private data. |
---|
| 412 | + */ |
---|
| 413 | + spinlock_t lock; |
---|
| 414 | + bool deleting; |
---|
| 415 | + refcount_t refcnt; |
---|
341 | 416 | struct rcu_head rcu; |
---|
| 417 | + struct hlist_node destroy_ht_node; |
---|
342 | 418 | }; |
---|
343 | 419 | |
---|
344 | 420 | struct qdisc_skb_cb { |
---|
345 | | - unsigned int pkt_len; |
---|
346 | | - u16 slave_dev_queue_mapping; |
---|
347 | | - u16 tc_classid; |
---|
| 421 | + struct { |
---|
| 422 | + unsigned int pkt_len; |
---|
| 423 | + u16 slave_dev_queue_mapping; |
---|
| 424 | + u16 tc_classid; |
---|
| 425 | + }; |
---|
348 | 426 | #define QDISC_CB_PRIV_LEN 20 |
---|
349 | 427 | unsigned char data[QDISC_CB_PRIV_LEN]; |
---|
| 428 | + u16 mru; |
---|
350 | 429 | }; |
---|
351 | 430 | |
---|
352 | 431 | typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv); |
---|
353 | 432 | |
---|
354 | 433 | struct tcf_chain { |
---|
| 434 | + /* Protects filter_chain. */ |
---|
| 435 | + struct mutex filter_chain_lock; |
---|
355 | 436 | struct tcf_proto __rcu *filter_chain; |
---|
356 | 437 | struct list_head list; |
---|
357 | 438 | struct tcf_block *block; |
---|
.. | .. |
---|
359 | 440 | unsigned int refcnt; |
---|
360 | 441 | unsigned int action_refcnt; |
---|
361 | 442 | bool explicitly_created; |
---|
| 443 | + bool flushing; |
---|
362 | 444 | const struct tcf_proto_ops *tmplt_ops; |
---|
363 | 445 | void *tmplt_priv; |
---|
| 446 | + struct rcu_head rcu; |
---|
364 | 447 | }; |
---|
365 | 448 | |
---|
366 | 449 | struct tcf_block { |
---|
| 450 | + /* Lock protects tcf_block and lifetime-management data of chains |
---|
| 451 | + * attached to the block (refcnt, action_refcnt, explicitly_created). |
---|
| 452 | + */ |
---|
| 453 | + struct mutex lock; |
---|
367 | 454 | struct list_head chain_list; |
---|
368 | 455 | u32 index; /* block index for shared blocks */ |
---|
369 | | - unsigned int refcnt; |
---|
| 456 | + u32 classid; /* which class this block belongs to */ |
---|
| 457 | + refcount_t refcnt; |
---|
370 | 458 | struct net *net; |
---|
371 | 459 | struct Qdisc *q; |
---|
372 | | - struct list_head cb_list; |
---|
| 460 | + struct rw_semaphore cb_lock; /* protects cb_list and offload counters */ |
---|
| 461 | + struct flow_block flow_block; |
---|
373 | 462 | struct list_head owner_list; |
---|
374 | 463 | bool keep_dst; |
---|
375 | | - unsigned int offloadcnt; /* Number of oddloaded filters */ |
---|
| 464 | + atomic_t offloadcnt; /* Number of oddloaded filters */ |
---|
376 | 465 | unsigned int nooffloaddevcnt; /* Number of devs unable to do offload */ |
---|
| 466 | + unsigned int lockeddevcnt; /* Number of devs that require rtnl lock. */ |
---|
377 | 467 | struct { |
---|
378 | 468 | struct tcf_chain *chain; |
---|
379 | 469 | struct list_head filter_chain_list; |
---|
380 | 470 | } chain0; |
---|
| 471 | + struct rcu_head rcu; |
---|
| 472 | + DECLARE_HASHTABLE(proto_destroy_ht, 7); |
---|
| 473 | + struct mutex proto_destroy_lock; /* Lock for proto_destroy hashtable. */ |
---|
381 | 474 | }; |
---|
382 | 475 | |
---|
383 | | -static inline void tcf_block_offload_inc(struct tcf_block *block, u32 *flags) |
---|
| 476 | +#ifdef CONFIG_PROVE_LOCKING |
---|
| 477 | +static inline bool lockdep_tcf_chain_is_locked(struct tcf_chain *chain) |
---|
384 | 478 | { |
---|
385 | | - if (*flags & TCA_CLS_FLAGS_IN_HW) |
---|
386 | | - return; |
---|
387 | | - *flags |= TCA_CLS_FLAGS_IN_HW; |
---|
388 | | - block->offloadcnt++; |
---|
| 479 | + return lockdep_is_held(&chain->filter_chain_lock); |
---|
389 | 480 | } |
---|
390 | 481 | |
---|
391 | | -static inline void tcf_block_offload_dec(struct tcf_block *block, u32 *flags) |
---|
| 482 | +static inline bool lockdep_tcf_proto_is_locked(struct tcf_proto *tp) |
---|
392 | 483 | { |
---|
393 | | - if (!(*flags & TCA_CLS_FLAGS_IN_HW)) |
---|
394 | | - return; |
---|
395 | | - *flags &= ~TCA_CLS_FLAGS_IN_HW; |
---|
396 | | - block->offloadcnt--; |
---|
| 484 | + return lockdep_is_held(&tp->lock); |
---|
| 485 | +} |
---|
| 486 | +#else |
---|
| 487 | +static inline bool lockdep_tcf_chain_is_locked(struct tcf_block *chain) |
---|
| 488 | +{ |
---|
| 489 | + return true; |
---|
397 | 490 | } |
---|
398 | 491 | |
---|
399 | | -static inline void |
---|
400 | | -tc_cls_offload_cnt_update(struct tcf_block *block, unsigned int *cnt, |
---|
401 | | - u32 *flags, bool add) |
---|
| 492 | +static inline bool lockdep_tcf_proto_is_locked(struct tcf_proto *tp) |
---|
402 | 493 | { |
---|
403 | | - if (add) { |
---|
404 | | - if (!*cnt) |
---|
405 | | - tcf_block_offload_inc(block, flags); |
---|
406 | | - (*cnt)++; |
---|
407 | | - } else { |
---|
408 | | - (*cnt)--; |
---|
409 | | - if (!*cnt) |
---|
410 | | - tcf_block_offload_dec(block, flags); |
---|
411 | | - } |
---|
| 494 | + return true; |
---|
412 | 495 | } |
---|
| 496 | +#endif /* #ifdef CONFIG_PROVE_LOCKING */ |
---|
| 497 | + |
---|
| 498 | +#define tcf_chain_dereference(p, chain) \ |
---|
| 499 | + rcu_dereference_protected(p, lockdep_tcf_chain_is_locked(chain)) |
---|
| 500 | + |
---|
| 501 | +#define tcf_proto_dereference(p, tp) \ |
---|
| 502 | + rcu_dereference_protected(p, lockdep_tcf_proto_is_locked(tp)) |
---|
413 | 503 | |
---|
414 | 504 | static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) |
---|
415 | 505 | { |
---|
416 | 506 | struct qdisc_skb_cb *qcb; |
---|
417 | 507 | |
---|
418 | | - BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz); |
---|
| 508 | + BUILD_BUG_ON(sizeof(skb->cb) < sizeof(*qcb)); |
---|
419 | 509 | BUILD_BUG_ON(sizeof(qcb->data) < sz); |
---|
| 510 | +} |
---|
| 511 | + |
---|
| 512 | +static inline int qdisc_qlen_cpu(const struct Qdisc *q) |
---|
| 513 | +{ |
---|
| 514 | + return this_cpu_ptr(q->cpu_qstats)->qlen; |
---|
420 | 515 | } |
---|
421 | 516 | |
---|
422 | 517 | static inline int qdisc_qlen(const struct Qdisc *q) |
---|
.. | .. |
---|
424 | 519 | return q->q.qlen; |
---|
425 | 520 | } |
---|
426 | 521 | |
---|
427 | | -static inline u32 qdisc_qlen_sum(const struct Qdisc *q) |
---|
| 522 | +static inline int qdisc_qlen_sum(const struct Qdisc *q) |
---|
428 | 523 | { |
---|
429 | | - u32 qlen = q->qstats.qlen; |
---|
| 524 | + __u32 qlen = q->qstats.qlen; |
---|
| 525 | + int i; |
---|
430 | 526 | |
---|
431 | | - if (q->flags & TCQ_F_NOLOCK) |
---|
432 | | - qlen += atomic_read(&q->q.atomic_qlen); |
---|
433 | | - else |
---|
| 527 | + if (qdisc_is_percpu_stats(q)) { |
---|
| 528 | + for_each_possible_cpu(i) |
---|
| 529 | + qlen += per_cpu_ptr(q->cpu_qstats, i)->qlen; |
---|
| 530 | + } else { |
---|
434 | 531 | qlen += q->q.qlen; |
---|
| 532 | + } |
---|
435 | 533 | |
---|
436 | 534 | return qlen; |
---|
437 | 535 | } |
---|
.. | .. |
---|
490 | 588 | return qdisc_lock(root); |
---|
491 | 589 | } |
---|
492 | 590 | |
---|
493 | | -static inline net_seqlock_t *qdisc_root_sleeping_running(const struct Qdisc *qdisc) |
---|
| 591 | +static inline seqcount_t *qdisc_root_sleeping_running(const struct Qdisc *qdisc) |
---|
494 | 592 | { |
---|
495 | 593 | struct Qdisc *root = qdisc_root_sleeping(qdisc); |
---|
496 | 594 | |
---|
.. | .. |
---|
588 | 686 | void qdisc_reset(struct Qdisc *qdisc); |
---|
589 | 687 | void qdisc_put(struct Qdisc *qdisc); |
---|
590 | 688 | void qdisc_put_unlocked(struct Qdisc *qdisc); |
---|
591 | | -void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n, |
---|
592 | | - unsigned int len); |
---|
| 689 | +void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, int n, int len); |
---|
| 690 | +#ifdef CONFIG_NET_SCHED |
---|
| 691 | +int qdisc_offload_dump_helper(struct Qdisc *q, enum tc_setup_type type, |
---|
| 692 | + void *type_data); |
---|
| 693 | +void qdisc_offload_graft_helper(struct net_device *dev, struct Qdisc *sch, |
---|
| 694 | + struct Qdisc *new, struct Qdisc *old, |
---|
| 695 | + enum tc_setup_type type, void *type_data, |
---|
| 696 | + struct netlink_ext_ack *extack); |
---|
| 697 | +#else |
---|
| 698 | +static inline int |
---|
| 699 | +qdisc_offload_dump_helper(struct Qdisc *q, enum tc_setup_type type, |
---|
| 700 | + void *type_data) |
---|
| 701 | +{ |
---|
| 702 | + q->flags &= ~TCQ_F_OFFLOADED; |
---|
| 703 | + return 0; |
---|
| 704 | +} |
---|
| 705 | + |
---|
| 706 | +static inline void |
---|
| 707 | +qdisc_offload_graft_helper(struct net_device *dev, struct Qdisc *sch, |
---|
| 708 | + struct Qdisc *new, struct Qdisc *old, |
---|
| 709 | + enum tc_setup_type type, void *type_data, |
---|
| 710 | + struct netlink_ext_ack *extack) |
---|
| 711 | +{ |
---|
| 712 | +} |
---|
| 713 | +#endif |
---|
593 | 714 | struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, |
---|
594 | 715 | const struct Qdisc_ops *ops, |
---|
595 | 716 | struct netlink_ext_ack *extack); |
---|
.. | .. |
---|
600 | 721 | void __qdisc_calculate_pkt_len(struct sk_buff *skb, |
---|
601 | 722 | const struct qdisc_size_table *stab); |
---|
602 | 723 | int skb_do_redirect(struct sk_buff *); |
---|
603 | | - |
---|
604 | | -static inline void skb_reset_tc(struct sk_buff *skb) |
---|
605 | | -{ |
---|
606 | | -#ifdef CONFIG_NET_CLS_ACT |
---|
607 | | - skb->tc_redirected = 0; |
---|
608 | | -#endif |
---|
609 | | -} |
---|
610 | | - |
---|
611 | | -static inline bool skb_is_tc_redirected(const struct sk_buff *skb) |
---|
612 | | -{ |
---|
613 | | -#ifdef CONFIG_NET_CLS_ACT |
---|
614 | | - return skb->tc_redirected; |
---|
615 | | -#else |
---|
616 | | - return false; |
---|
617 | | -#endif |
---|
618 | | -} |
---|
619 | 724 | |
---|
620 | 725 | static inline bool skb_at_tc_ingress(const struct sk_buff *skb) |
---|
621 | 726 | { |
---|
.. | .. |
---|
652 | 757 | } |
---|
653 | 758 | } |
---|
654 | 759 | |
---|
655 | | -static inline void qdisc_reset_all_tx(struct net_device *dev) |
---|
656 | | -{ |
---|
657 | | - qdisc_reset_all_tx_gt(dev, 0); |
---|
658 | | -} |
---|
659 | | - |
---|
660 | 760 | /* Are all TX queues of the device empty? */ |
---|
661 | 761 | static inline bool qdisc_all_tx_empty(const struct net_device *dev) |
---|
662 | 762 | { |
---|
.. | .. |
---|
667 | 767 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); |
---|
668 | 768 | const struct Qdisc *q = rcu_dereference(txq->qdisc); |
---|
669 | 769 | |
---|
670 | | - if (q->q.qlen) { |
---|
| 770 | + if (!qdisc_is_empty(q)) { |
---|
671 | 771 | rcu_read_unlock(); |
---|
672 | 772 | return false; |
---|
673 | 773 | } |
---|
.. | .. |
---|
737 | 837 | return sch->enqueue(skb, sch, to_free); |
---|
738 | 838 | } |
---|
739 | 839 | |
---|
740 | | -static inline bool qdisc_is_percpu_stats(const struct Qdisc *q) |
---|
741 | | -{ |
---|
742 | | - return q->flags & TCQ_F_CPUSTATS; |
---|
743 | | -} |
---|
744 | | - |
---|
745 | 840 | static inline void _bstats_update(struct gnet_stats_basic_packed *bstats, |
---|
746 | 841 | __u64 bytes, __u32 packets) |
---|
747 | 842 | { |
---|
.. | .. |
---|
809 | 904 | this_cpu_add(sch->cpu_qstats->backlog, qdisc_pkt_len(skb)); |
---|
810 | 905 | } |
---|
811 | 906 | |
---|
812 | | -static inline void qdisc_qstats_atomic_qlen_inc(struct Qdisc *sch) |
---|
| 907 | +static inline void qdisc_qstats_cpu_qlen_inc(struct Qdisc *sch) |
---|
813 | 908 | { |
---|
814 | | - atomic_inc(&sch->q.atomic_qlen); |
---|
| 909 | + this_cpu_inc(sch->cpu_qstats->qlen); |
---|
815 | 910 | } |
---|
816 | 911 | |
---|
817 | | -static inline void qdisc_qstats_atomic_qlen_dec(struct Qdisc *sch) |
---|
| 912 | +static inline void qdisc_qstats_cpu_qlen_dec(struct Qdisc *sch) |
---|
818 | 913 | { |
---|
819 | | - atomic_dec(&sch->q.atomic_qlen); |
---|
| 914 | + this_cpu_dec(sch->cpu_qstats->qlen); |
---|
820 | 915 | } |
---|
821 | 916 | |
---|
822 | 917 | static inline void qdisc_qstats_cpu_requeues_inc(struct Qdisc *sch) |
---|
.. | .. |
---|
854 | 949 | sch->qstats.overlimits++; |
---|
855 | 950 | } |
---|
856 | 951 | |
---|
| 952 | +static inline int qdisc_qstats_copy(struct gnet_dump *d, struct Qdisc *sch) |
---|
| 953 | +{ |
---|
| 954 | + __u32 qlen = qdisc_qlen_sum(sch); |
---|
| 955 | + |
---|
| 956 | + return gnet_stats_copy_queue(d, sch->cpu_qstats, &sch->qstats, qlen); |
---|
| 957 | +} |
---|
| 958 | + |
---|
| 959 | +static inline void qdisc_qstats_qlen_backlog(struct Qdisc *sch, __u32 *qlen, |
---|
| 960 | + __u32 *backlog) |
---|
| 961 | +{ |
---|
| 962 | + struct gnet_stats_queue qstats = { 0 }; |
---|
| 963 | + __u32 len = qdisc_qlen_sum(sch); |
---|
| 964 | + |
---|
| 965 | + __gnet_stats_copy_queue(&qstats, sch->cpu_qstats, &sch->qstats, len); |
---|
| 966 | + *qlen = qstats.qlen; |
---|
| 967 | + *backlog = qstats.backlog; |
---|
| 968 | +} |
---|
| 969 | + |
---|
| 970 | +static inline void qdisc_tree_flush_backlog(struct Qdisc *sch) |
---|
| 971 | +{ |
---|
| 972 | + __u32 qlen, backlog; |
---|
| 973 | + |
---|
| 974 | + qdisc_qstats_qlen_backlog(sch, &qlen, &backlog); |
---|
| 975 | + qdisc_tree_reduce_backlog(sch, qlen, backlog); |
---|
| 976 | +} |
---|
| 977 | + |
---|
| 978 | +static inline void qdisc_purge_queue(struct Qdisc *sch) |
---|
| 979 | +{ |
---|
| 980 | + __u32 qlen, backlog; |
---|
| 981 | + |
---|
| 982 | + qdisc_qstats_qlen_backlog(sch, &qlen, &backlog); |
---|
| 983 | + qdisc_reset(sch); |
---|
| 984 | + qdisc_tree_reduce_backlog(sch, qlen, backlog); |
---|
| 985 | +} |
---|
| 986 | + |
---|
857 | 987 | static inline void qdisc_skb_head_init(struct qdisc_skb_head *qh) |
---|
858 | 988 | { |
---|
859 | 989 | qh->head = NULL; |
---|
.. | .. |
---|
861 | 991 | qh->qlen = 0; |
---|
862 | 992 | } |
---|
863 | 993 | |
---|
864 | | -static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch, |
---|
865 | | - struct qdisc_skb_head *qh) |
---|
| 994 | +static inline void __qdisc_enqueue_tail(struct sk_buff *skb, |
---|
| 995 | + struct qdisc_skb_head *qh) |
---|
866 | 996 | { |
---|
867 | 997 | struct sk_buff *last = qh->tail; |
---|
868 | 998 | |
---|
.. | .. |
---|
875 | 1005 | qh->head = skb; |
---|
876 | 1006 | } |
---|
877 | 1007 | qh->qlen++; |
---|
878 | | - qdisc_qstats_backlog_inc(sch, skb); |
---|
879 | | - |
---|
880 | | - return NET_XMIT_SUCCESS; |
---|
881 | 1008 | } |
---|
882 | 1009 | |
---|
883 | 1010 | static inline int qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch) |
---|
884 | 1011 | { |
---|
885 | | - return __qdisc_enqueue_tail(skb, sch, &sch->q); |
---|
| 1012 | + __qdisc_enqueue_tail(skb, &sch->q); |
---|
| 1013 | + qdisc_qstats_backlog_inc(sch, skb); |
---|
| 1014 | + return NET_XMIT_SUCCESS; |
---|
| 1015 | +} |
---|
| 1016 | + |
---|
| 1017 | +static inline void __qdisc_enqueue_head(struct sk_buff *skb, |
---|
| 1018 | + struct qdisc_skb_head *qh) |
---|
| 1019 | +{ |
---|
| 1020 | + skb->next = qh->head; |
---|
| 1021 | + |
---|
| 1022 | + if (!qh->head) |
---|
| 1023 | + qh->tail = skb; |
---|
| 1024 | + qh->head = skb; |
---|
| 1025 | + qh->qlen++; |
---|
886 | 1026 | } |
---|
887 | 1027 | |
---|
888 | 1028 | static inline struct sk_buff *__qdisc_dequeue_head(struct qdisc_skb_head *qh) |
---|
.. | .. |
---|
948 | 1088 | return 0; |
---|
949 | 1089 | } |
---|
950 | 1090 | |
---|
951 | | -static inline unsigned int qdisc_queue_drop_head(struct Qdisc *sch, |
---|
952 | | - struct sk_buff **to_free) |
---|
953 | | -{ |
---|
954 | | - return __qdisc_queue_drop_head(sch, &sch->q, to_free); |
---|
955 | | -} |
---|
956 | | - |
---|
957 | 1091 | static inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch) |
---|
958 | 1092 | { |
---|
959 | 1093 | const struct qdisc_skb_head *qh = &sch->q; |
---|
.. | .. |
---|
981 | 1115 | return skb; |
---|
982 | 1116 | } |
---|
983 | 1117 | |
---|
| 1118 | +static inline void qdisc_update_stats_at_dequeue(struct Qdisc *sch, |
---|
| 1119 | + struct sk_buff *skb) |
---|
| 1120 | +{ |
---|
| 1121 | + if (qdisc_is_percpu_stats(sch)) { |
---|
| 1122 | + qdisc_qstats_cpu_backlog_dec(sch, skb); |
---|
| 1123 | + qdisc_bstats_cpu_update(sch, skb); |
---|
| 1124 | + qdisc_qstats_cpu_qlen_dec(sch); |
---|
| 1125 | + } else { |
---|
| 1126 | + qdisc_qstats_backlog_dec(sch, skb); |
---|
| 1127 | + qdisc_bstats_update(sch, skb); |
---|
| 1128 | + sch->q.qlen--; |
---|
| 1129 | + } |
---|
| 1130 | +} |
---|
| 1131 | + |
---|
| 1132 | +static inline void qdisc_update_stats_at_enqueue(struct Qdisc *sch, |
---|
| 1133 | + unsigned int pkt_len) |
---|
| 1134 | +{ |
---|
| 1135 | + if (qdisc_is_percpu_stats(sch)) { |
---|
| 1136 | + qdisc_qstats_cpu_qlen_inc(sch); |
---|
| 1137 | + this_cpu_add(sch->cpu_qstats->backlog, pkt_len); |
---|
| 1138 | + } else { |
---|
| 1139 | + sch->qstats.backlog += pkt_len; |
---|
| 1140 | + sch->q.qlen++; |
---|
| 1141 | + } |
---|
| 1142 | +} |
---|
| 1143 | + |
---|
984 | 1144 | /* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */ |
---|
985 | 1145 | static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch) |
---|
986 | 1146 | { |
---|
.. | .. |
---|
988 | 1148 | |
---|
989 | 1149 | if (skb) { |
---|
990 | 1150 | skb = __skb_dequeue(&sch->gso_skb); |
---|
991 | | - qdisc_qstats_backlog_dec(sch, skb); |
---|
992 | | - sch->q.qlen--; |
---|
| 1151 | + if (qdisc_is_percpu_stats(sch)) { |
---|
| 1152 | + qdisc_qstats_cpu_backlog_dec(sch, skb); |
---|
| 1153 | + qdisc_qstats_cpu_qlen_dec(sch); |
---|
| 1154 | + } else { |
---|
| 1155 | + qdisc_qstats_backlog_dec(sch, skb); |
---|
| 1156 | + sch->q.qlen--; |
---|
| 1157 | + } |
---|
993 | 1158 | } else { |
---|
994 | 1159 | skb = sch->dequeue(sch); |
---|
995 | 1160 | } |
---|
.. | .. |
---|
1016 | 1181 | static inline void qdisc_reset_queue(struct Qdisc *sch) |
---|
1017 | 1182 | { |
---|
1018 | 1183 | __qdisc_reset_queue(&sch->q); |
---|
1019 | | - sch->qstats.backlog = 0; |
---|
1020 | 1184 | } |
---|
1021 | 1185 | |
---|
1022 | 1186 | static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new, |
---|
.. | .. |
---|
1027 | 1191 | sch_tree_lock(sch); |
---|
1028 | 1192 | old = *pold; |
---|
1029 | 1193 | *pold = new; |
---|
1030 | | - if (old != NULL) { |
---|
1031 | | - unsigned int qlen = old->q.qlen; |
---|
1032 | | - unsigned int backlog = old->qstats.backlog; |
---|
1033 | | - |
---|
1034 | | - qdisc_reset(old); |
---|
1035 | | - qdisc_tree_reduce_backlog(old, qlen, backlog); |
---|
1036 | | - } |
---|
| 1194 | + if (old != NULL) |
---|
| 1195 | + qdisc_purge_queue(old); |
---|
1037 | 1196 | sch_tree_unlock(sch); |
---|
1038 | 1197 | |
---|
1039 | 1198 | return old; |
---|
.. | .. |
---|
1134 | 1293 | */ |
---|
1135 | 1294 | struct mini_Qdisc { |
---|
1136 | 1295 | struct tcf_proto *filter_list; |
---|
| 1296 | + struct tcf_block *block; |
---|
1137 | 1297 | struct gnet_stats_basic_cpu __percpu *cpu_bstats; |
---|
1138 | 1298 | struct gnet_stats_queue __percpu *cpu_qstats; |
---|
1139 | 1299 | struct rcu_head rcu; |
---|
.. | .. |
---|
1160 | 1320 | struct tcf_proto *tp_head); |
---|
1161 | 1321 | void mini_qdisc_pair_init(struct mini_Qdisc_pair *miniqp, struct Qdisc *qdisc, |
---|
1162 | 1322 | struct mini_Qdisc __rcu **p_miniq); |
---|
| 1323 | +void mini_qdisc_pair_block_init(struct mini_Qdisc_pair *miniqp, |
---|
| 1324 | + struct tcf_block *block); |
---|
1163 | 1325 | |
---|
1164 | | -static inline void skb_tc_reinsert(struct sk_buff *skb, struct tcf_result *res) |
---|
| 1326 | +static inline int skb_tc_reinsert(struct sk_buff *skb, struct tcf_result *res) |
---|
1165 | 1327 | { |
---|
1166 | | - struct gnet_stats_queue *stats = res->qstats; |
---|
1167 | | - int ret; |
---|
1168 | | - |
---|
1169 | | - if (res->ingress) |
---|
1170 | | - ret = netif_receive_skb(skb); |
---|
1171 | | - else |
---|
1172 | | - ret = dev_queue_xmit(skb); |
---|
1173 | | - if (ret && stats) |
---|
1174 | | - qstats_overlimit_inc(res->qstats); |
---|
| 1328 | + return res->ingress ? netif_receive_skb(skb) : dev_queue_xmit(skb); |
---|
1175 | 1329 | } |
---|
1176 | 1330 | |
---|
1177 | 1331 | #endif |
---|