diff options
author | Jaroslav Kysela <perex@hera.kernel.org> | 2005-06-21 10:39:41 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@hera.kernel.org> | 2005-06-21 10:39:41 -0400 |
commit | fae6ec69c84d71b1d5bda9ede1a262c1681684aa (patch) | |
tree | eb4aff9a5c2b7d04ce09a3717bb1dd4a79fe7595 /net/sched | |
parent | bbc0274e9bb2e3f1d724d445a2bd32566b9b66f7 (diff) | |
parent | 1d345dac1f30af1cd9f3a1faa12f9f18f17f236e (diff) |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/Kconfig | 2 | ||||
-rw-r--r-- | net/sched/act_api.c | 13 | ||||
-rw-r--r-- | net/sched/cls_api.c | 5 | ||||
-rw-r--r-- | net/sched/cls_basic.c | 3 | ||||
-rw-r--r-- | net/sched/em_meta.c | 295 | ||||
-rw-r--r-- | net/sched/sch_api.c | 10 | ||||
-rw-r--r-- | net/sched/sch_dsmark.c | 373 | ||||
-rw-r--r-- | net/sched/sch_fifo.c | 152 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 84 |
9 files changed, 550 insertions, 387 deletions
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index b0941186f867..b22c9beb604d 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -405,7 +405,7 @@ config NET_EMATCH_STACK | |||
405 | ---help--- | 405 | ---help--- |
406 | Size of the local stack variable used while evaluating the tree of | 406 | Size of the local stack variable used while evaluating the tree of |
407 | ematches. Limits the depth of the tree, i.e. the number of | 407 | ematches. Limits the depth of the tree, i.e. the number of |
408 | encapsulated precedences. Every level requires 4 bytes of addtional | 408 | encapsulated precedences. Every level requires 4 bytes of additional |
409 | stack space. | 409 | stack space. |
410 | 410 | ||
411 | config NET_EMATCH_CMP | 411 | config NET_EMATCH_CMP |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index cafcb084098d..9594206e6035 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -428,15 +428,15 @@ errout: | |||
428 | 428 | ||
429 | static int | 429 | static int |
430 | tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq, | 430 | tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq, |
431 | unsigned flags, int event, int bind, int ref) | 431 | u16 flags, int event, int bind, int ref) |
432 | { | 432 | { |
433 | struct tcamsg *t; | 433 | struct tcamsg *t; |
434 | struct nlmsghdr *nlh; | 434 | struct nlmsghdr *nlh; |
435 | unsigned char *b = skb->tail; | 435 | unsigned char *b = skb->tail; |
436 | struct rtattr *x; | 436 | struct rtattr *x; |
437 | 437 | ||
438 | nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*t)); | 438 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags); |
439 | nlh->nlmsg_flags = flags; | 439 | |
440 | t = NLMSG_DATA(nlh); | 440 | t = NLMSG_DATA(nlh); |
441 | t->tca_family = AF_UNSPEC; | 441 | t->tca_family = AF_UNSPEC; |
442 | 442 | ||
@@ -669,7 +669,7 @@ err: | |||
669 | } | 669 | } |
670 | 670 | ||
671 | static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, | 671 | static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, |
672 | unsigned flags) | 672 | u16 flags) |
673 | { | 673 | { |
674 | struct tcamsg *t; | 674 | struct tcamsg *t; |
675 | struct nlmsghdr *nlh; | 675 | struct nlmsghdr *nlh; |
@@ -684,8 +684,7 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, | |||
684 | 684 | ||
685 | b = (unsigned char *)skb->tail; | 685 | b = (unsigned char *)skb->tail; |
686 | 686 | ||
687 | nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*t)); | 687 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags); |
688 | nlh->nlmsg_flags = flags; | ||
689 | t = NLMSG_DATA(nlh); | 688 | t = NLMSG_DATA(nlh); |
690 | t->tca_family = AF_UNSPEC; | 689 | t->tca_family = AF_UNSPEC; |
691 | 690 | ||
@@ -881,7 +880,7 @@ static int __init tc_action_init(void) | |||
881 | link_p[RTM_GETACTION-RTM_BASE].dumpit = tc_dump_action; | 880 | link_p[RTM_GETACTION-RTM_BASE].dumpit = tc_dump_action; |
882 | } | 881 | } |
883 | 882 | ||
884 | printk("TC classifier action (bugs to netdev@oss.sgi.com cc " | 883 | printk("TC classifier action (bugs to netdev@vger.kernel.org cc " |
885 | "hadi@cyberus.ca)\n"); | 884 | "hadi@cyberus.ca)\n"); |
886 | return 0; | 885 | return 0; |
887 | } | 886 | } |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 56e66c3fe0fa..1616bf5c9627 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -322,14 +322,13 @@ errout: | |||
322 | 322 | ||
323 | static int | 323 | static int |
324 | tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh, | 324 | tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh, |
325 | u32 pid, u32 seq, unsigned flags, int event) | 325 | u32 pid, u32 seq, u16 flags, int event) |
326 | { | 326 | { |
327 | struct tcmsg *tcm; | 327 | struct tcmsg *tcm; |
328 | struct nlmsghdr *nlh; | 328 | struct nlmsghdr *nlh; |
329 | unsigned char *b = skb->tail; | 329 | unsigned char *b = skb->tail; |
330 | 330 | ||
331 | nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm)); | 331 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
332 | nlh->nlmsg_flags = flags; | ||
333 | tcm = NLMSG_DATA(nlh); | 332 | tcm = NLMSG_DATA(nlh); |
334 | tcm->tcm_family = AF_UNSPEC; | 333 | tcm->tcm_family = AF_UNSPEC; |
335 | tcm->tcm_ifindex = tp->q->dev->ifindex; | 334 | tcm->tcm_ifindex = tp->q->dev->ifindex; |
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 0d2d4415f334..dfb300bb6baa 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -261,6 +261,9 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh, | |||
261 | rta = (struct rtattr *) b; | 261 | rta = (struct rtattr *) b; |
262 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); | 262 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
263 | 263 | ||
264 | if (f->res.classid) | ||
265 | RTA_PUT(skb, TCA_BASIC_CLASSID, sizeof(u32), &f->res.classid); | ||
266 | |||
264 | if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 || | 267 | if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 || |
265 | tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0) | 268 | tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0) |
266 | goto rtattr_failure; | 269 | goto rtattr_failure; |
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index f1eeaf65cee5..48bb23c2a35a 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c | |||
@@ -32,7 +32,7 @@ | |||
32 | * +-----------+ +-----------+ | 32 | * +-----------+ +-----------+ |
33 | * | | | 33 | * | | |
34 | * ---> meta_ops[INT][INDEV](...) | | 34 | * ---> meta_ops[INT][INDEV](...) | |
35 | * | | | 35 | * | | |
36 | * ----------- | | 36 | * ----------- | |
37 | * V V | 37 | * V V |
38 | * +-----------+ +-----------+ | 38 | * +-----------+ +-----------+ |
@@ -70,6 +70,7 @@ | |||
70 | #include <net/dst.h> | 70 | #include <net/dst.h> |
71 | #include <net/route.h> | 71 | #include <net/route.h> |
72 | #include <net/pkt_cls.h> | 72 | #include <net/pkt_cls.h> |
73 | #include <net/sock.h> | ||
73 | 74 | ||
74 | struct meta_obj | 75 | struct meta_obj |
75 | { | 76 | { |
@@ -284,6 +285,214 @@ META_COLLECTOR(int_rtiif) | |||
284 | } | 285 | } |
285 | 286 | ||
286 | /************************************************************************** | 287 | /************************************************************************** |
288 | * Socket Attributes | ||
289 | **************************************************************************/ | ||
290 | |||
291 | #define SKIP_NONLOCAL(skb) \ | ||
292 | if (unlikely(skb->sk == NULL)) { \ | ||
293 | *err = -1; \ | ||
294 | return; \ | ||
295 | } | ||
296 | |||
297 | META_COLLECTOR(int_sk_family) | ||
298 | { | ||
299 | SKIP_NONLOCAL(skb); | ||
300 | dst->value = skb->sk->sk_family; | ||
301 | } | ||
302 | |||
303 | META_COLLECTOR(int_sk_state) | ||
304 | { | ||
305 | SKIP_NONLOCAL(skb); | ||
306 | dst->value = skb->sk->sk_state; | ||
307 | } | ||
308 | |||
309 | META_COLLECTOR(int_sk_reuse) | ||
310 | { | ||
311 | SKIP_NONLOCAL(skb); | ||
312 | dst->value = skb->sk->sk_reuse; | ||
313 | } | ||
314 | |||
315 | META_COLLECTOR(int_sk_bound_if) | ||
316 | { | ||
317 | SKIP_NONLOCAL(skb); | ||
318 | /* No error if bound_dev_if is 0, legal userspace check */ | ||
319 | dst->value = skb->sk->sk_bound_dev_if; | ||
320 | } | ||
321 | |||
322 | META_COLLECTOR(var_sk_bound_if) | ||
323 | { | ||
324 | SKIP_NONLOCAL(skb); | ||
325 | |||
326 | if (skb->sk->sk_bound_dev_if == 0) { | ||
327 | dst->value = (unsigned long) "any"; | ||
328 | dst->len = 3; | ||
329 | } else { | ||
330 | struct net_device *dev; | ||
331 | |||
332 | dev = dev_get_by_index(skb->sk->sk_bound_dev_if); | ||
333 | *err = var_dev(dev, dst); | ||
334 | if (dev) | ||
335 | dev_put(dev); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | META_COLLECTOR(int_sk_refcnt) | ||
340 | { | ||
341 | SKIP_NONLOCAL(skb); | ||
342 | dst->value = atomic_read(&skb->sk->sk_refcnt); | ||
343 | } | ||
344 | |||
345 | META_COLLECTOR(int_sk_rcvbuf) | ||
346 | { | ||
347 | SKIP_NONLOCAL(skb); | ||
348 | dst->value = skb->sk->sk_rcvbuf; | ||
349 | } | ||
350 | |||
351 | META_COLLECTOR(int_sk_shutdown) | ||
352 | { | ||
353 | SKIP_NONLOCAL(skb); | ||
354 | dst->value = skb->sk->sk_shutdown; | ||
355 | } | ||
356 | |||
357 | META_COLLECTOR(int_sk_proto) | ||
358 | { | ||
359 | SKIP_NONLOCAL(skb); | ||
360 | dst->value = skb->sk->sk_protocol; | ||
361 | } | ||
362 | |||
363 | META_COLLECTOR(int_sk_type) | ||
364 | { | ||
365 | SKIP_NONLOCAL(skb); | ||
366 | dst->value = skb->sk->sk_type; | ||
367 | } | ||
368 | |||
369 | META_COLLECTOR(int_sk_rmem_alloc) | ||
370 | { | ||
371 | SKIP_NONLOCAL(skb); | ||
372 | dst->value = atomic_read(&skb->sk->sk_rmem_alloc); | ||
373 | } | ||
374 | |||
375 | META_COLLECTOR(int_sk_wmem_alloc) | ||
376 | { | ||
377 | SKIP_NONLOCAL(skb); | ||
378 | dst->value = atomic_read(&skb->sk->sk_wmem_alloc); | ||
379 | } | ||
380 | |||
381 | META_COLLECTOR(int_sk_omem_alloc) | ||
382 | { | ||
383 | SKIP_NONLOCAL(skb); | ||
384 | dst->value = atomic_read(&skb->sk->sk_omem_alloc); | ||
385 | } | ||
386 | |||
387 | META_COLLECTOR(int_sk_rcv_qlen) | ||
388 | { | ||
389 | SKIP_NONLOCAL(skb); | ||
390 | dst->value = skb->sk->sk_receive_queue.qlen; | ||
391 | } | ||
392 | |||
393 | META_COLLECTOR(int_sk_snd_qlen) | ||
394 | { | ||
395 | SKIP_NONLOCAL(skb); | ||
396 | dst->value = skb->sk->sk_write_queue.qlen; | ||
397 | } | ||
398 | |||
399 | META_COLLECTOR(int_sk_wmem_queued) | ||
400 | { | ||
401 | SKIP_NONLOCAL(skb); | ||
402 | dst->value = skb->sk->sk_wmem_queued; | ||
403 | } | ||
404 | |||
405 | META_COLLECTOR(int_sk_fwd_alloc) | ||
406 | { | ||
407 | SKIP_NONLOCAL(skb); | ||
408 | dst->value = skb->sk->sk_forward_alloc; | ||
409 | } | ||
410 | |||
411 | META_COLLECTOR(int_sk_sndbuf) | ||
412 | { | ||
413 | SKIP_NONLOCAL(skb); | ||
414 | dst->value = skb->sk->sk_sndbuf; | ||
415 | } | ||
416 | |||
417 | META_COLLECTOR(int_sk_alloc) | ||
418 | { | ||
419 | SKIP_NONLOCAL(skb); | ||
420 | dst->value = skb->sk->sk_allocation; | ||
421 | } | ||
422 | |||
423 | META_COLLECTOR(int_sk_route_caps) | ||
424 | { | ||
425 | SKIP_NONLOCAL(skb); | ||
426 | dst->value = skb->sk->sk_route_caps; | ||
427 | } | ||
428 | |||
429 | META_COLLECTOR(int_sk_hashent) | ||
430 | { | ||
431 | SKIP_NONLOCAL(skb); | ||
432 | dst->value = skb->sk->sk_hashent; | ||
433 | } | ||
434 | |||
435 | META_COLLECTOR(int_sk_lingertime) | ||
436 | { | ||
437 | SKIP_NONLOCAL(skb); | ||
438 | dst->value = skb->sk->sk_lingertime / HZ; | ||
439 | } | ||
440 | |||
441 | META_COLLECTOR(int_sk_err_qlen) | ||
442 | { | ||
443 | SKIP_NONLOCAL(skb); | ||
444 | dst->value = skb->sk->sk_error_queue.qlen; | ||
445 | } | ||
446 | |||
447 | META_COLLECTOR(int_sk_ack_bl) | ||
448 | { | ||
449 | SKIP_NONLOCAL(skb); | ||
450 | dst->value = skb->sk->sk_ack_backlog; | ||
451 | } | ||
452 | |||
453 | META_COLLECTOR(int_sk_max_ack_bl) | ||
454 | { | ||
455 | SKIP_NONLOCAL(skb); | ||
456 | dst->value = skb->sk->sk_max_ack_backlog; | ||
457 | } | ||
458 | |||
459 | META_COLLECTOR(int_sk_prio) | ||
460 | { | ||
461 | SKIP_NONLOCAL(skb); | ||
462 | dst->value = skb->sk->sk_priority; | ||
463 | } | ||
464 | |||
465 | META_COLLECTOR(int_sk_rcvlowat) | ||
466 | { | ||
467 | SKIP_NONLOCAL(skb); | ||
468 | dst->value = skb->sk->sk_rcvlowat; | ||
469 | } | ||
470 | |||
471 | META_COLLECTOR(int_sk_rcvtimeo) | ||
472 | { | ||
473 | SKIP_NONLOCAL(skb); | ||
474 | dst->value = skb->sk->sk_rcvtimeo / HZ; | ||
475 | } | ||
476 | |||
477 | META_COLLECTOR(int_sk_sndtimeo) | ||
478 | { | ||
479 | SKIP_NONLOCAL(skb); | ||
480 | dst->value = skb->sk->sk_sndtimeo / HZ; | ||
481 | } | ||
482 | |||
483 | META_COLLECTOR(int_sk_sendmsg_off) | ||
484 | { | ||
485 | SKIP_NONLOCAL(skb); | ||
486 | dst->value = skb->sk->sk_sndmsg_off; | ||
487 | } | ||
488 | |||
489 | META_COLLECTOR(int_sk_write_pend) | ||
490 | { | ||
491 | SKIP_NONLOCAL(skb); | ||
492 | dst->value = skb->sk->sk_write_pending; | ||
493 | } | ||
494 | |||
495 | /************************************************************************** | ||
287 | * Meta value collectors assignment table | 496 | * Meta value collectors assignment table |
288 | **************************************************************************/ | 497 | **************************************************************************/ |
289 | 498 | ||
@@ -293,41 +502,75 @@ struct meta_ops | |||
293 | struct meta_value *, struct meta_obj *, int *); | 502 | struct meta_value *, struct meta_obj *, int *); |
294 | }; | 503 | }; |
295 | 504 | ||
505 | #define META_ID(name) TCF_META_ID_##name | ||
506 | #define META_FUNC(name) { .get = meta_##name } | ||
507 | |||
296 | /* Meta value operations table listing all meta value collectors and | 508 | /* Meta value operations table listing all meta value collectors and |
297 | * assigns them to a type and meta id. */ | 509 | * assigns them to a type and meta id. */ |
298 | static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { | 510 | static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { |
299 | [TCF_META_TYPE_VAR] = { | 511 | [TCF_META_TYPE_VAR] = { |
300 | [TCF_META_ID_DEV] = { .get = meta_var_dev }, | 512 | [META_ID(DEV)] = META_FUNC(var_dev), |
301 | [TCF_META_ID_INDEV] = { .get = meta_var_indev }, | 513 | [META_ID(INDEV)] = META_FUNC(var_indev), |
302 | [TCF_META_ID_REALDEV] = { .get = meta_var_realdev } | 514 | [META_ID(REALDEV)] = META_FUNC(var_realdev), |
515 | [META_ID(SK_BOUND_IF)] = META_FUNC(var_sk_bound_if), | ||
303 | }, | 516 | }, |
304 | [TCF_META_TYPE_INT] = { | 517 | [TCF_META_TYPE_INT] = { |
305 | [TCF_META_ID_RANDOM] = { .get = meta_int_random }, | 518 | [META_ID(RANDOM)] = META_FUNC(int_random), |
306 | [TCF_META_ID_LOADAVG_0] = { .get = meta_int_loadavg_0 }, | 519 | [META_ID(LOADAVG_0)] = META_FUNC(int_loadavg_0), |
307 | [TCF_META_ID_LOADAVG_1] = { .get = meta_int_loadavg_1 }, | 520 | [META_ID(LOADAVG_1)] = META_FUNC(int_loadavg_1), |
308 | [TCF_META_ID_LOADAVG_2] = { .get = meta_int_loadavg_2 }, | 521 | [META_ID(LOADAVG_2)] = META_FUNC(int_loadavg_2), |
309 | [TCF_META_ID_DEV] = { .get = meta_int_dev }, | 522 | [META_ID(DEV)] = META_FUNC(int_dev), |
310 | [TCF_META_ID_INDEV] = { .get = meta_int_indev }, | 523 | [META_ID(INDEV)] = META_FUNC(int_indev), |
311 | [TCF_META_ID_REALDEV] = { .get = meta_int_realdev }, | 524 | [META_ID(REALDEV)] = META_FUNC(int_realdev), |
312 | [TCF_META_ID_PRIORITY] = { .get = meta_int_priority }, | 525 | [META_ID(PRIORITY)] = META_FUNC(int_priority), |
313 | [TCF_META_ID_PROTOCOL] = { .get = meta_int_protocol }, | 526 | [META_ID(PROTOCOL)] = META_FUNC(int_protocol), |
314 | [TCF_META_ID_SECURITY] = { .get = meta_int_security }, | 527 | [META_ID(SECURITY)] = META_FUNC(int_security), |
315 | [TCF_META_ID_PKTTYPE] = { .get = meta_int_pkttype }, | 528 | [META_ID(PKTTYPE)] = META_FUNC(int_pkttype), |
316 | [TCF_META_ID_PKTLEN] = { .get = meta_int_pktlen }, | 529 | [META_ID(PKTLEN)] = META_FUNC(int_pktlen), |
317 | [TCF_META_ID_DATALEN] = { .get = meta_int_datalen }, | 530 | [META_ID(DATALEN)] = META_FUNC(int_datalen), |
318 | [TCF_META_ID_MACLEN] = { .get = meta_int_maclen }, | 531 | [META_ID(MACLEN)] = META_FUNC(int_maclen), |
319 | #ifdef CONFIG_NETFILTER | 532 | #ifdef CONFIG_NETFILTER |
320 | [TCF_META_ID_NFMARK] = { .get = meta_int_nfmark }, | 533 | [META_ID(NFMARK)] = META_FUNC(int_nfmark), |
321 | #endif | 534 | #endif |
322 | [TCF_META_ID_TCINDEX] = { .get = meta_int_tcindex }, | 535 | [META_ID(TCINDEX)] = META_FUNC(int_tcindex), |
323 | #ifdef CONFIG_NET_CLS_ACT | 536 | #ifdef CONFIG_NET_CLS_ACT |
324 | [TCF_META_ID_TCVERDICT] = { .get = meta_int_tcverd }, | 537 | [META_ID(TCVERDICT)] = META_FUNC(int_tcverd), |
325 | [TCF_META_ID_TCCLASSID] = { .get = meta_int_tcclassid }, | 538 | [META_ID(TCCLASSID)] = META_FUNC(int_tcclassid), |
326 | #endif | 539 | #endif |
327 | #ifdef CONFIG_NET_CLS_ROUTE | 540 | #ifdef CONFIG_NET_CLS_ROUTE |
328 | [TCF_META_ID_RTCLASSID] = { .get = meta_int_rtclassid }, | 541 | [META_ID(RTCLASSID)] = META_FUNC(int_rtclassid), |
329 | #endif | 542 | #endif |
330 | [TCF_META_ID_RTIIF] = { .get = meta_int_rtiif } | 543 | [META_ID(RTIIF)] = META_FUNC(int_rtiif), |
544 | [META_ID(SK_FAMILY)] = META_FUNC(int_sk_family), | ||
545 | [META_ID(SK_STATE)] = META_FUNC(int_sk_state), | ||
546 | [META_ID(SK_REUSE)] = META_FUNC(int_sk_reuse), | ||
547 | [META_ID(SK_BOUND_IF)] = META_FUNC(int_sk_bound_if), | ||
548 | [META_ID(SK_REFCNT)] = META_FUNC(int_sk_refcnt), | ||
549 | [META_ID(SK_RCVBUF)] = META_FUNC(int_sk_rcvbuf), | ||
550 | [META_ID(SK_SNDBUF)] = META_FUNC(int_sk_sndbuf), | ||
551 | [META_ID(SK_SHUTDOWN)] = META_FUNC(int_sk_shutdown), | ||
552 | [META_ID(SK_PROTO)] = META_FUNC(int_sk_proto), | ||
553 | [META_ID(SK_TYPE)] = META_FUNC(int_sk_type), | ||
554 | [META_ID(SK_RMEM_ALLOC)] = META_FUNC(int_sk_rmem_alloc), | ||
555 | [META_ID(SK_WMEM_ALLOC)] = META_FUNC(int_sk_wmem_alloc), | ||
556 | [META_ID(SK_OMEM_ALLOC)] = META_FUNC(int_sk_omem_alloc), | ||
557 | [META_ID(SK_WMEM_QUEUED)] = META_FUNC(int_sk_wmem_queued), | ||
558 | [META_ID(SK_RCV_QLEN)] = META_FUNC(int_sk_rcv_qlen), | ||
559 | [META_ID(SK_SND_QLEN)] = META_FUNC(int_sk_snd_qlen), | ||
560 | [META_ID(SK_ERR_QLEN)] = META_FUNC(int_sk_err_qlen), | ||
561 | [META_ID(SK_FORWARD_ALLOCS)] = META_FUNC(int_sk_fwd_alloc), | ||
562 | [META_ID(SK_ALLOCS)] = META_FUNC(int_sk_alloc), | ||
563 | [META_ID(SK_ROUTE_CAPS)] = META_FUNC(int_sk_route_caps), | ||
564 | [META_ID(SK_HASHENT)] = META_FUNC(int_sk_hashent), | ||
565 | [META_ID(SK_LINGERTIME)] = META_FUNC(int_sk_lingertime), | ||
566 | [META_ID(SK_ACK_BACKLOG)] = META_FUNC(int_sk_ack_bl), | ||
567 | [META_ID(SK_MAX_ACK_BACKLOG)] = META_FUNC(int_sk_max_ack_bl), | ||
568 | [META_ID(SK_PRIO)] = META_FUNC(int_sk_prio), | ||
569 | [META_ID(SK_RCVLOWAT)] = META_FUNC(int_sk_rcvlowat), | ||
570 | [META_ID(SK_RCVTIMEO)] = META_FUNC(int_sk_rcvtimeo), | ||
571 | [META_ID(SK_SNDTIMEO)] = META_FUNC(int_sk_sndtimeo), | ||
572 | [META_ID(SK_SENDMSG_OFF)] = META_FUNC(int_sk_sendmsg_off), | ||
573 | [META_ID(SK_WRITE_PENDING)] = META_FUNC(int_sk_write_pend), | ||
331 | } | 574 | } |
332 | }; | 575 | }; |
333 | 576 | ||
@@ -396,9 +639,9 @@ static int meta_int_compare(struct meta_obj *a, struct meta_obj *b) | |||
396 | /* Let gcc optimize it, the unlikely is not really based on | 639 | /* Let gcc optimize it, the unlikely is not really based on |
397 | * some numbers but jump free code for mismatches seems | 640 | * some numbers but jump free code for mismatches seems |
398 | * more logical. */ | 641 | * more logical. */ |
399 | if (unlikely(a == b)) | 642 | if (unlikely(a->value == b->value)) |
400 | return 0; | 643 | return 0; |
401 | else if (a < b) | 644 | else if (a->value < b->value) |
402 | return -1; | 645 | return -1; |
403 | else | 646 | else |
404 | return 1; | 647 | return 1; |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 07977f8f2679..97c1c75d5c78 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -760,15 +760,14 @@ graft: | |||
760 | } | 760 | } |
761 | 761 | ||
762 | static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | 762 | static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, |
763 | u32 pid, u32 seq, unsigned flags, int event) | 763 | u32 pid, u32 seq, u16 flags, int event) |
764 | { | 764 | { |
765 | struct tcmsg *tcm; | 765 | struct tcmsg *tcm; |
766 | struct nlmsghdr *nlh; | 766 | struct nlmsghdr *nlh; |
767 | unsigned char *b = skb->tail; | 767 | unsigned char *b = skb->tail; |
768 | struct gnet_dump d; | 768 | struct gnet_dump d; |
769 | 769 | ||
770 | nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm)); | 770 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
771 | nlh->nlmsg_flags = flags; | ||
772 | tcm = NLMSG_DATA(nlh); | 771 | tcm = NLMSG_DATA(nlh); |
773 | tcm->tcm_family = AF_UNSPEC; | 772 | tcm->tcm_family = AF_UNSPEC; |
774 | tcm->tcm_ifindex = q->dev->ifindex; | 773 | tcm->tcm_ifindex = q->dev->ifindex; |
@@ -997,7 +996,7 @@ out: | |||
997 | 996 | ||
998 | static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, | 997 | static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, |
999 | unsigned long cl, | 998 | unsigned long cl, |
1000 | u32 pid, u32 seq, unsigned flags, int event) | 999 | u32 pid, u32 seq, u16 flags, int event) |
1001 | { | 1000 | { |
1002 | struct tcmsg *tcm; | 1001 | struct tcmsg *tcm; |
1003 | struct nlmsghdr *nlh; | 1002 | struct nlmsghdr *nlh; |
@@ -1005,8 +1004,7 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, | |||
1005 | struct gnet_dump d; | 1004 | struct gnet_dump d; |
1006 | struct Qdisc_class_ops *cl_ops = q->ops->cl_ops; | 1005 | struct Qdisc_class_ops *cl_ops = q->ops->cl_ops; |
1007 | 1006 | ||
1008 | nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm)); | 1007 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
1009 | nlh->nlmsg_flags = flags; | ||
1010 | tcm = NLMSG_DATA(nlh); | 1008 | tcm = NLMSG_DATA(nlh); |
1011 | tcm->tcm_family = AF_UNSPEC; | 1009 | tcm->tcm_family = AF_UNSPEC; |
1012 | tcm->tcm_ifindex = q->dev->ifindex; | 1010 | tcm->tcm_ifindex = q->dev->ifindex; |
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 8a3db9d95bab..13e0e7b3856b 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <asm/byteorder.h> | 18 | #include <asm/byteorder.h> |
19 | 19 | ||
20 | 20 | ||
21 | #if 1 /* control */ | 21 | #if 0 /* control */ |
22 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | 22 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) |
23 | #else | 23 | #else |
24 | #define DPRINTK(format,args...) | 24 | #define DPRINTK(format,args...) |
@@ -31,7 +31,7 @@ | |||
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | 33 | ||
34 | #define PRIV(sch) qdisc_priv(sch) | 34 | #define PRIV(sch) ((struct dsmark_qdisc_data *) qdisc_priv(sch)) |
35 | 35 | ||
36 | 36 | ||
37 | /* | 37 | /* |
@@ -55,145 +55,163 @@ | |||
55 | struct dsmark_qdisc_data { | 55 | struct dsmark_qdisc_data { |
56 | struct Qdisc *q; | 56 | struct Qdisc *q; |
57 | struct tcf_proto *filter_list; | 57 | struct tcf_proto *filter_list; |
58 | __u8 *mask; /* "owns" the array */ | 58 | u8 *mask; /* "owns" the array */ |
59 | __u8 *value; | 59 | u8 *value; |
60 | __u16 indices; | 60 | u16 indices; |
61 | __u32 default_index; /* index range is 0...0xffff */ | 61 | u32 default_index; /* index range is 0...0xffff */ |
62 | int set_tc_index; | 62 | int set_tc_index; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static inline int dsmark_valid_indices(u16 indices) | ||
66 | { | ||
67 | while (indices != 1) { | ||
68 | if (indices & 1) | ||
69 | return 0; | ||
70 | indices >>= 1; | ||
71 | } | ||
72 | |||
73 | return 1; | ||
74 | } | ||
65 | 75 | ||
66 | /* ------------------------- Class/flow operations ------------------------- */ | 76 | static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index) |
77 | { | ||
78 | return (index <= p->indices && index > 0); | ||
79 | } | ||
67 | 80 | ||
81 | /* ------------------------- Class/flow operations ------------------------- */ | ||
68 | 82 | ||
69 | static int dsmark_graft(struct Qdisc *sch,unsigned long arg, | 83 | static int dsmark_graft(struct Qdisc *sch, unsigned long arg, |
70 | struct Qdisc *new,struct Qdisc **old) | 84 | struct Qdisc *new, struct Qdisc **old) |
71 | { | 85 | { |
72 | struct dsmark_qdisc_data *p = PRIV(sch); | 86 | struct dsmark_qdisc_data *p = PRIV(sch); |
73 | 87 | ||
74 | DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",sch,p,new, | 88 | DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n", |
75 | old); | 89 | sch, p, new, old); |
76 | if (!new) | 90 | |
77 | new = &noop_qdisc; | 91 | if (new == NULL) { |
92 | new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); | ||
93 | if (new == NULL) | ||
94 | new = &noop_qdisc; | ||
95 | } | ||
96 | |||
78 | sch_tree_lock(sch); | 97 | sch_tree_lock(sch); |
79 | *old = xchg(&p->q,new); | 98 | *old = xchg(&p->q, new); |
80 | if (*old) | 99 | qdisc_reset(*old); |
81 | qdisc_reset(*old); | ||
82 | sch->q.qlen = 0; | 100 | sch->q.qlen = 0; |
83 | sch_tree_unlock(sch); /* @@@ move up ? */ | 101 | sch_tree_unlock(sch); |
102 | |||
84 | return 0; | 103 | return 0; |
85 | } | 104 | } |
86 | 105 | ||
87 | |||
88 | static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg) | 106 | static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg) |
89 | { | 107 | { |
90 | struct dsmark_qdisc_data *p = PRIV(sch); | 108 | return PRIV(sch)->q; |
91 | |||
92 | return p->q; | ||
93 | } | 109 | } |
94 | 110 | ||
95 | 111 | static unsigned long dsmark_get(struct Qdisc *sch, u32 classid) | |
96 | static unsigned long dsmark_get(struct Qdisc *sch,u32 classid) | ||
97 | { | 112 | { |
98 | struct dsmark_qdisc_data *p __attribute__((unused)) = PRIV(sch); | 113 | DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n", |
114 | sch, PRIV(sch), classid); | ||
99 | 115 | ||
100 | DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid); | 116 | return TC_H_MIN(classid) + 1; |
101 | return TC_H_MIN(classid)+1; | ||
102 | } | 117 | } |
103 | 118 | ||
104 | |||
105 | static unsigned long dsmark_bind_filter(struct Qdisc *sch, | 119 | static unsigned long dsmark_bind_filter(struct Qdisc *sch, |
106 | unsigned long parent, u32 classid) | 120 | unsigned long parent, u32 classid) |
107 | { | 121 | { |
108 | return dsmark_get(sch,classid); | 122 | return dsmark_get(sch, classid); |
109 | } | 123 | } |
110 | 124 | ||
111 | |||
112 | static void dsmark_put(struct Qdisc *sch, unsigned long cl) | 125 | static void dsmark_put(struct Qdisc *sch, unsigned long cl) |
113 | { | 126 | { |
114 | } | 127 | } |
115 | 128 | ||
116 | |||
117 | static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent, | 129 | static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent, |
118 | struct rtattr **tca, unsigned long *arg) | 130 | struct rtattr **tca, unsigned long *arg) |
119 | { | 131 | { |
120 | struct dsmark_qdisc_data *p = PRIV(sch); | 132 | struct dsmark_qdisc_data *p = PRIV(sch); |
121 | struct rtattr *opt = tca[TCA_OPTIONS-1]; | 133 | struct rtattr *opt = tca[TCA_OPTIONS-1]; |
122 | struct rtattr *tb[TCA_DSMARK_MAX]; | 134 | struct rtattr *tb[TCA_DSMARK_MAX]; |
135 | int err = -EINVAL; | ||
136 | u8 mask = 0; | ||
123 | 137 | ||
124 | DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x)," | 138 | DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x)," |
125 | "arg 0x%lx\n",sch,p,classid,parent,*arg); | 139 | "arg 0x%lx\n", sch, p, classid, parent, *arg); |
126 | if (*arg > p->indices) | 140 | |
127 | return -ENOENT; | 141 | if (!dsmark_valid_index(p, *arg)) { |
128 | if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt)) | 142 | err = -ENOENT; |
129 | return -EINVAL; | 143 | goto rtattr_failure; |
130 | if (tb[TCA_DSMARK_MASK-1]) { | ||
131 | if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1])) | ||
132 | return -EINVAL; | ||
133 | p->mask[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_MASK-1]); | ||
134 | } | ||
135 | if (tb[TCA_DSMARK_VALUE-1]) { | ||
136 | if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE-1])) | ||
137 | return -EINVAL; | ||
138 | p->value[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_VALUE-1]); | ||
139 | } | 144 | } |
140 | return 0; | ||
141 | } | ||
142 | 145 | ||
146 | if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt)) | ||
147 | goto rtattr_failure; | ||
148 | |||
149 | if (tb[TCA_DSMARK_MASK-1]) | ||
150 | mask = RTA_GET_U8(tb[TCA_DSMARK_MASK-1]); | ||
151 | |||
152 | if (tb[TCA_DSMARK_VALUE-1]) | ||
153 | p->value[*arg-1] = RTA_GET_U8(tb[TCA_DSMARK_VALUE-1]); | ||
154 | |||
155 | if (tb[TCA_DSMARK_MASK-1]) | ||
156 | p->mask[*arg-1] = mask; | ||
143 | 157 | ||
144 | static int dsmark_delete(struct Qdisc *sch,unsigned long arg) | 158 | err = 0; |
159 | |||
160 | rtattr_failure: | ||
161 | return err; | ||
162 | } | ||
163 | |||
164 | static int dsmark_delete(struct Qdisc *sch, unsigned long arg) | ||
145 | { | 165 | { |
146 | struct dsmark_qdisc_data *p = PRIV(sch); | 166 | struct dsmark_qdisc_data *p = PRIV(sch); |
147 | 167 | ||
148 | if (!arg || arg > p->indices) | 168 | if (!dsmark_valid_index(p, arg)) |
149 | return -EINVAL; | 169 | return -EINVAL; |
170 | |||
150 | p->mask[arg-1] = 0xff; | 171 | p->mask[arg-1] = 0xff; |
151 | p->value[arg-1] = 0; | 172 | p->value[arg-1] = 0; |
173 | |||
152 | return 0; | 174 | return 0; |
153 | } | 175 | } |
154 | 176 | ||
155 | |||
156 | static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker) | 177 | static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker) |
157 | { | 178 | { |
158 | struct dsmark_qdisc_data *p = PRIV(sch); | 179 | struct dsmark_qdisc_data *p = PRIV(sch); |
159 | int i; | 180 | int i; |
160 | 181 | ||
161 | DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker); | 182 | DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker); |
183 | |||
162 | if (walker->stop) | 184 | if (walker->stop) |
163 | return; | 185 | return; |
186 | |||
164 | for (i = 0; i < p->indices; i++) { | 187 | for (i = 0; i < p->indices; i++) { |
165 | if (p->mask[i] == 0xff && !p->value[i]) | 188 | if (p->mask[i] == 0xff && !p->value[i]) |
166 | continue; | 189 | goto ignore; |
167 | if (walker->count >= walker->skip) { | 190 | if (walker->count >= walker->skip) { |
168 | if (walker->fn(sch, i+1, walker) < 0) { | 191 | if (walker->fn(sch, i+1, walker) < 0) { |
169 | walker->stop = 1; | 192 | walker->stop = 1; |
170 | break; | 193 | break; |
171 | } | 194 | } |
172 | } | 195 | } |
173 | walker->count++; | 196 | ignore: |
197 | walker->count++; | ||
174 | } | 198 | } |
175 | } | 199 | } |
176 | 200 | ||
177 | |||
178 | static struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,unsigned long cl) | 201 | static struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,unsigned long cl) |
179 | { | 202 | { |
180 | struct dsmark_qdisc_data *p = PRIV(sch); | 203 | return &PRIV(sch)->filter_list; |
181 | |||
182 | return &p->filter_list; | ||
183 | } | 204 | } |
184 | 205 | ||
185 | |||
186 | /* --------------------------- Qdisc operations ---------------------------- */ | 206 | /* --------------------------- Qdisc operations ---------------------------- */ |
187 | 207 | ||
188 | |||
189 | static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) | 208 | static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) |
190 | { | 209 | { |
191 | struct dsmark_qdisc_data *p = PRIV(sch); | 210 | struct dsmark_qdisc_data *p = PRIV(sch); |
192 | struct tcf_result res; | 211 | int err; |
193 | int result; | 212 | |
194 | int ret = NET_XMIT_POLICED; | 213 | D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p); |
195 | 214 | ||
196 | D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p); | ||
197 | if (p->set_tc_index) { | 215 | if (p->set_tc_index) { |
198 | /* FIXME: Safe with non-linear skbs? --RR */ | 216 | /* FIXME: Safe with non-linear skbs? --RR */ |
199 | switch (skb->protocol) { | 217 | switch (skb->protocol) { |
@@ -210,17 +228,21 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
210 | break; | 228 | break; |
211 | }; | 229 | }; |
212 | } | 230 | } |
213 | result = TC_POLICE_OK; /* be nice to gcc */ | 231 | |
214 | if (TC_H_MAJ(skb->priority) == sch->handle) { | 232 | if (TC_H_MAJ(skb->priority) == sch->handle) |
215 | skb->tc_index = TC_H_MIN(skb->priority); | 233 | skb->tc_index = TC_H_MIN(skb->priority); |
216 | } else { | 234 | else { |
217 | result = tc_classify(skb,p->filter_list,&res); | 235 | struct tcf_result res; |
218 | D2PRINTK("result %d class 0x%04x\n",result,res.classid); | 236 | int result = tc_classify(skb, p->filter_list, &res); |
237 | |||
238 | D2PRINTK("result %d class 0x%04x\n", result, res.classid); | ||
239 | |||
219 | switch (result) { | 240 | switch (result) { |
220 | #ifdef CONFIG_NET_CLS_POLICE | 241 | #ifdef CONFIG_NET_CLS_POLICE |
221 | case TC_POLICE_SHOT: | 242 | case TC_POLICE_SHOT: |
222 | kfree_skb(skb); | 243 | kfree_skb(skb); |
223 | break; | 244 | sch->qstats.drops++; |
245 | return NET_XMIT_POLICED; | ||
224 | #if 0 | 246 | #if 0 |
225 | case TC_POLICE_RECLASSIFY: | 247 | case TC_POLICE_RECLASSIFY: |
226 | /* FIXME: what to do here ??? */ | 248 | /* FIXME: what to do here ??? */ |
@@ -237,43 +259,45 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
237 | break; | 259 | break; |
238 | }; | 260 | }; |
239 | } | 261 | } |
240 | if ( | ||
241 | #ifdef CONFIG_NET_CLS_POLICE | ||
242 | result == TC_POLICE_SHOT || | ||
243 | #endif | ||
244 | 262 | ||
245 | ((ret = p->q->enqueue(skb,p->q)) != 0)) { | 263 | err = p->q->enqueue(skb,p->q); |
264 | if (err != NET_XMIT_SUCCESS) { | ||
246 | sch->qstats.drops++; | 265 | sch->qstats.drops++; |
247 | return ret; | 266 | return err; |
248 | } | 267 | } |
268 | |||
249 | sch->bstats.bytes += skb->len; | 269 | sch->bstats.bytes += skb->len; |
250 | sch->bstats.packets++; | 270 | sch->bstats.packets++; |
251 | sch->q.qlen++; | 271 | sch->q.qlen++; |
252 | return ret; | ||
253 | } | ||
254 | 272 | ||
273 | return NET_XMIT_SUCCESS; | ||
274 | } | ||
255 | 275 | ||
256 | static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) | 276 | static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) |
257 | { | 277 | { |
258 | struct dsmark_qdisc_data *p = PRIV(sch); | 278 | struct dsmark_qdisc_data *p = PRIV(sch); |
259 | struct sk_buff *skb; | 279 | struct sk_buff *skb; |
260 | int index; | 280 | u32 index; |
281 | |||
282 | D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n", sch, p); | ||
261 | 283 | ||
262 | D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n",sch,p); | ||
263 | skb = p->q->ops->dequeue(p->q); | 284 | skb = p->q->ops->dequeue(p->q); |
264 | if (!skb) | 285 | if (skb == NULL) |
265 | return NULL; | 286 | return NULL; |
287 | |||
266 | sch->q.qlen--; | 288 | sch->q.qlen--; |
267 | index = skb->tc_index & (p->indices-1); | 289 | |
268 | D2PRINTK("index %d->%d\n",skb->tc_index,index); | 290 | index = skb->tc_index & (p->indices - 1); |
291 | D2PRINTK("index %d->%d\n", skb->tc_index, index); | ||
292 | |||
269 | switch (skb->protocol) { | 293 | switch (skb->protocol) { |
270 | case __constant_htons(ETH_P_IP): | 294 | case __constant_htons(ETH_P_IP): |
271 | ipv4_change_dsfield(skb->nh.iph, | 295 | ipv4_change_dsfield(skb->nh.iph, p->mask[index], |
272 | p->mask[index],p->value[index]); | 296 | p->value[index]); |
273 | break; | 297 | break; |
274 | case __constant_htons(ETH_P_IPV6): | 298 | case __constant_htons(ETH_P_IPV6): |
275 | ipv6_change_dsfield(skb->nh.ipv6h, | 299 | ipv6_change_dsfield(skb->nh.ipv6h, p->mask[index], |
276 | p->mask[index],p->value[index]); | 300 | p->value[index]); |
277 | break; | 301 | break; |
278 | default: | 302 | default: |
279 | /* | 303 | /* |
@@ -287,152 +311,162 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) | |||
287 | htons(skb->protocol)); | 311 | htons(skb->protocol)); |
288 | break; | 312 | break; |
289 | }; | 313 | }; |
314 | |||
290 | return skb; | 315 | return skb; |
291 | } | 316 | } |
292 | 317 | ||
293 | |||
294 | static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch) | 318 | static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch) |
295 | { | 319 | { |
296 | int ret; | ||
297 | struct dsmark_qdisc_data *p = PRIV(sch); | 320 | struct dsmark_qdisc_data *p = PRIV(sch); |
321 | int err; | ||
298 | 322 | ||
299 | D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p); | 323 | D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p); |
300 | if ((ret = p->q->ops->requeue(skb, p->q)) == 0) { | 324 | |
301 | sch->q.qlen++; | 325 | err = p->q->ops->requeue(skb, p->q); |
302 | sch->qstats.requeues++; | 326 | if (err != NET_XMIT_SUCCESS) { |
303 | return 0; | 327 | sch->qstats.drops++; |
328 | return err; | ||
304 | } | 329 | } |
305 | sch->qstats.drops++; | ||
306 | return ret; | ||
307 | } | ||
308 | 330 | ||
331 | sch->q.qlen++; | ||
332 | sch->qstats.requeues++; | ||
333 | |||
334 | return NET_XMIT_SUCCESS; | ||
335 | } | ||
309 | 336 | ||
310 | static unsigned int dsmark_drop(struct Qdisc *sch) | 337 | static unsigned int dsmark_drop(struct Qdisc *sch) |
311 | { | 338 | { |
312 | struct dsmark_qdisc_data *p = PRIV(sch); | 339 | struct dsmark_qdisc_data *p = PRIV(sch); |
313 | unsigned int len; | 340 | unsigned int len; |
314 | 341 | ||
315 | DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p); | 342 | DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n", sch, p); |
316 | if (!p->q->ops->drop) | 343 | |
317 | return 0; | 344 | if (p->q->ops->drop == NULL) |
318 | if (!(len = p->q->ops->drop(p->q))) | ||
319 | return 0; | 345 | return 0; |
320 | sch->q.qlen--; | 346 | |
347 | len = p->q->ops->drop(p->q); | ||
348 | if (len) | ||
349 | sch->q.qlen--; | ||
350 | |||
321 | return len; | 351 | return len; |
322 | } | 352 | } |
323 | 353 | ||
324 | 354 | static int dsmark_init(struct Qdisc *sch, struct rtattr *opt) | |
325 | static int dsmark_init(struct Qdisc *sch,struct rtattr *opt) | ||
326 | { | 355 | { |
327 | struct dsmark_qdisc_data *p = PRIV(sch); | 356 | struct dsmark_qdisc_data *p = PRIV(sch); |
328 | struct rtattr *tb[TCA_DSMARK_MAX]; | 357 | struct rtattr *tb[TCA_DSMARK_MAX]; |
329 | __u16 tmp; | 358 | int err = -EINVAL; |
330 | 359 | u32 default_index = NO_DEFAULT_INDEX; | |
331 | DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); | 360 | u16 indices; |
332 | if (!opt || | 361 | u8 *mask; |
333 | rtattr_parse(tb,TCA_DSMARK_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0 || | 362 | |
334 | !tb[TCA_DSMARK_INDICES-1] || | 363 | DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt); |
335 | RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16)) | 364 | |
336 | return -EINVAL; | 365 | if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt) < 0) |
337 | p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]); | 366 | goto errout; |
338 | if (!p->indices) | 367 | |
339 | return -EINVAL; | 368 | indices = RTA_GET_U16(tb[TCA_DSMARK_INDICES-1]); |
340 | for (tmp = p->indices; tmp != 1; tmp >>= 1) { | 369 | if (!indices || !dsmark_valid_indices(indices)) |
341 | if (tmp & 1) | 370 | goto errout; |
342 | return -EINVAL; | 371 | |
343 | } | 372 | if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) |
344 | p->default_index = NO_DEFAULT_INDEX; | 373 | default_index = RTA_GET_U16(tb[TCA_DSMARK_DEFAULT_INDEX-1]); |
345 | if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) { | 374 | |
346 | if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX-1]) < sizeof(__u16)) | 375 | mask = kmalloc(indices * 2, GFP_KERNEL); |
347 | return -EINVAL; | 376 | if (mask == NULL) { |
348 | p->default_index = | 377 | err = -ENOMEM; |
349 | *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]); | 378 | goto errout; |
350 | } | 379 | } |
351 | p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1]; | 380 | |
352 | p->mask = kmalloc(p->indices*2,GFP_KERNEL); | 381 | p->mask = mask; |
353 | if (!p->mask) | 382 | memset(p->mask, 0xff, indices); |
354 | return -ENOMEM; | 383 | |
355 | p->value = p->mask+p->indices; | 384 | p->value = p->mask + indices; |
356 | memset(p->mask,0xff,p->indices); | 385 | memset(p->value, 0, indices); |
357 | memset(p->value,0,p->indices); | 386 | |
358 | if (!(p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops))) | 387 | p->indices = indices; |
388 | p->default_index = default_index; | ||
389 | p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]); | ||
390 | |||
391 | p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); | ||
392 | if (p->q == NULL) | ||
359 | p->q = &noop_qdisc; | 393 | p->q = &noop_qdisc; |
360 | DPRINTK("dsmark_init: qdisc %p\n",&p->q); | ||
361 | return 0; | ||
362 | } | ||
363 | 394 | ||
395 | DPRINTK("dsmark_init: qdisc %p\n", p->q); | ||
396 | |||
397 | err = 0; | ||
398 | errout: | ||
399 | rtattr_failure: | ||
400 | return err; | ||
401 | } | ||
364 | 402 | ||
365 | static void dsmark_reset(struct Qdisc *sch) | 403 | static void dsmark_reset(struct Qdisc *sch) |
366 | { | 404 | { |
367 | struct dsmark_qdisc_data *p = PRIV(sch); | 405 | struct dsmark_qdisc_data *p = PRIV(sch); |
368 | 406 | ||
369 | DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p); | 407 | DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n", sch, p); |
370 | qdisc_reset(p->q); | 408 | qdisc_reset(p->q); |
371 | sch->q.qlen = 0; | 409 | sch->q.qlen = 0; |
372 | } | 410 | } |
373 | 411 | ||
374 | |||
375 | static void dsmark_destroy(struct Qdisc *sch) | 412 | static void dsmark_destroy(struct Qdisc *sch) |
376 | { | 413 | { |
377 | struct dsmark_qdisc_data *p = PRIV(sch); | 414 | struct dsmark_qdisc_data *p = PRIV(sch); |
378 | struct tcf_proto *tp; | 415 | struct tcf_proto *tp; |
379 | 416 | ||
380 | DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n",sch,p); | 417 | DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n", sch, p); |
418 | |||
381 | while (p->filter_list) { | 419 | while (p->filter_list) { |
382 | tp = p->filter_list; | 420 | tp = p->filter_list; |
383 | p->filter_list = tp->next; | 421 | p->filter_list = tp->next; |
384 | tcf_destroy(tp); | 422 | tcf_destroy(tp); |
385 | } | 423 | } |
424 | |||
386 | qdisc_destroy(p->q); | 425 | qdisc_destroy(p->q); |
387 | kfree(p->mask); | 426 | kfree(p->mask); |
388 | } | 427 | } |
389 | 428 | ||
390 | |||
391 | static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl, | 429 | static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl, |
392 | struct sk_buff *skb, struct tcmsg *tcm) | 430 | struct sk_buff *skb, struct tcmsg *tcm) |
393 | { | 431 | { |
394 | struct dsmark_qdisc_data *p = PRIV(sch); | 432 | struct dsmark_qdisc_data *p = PRIV(sch); |
395 | unsigned char *b = skb->tail; | 433 | struct rtattr *opts = NULL; |
396 | struct rtattr *rta; | 434 | |
435 | DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n", sch, p, cl); | ||
397 | 436 | ||
398 | DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n",sch,p,cl); | 437 | if (!dsmark_valid_index(p, cl)) |
399 | if (!cl || cl > p->indices) | ||
400 | return -EINVAL; | 438 | return -EINVAL; |
401 | tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle),cl-1); | 439 | |
402 | rta = (struct rtattr *) b; | 440 | tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1); |
403 | RTA_PUT(skb,TCA_OPTIONS,0,NULL); | 441 | |
404 | RTA_PUT(skb,TCA_DSMARK_MASK,1,&p->mask[cl-1]); | 442 | opts = RTA_NEST(skb, TCA_OPTIONS); |
405 | RTA_PUT(skb,TCA_DSMARK_VALUE,1,&p->value[cl-1]); | 443 | RTA_PUT_U8(skb,TCA_DSMARK_MASK, p->mask[cl-1]); |
406 | rta->rta_len = skb->tail-b; | 444 | RTA_PUT_U8(skb,TCA_DSMARK_VALUE, p->value[cl-1]); |
407 | return skb->len; | 445 | |
446 | return RTA_NEST_END(skb, opts); | ||
408 | 447 | ||
409 | rtattr_failure: | 448 | rtattr_failure: |
410 | skb_trim(skb,b-skb->data); | 449 | return RTA_NEST_CANCEL(skb, opts); |
411 | return -1; | ||
412 | } | 450 | } |
413 | 451 | ||
414 | static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb) | 452 | static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb) |
415 | { | 453 | { |
416 | struct dsmark_qdisc_data *p = PRIV(sch); | 454 | struct dsmark_qdisc_data *p = PRIV(sch); |
417 | unsigned char *b = skb->tail; | 455 | struct rtattr *opts = NULL; |
418 | struct rtattr *rta; | ||
419 | 456 | ||
420 | rta = (struct rtattr *) b; | 457 | opts = RTA_NEST(skb, TCA_OPTIONS); |
421 | RTA_PUT(skb,TCA_OPTIONS,0,NULL); | 458 | RTA_PUT_U16(skb, TCA_DSMARK_INDICES, p->indices); |
422 | RTA_PUT(skb,TCA_DSMARK_INDICES,sizeof(__u16),&p->indices); | 459 | |
423 | if (p->default_index != NO_DEFAULT_INDEX) { | 460 | if (p->default_index != NO_DEFAULT_INDEX) |
424 | __u16 tmp = p->default_index; | 461 | RTA_PUT_U16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index); |
425 | 462 | ||
426 | RTA_PUT(skb,TCA_DSMARK_DEFAULT_INDEX, sizeof(__u16), &tmp); | ||
427 | } | ||
428 | if (p->set_tc_index) | 463 | if (p->set_tc_index) |
429 | RTA_PUT(skb, TCA_DSMARK_SET_TC_INDEX, 0, NULL); | 464 | RTA_PUT_FLAG(skb, TCA_DSMARK_SET_TC_INDEX); |
430 | rta->rta_len = skb->tail-b; | 465 | |
431 | return skb->len; | 466 | return RTA_NEST_END(skb, opts); |
432 | 467 | ||
433 | rtattr_failure: | 468 | rtattr_failure: |
434 | skb_trim(skb,b-skb->data); | 469 | return RTA_NEST_CANCEL(skb, opts); |
435 | return -1; | ||
436 | } | 470 | } |
437 | 471 | ||
438 | static struct Qdisc_class_ops dsmark_class_ops = { | 472 | static struct Qdisc_class_ops dsmark_class_ops = { |
@@ -470,10 +504,13 @@ static int __init dsmark_module_init(void) | |||
470 | { | 504 | { |
471 | return register_qdisc(&dsmark_qdisc_ops); | 505 | return register_qdisc(&dsmark_qdisc_ops); |
472 | } | 506 | } |
507 | |||
473 | static void __exit dsmark_module_exit(void) | 508 | static void __exit dsmark_module_exit(void) |
474 | { | 509 | { |
475 | unregister_qdisc(&dsmark_qdisc_ops); | 510 | unregister_qdisc(&dsmark_qdisc_ops); |
476 | } | 511 | } |
512 | |||
477 | module_init(dsmark_module_init) | 513 | module_init(dsmark_module_init) |
478 | module_exit(dsmark_module_exit) | 514 | module_exit(dsmark_module_exit) |
515 | |||
479 | MODULE_LICENSE("GPL"); | 516 | MODULE_LICENSE("GPL"); |
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 4888305c96da..033083bf0e74 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c | |||
@@ -11,131 +11,38 @@ | |||
11 | 11 | ||
12 | #include <linux/config.h> | 12 | #include <linux/config.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <asm/uaccess.h> | ||
15 | #include <asm/system.h> | ||
16 | #include <linux/bitops.h> | ||
17 | #include <linux/types.h> | 14 | #include <linux/types.h> |
18 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
19 | #include <linux/sched.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/socket.h> | ||
23 | #include <linux/sockios.h> | ||
24 | #include <linux/in.h> | ||
25 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/if_ether.h> | ||
28 | #include <linux/inet.h> | ||
29 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
30 | #include <linux/etherdevice.h> | ||
31 | #include <linux/notifier.h> | ||
32 | #include <net/ip.h> | ||
33 | #include <net/route.h> | ||
34 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
35 | #include <net/sock.h> | ||
36 | #include <net/pkt_sched.h> | 19 | #include <net/pkt_sched.h> |
37 | 20 | ||
38 | /* 1 band FIFO pseudo-"scheduler" */ | 21 | /* 1 band FIFO pseudo-"scheduler" */ |
39 | 22 | ||
40 | struct fifo_sched_data | 23 | struct fifo_sched_data |
41 | { | 24 | { |
42 | unsigned limit; | 25 | u32 limit; |
43 | }; | 26 | }; |
44 | 27 | ||
45 | static int | 28 | static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) |
46 | bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) | ||
47 | { | 29 | { |
48 | struct fifo_sched_data *q = qdisc_priv(sch); | 30 | struct fifo_sched_data *q = qdisc_priv(sch); |
49 | 31 | ||
50 | if (sch->qstats.backlog + skb->len <= q->limit) { | 32 | if (likely(sch->qstats.backlog + skb->len <= q->limit)) |
51 | __skb_queue_tail(&sch->q, skb); | 33 | return qdisc_enqueue_tail(skb, sch); |
52 | sch->qstats.backlog += skb->len; | ||
53 | sch->bstats.bytes += skb->len; | ||
54 | sch->bstats.packets++; | ||
55 | return 0; | ||
56 | } | ||
57 | sch->qstats.drops++; | ||
58 | #ifdef CONFIG_NET_CLS_POLICE | ||
59 | if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch)) | ||
60 | #endif | ||
61 | kfree_skb(skb); | ||
62 | return NET_XMIT_DROP; | ||
63 | } | ||
64 | |||
65 | static int | ||
66 | bfifo_requeue(struct sk_buff *skb, struct Qdisc* sch) | ||
67 | { | ||
68 | __skb_queue_head(&sch->q, skb); | ||
69 | sch->qstats.backlog += skb->len; | ||
70 | sch->qstats.requeues++; | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static struct sk_buff * | ||
75 | bfifo_dequeue(struct Qdisc* sch) | ||
76 | { | ||
77 | struct sk_buff *skb; | ||
78 | 34 | ||
79 | skb = __skb_dequeue(&sch->q); | 35 | return qdisc_reshape_fail(skb, sch); |
80 | if (skb) | ||
81 | sch->qstats.backlog -= skb->len; | ||
82 | return skb; | ||
83 | } | 36 | } |
84 | 37 | ||
85 | static unsigned int | 38 | static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) |
86 | fifo_drop(struct Qdisc* sch) | ||
87 | { | ||
88 | struct sk_buff *skb; | ||
89 | |||
90 | skb = __skb_dequeue_tail(&sch->q); | ||
91 | if (skb) { | ||
92 | unsigned int len = skb->len; | ||
93 | sch->qstats.backlog -= len; | ||
94 | kfree_skb(skb); | ||
95 | return len; | ||
96 | } | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static void | ||
101 | fifo_reset(struct Qdisc* sch) | ||
102 | { | ||
103 | skb_queue_purge(&sch->q); | ||
104 | sch->qstats.backlog = 0; | ||
105 | } | ||
106 | |||
107 | static int | ||
108 | pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) | ||
109 | { | 39 | { |
110 | struct fifo_sched_data *q = qdisc_priv(sch); | 40 | struct fifo_sched_data *q = qdisc_priv(sch); |
111 | 41 | ||
112 | if (sch->q.qlen < q->limit) { | 42 | if (likely(skb_queue_len(&sch->q) < q->limit)) |
113 | __skb_queue_tail(&sch->q, skb); | 43 | return qdisc_enqueue_tail(skb, sch); |
114 | sch->bstats.bytes += skb->len; | ||
115 | sch->bstats.packets++; | ||
116 | return 0; | ||
117 | } | ||
118 | sch->qstats.drops++; | ||
119 | #ifdef CONFIG_NET_CLS_POLICE | ||
120 | if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch)) | ||
121 | #endif | ||
122 | kfree_skb(skb); | ||
123 | return NET_XMIT_DROP; | ||
124 | } | ||
125 | |||
126 | static int | ||
127 | pfifo_requeue(struct sk_buff *skb, struct Qdisc* sch) | ||
128 | { | ||
129 | __skb_queue_head(&sch->q, skb); | ||
130 | sch->qstats.requeues++; | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | 44 | ||
135 | static struct sk_buff * | 45 | return qdisc_reshape_fail(skb, sch); |
136 | pfifo_dequeue(struct Qdisc* sch) | ||
137 | { | ||
138 | return __skb_dequeue(&sch->q); | ||
139 | } | 46 | } |
140 | 47 | ||
141 | static int fifo_init(struct Qdisc *sch, struct rtattr *opt) | 48 | static int fifo_init(struct Qdisc *sch, struct rtattr *opt) |
@@ -143,66 +50,59 @@ static int fifo_init(struct Qdisc *sch, struct rtattr *opt) | |||
143 | struct fifo_sched_data *q = qdisc_priv(sch); | 50 | struct fifo_sched_data *q = qdisc_priv(sch); |
144 | 51 | ||
145 | if (opt == NULL) { | 52 | if (opt == NULL) { |
146 | unsigned int limit = sch->dev->tx_queue_len ? : 1; | 53 | u32 limit = sch->dev->tx_queue_len ? : 1; |
147 | 54 | ||
148 | if (sch->ops == &bfifo_qdisc_ops) | 55 | if (sch->ops == &bfifo_qdisc_ops) |
149 | q->limit = limit*sch->dev->mtu; | 56 | limit *= sch->dev->mtu; |
150 | else | 57 | |
151 | q->limit = limit; | 58 | q->limit = limit; |
152 | } else { | 59 | } else { |
153 | struct tc_fifo_qopt *ctl = RTA_DATA(opt); | 60 | struct tc_fifo_qopt *ctl = RTA_DATA(opt); |
154 | if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) | 61 | |
62 | if (RTA_PAYLOAD(opt) < sizeof(*ctl)) | ||
155 | return -EINVAL; | 63 | return -EINVAL; |
64 | |||
156 | q->limit = ctl->limit; | 65 | q->limit = ctl->limit; |
157 | } | 66 | } |
67 | |||
158 | return 0; | 68 | return 0; |
159 | } | 69 | } |
160 | 70 | ||
161 | static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb) | 71 | static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb) |
162 | { | 72 | { |
163 | struct fifo_sched_data *q = qdisc_priv(sch); | 73 | struct fifo_sched_data *q = qdisc_priv(sch); |
164 | unsigned char *b = skb->tail; | 74 | struct tc_fifo_qopt opt = { .limit = q->limit }; |
165 | struct tc_fifo_qopt opt; | ||
166 | 75 | ||
167 | opt.limit = q->limit; | ||
168 | RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | 76 | RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); |
169 | |||
170 | return skb->len; | 77 | return skb->len; |
171 | 78 | ||
172 | rtattr_failure: | 79 | rtattr_failure: |
173 | skb_trim(skb, b - skb->data); | ||
174 | return -1; | 80 | return -1; |
175 | } | 81 | } |
176 | 82 | ||
177 | struct Qdisc_ops pfifo_qdisc_ops = { | 83 | struct Qdisc_ops pfifo_qdisc_ops = { |
178 | .next = NULL, | ||
179 | .cl_ops = NULL, | ||
180 | .id = "pfifo", | 84 | .id = "pfifo", |
181 | .priv_size = sizeof(struct fifo_sched_data), | 85 | .priv_size = sizeof(struct fifo_sched_data), |
182 | .enqueue = pfifo_enqueue, | 86 | .enqueue = pfifo_enqueue, |
183 | .dequeue = pfifo_dequeue, | 87 | .dequeue = qdisc_dequeue_head, |
184 | .requeue = pfifo_requeue, | 88 | .requeue = qdisc_requeue, |
185 | .drop = fifo_drop, | 89 | .drop = qdisc_queue_drop, |
186 | .init = fifo_init, | 90 | .init = fifo_init, |
187 | .reset = fifo_reset, | 91 | .reset = qdisc_reset_queue, |
188 | .destroy = NULL, | ||
189 | .change = fifo_init, | 92 | .change = fifo_init, |
190 | .dump = fifo_dump, | 93 | .dump = fifo_dump, |
191 | .owner = THIS_MODULE, | 94 | .owner = THIS_MODULE, |
192 | }; | 95 | }; |
193 | 96 | ||
194 | struct Qdisc_ops bfifo_qdisc_ops = { | 97 | struct Qdisc_ops bfifo_qdisc_ops = { |
195 | .next = NULL, | ||
196 | .cl_ops = NULL, | ||
197 | .id = "bfifo", | 98 | .id = "bfifo", |
198 | .priv_size = sizeof(struct fifo_sched_data), | 99 | .priv_size = sizeof(struct fifo_sched_data), |
199 | .enqueue = bfifo_enqueue, | 100 | .enqueue = bfifo_enqueue, |
200 | .dequeue = bfifo_dequeue, | 101 | .dequeue = qdisc_dequeue_head, |
201 | .requeue = bfifo_requeue, | 102 | .requeue = qdisc_requeue, |
202 | .drop = fifo_drop, | 103 | .drop = qdisc_queue_drop, |
203 | .init = fifo_init, | 104 | .init = fifo_init, |
204 | .reset = fifo_reset, | 105 | .reset = qdisc_reset_queue, |
205 | .destroy = NULL, | ||
206 | .change = fifo_init, | 106 | .change = fifo_init, |
207 | .dump = fifo_dump, | 107 | .dump = fifo_dump, |
208 | .owner = THIS_MODULE, | 108 | .owner = THIS_MODULE, |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 87e48a4e1051..7683b34dc6a9 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -243,31 +243,27 @@ static void dev_watchdog_down(struct net_device *dev) | |||
243 | cheaper. | 243 | cheaper. |
244 | */ | 244 | */ |
245 | 245 | ||
246 | static int | 246 | static int noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc) |
247 | noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc) | ||
248 | { | 247 | { |
249 | kfree_skb(skb); | 248 | kfree_skb(skb); |
250 | return NET_XMIT_CN; | 249 | return NET_XMIT_CN; |
251 | } | 250 | } |
252 | 251 | ||
253 | static struct sk_buff * | 252 | static struct sk_buff *noop_dequeue(struct Qdisc * qdisc) |
254 | noop_dequeue(struct Qdisc * qdisc) | ||
255 | { | 253 | { |
256 | return NULL; | 254 | return NULL; |
257 | } | 255 | } |
258 | 256 | ||
259 | static int | 257 | static int noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc) |
260 | noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc) | ||
261 | { | 258 | { |
262 | if (net_ratelimit()) | 259 | if (net_ratelimit()) |
263 | printk(KERN_DEBUG "%s deferred output. It is buggy.\n", skb->dev->name); | 260 | printk(KERN_DEBUG "%s deferred output. It is buggy.\n", |
261 | skb->dev->name); | ||
264 | kfree_skb(skb); | 262 | kfree_skb(skb); |
265 | return NET_XMIT_CN; | 263 | return NET_XMIT_CN; |
266 | } | 264 | } |
267 | 265 | ||
268 | struct Qdisc_ops noop_qdisc_ops = { | 266 | struct Qdisc_ops noop_qdisc_ops = { |
269 | .next = NULL, | ||
270 | .cl_ops = NULL, | ||
271 | .id = "noop", | 267 | .id = "noop", |
272 | .priv_size = 0, | 268 | .priv_size = 0, |
273 | .enqueue = noop_enqueue, | 269 | .enqueue = noop_enqueue, |
@@ -285,8 +281,6 @@ struct Qdisc noop_qdisc = { | |||
285 | }; | 281 | }; |
286 | 282 | ||
287 | static struct Qdisc_ops noqueue_qdisc_ops = { | 283 | static struct Qdisc_ops noqueue_qdisc_ops = { |
288 | .next = NULL, | ||
289 | .cl_ops = NULL, | ||
290 | .id = "noqueue", | 284 | .id = "noqueue", |
291 | .priv_size = 0, | 285 | .priv_size = 0, |
292 | .enqueue = noop_enqueue, | 286 | .enqueue = noop_enqueue, |
@@ -311,97 +305,87 @@ static const u8 prio2band[TC_PRIO_MAX+1] = | |||
311 | generic prio+fifo combination. | 305 | generic prio+fifo combination. |
312 | */ | 306 | */ |
313 | 307 | ||
314 | static int | 308 | #define PFIFO_FAST_BANDS 3 |
315 | pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) | 309 | |
310 | static inline struct sk_buff_head *prio2list(struct sk_buff *skb, | ||
311 | struct Qdisc *qdisc) | ||
316 | { | 312 | { |
317 | struct sk_buff_head *list = qdisc_priv(qdisc); | 313 | struct sk_buff_head *list = qdisc_priv(qdisc); |
314 | return list + prio2band[skb->priority & TC_PRIO_MAX]; | ||
315 | } | ||
318 | 316 | ||
319 | list += prio2band[skb->priority&TC_PRIO_MAX]; | 317 | static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) |
318 | { | ||
319 | struct sk_buff_head *list = prio2list(skb, qdisc); | ||
320 | 320 | ||
321 | if (list->qlen < qdisc->dev->tx_queue_len) { | 321 | if (skb_queue_len(list) < qdisc->dev->tx_queue_len) { |
322 | __skb_queue_tail(list, skb); | ||
323 | qdisc->q.qlen++; | 322 | qdisc->q.qlen++; |
324 | qdisc->bstats.bytes += skb->len; | 323 | return __qdisc_enqueue_tail(skb, qdisc, list); |
325 | qdisc->bstats.packets++; | ||
326 | return 0; | ||
327 | } | 324 | } |
328 | qdisc->qstats.drops++; | 325 | |
329 | kfree_skb(skb); | 326 | return qdisc_drop(skb, qdisc); |
330 | return NET_XMIT_DROP; | ||
331 | } | 327 | } |
332 | 328 | ||
333 | static struct sk_buff * | 329 | static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc) |
334 | pfifo_fast_dequeue(struct Qdisc* qdisc) | ||
335 | { | 330 | { |
336 | int prio; | 331 | int prio; |
337 | struct sk_buff_head *list = qdisc_priv(qdisc); | 332 | struct sk_buff_head *list = qdisc_priv(qdisc); |
338 | struct sk_buff *skb; | ||
339 | 333 | ||
340 | for (prio = 0; prio < 3; prio++, list++) { | 334 | for (prio = 0; prio < PFIFO_FAST_BANDS; prio++, list++) { |
341 | skb = __skb_dequeue(list); | 335 | struct sk_buff *skb = __qdisc_dequeue_head(qdisc, list); |
342 | if (skb) { | 336 | if (skb) { |
343 | qdisc->q.qlen--; | 337 | qdisc->q.qlen--; |
344 | return skb; | 338 | return skb; |
345 | } | 339 | } |
346 | } | 340 | } |
341 | |||
347 | return NULL; | 342 | return NULL; |
348 | } | 343 | } |
349 | 344 | ||
350 | static int | 345 | static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc) |
351 | pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc) | ||
352 | { | 346 | { |
353 | struct sk_buff_head *list = qdisc_priv(qdisc); | ||
354 | |||
355 | list += prio2band[skb->priority&TC_PRIO_MAX]; | ||
356 | |||
357 | __skb_queue_head(list, skb); | ||
358 | qdisc->q.qlen++; | 347 | qdisc->q.qlen++; |
359 | qdisc->qstats.requeues++; | 348 | return __qdisc_requeue(skb, qdisc, prio2list(skb, qdisc)); |
360 | return 0; | ||
361 | } | 349 | } |
362 | 350 | ||
363 | static void | 351 | static void pfifo_fast_reset(struct Qdisc* qdisc) |
364 | pfifo_fast_reset(struct Qdisc* qdisc) | ||
365 | { | 352 | { |
366 | int prio; | 353 | int prio; |
367 | struct sk_buff_head *list = qdisc_priv(qdisc); | 354 | struct sk_buff_head *list = qdisc_priv(qdisc); |
368 | 355 | ||
369 | for (prio=0; prio < 3; prio++) | 356 | for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) |
370 | skb_queue_purge(list+prio); | 357 | __qdisc_reset_queue(qdisc, list + prio); |
358 | |||
359 | qdisc->qstats.backlog = 0; | ||
371 | qdisc->q.qlen = 0; | 360 | qdisc->q.qlen = 0; |
372 | } | 361 | } |
373 | 362 | ||
374 | static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb) | 363 | static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb) |
375 | { | 364 | { |
376 | unsigned char *b = skb->tail; | 365 | struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS }; |
377 | struct tc_prio_qopt opt; | ||
378 | 366 | ||
379 | opt.bands = 3; | ||
380 | memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1); | 367 | memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1); |
381 | RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | 368 | RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); |
382 | return skb->len; | 369 | return skb->len; |
383 | 370 | ||
384 | rtattr_failure: | 371 | rtattr_failure: |
385 | skb_trim(skb, b - skb->data); | ||
386 | return -1; | 372 | return -1; |
387 | } | 373 | } |
388 | 374 | ||
389 | static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt) | 375 | static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt) |
390 | { | 376 | { |
391 | int i; | 377 | int prio; |
392 | struct sk_buff_head *list = qdisc_priv(qdisc); | 378 | struct sk_buff_head *list = qdisc_priv(qdisc); |
393 | 379 | ||
394 | for (i=0; i<3; i++) | 380 | for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) |
395 | skb_queue_head_init(list+i); | 381 | skb_queue_head_init(list + prio); |
396 | 382 | ||
397 | return 0; | 383 | return 0; |
398 | } | 384 | } |
399 | 385 | ||
400 | static struct Qdisc_ops pfifo_fast_ops = { | 386 | static struct Qdisc_ops pfifo_fast_ops = { |
401 | .next = NULL, | ||
402 | .cl_ops = NULL, | ||
403 | .id = "pfifo_fast", | 387 | .id = "pfifo_fast", |
404 | .priv_size = 3 * sizeof(struct sk_buff_head), | 388 | .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head), |
405 | .enqueue = pfifo_fast_enqueue, | 389 | .enqueue = pfifo_fast_enqueue, |
406 | .dequeue = pfifo_fast_dequeue, | 390 | .dequeue = pfifo_fast_dequeue, |
407 | .requeue = pfifo_fast_requeue, | 391 | .requeue = pfifo_fast_requeue, |