diff options
Diffstat (limited to 'net/sched')
32 files changed, 511 insertions, 768 deletions
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index f4544dd86476..475df8449be9 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -46,62 +46,6 @@ config NET_SCH_FIFO | |||
46 | 46 | ||
47 | if NET_SCHED | 47 | if NET_SCHED |
48 | 48 | ||
49 | choice | ||
50 | prompt "Packet scheduler clock source" | ||
51 | default NET_SCH_CLK_GETTIMEOFDAY | ||
52 | ---help--- | ||
53 | Packet schedulers need a monotonic clock that increments at a static | ||
54 | rate. The kernel provides several suitable interfaces, each with | ||
55 | different properties: | ||
56 | |||
57 | - high resolution (us or better) | ||
58 | - fast to read (minimal locking, no i/o access) | ||
59 | - synchronized on all processors | ||
60 | - handles cpu clock frequency changes | ||
61 | |||
62 | but nothing provides all of the above. | ||
63 | |||
64 | config NET_SCH_CLK_JIFFIES | ||
65 | bool "Timer interrupt" | ||
66 | ---help--- | ||
67 | Say Y here if you want to use the timer interrupt (jiffies) as clock | ||
68 | source. This clock source is fast, synchronized on all processors and | ||
69 | handles cpu clock frequency changes, but its resolution is too low | ||
70 | for accurate shaping except at very low speed. | ||
71 | |||
72 | config NET_SCH_CLK_GETTIMEOFDAY | ||
73 | bool "gettimeofday" | ||
74 | ---help--- | ||
75 | Say Y here if you want to use gettimeofday as clock source. This clock | ||
76 | source has high resolution, is synchronized on all processors and | ||
77 | handles cpu clock frequency changes, but it is slow. | ||
78 | |||
79 | Choose this if you need a high resolution clock source but can't use | ||
80 | the CPU's cycle counter. | ||
81 | |||
82 | # don't allow on SMP x86 because they can have unsynchronized TSCs. | ||
83 | # gettimeofday is a good alternative | ||
84 | config NET_SCH_CLK_CPU | ||
85 | bool "CPU cycle counter" | ||
86 | depends on ((X86_TSC || X86_64) && !SMP) || ALPHA || SPARC64 || PPC64 || IA64 | ||
87 | ---help--- | ||
88 | Say Y here if you want to use the CPU's cycle counter as clock source. | ||
89 | This is a cheap and high resolution clock source, but on some | ||
90 | architectures it is not synchronized on all processors and doesn't | ||
91 | handle cpu clock frequency changes. | ||
92 | |||
93 | The useable cycle counters are: | ||
94 | |||
95 | x86/x86_64 - Timestamp Counter | ||
96 | alpha - Cycle Counter | ||
97 | sparc64 - %ticks register | ||
98 | ppc64 - Time base | ||
99 | ia64 - Interval Time Counter | ||
100 | |||
101 | Choose this if your CPU's cycle counter is working properly. | ||
102 | |||
103 | endchoice | ||
104 | |||
105 | comment "Queueing/Scheduling" | 49 | comment "Queueing/Scheduling" |
106 | 50 | ||
107 | config NET_SCH_CBQ | 51 | config NET_SCH_CBQ |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index cb21617a5670..711dd26c95c3 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -25,12 +25,12 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
27 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
28 | #include <linux/rtnetlink.h> | ||
29 | #include <linux/init.h> | 28 | #include <linux/init.h> |
30 | #include <linux/kmod.h> | 29 | #include <linux/kmod.h> |
31 | #include <net/sock.h> | 30 | #include <net/sock.h> |
32 | #include <net/sch_generic.h> | 31 | #include <net/sch_generic.h> |
33 | #include <net/act_api.h> | 32 | #include <net/act_api.h> |
33 | #include <net/netlink.h> | ||
34 | 34 | ||
35 | void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) | 35 | void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) |
36 | { | 36 | { |
@@ -93,15 +93,15 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, | |||
93 | continue; | 93 | continue; |
94 | a->priv = p; | 94 | a->priv = p; |
95 | a->order = n_i; | 95 | a->order = n_i; |
96 | r = (struct rtattr*) skb->tail; | 96 | r = (struct rtattr *)skb_tail_pointer(skb); |
97 | RTA_PUT(skb, a->order, 0, NULL); | 97 | RTA_PUT(skb, a->order, 0, NULL); |
98 | err = tcf_action_dump_1(skb, a, 0, 0); | 98 | err = tcf_action_dump_1(skb, a, 0, 0); |
99 | if (err < 0) { | 99 | if (err < 0) { |
100 | index--; | 100 | index--; |
101 | skb_trim(skb, (u8*)r - skb->data); | 101 | nlmsg_trim(skb, r); |
102 | goto done; | 102 | goto done; |
103 | } | 103 | } |
104 | r->rta_len = skb->tail - (u8*)r; | 104 | r->rta_len = skb_tail_pointer(skb) - (u8 *)r; |
105 | n_i++; | 105 | n_i++; |
106 | if (n_i >= TCA_ACT_MAX_PRIO) | 106 | if (n_i >= TCA_ACT_MAX_PRIO) |
107 | goto done; | 107 | goto done; |
@@ -114,7 +114,7 @@ done: | |||
114 | return n_i; | 114 | return n_i; |
115 | 115 | ||
116 | rtattr_failure: | 116 | rtattr_failure: |
117 | skb_trim(skb, (u8*)r - skb->data); | 117 | nlmsg_trim(skb, r); |
118 | goto done; | 118 | goto done; |
119 | } | 119 | } |
120 | 120 | ||
@@ -125,7 +125,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a, | |||
125 | struct rtattr *r ; | 125 | struct rtattr *r ; |
126 | int i= 0, n_i = 0; | 126 | int i= 0, n_i = 0; |
127 | 127 | ||
128 | r = (struct rtattr*) skb->tail; | 128 | r = (struct rtattr *)skb_tail_pointer(skb); |
129 | RTA_PUT(skb, a->order, 0, NULL); | 129 | RTA_PUT(skb, a->order, 0, NULL); |
130 | RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); | 130 | RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); |
131 | for (i = 0; i < (hinfo->hmask + 1); i++) { | 131 | for (i = 0; i < (hinfo->hmask + 1); i++) { |
@@ -140,11 +140,11 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a, | |||
140 | } | 140 | } |
141 | } | 141 | } |
142 | RTA_PUT(skb, TCA_FCNT, 4, &n_i); | 142 | RTA_PUT(skb, TCA_FCNT, 4, &n_i); |
143 | r->rta_len = skb->tail - (u8*)r; | 143 | r->rta_len = skb_tail_pointer(skb) - (u8 *)r; |
144 | 144 | ||
145 | return n_i; | 145 | return n_i; |
146 | rtattr_failure: | 146 | rtattr_failure: |
147 | skb_trim(skb, (u8*)r - skb->data); | 147 | nlmsg_trim(skb, r); |
148 | return -EINVAL; | 148 | return -EINVAL; |
149 | } | 149 | } |
150 | 150 | ||
@@ -423,7 +423,7 @@ int | |||
423 | tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 423 | tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
424 | { | 424 | { |
425 | int err = -EINVAL; | 425 | int err = -EINVAL; |
426 | unsigned char *b = skb->tail; | 426 | unsigned char *b = skb_tail_pointer(skb); |
427 | struct rtattr *r; | 427 | struct rtattr *r; |
428 | 428 | ||
429 | if (a->ops == NULL || a->ops->dump == NULL) | 429 | if (a->ops == NULL || a->ops->dump == NULL) |
@@ -432,15 +432,15 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | |||
432 | RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); | 432 | RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); |
433 | if (tcf_action_copy_stats(skb, a, 0)) | 433 | if (tcf_action_copy_stats(skb, a, 0)) |
434 | goto rtattr_failure; | 434 | goto rtattr_failure; |
435 | r = (struct rtattr*) skb->tail; | 435 | r = (struct rtattr *)skb_tail_pointer(skb); |
436 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); | 436 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
437 | if ((err = tcf_action_dump_old(skb, a, bind, ref)) > 0) { | 437 | if ((err = tcf_action_dump_old(skb, a, bind, ref)) > 0) { |
438 | r->rta_len = skb->tail - (u8*)r; | 438 | r->rta_len = skb_tail_pointer(skb) - (u8 *)r; |
439 | return err; | 439 | return err; |
440 | } | 440 | } |
441 | 441 | ||
442 | rtattr_failure: | 442 | rtattr_failure: |
443 | skb_trim(skb, b - skb->data); | 443 | nlmsg_trim(skb, b); |
444 | return -1; | 444 | return -1; |
445 | } | 445 | } |
446 | 446 | ||
@@ -449,17 +449,17 @@ tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref) | |||
449 | { | 449 | { |
450 | struct tc_action *a; | 450 | struct tc_action *a; |
451 | int err = -EINVAL; | 451 | int err = -EINVAL; |
452 | unsigned char *b = skb->tail; | 452 | unsigned char *b = skb_tail_pointer(skb); |
453 | struct rtattr *r ; | 453 | struct rtattr *r ; |
454 | 454 | ||
455 | while ((a = act) != NULL) { | 455 | while ((a = act) != NULL) { |
456 | r = (struct rtattr*) skb->tail; | 456 | r = (struct rtattr *)skb_tail_pointer(skb); |
457 | act = a->next; | 457 | act = a->next; |
458 | RTA_PUT(skb, a->order, 0, NULL); | 458 | RTA_PUT(skb, a->order, 0, NULL); |
459 | err = tcf_action_dump_1(skb, a, bind, ref); | 459 | err = tcf_action_dump_1(skb, a, bind, ref); |
460 | if (err < 0) | 460 | if (err < 0) |
461 | goto errout; | 461 | goto errout; |
462 | r->rta_len = skb->tail - (u8*)r; | 462 | r->rta_len = skb_tail_pointer(skb) - (u8 *)r; |
463 | } | 463 | } |
464 | 464 | ||
465 | return 0; | 465 | return 0; |
@@ -467,7 +467,7 @@ tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref) | |||
467 | rtattr_failure: | 467 | rtattr_failure: |
468 | err = -EINVAL; | 468 | err = -EINVAL; |
469 | errout: | 469 | errout: |
470 | skb_trim(skb, b - skb->data); | 470 | nlmsg_trim(skb, b); |
471 | return err; | 471 | return err; |
472 | } | 472 | } |
473 | 473 | ||
@@ -635,7 +635,7 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq, | |||
635 | { | 635 | { |
636 | struct tcamsg *t; | 636 | struct tcamsg *t; |
637 | struct nlmsghdr *nlh; | 637 | struct nlmsghdr *nlh; |
638 | unsigned char *b = skb->tail; | 638 | unsigned char *b = skb_tail_pointer(skb); |
639 | struct rtattr *x; | 639 | struct rtattr *x; |
640 | 640 | ||
641 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags); | 641 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags); |
@@ -645,20 +645,20 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq, | |||
645 | t->tca__pad1 = 0; | 645 | t->tca__pad1 = 0; |
646 | t->tca__pad2 = 0; | 646 | t->tca__pad2 = 0; |
647 | 647 | ||
648 | x = (struct rtattr*) skb->tail; | 648 | x = (struct rtattr *)skb_tail_pointer(skb); |
649 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); | 649 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); |
650 | 650 | ||
651 | if (tcf_action_dump(skb, a, bind, ref) < 0) | 651 | if (tcf_action_dump(skb, a, bind, ref) < 0) |
652 | goto rtattr_failure; | 652 | goto rtattr_failure; |
653 | 653 | ||
654 | x->rta_len = skb->tail - (u8*)x; | 654 | x->rta_len = skb_tail_pointer(skb) - (u8 *)x; |
655 | 655 | ||
656 | nlh->nlmsg_len = skb->tail - b; | 656 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
657 | return skb->len; | 657 | return skb->len; |
658 | 658 | ||
659 | rtattr_failure: | 659 | rtattr_failure: |
660 | nlmsg_failure: | 660 | nlmsg_failure: |
661 | skb_trim(skb, b - skb->data); | 661 | nlmsg_trim(skb, b); |
662 | return -1; | 662 | return -1; |
663 | } | 663 | } |
664 | 664 | ||
@@ -767,7 +767,7 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid) | |||
767 | return -ENOBUFS; | 767 | return -ENOBUFS; |
768 | } | 768 | } |
769 | 769 | ||
770 | b = (unsigned char *)skb->tail; | 770 | b = skb_tail_pointer(skb); |
771 | 771 | ||
772 | if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0) | 772 | if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0) |
773 | goto err_out; | 773 | goto err_out; |
@@ -783,16 +783,16 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid) | |||
783 | t->tca__pad1 = 0; | 783 | t->tca__pad1 = 0; |
784 | t->tca__pad2 = 0; | 784 | t->tca__pad2 = 0; |
785 | 785 | ||
786 | x = (struct rtattr *) skb->tail; | 786 | x = (struct rtattr *)skb_tail_pointer(skb); |
787 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); | 787 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); |
788 | 788 | ||
789 | err = a->ops->walk(skb, &dcb, RTM_DELACTION, a); | 789 | err = a->ops->walk(skb, &dcb, RTM_DELACTION, a); |
790 | if (err < 0) | 790 | if (err < 0) |
791 | goto rtattr_failure; | 791 | goto rtattr_failure; |
792 | 792 | ||
793 | x->rta_len = skb->tail - (u8 *) x; | 793 | x->rta_len = skb_tail_pointer(skb) - (u8 *)x; |
794 | 794 | ||
795 | nlh->nlmsg_len = skb->tail - b; | 795 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
796 | nlh->nlmsg_flags |= NLM_F_ROOT; | 796 | nlh->nlmsg_flags |= NLM_F_ROOT; |
797 | module_put(a->ops->owner); | 797 | module_put(a->ops->owner); |
798 | kfree(a); | 798 | kfree(a); |
@@ -884,7 +884,7 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, | |||
884 | if (!skb) | 884 | if (!skb) |
885 | return -ENOBUFS; | 885 | return -ENOBUFS; |
886 | 886 | ||
887 | b = (unsigned char *)skb->tail; | 887 | b = skb_tail_pointer(skb); |
888 | 888 | ||
889 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags); | 889 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags); |
890 | t = NLMSG_DATA(nlh); | 890 | t = NLMSG_DATA(nlh); |
@@ -892,15 +892,15 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, | |||
892 | t->tca__pad1 = 0; | 892 | t->tca__pad1 = 0; |
893 | t->tca__pad2 = 0; | 893 | t->tca__pad2 = 0; |
894 | 894 | ||
895 | x = (struct rtattr*) skb->tail; | 895 | x = (struct rtattr *)skb_tail_pointer(skb); |
896 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); | 896 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); |
897 | 897 | ||
898 | if (tcf_action_dump(skb, a, 0, 0) < 0) | 898 | if (tcf_action_dump(skb, a, 0, 0) < 0) |
899 | goto rtattr_failure; | 899 | goto rtattr_failure; |
900 | 900 | ||
901 | x->rta_len = skb->tail - (u8*)x; | 901 | x->rta_len = skb_tail_pointer(skb) - (u8 *)x; |
902 | 902 | ||
903 | nlh->nlmsg_len = skb->tail - b; | 903 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
904 | NETLINK_CB(skb).dst_group = RTNLGRP_TC; | 904 | NETLINK_CB(skb).dst_group = RTNLGRP_TC; |
905 | 905 | ||
906 | err = rtnetlink_send(skb, pid, RTNLGRP_TC, flags&NLM_F_ECHO); | 906 | err = rtnetlink_send(skb, pid, RTNLGRP_TC, flags&NLM_F_ECHO); |
@@ -1015,7 +1015,7 @@ static int | |||
1015 | tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | 1015 | tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) |
1016 | { | 1016 | { |
1017 | struct nlmsghdr *nlh; | 1017 | struct nlmsghdr *nlh; |
1018 | unsigned char *b = skb->tail; | 1018 | unsigned char *b = skb_tail_pointer(skb); |
1019 | struct rtattr *x; | 1019 | struct rtattr *x; |
1020 | struct tc_action_ops *a_o; | 1020 | struct tc_action_ops *a_o; |
1021 | struct tc_action a; | 1021 | struct tc_action a; |
@@ -1048,7 +1048,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1048 | t->tca__pad1 = 0; | 1048 | t->tca__pad1 = 0; |
1049 | t->tca__pad2 = 0; | 1049 | t->tca__pad2 = 0; |
1050 | 1050 | ||
1051 | x = (struct rtattr *) skb->tail; | 1051 | x = (struct rtattr *)skb_tail_pointer(skb); |
1052 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); | 1052 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); |
1053 | 1053 | ||
1054 | ret = a_o->walk(skb, cb, RTM_GETACTION, &a); | 1054 | ret = a_o->walk(skb, cb, RTM_GETACTION, &a); |
@@ -1056,12 +1056,12 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1056 | goto rtattr_failure; | 1056 | goto rtattr_failure; |
1057 | 1057 | ||
1058 | if (ret > 0) { | 1058 | if (ret > 0) { |
1059 | x->rta_len = skb->tail - (u8 *) x; | 1059 | x->rta_len = skb_tail_pointer(skb) - (u8 *)x; |
1060 | ret = skb->len; | 1060 | ret = skb->len; |
1061 | } else | 1061 | } else |
1062 | skb_trim(skb, (u8*)x - skb->data); | 1062 | nlmsg_trim(skb, x); |
1063 | 1063 | ||
1064 | nlh->nlmsg_len = skb->tail - b; | 1064 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
1065 | if (NETLINK_CB(cb->skb).pid && ret) | 1065 | if (NETLINK_CB(cb->skb).pid && ret) |
1066 | nlh->nlmsg_flags |= NLM_F_MULTI; | 1066 | nlh->nlmsg_flags |= NLM_F_MULTI; |
1067 | module_put(a_o->owner); | 1067 | module_put(a_o->owner); |
@@ -1070,20 +1070,15 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1070 | rtattr_failure: | 1070 | rtattr_failure: |
1071 | nlmsg_failure: | 1071 | nlmsg_failure: |
1072 | module_put(a_o->owner); | 1072 | module_put(a_o->owner); |
1073 | skb_trim(skb, b - skb->data); | 1073 | nlmsg_trim(skb, b); |
1074 | return skb->len; | 1074 | return skb->len; |
1075 | } | 1075 | } |
1076 | 1076 | ||
1077 | static int __init tc_action_init(void) | 1077 | static int __init tc_action_init(void) |
1078 | { | 1078 | { |
1079 | struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC]; | 1079 | rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL); |
1080 | 1080 | rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL); | |
1081 | if (link_p) { | 1081 | rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action); |
1082 | link_p[RTM_NEWACTION-RTM_BASE].doit = tc_ctl_action; | ||
1083 | link_p[RTM_DELACTION-RTM_BASE].doit = tc_ctl_action; | ||
1084 | link_p[RTM_GETACTION-RTM_BASE].doit = tc_ctl_action; | ||
1085 | link_p[RTM_GETACTION-RTM_BASE].dumpit = tc_dump_action; | ||
1086 | } | ||
1087 | 1082 | ||
1088 | return 0; | 1083 | return 0; |
1089 | } | 1084 | } |
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index 87d0faf32867..7517f3791541 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/proc_fs.h> | 30 | #include <linux/proc_fs.h> |
31 | #include <net/netlink.h> | ||
31 | #include <net/sock.h> | 32 | #include <net/sock.h> |
32 | #include <net/pkt_sched.h> | 33 | #include <net/pkt_sched.h> |
33 | #include <linux/tc_act/tc_gact.h> | 34 | #include <linux/tc_act/tc_gact.h> |
@@ -155,7 +156,7 @@ static int tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result | |||
155 | 156 | ||
156 | static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 157 | static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
157 | { | 158 | { |
158 | unsigned char *b = skb->tail; | 159 | unsigned char *b = skb_tail_pointer(skb); |
159 | struct tc_gact opt; | 160 | struct tc_gact opt; |
160 | struct tcf_gact *gact = a->priv; | 161 | struct tcf_gact *gact = a->priv; |
161 | struct tcf_t t; | 162 | struct tcf_t t; |
@@ -181,7 +182,7 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int | |||
181 | return skb->len; | 182 | return skb->len; |
182 | 183 | ||
183 | rtattr_failure: | 184 | rtattr_failure: |
184 | skb_trim(skb, b - skb->data); | 185 | nlmsg_trim(skb, b); |
185 | return -1; | 186 | return -1; |
186 | } | 187 | } |
187 | 188 | ||
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 47f0b1324239..00b05f422d45 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
32 | #include <linux/kmod.h> | 32 | #include <linux/kmod.h> |
33 | #include <net/netlink.h> | ||
33 | #include <net/sock.h> | 34 | #include <net/sock.h> |
34 | #include <net/pkt_sched.h> | 35 | #include <net/pkt_sched.h> |
35 | #include <linux/tc_act/tc_ipt.h> | 36 | #include <linux/tc_act/tc_ipt.h> |
@@ -245,7 +246,7 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, | |||
245 | 246 | ||
246 | static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 247 | static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
247 | { | 248 | { |
248 | unsigned char *b = skb->tail; | 249 | unsigned char *b = skb_tail_pointer(skb); |
249 | struct tcf_ipt *ipt = a->priv; | 250 | struct tcf_ipt *ipt = a->priv; |
250 | struct ipt_entry_target *t; | 251 | struct ipt_entry_target *t; |
251 | struct tcf_t tm; | 252 | struct tcf_t tm; |
@@ -277,7 +278,7 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int | |||
277 | return skb->len; | 278 | return skb->len; |
278 | 279 | ||
279 | rtattr_failure: | 280 | rtattr_failure: |
280 | skb_trim(skb, b - skb->data); | 281 | nlmsg_trim(skb, b); |
281 | kfree(t); | 282 | kfree(t); |
282 | return -1; | 283 | return -1; |
283 | } | 284 | } |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 3e93683e9ab3..de21c92faaa2 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
33 | #include <net/netlink.h> | ||
33 | #include <net/sock.h> | 34 | #include <net/sock.h> |
34 | #include <net/pkt_sched.h> | 35 | #include <net/pkt_sched.h> |
35 | #include <linux/tc_act/tc_mirred.h> | 36 | #include <linux/tc_act/tc_mirred.h> |
@@ -206,7 +207,7 @@ bad_mirred: | |||
206 | 207 | ||
207 | static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 208 | static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
208 | { | 209 | { |
209 | unsigned char *b = skb->tail; | 210 | unsigned char *b = skb_tail_pointer(skb); |
210 | struct tcf_mirred *m = a->priv; | 211 | struct tcf_mirred *m = a->priv; |
211 | struct tc_mirred opt; | 212 | struct tc_mirred opt; |
212 | struct tcf_t t; | 213 | struct tcf_t t; |
@@ -225,7 +226,7 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i | |||
225 | return skb->len; | 226 | return skb->len; |
226 | 227 | ||
227 | rtattr_failure: | 228 | rtattr_failure: |
228 | skb_trim(skb, b - skb->data); | 229 | nlmsg_trim(skb, b); |
229 | return -1; | 230 | return -1; |
230 | } | 231 | } |
231 | 232 | ||
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 3d6a2fcc9ce4..45b3cda86a21 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/proc_fs.h> | 29 | #include <linux/proc_fs.h> |
30 | #include <net/netlink.h> | ||
30 | #include <net/sock.h> | 31 | #include <net/sock.h> |
31 | #include <net/pkt_sched.h> | 32 | #include <net/pkt_sched.h> |
32 | #include <linux/tc_act/tc_pedit.h> | 33 | #include <linux/tc_act/tc_pedit.h> |
@@ -136,7 +137,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, | |||
136 | } | 137 | } |
137 | } | 138 | } |
138 | 139 | ||
139 | pptr = skb->nh.raw; | 140 | pptr = skb_network_header(skb); |
140 | 141 | ||
141 | spin_lock(&p->tcf_lock); | 142 | spin_lock(&p->tcf_lock); |
142 | 143 | ||
@@ -195,7 +196,7 @@ done: | |||
195 | static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, | 196 | static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, |
196 | int bind, int ref) | 197 | int bind, int ref) |
197 | { | 198 | { |
198 | unsigned char *b = skb->tail; | 199 | unsigned char *b = skb_tail_pointer(skb); |
199 | struct tcf_pedit *p = a->priv; | 200 | struct tcf_pedit *p = a->priv; |
200 | struct tc_pedit *opt; | 201 | struct tc_pedit *opt; |
201 | struct tcf_t t; | 202 | struct tcf_t t; |
@@ -226,7 +227,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, | |||
226 | return skb->len; | 227 | return skb->len; |
227 | 228 | ||
228 | rtattr_failure: | 229 | rtattr_failure: |
229 | skb_trim(skb, b - skb->data); | 230 | nlmsg_trim(skb, b); |
230 | kfree(opt); | 231 | kfree(opt); |
231 | return -1; | 232 | return -1; |
232 | } | 233 | } |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 10a5a5c36f76..616f465f407e 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <net/sock.h> | 31 | #include <net/sock.h> |
32 | #include <net/act_api.h> | 32 | #include <net/act_api.h> |
33 | #include <net/netlink.h> | ||
33 | 34 | ||
34 | #define L2T(p,L) ((p)->tcfp_R_tab->data[(L)>>(p)->tcfp_R_tab->rate.cell_log]) | 35 | #define L2T(p,L) ((p)->tcfp_R_tab->data[(L)>>(p)->tcfp_R_tab->rate.cell_log]) |
35 | #define L2T_P(p,L) ((p)->tcfp_P_tab->data[(L)>>(p)->tcfp_P_tab->rate.cell_log]) | 36 | #define L2T_P(p,L) ((p)->tcfp_P_tab->data[(L)>>(p)->tcfp_P_tab->rate.cell_log]) |
@@ -80,7 +81,7 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c | |||
80 | continue; | 81 | continue; |
81 | a->priv = p; | 82 | a->priv = p; |
82 | a->order = index; | 83 | a->order = index; |
83 | r = (struct rtattr*) skb->tail; | 84 | r = (struct rtattr *)skb_tail_pointer(skb); |
84 | RTA_PUT(skb, a->order, 0, NULL); | 85 | RTA_PUT(skb, a->order, 0, NULL); |
85 | if (type == RTM_DELACTION) | 86 | if (type == RTM_DELACTION) |
86 | err = tcf_action_dump_1(skb, a, 0, 1); | 87 | err = tcf_action_dump_1(skb, a, 0, 1); |
@@ -88,10 +89,10 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c | |||
88 | err = tcf_action_dump_1(skb, a, 0, 0); | 89 | err = tcf_action_dump_1(skb, a, 0, 0); |
89 | if (err < 0) { | 90 | if (err < 0) { |
90 | index--; | 91 | index--; |
91 | skb_trim(skb, (u8*)r - skb->data); | 92 | nlmsg_trim(skb, r); |
92 | goto done; | 93 | goto done; |
93 | } | 94 | } |
94 | r->rta_len = skb->tail - (u8*)r; | 95 | r->rta_len = skb_tail_pointer(skb) - (u8 *)r; |
95 | n_i++; | 96 | n_i++; |
96 | } | 97 | } |
97 | } | 98 | } |
@@ -102,7 +103,7 @@ done: | |||
102 | return n_i; | 103 | return n_i; |
103 | 104 | ||
104 | rtattr_failure: | 105 | rtattr_failure: |
105 | skb_trim(skb, (u8*)r - skb->data); | 106 | nlmsg_trim(skb, r); |
106 | goto done; | 107 | goto done; |
107 | } | 108 | } |
108 | #endif | 109 | #endif |
@@ -240,7 +241,7 @@ override: | |||
240 | if (ret != ACT_P_CREATED) | 241 | if (ret != ACT_P_CREATED) |
241 | return ret; | 242 | return ret; |
242 | 243 | ||
243 | PSCHED_GET_TIME(police->tcfp_t_c); | 244 | police->tcfp_t_c = psched_get_time(); |
244 | police->tcf_index = parm->index ? parm->index : | 245 | police->tcf_index = parm->index ? parm->index : |
245 | tcf_hash_new_index(&police_idx_gen, &police_hash_info); | 246 | tcf_hash_new_index(&police_idx_gen, &police_hash_info); |
246 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); | 247 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); |
@@ -295,10 +296,9 @@ static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, | |||
295 | return police->tcfp_result; | 296 | return police->tcfp_result; |
296 | } | 297 | } |
297 | 298 | ||
298 | PSCHED_GET_TIME(now); | 299 | now = psched_get_time(); |
299 | 300 | toks = psched_tdiff_bounded(now, police->tcfp_t_c, | |
300 | toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c, | 301 | police->tcfp_burst); |
301 | police->tcfp_burst); | ||
302 | if (police->tcfp_P_tab) { | 302 | if (police->tcfp_P_tab) { |
303 | ptoks = toks + police->tcfp_ptoks; | 303 | ptoks = toks + police->tcfp_ptoks; |
304 | if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) | 304 | if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) |
@@ -326,7 +326,7 @@ static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, | |||
326 | static int | 326 | static int |
327 | tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 327 | tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
328 | { | 328 | { |
329 | unsigned char *b = skb->tail; | 329 | unsigned char *b = skb_tail_pointer(skb); |
330 | struct tcf_police *police = a->priv; | 330 | struct tcf_police *police = a->priv; |
331 | struct tc_police opt; | 331 | struct tc_police opt; |
332 | 332 | ||
@@ -355,7 +355,7 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | |||
355 | return skb->len; | 355 | return skb->len; |
356 | 356 | ||
357 | rtattr_failure: | 357 | rtattr_failure: |
358 | skb_trim(skb, b - skb->data); | 358 | nlmsg_trim(skb, b); |
359 | return -1; | 359 | return -1; |
360 | } | 360 | } |
361 | 361 | ||
@@ -494,7 +494,7 @@ struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) | |||
494 | } | 494 | } |
495 | if (police->tcfp_P_tab) | 495 | if (police->tcfp_P_tab) |
496 | police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); | 496 | police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); |
497 | PSCHED_GET_TIME(police->tcfp_t_c); | 497 | police->tcfp_t_c = psched_get_time(); |
498 | police->tcf_index = parm->index ? parm->index : | 498 | police->tcf_index = parm->index ? parm->index : |
499 | tcf_police_new_index(); | 499 | tcf_police_new_index(); |
500 | police->tcf_action = parm->action; | 500 | police->tcf_action = parm->action; |
@@ -542,9 +542,9 @@ int tcf_police(struct sk_buff *skb, struct tcf_police *police) | |||
542 | return police->tcfp_result; | 542 | return police->tcfp_result; |
543 | } | 543 | } |
544 | 544 | ||
545 | PSCHED_GET_TIME(now); | 545 | now = psched_get_time(); |
546 | toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c, | 546 | toks = psched_tdiff_bounded(now, police->tcfp_t_c, |
547 | police->tcfp_burst); | 547 | police->tcfp_burst); |
548 | if (police->tcfp_P_tab) { | 548 | if (police->tcfp_P_tab) { |
549 | ptoks = toks + police->tcfp_ptoks; | 549 | ptoks = toks + police->tcfp_ptoks; |
550 | if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) | 550 | if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) |
@@ -572,7 +572,7 @@ EXPORT_SYMBOL(tcf_police); | |||
572 | 572 | ||
573 | int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police) | 573 | int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police) |
574 | { | 574 | { |
575 | unsigned char *b = skb->tail; | 575 | unsigned char *b = skb_tail_pointer(skb); |
576 | struct tc_police opt; | 576 | struct tc_police opt; |
577 | 577 | ||
578 | opt.index = police->tcf_index; | 578 | opt.index = police->tcf_index; |
@@ -598,7 +598,7 @@ int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police) | |||
598 | return skb->len; | 598 | return skb->len; |
599 | 599 | ||
600 | rtattr_failure: | 600 | rtattr_failure: |
601 | skb_trim(skb, b - skb->data); | 601 | nlmsg_trim(skb, b); |
602 | return -1; | 602 | return -1; |
603 | } | 603 | } |
604 | 604 | ||
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index c7971182af07..36e1edad5990 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
19 | #include <net/netlink.h> | ||
19 | #include <net/pkt_sched.h> | 20 | #include <net/pkt_sched.h> |
20 | 21 | ||
21 | #define TCA_ACT_SIMP 22 | 22 | #define TCA_ACT_SIMP 22 |
@@ -155,7 +156,7 @@ static inline int tcf_simp_cleanup(struct tc_action *a, int bind) | |||
155 | static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, | 156 | static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, |
156 | int bind, int ref) | 157 | int bind, int ref) |
157 | { | 158 | { |
158 | unsigned char *b = skb->tail; | 159 | unsigned char *b = skb_tail_pointer(skb); |
159 | struct tcf_defact *d = a->priv; | 160 | struct tcf_defact *d = a->priv; |
160 | struct tc_defact opt; | 161 | struct tc_defact opt; |
161 | struct tcf_t t; | 162 | struct tcf_t t; |
@@ -173,7 +174,7 @@ static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, | |||
173 | return skb->len; | 174 | return skb->len; |
174 | 175 | ||
175 | rtattr_failure: | 176 | rtattr_failure: |
176 | skb_trim(skb, b - skb->data); | 177 | nlmsg_trim(skb, b); |
177 | return -1; | 178 | return -1; |
178 | } | 179 | } |
179 | 180 | ||
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 5c6ffdb77d2d..ebf94edf0478 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -29,9 +29,10 @@ | |||
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
31 | #include <linux/skbuff.h> | 31 | #include <linux/skbuff.h> |
32 | #include <linux/rtnetlink.h> | ||
33 | #include <linux/init.h> | 32 | #include <linux/init.h> |
34 | #include <linux/kmod.h> | 33 | #include <linux/kmod.h> |
34 | #include <linux/netlink.h> | ||
35 | #include <net/netlink.h> | ||
35 | #include <net/sock.h> | 36 | #include <net/sock.h> |
36 | #include <net/pkt_sched.h> | 37 | #include <net/pkt_sched.h> |
37 | #include <net/pkt_cls.h> | 38 | #include <net/pkt_cls.h> |
@@ -323,7 +324,7 @@ tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh, | |||
323 | { | 324 | { |
324 | struct tcmsg *tcm; | 325 | struct tcmsg *tcm; |
325 | struct nlmsghdr *nlh; | 326 | struct nlmsghdr *nlh; |
326 | unsigned char *b = skb->tail; | 327 | unsigned char *b = skb_tail_pointer(skb); |
327 | 328 | ||
328 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); | 329 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
329 | tcm = NLMSG_DATA(nlh); | 330 | tcm = NLMSG_DATA(nlh); |
@@ -340,12 +341,12 @@ tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh, | |||
340 | if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0) | 341 | if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0) |
341 | goto rtattr_failure; | 342 | goto rtattr_failure; |
342 | } | 343 | } |
343 | nlh->nlmsg_len = skb->tail - b; | 344 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
344 | return skb->len; | 345 | return skb->len; |
345 | 346 | ||
346 | nlmsg_failure: | 347 | nlmsg_failure: |
347 | rtattr_failure: | 348 | rtattr_failure: |
348 | skb_trim(skb, b - skb->data); | 349 | nlmsg_trim(skb, b); |
349 | return -1; | 350 | return -1; |
350 | } | 351 | } |
351 | 352 | ||
@@ -399,7 +400,6 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) | |||
399 | if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL) | 400 | if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL) |
400 | return skb->len; | 401 | return skb->len; |
401 | 402 | ||
402 | read_lock(&qdisc_tree_lock); | ||
403 | if (!tcm->tcm_parent) | 403 | if (!tcm->tcm_parent) |
404 | q = dev->qdisc_sleeping; | 404 | q = dev->qdisc_sleeping; |
405 | else | 405 | else |
@@ -456,7 +456,6 @@ errout: | |||
456 | if (cl) | 456 | if (cl) |
457 | cops->put(q, cl); | 457 | cops->put(q, cl); |
458 | out: | 458 | out: |
459 | read_unlock(&qdisc_tree_lock); | ||
460 | dev_put(dev); | 459 | dev_put(dev); |
461 | return skb->len; | 460 | return skb->len; |
462 | } | 461 | } |
@@ -563,30 +562,30 @@ tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts, | |||
563 | * to work with both old and new modes of entering | 562 | * to work with both old and new modes of entering |
564 | * tc data even if iproute2 was newer - jhs | 563 | * tc data even if iproute2 was newer - jhs |
565 | */ | 564 | */ |
566 | struct rtattr * p_rta = (struct rtattr*) skb->tail; | 565 | struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb); |
567 | 566 | ||
568 | if (exts->action->type != TCA_OLD_COMPAT) { | 567 | if (exts->action->type != TCA_OLD_COMPAT) { |
569 | RTA_PUT(skb, map->action, 0, NULL); | 568 | RTA_PUT(skb, map->action, 0, NULL); |
570 | if (tcf_action_dump(skb, exts->action, 0, 0) < 0) | 569 | if (tcf_action_dump(skb, exts->action, 0, 0) < 0) |
571 | goto rtattr_failure; | 570 | goto rtattr_failure; |
572 | p_rta->rta_len = skb->tail - (u8*)p_rta; | 571 | p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; |
573 | } else if (map->police) { | 572 | } else if (map->police) { |
574 | RTA_PUT(skb, map->police, 0, NULL); | 573 | RTA_PUT(skb, map->police, 0, NULL); |
575 | if (tcf_action_dump_old(skb, exts->action, 0, 0) < 0) | 574 | if (tcf_action_dump_old(skb, exts->action, 0, 0) < 0) |
576 | goto rtattr_failure; | 575 | goto rtattr_failure; |
577 | p_rta->rta_len = skb->tail - (u8*)p_rta; | 576 | p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; |
578 | } | 577 | } |
579 | } | 578 | } |
580 | #elif defined CONFIG_NET_CLS_POLICE | 579 | #elif defined CONFIG_NET_CLS_POLICE |
581 | if (map->police && exts->police) { | 580 | if (map->police && exts->police) { |
582 | struct rtattr * p_rta = (struct rtattr*) skb->tail; | 581 | struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb); |
583 | 582 | ||
584 | RTA_PUT(skb, map->police, 0, NULL); | 583 | RTA_PUT(skb, map->police, 0, NULL); |
585 | 584 | ||
586 | if (tcf_police_dump(skb, exts->police) < 0) | 585 | if (tcf_police_dump(skb, exts->police) < 0) |
587 | goto rtattr_failure; | 586 | goto rtattr_failure; |
588 | 587 | ||
589 | p_rta->rta_len = skb->tail - (u8*)p_rta; | 588 | p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; |
590 | } | 589 | } |
591 | #endif | 590 | #endif |
592 | return 0; | 591 | return 0; |
@@ -614,18 +613,11 @@ rtattr_failure: __attribute__ ((unused)) | |||
614 | 613 | ||
615 | static int __init tc_filter_init(void) | 614 | static int __init tc_filter_init(void) |
616 | { | 615 | { |
617 | struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC]; | 616 | rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL); |
617 | rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL); | ||
618 | rtnl_register(PF_UNSPEC, RTM_GETTFILTER, tc_ctl_tfilter, | ||
619 | tc_dump_tfilter); | ||
618 | 620 | ||
619 | /* Setup rtnetlink links. It is made here to avoid | ||
620 | exporting large number of public symbols. | ||
621 | */ | ||
622 | |||
623 | if (link_p) { | ||
624 | link_p[RTM_NEWTFILTER-RTM_BASE].doit = tc_ctl_tfilter; | ||
625 | link_p[RTM_DELTFILTER-RTM_BASE].doit = tc_ctl_tfilter; | ||
626 | link_p[RTM_GETTFILTER-RTM_BASE].doit = tc_ctl_tfilter; | ||
627 | link_p[RTM_GETTFILTER-RTM_BASE].dumpit = tc_dump_tfilter; | ||
628 | } | ||
629 | return 0; | 621 | return 0; |
630 | } | 622 | } |
631 | 623 | ||
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 4a91f082a81d..c885412d79d5 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
19 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
20 | #include <net/netlink.h> | ||
20 | #include <net/act_api.h> | 21 | #include <net/act_api.h> |
21 | #include <net/pkt_cls.h> | 22 | #include <net/pkt_cls.h> |
22 | 23 | ||
@@ -245,7 +246,7 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh, | |||
245 | struct sk_buff *skb, struct tcmsg *t) | 246 | struct sk_buff *skb, struct tcmsg *t) |
246 | { | 247 | { |
247 | struct basic_filter *f = (struct basic_filter *) fh; | 248 | struct basic_filter *f = (struct basic_filter *) fh; |
248 | unsigned char *b = skb->tail; | 249 | unsigned char *b = skb_tail_pointer(skb); |
249 | struct rtattr *rta; | 250 | struct rtattr *rta; |
250 | 251 | ||
251 | if (f == NULL) | 252 | if (f == NULL) |
@@ -263,11 +264,11 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh, | |||
263 | tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0) | 264 | tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0) |
264 | goto rtattr_failure; | 265 | goto rtattr_failure; |
265 | 266 | ||
266 | rta->rta_len = (skb->tail - b); | 267 | rta->rta_len = skb_tail_pointer(skb) - b; |
267 | return skb->len; | 268 | return skb->len; |
268 | 269 | ||
269 | rtattr_failure: | 270 | rtattr_failure: |
270 | skb_trim(skb, b - skb->data); | 271 | nlmsg_trim(skb, b); |
271 | return -1; | 272 | return -1; |
272 | } | 273 | } |
273 | 274 | ||
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 5dbb9d451f73..bbec4a0d4dcb 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/notifier.h> | 38 | #include <linux/notifier.h> |
39 | #include <linux/netfilter.h> | 39 | #include <linux/netfilter.h> |
40 | #include <net/ip.h> | 40 | #include <net/ip.h> |
41 | #include <net/netlink.h> | ||
41 | #include <net/route.h> | 42 | #include <net/route.h> |
42 | #include <linux/skbuff.h> | 43 | #include <linux/skbuff.h> |
43 | #include <net/sock.h> | 44 | #include <net/sock.h> |
@@ -348,7 +349,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, | |||
348 | { | 349 | { |
349 | struct fw_head *head = (struct fw_head *)tp->root; | 350 | struct fw_head *head = (struct fw_head *)tp->root; |
350 | struct fw_filter *f = (struct fw_filter*)fh; | 351 | struct fw_filter *f = (struct fw_filter*)fh; |
351 | unsigned char *b = skb->tail; | 352 | unsigned char *b = skb_tail_pointer(skb); |
352 | struct rtattr *rta; | 353 | struct rtattr *rta; |
353 | 354 | ||
354 | if (f == NULL) | 355 | if (f == NULL) |
@@ -374,7 +375,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, | |||
374 | if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0) | 375 | if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0) |
375 | goto rtattr_failure; | 376 | goto rtattr_failure; |
376 | 377 | ||
377 | rta->rta_len = skb->tail - b; | 378 | rta->rta_len = skb_tail_pointer(skb) - b; |
378 | 379 | ||
379 | if (tcf_exts_dump_stats(skb, &f->exts, &fw_ext_map) < 0) | 380 | if (tcf_exts_dump_stats(skb, &f->exts, &fw_ext_map) < 0) |
380 | goto rtattr_failure; | 381 | goto rtattr_failure; |
@@ -382,7 +383,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, | |||
382 | return skb->len; | 383 | return skb->len; |
383 | 384 | ||
384 | rtattr_failure: | 385 | rtattr_failure: |
385 | skb_trim(skb, b - skb->data); | 386 | nlmsg_trim(skb, b); |
386 | return -1; | 387 | return -1; |
387 | } | 388 | } |
388 | 389 | ||
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index abc47cc48ad0..cc941d0ee3a5 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/etherdevice.h> | 28 | #include <linux/etherdevice.h> |
29 | #include <linux/notifier.h> | 29 | #include <linux/notifier.h> |
30 | #include <net/ip.h> | 30 | #include <net/ip.h> |
31 | #include <net/netlink.h> | ||
31 | #include <net/route.h> | 32 | #include <net/route.h> |
32 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
33 | #include <net/sock.h> | 34 | #include <net/sock.h> |
@@ -88,9 +89,9 @@ static __inline__ int route4_fastmap_hash(u32 id, int iif) | |||
88 | static inline | 89 | static inline |
89 | void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 id) | 90 | void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 id) |
90 | { | 91 | { |
91 | spin_lock_bh(&dev->queue_lock); | 92 | qdisc_lock_tree(dev); |
92 | memset(head->fastmap, 0, sizeof(head->fastmap)); | 93 | memset(head->fastmap, 0, sizeof(head->fastmap)); |
93 | spin_unlock_bh(&dev->queue_lock); | 94 | qdisc_unlock_tree(dev); |
94 | } | 95 | } |
95 | 96 | ||
96 | static inline void | 97 | static inline void |
@@ -562,7 +563,7 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh, | |||
562 | struct sk_buff *skb, struct tcmsg *t) | 563 | struct sk_buff *skb, struct tcmsg *t) |
563 | { | 564 | { |
564 | struct route4_filter *f = (struct route4_filter*)fh; | 565 | struct route4_filter *f = (struct route4_filter*)fh; |
565 | unsigned char *b = skb->tail; | 566 | unsigned char *b = skb_tail_pointer(skb); |
566 | struct rtattr *rta; | 567 | struct rtattr *rta; |
567 | u32 id; | 568 | u32 id; |
568 | 569 | ||
@@ -591,7 +592,7 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh, | |||
591 | if (tcf_exts_dump(skb, &f->exts, &route_ext_map) < 0) | 592 | if (tcf_exts_dump(skb, &f->exts, &route_ext_map) < 0) |
592 | goto rtattr_failure; | 593 | goto rtattr_failure; |
593 | 594 | ||
594 | rta->rta_len = skb->tail - b; | 595 | rta->rta_len = skb_tail_pointer(skb) - b; |
595 | 596 | ||
596 | if (tcf_exts_dump_stats(skb, &f->exts, &route_ext_map) < 0) | 597 | if (tcf_exts_dump_stats(skb, &f->exts, &route_ext_map) < 0) |
597 | goto rtattr_failure; | 598 | goto rtattr_failure; |
@@ -599,7 +600,7 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh, | |||
599 | return skb->len; | 600 | return skb->len; |
600 | 601 | ||
601 | rtattr_failure: | 602 | rtattr_failure: |
602 | skb_trim(skb, b - skb->data); | 603 | nlmsg_trim(skb, b); |
603 | return -1; | 604 | return -1; |
604 | } | 605 | } |
605 | 606 | ||
diff --git a/net/sched/cls_rsvp.c b/net/sched/cls_rsvp.c index 1d4a1fb17608..0a683c07c648 100644 --- a/net/sched/cls_rsvp.c +++ b/net/sched/cls_rsvp.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <net/route.h> | 31 | #include <net/route.h> |
32 | #include <linux/skbuff.h> | 32 | #include <linux/skbuff.h> |
33 | #include <net/sock.h> | 33 | #include <net/sock.h> |
34 | #include <net/netlink.h> | ||
34 | #include <net/act_api.h> | 35 | #include <net/act_api.h> |
35 | #include <net/pkt_cls.h> | 36 | #include <net/pkt_cls.h> |
36 | 37 | ||
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 7853621a04cc..22f9ede70e8f 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h | |||
@@ -143,9 +143,9 @@ static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp, | |||
143 | u8 tunnelid = 0; | 143 | u8 tunnelid = 0; |
144 | u8 *xprt; | 144 | u8 *xprt; |
145 | #if RSVP_DST_LEN == 4 | 145 | #if RSVP_DST_LEN == 4 |
146 | struct ipv6hdr *nhptr = skb->nh.ipv6h; | 146 | struct ipv6hdr *nhptr = ipv6_hdr(skb); |
147 | #else | 147 | #else |
148 | struct iphdr *nhptr = skb->nh.iph; | 148 | struct iphdr *nhptr = ip_hdr(skb); |
149 | #endif | 149 | #endif |
150 | 150 | ||
151 | restart: | 151 | restart: |
@@ -160,7 +160,7 @@ restart: | |||
160 | dst = &nhptr->daddr; | 160 | dst = &nhptr->daddr; |
161 | protocol = nhptr->protocol; | 161 | protocol = nhptr->protocol; |
162 | xprt = ((u8*)nhptr) + (nhptr->ihl<<2); | 162 | xprt = ((u8*)nhptr) + (nhptr->ihl<<2); |
163 | if (nhptr->frag_off&__constant_htons(IP_MF|IP_OFFSET)) | 163 | if (nhptr->frag_off & htons(IP_MF|IP_OFFSET)) |
164 | return -1; | 164 | return -1; |
165 | #endif | 165 | #endif |
166 | 166 | ||
@@ -593,7 +593,7 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, | |||
593 | { | 593 | { |
594 | struct rsvp_filter *f = (struct rsvp_filter*)fh; | 594 | struct rsvp_filter *f = (struct rsvp_filter*)fh; |
595 | struct rsvp_session *s; | 595 | struct rsvp_session *s; |
596 | unsigned char *b = skb->tail; | 596 | unsigned char *b = skb_tail_pointer(skb); |
597 | struct rtattr *rta; | 597 | struct rtattr *rta; |
598 | struct tc_rsvp_pinfo pinfo; | 598 | struct tc_rsvp_pinfo pinfo; |
599 | 599 | ||
@@ -623,14 +623,14 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, | |||
623 | if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0) | 623 | if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0) |
624 | goto rtattr_failure; | 624 | goto rtattr_failure; |
625 | 625 | ||
626 | rta->rta_len = skb->tail - b; | 626 | rta->rta_len = skb_tail_pointer(skb) - b; |
627 | 627 | ||
628 | if (tcf_exts_dump_stats(skb, &f->exts, &rsvp_ext_map) < 0) | 628 | if (tcf_exts_dump_stats(skb, &f->exts, &rsvp_ext_map) < 0) |
629 | goto rtattr_failure; | 629 | goto rtattr_failure; |
630 | return skb->len; | 630 | return skb->len; |
631 | 631 | ||
632 | rtattr_failure: | 632 | rtattr_failure: |
633 | skb_trim(skb, b - skb->data); | 633 | nlmsg_trim(skb, b); |
634 | return -1; | 634 | return -1; |
635 | } | 635 | } |
636 | 636 | ||
diff --git a/net/sched/cls_rsvp6.c b/net/sched/cls_rsvp6.c index a2979d89798f..93b6abed57db 100644 --- a/net/sched/cls_rsvp6.c +++ b/net/sched/cls_rsvp6.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <net/sock.h> | 34 | #include <net/sock.h> |
35 | #include <net/act_api.h> | 35 | #include <net/act_api.h> |
36 | #include <net/pkt_cls.h> | 36 | #include <net/pkt_cls.h> |
37 | #include <net/netlink.h> | ||
37 | 38 | ||
38 | #define RSVP_DST_LEN 4 | 39 | #define RSVP_DST_LEN 4 |
39 | #define RSVP_ID "rsvp6" | 40 | #define RSVP_ID "rsvp6" |
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 7563fdcef4b7..47ac0c556429 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
13 | #include <net/ip.h> | 13 | #include <net/ip.h> |
14 | #include <net/act_api.h> | 14 | #include <net/act_api.h> |
15 | #include <net/netlink.h> | ||
15 | #include <net/pkt_cls.h> | 16 | #include <net/pkt_cls.h> |
16 | #include <net/route.h> | 17 | #include <net/route.h> |
17 | 18 | ||
@@ -448,7 +449,7 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh, | |||
448 | { | 449 | { |
449 | struct tcindex_data *p = PRIV(tp); | 450 | struct tcindex_data *p = PRIV(tp); |
450 | struct tcindex_filter_result *r = (struct tcindex_filter_result *) fh; | 451 | struct tcindex_filter_result *r = (struct tcindex_filter_result *) fh; |
451 | unsigned char *b = skb->tail; | 452 | unsigned char *b = skb_tail_pointer(skb); |
452 | struct rtattr *rta; | 453 | struct rtattr *rta; |
453 | 454 | ||
454 | DPRINTK("tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n", | 455 | DPRINTK("tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n", |
@@ -463,7 +464,7 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh, | |||
463 | RTA_PUT(skb,TCA_TCINDEX_SHIFT,sizeof(p->shift),&p->shift); | 464 | RTA_PUT(skb,TCA_TCINDEX_SHIFT,sizeof(p->shift),&p->shift); |
464 | RTA_PUT(skb,TCA_TCINDEX_FALL_THROUGH,sizeof(p->fall_through), | 465 | RTA_PUT(skb,TCA_TCINDEX_FALL_THROUGH,sizeof(p->fall_through), |
465 | &p->fall_through); | 466 | &p->fall_through); |
466 | rta->rta_len = skb->tail-b; | 467 | rta->rta_len = skb_tail_pointer(skb) - b; |
467 | } else { | 468 | } else { |
468 | if (p->perfect) { | 469 | if (p->perfect) { |
469 | t->tcm_handle = r-p->perfect; | 470 | t->tcm_handle = r-p->perfect; |
@@ -486,7 +487,7 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh, | |||
486 | 487 | ||
487 | if (tcf_exts_dump(skb, &r->exts, &tcindex_ext_map) < 0) | 488 | if (tcf_exts_dump(skb, &r->exts, &tcindex_ext_map) < 0) |
488 | goto rtattr_failure; | 489 | goto rtattr_failure; |
489 | rta->rta_len = skb->tail-b; | 490 | rta->rta_len = skb_tail_pointer(skb) - b; |
490 | 491 | ||
491 | if (tcf_exts_dump_stats(skb, &r->exts, &tcindex_ext_map) < 0) | 492 | if (tcf_exts_dump_stats(skb, &r->exts, &tcindex_ext_map) < 0) |
492 | goto rtattr_failure; | 493 | goto rtattr_failure; |
@@ -495,7 +496,7 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh, | |||
495 | return skb->len; | 496 | return skb->len; |
496 | 497 | ||
497 | rtattr_failure: | 498 | rtattr_failure: |
498 | skb_trim(skb, b - skb->data); | 499 | nlmsg_trim(skb, b); |
499 | return -1; | 500 | return -1; |
500 | } | 501 | } |
501 | 502 | ||
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 0bcb16928d25..c7a347bd6d70 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/notifier.h> | 50 | #include <linux/notifier.h> |
51 | #include <linux/rtnetlink.h> | 51 | #include <linux/rtnetlink.h> |
52 | #include <net/ip.h> | 52 | #include <net/ip.h> |
53 | #include <net/netlink.h> | ||
53 | #include <net/route.h> | 54 | #include <net/route.h> |
54 | #include <linux/skbuff.h> | 55 | #include <linux/skbuff.h> |
55 | #include <net/sock.h> | 56 | #include <net/sock.h> |
@@ -119,7 +120,7 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re | |||
119 | } stack[TC_U32_MAXDEPTH]; | 120 | } stack[TC_U32_MAXDEPTH]; |
120 | 121 | ||
121 | struct tc_u_hnode *ht = (struct tc_u_hnode*)tp->root; | 122 | struct tc_u_hnode *ht = (struct tc_u_hnode*)tp->root; |
122 | u8 *ptr = skb->nh.raw; | 123 | u8 *ptr = skb_network_header(skb); |
123 | struct tc_u_knode *n; | 124 | struct tc_u_knode *n; |
124 | int sdepth = 0; | 125 | int sdepth = 0; |
125 | int off2 = 0; | 126 | int off2 = 0; |
@@ -213,7 +214,7 @@ check_terminal: | |||
213 | off2 = 0; | 214 | off2 = 0; |
214 | } | 215 | } |
215 | 216 | ||
216 | if (ptr < skb->tail) | 217 | if (ptr < skb_tail_pointer(skb)) |
217 | goto next_ht; | 218 | goto next_ht; |
218 | } | 219 | } |
219 | 220 | ||
@@ -435,7 +436,7 @@ static void u32_destroy(struct tcf_proto *tp) | |||
435 | BUG_TRAP(ht->refcnt == 0); | 436 | BUG_TRAP(ht->refcnt == 0); |
436 | 437 | ||
437 | kfree(ht); | 438 | kfree(ht); |
438 | }; | 439 | } |
439 | 440 | ||
440 | kfree(tp_c); | 441 | kfree(tp_c); |
441 | } | 442 | } |
@@ -718,7 +719,7 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, | |||
718 | struct sk_buff *skb, struct tcmsg *t) | 719 | struct sk_buff *skb, struct tcmsg *t) |
719 | { | 720 | { |
720 | struct tc_u_knode *n = (struct tc_u_knode*)fh; | 721 | struct tc_u_knode *n = (struct tc_u_knode*)fh; |
721 | unsigned char *b = skb->tail; | 722 | unsigned char *b = skb_tail_pointer(skb); |
722 | struct rtattr *rta; | 723 | struct rtattr *rta; |
723 | 724 | ||
724 | if (n == NULL) | 725 | if (n == NULL) |
@@ -765,14 +766,14 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, | |||
765 | #endif | 766 | #endif |
766 | } | 767 | } |
767 | 768 | ||
768 | rta->rta_len = skb->tail - b; | 769 | rta->rta_len = skb_tail_pointer(skb) - b; |
769 | if (TC_U32_KEY(n->handle)) | 770 | if (TC_U32_KEY(n->handle)) |
770 | if (tcf_exts_dump_stats(skb, &n->exts, &u32_ext_map) < 0) | 771 | if (tcf_exts_dump_stats(skb, &n->exts, &u32_ext_map) < 0) |
771 | goto rtattr_failure; | 772 | goto rtattr_failure; |
772 | return skb->len; | 773 | return skb->len; |
773 | 774 | ||
774 | rtattr_failure: | 775 | rtattr_failure: |
775 | skb_trim(skb, b - skb->data); | 776 | nlmsg_trim(skb, b); |
776 | return -1; | 777 | return -1; |
777 | } | 778 | } |
778 | 779 | ||
diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c index cd0600c67969..0a2a7fe08de3 100644 --- a/net/sched/em_u32.c +++ b/net/sched/em_u32.c | |||
@@ -22,7 +22,7 @@ static int em_u32_match(struct sk_buff *skb, struct tcf_ematch *em, | |||
22 | struct tcf_pkt_info *info) | 22 | struct tcf_pkt_info *info) |
23 | { | 23 | { |
24 | struct tc_u32_key *key = (struct tc_u32_key *) em->data; | 24 | struct tc_u32_key *key = (struct tc_u32_key *) em->data; |
25 | unsigned char *ptr = skb->nh.raw; | 25 | const unsigned char *ptr = skb_network_header(skb); |
26 | 26 | ||
27 | if (info) { | 27 | if (info) { |
28 | if (info->ptr) | 28 | if (info->ptr) |
diff --git a/net/sched/ematch.c b/net/sched/ematch.c index 959c306c5714..63146d339d81 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c | |||
@@ -418,17 +418,19 @@ void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree) | |||
418 | int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv) | 418 | int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv) |
419 | { | 419 | { |
420 | int i; | 420 | int i; |
421 | struct rtattr * top_start = (struct rtattr*) skb->tail; | 421 | u8 *tail; |
422 | struct rtattr * list_start; | 422 | struct rtattr *top_start = (struct rtattr *)skb_tail_pointer(skb); |
423 | struct rtattr *list_start; | ||
423 | 424 | ||
424 | RTA_PUT(skb, tlv, 0, NULL); | 425 | RTA_PUT(skb, tlv, 0, NULL); |
425 | RTA_PUT(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr); | 426 | RTA_PUT(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr); |
426 | 427 | ||
427 | list_start = (struct rtattr *) skb->tail; | 428 | list_start = (struct rtattr *)skb_tail_pointer(skb); |
428 | RTA_PUT(skb, TCA_EMATCH_TREE_LIST, 0, NULL); | 429 | RTA_PUT(skb, TCA_EMATCH_TREE_LIST, 0, NULL); |
429 | 430 | ||
431 | tail = skb_tail_pointer(skb); | ||
430 | for (i = 0; i < tree->hdr.nmatches; i++) { | 432 | for (i = 0; i < tree->hdr.nmatches; i++) { |
431 | struct rtattr *match_start = (struct rtattr*) skb->tail; | 433 | struct rtattr *match_start = (struct rtattr *)tail; |
432 | struct tcf_ematch *em = tcf_em_get_match(tree, i); | 434 | struct tcf_ematch *em = tcf_em_get_match(tree, i); |
433 | struct tcf_ematch_hdr em_hdr = { | 435 | struct tcf_ematch_hdr em_hdr = { |
434 | .kind = em->ops ? em->ops->kind : TCF_EM_CONTAINER, | 436 | .kind = em->ops ? em->ops->kind : TCF_EM_CONTAINER, |
@@ -447,11 +449,12 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv) | |||
447 | } else if (em->datalen > 0) | 449 | } else if (em->datalen > 0) |
448 | RTA_PUT_NOHDR(skb, em->datalen, (void *) em->data); | 450 | RTA_PUT_NOHDR(skb, em->datalen, (void *) em->data); |
449 | 451 | ||
450 | match_start->rta_len = skb->tail - (u8*) match_start; | 452 | tail = skb_tail_pointer(skb); |
453 | match_start->rta_len = tail - (u8 *)match_start; | ||
451 | } | 454 | } |
452 | 455 | ||
453 | list_start->rta_len = skb->tail - (u8 *) list_start; | 456 | list_start->rta_len = tail - (u8 *)list_start; |
454 | top_start->rta_len = skb->tail - (u8 *) top_start; | 457 | top_start->rta_len = tail - (u8 *)top_start; |
455 | 458 | ||
456 | return 0; | 459 | return 0; |
457 | 460 | ||
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index ecc988af4a9a..8699e7006d80 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -27,14 +27,15 @@ | |||
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/netdevice.h> | 28 | #include <linux/netdevice.h> |
29 | #include <linux/skbuff.h> | 29 | #include <linux/skbuff.h> |
30 | #include <linux/rtnetlink.h> | ||
31 | #include <linux/init.h> | 30 | #include <linux/init.h> |
32 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
33 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
34 | #include <linux/kmod.h> | 33 | #include <linux/kmod.h> |
35 | #include <linux/list.h> | 34 | #include <linux/list.h> |
36 | #include <linux/bitops.h> | 35 | #include <linux/bitops.h> |
36 | #include <linux/hrtimer.h> | ||
37 | 37 | ||
38 | #include <net/netlink.h> | ||
38 | #include <net/sock.h> | 39 | #include <net/sock.h> |
39 | #include <net/pkt_sched.h> | 40 | #include <net/pkt_sched.h> |
40 | 41 | ||
@@ -190,7 +191,7 @@ int unregister_qdisc(struct Qdisc_ops *qops) | |||
190 | (root qdisc, all its children, children of children etc.) | 191 | (root qdisc, all its children, children of children etc.) |
191 | */ | 192 | */ |
192 | 193 | ||
193 | static struct Qdisc *__qdisc_lookup(struct net_device *dev, u32 handle) | 194 | struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) |
194 | { | 195 | { |
195 | struct Qdisc *q; | 196 | struct Qdisc *q; |
196 | 197 | ||
@@ -201,16 +202,6 @@ static struct Qdisc *__qdisc_lookup(struct net_device *dev, u32 handle) | |||
201 | return NULL; | 202 | return NULL; |
202 | } | 203 | } |
203 | 204 | ||
204 | struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) | ||
205 | { | ||
206 | struct Qdisc *q; | ||
207 | |||
208 | read_lock(&qdisc_tree_lock); | ||
209 | q = __qdisc_lookup(dev, handle); | ||
210 | read_unlock(&qdisc_tree_lock); | ||
211 | return q; | ||
212 | } | ||
213 | |||
214 | static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) | 205 | static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) |
215 | { | 206 | { |
216 | unsigned long cl; | 207 | unsigned long cl; |
@@ -291,6 +282,48 @@ void qdisc_put_rtab(struct qdisc_rate_table *tab) | |||
291 | } | 282 | } |
292 | } | 283 | } |
293 | 284 | ||
285 | static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) | ||
286 | { | ||
287 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, | ||
288 | timer); | ||
289 | struct net_device *dev = wd->qdisc->dev; | ||
290 | |||
291 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | ||
292 | smp_wmb(); | ||
293 | if (spin_trylock(&dev->queue_lock)) { | ||
294 | qdisc_run(dev); | ||
295 | spin_unlock(&dev->queue_lock); | ||
296 | } else | ||
297 | netif_schedule(dev); | ||
298 | |||
299 | return HRTIMER_NORESTART; | ||
300 | } | ||
301 | |||
302 | void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc) | ||
303 | { | ||
304 | hrtimer_init(&wd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | ||
305 | wd->timer.function = qdisc_watchdog; | ||
306 | wd->qdisc = qdisc; | ||
307 | } | ||
308 | EXPORT_SYMBOL(qdisc_watchdog_init); | ||
309 | |||
310 | void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires) | ||
311 | { | ||
312 | ktime_t time; | ||
313 | |||
314 | wd->qdisc->flags |= TCQ_F_THROTTLED; | ||
315 | time = ktime_set(0, 0); | ||
316 | time = ktime_add_ns(time, PSCHED_US2NS(expires)); | ||
317 | hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); | ||
318 | } | ||
319 | EXPORT_SYMBOL(qdisc_watchdog_schedule); | ||
320 | |||
321 | void qdisc_watchdog_cancel(struct qdisc_watchdog *wd) | ||
322 | { | ||
323 | hrtimer_cancel(&wd->timer); | ||
324 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | ||
325 | } | ||
326 | EXPORT_SYMBOL(qdisc_watchdog_cancel); | ||
294 | 327 | ||
295 | /* Allocate an unique handle from space managed by kernel */ | 328 | /* Allocate an unique handle from space managed by kernel */ |
296 | 329 | ||
@@ -362,7 +395,7 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) | |||
362 | if (n == 0) | 395 | if (n == 0) |
363 | return; | 396 | return; |
364 | while ((parentid = sch->parent)) { | 397 | while ((parentid = sch->parent)) { |
365 | sch = __qdisc_lookup(sch->dev, TC_H_MAJ(parentid)); | 398 | sch = qdisc_lookup(sch->dev, TC_H_MAJ(parentid)); |
366 | cops = sch->ops->cl_ops; | 399 | cops = sch->ops->cl_ops; |
367 | if (cops->qlen_notify) { | 400 | if (cops->qlen_notify) { |
368 | cl = cops->get(sch, parentid); | 401 | cl = cops->get(sch, parentid); |
@@ -467,12 +500,16 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) | |||
467 | 500 | ||
468 | if (handle == TC_H_INGRESS) { | 501 | if (handle == TC_H_INGRESS) { |
469 | sch->flags |= TCQ_F_INGRESS; | 502 | sch->flags |= TCQ_F_INGRESS; |
503 | sch->stats_lock = &dev->ingress_lock; | ||
470 | handle = TC_H_MAKE(TC_H_INGRESS, 0); | 504 | handle = TC_H_MAKE(TC_H_INGRESS, 0); |
471 | } else if (handle == 0) { | 505 | } else { |
472 | handle = qdisc_alloc_handle(dev); | 506 | sch->stats_lock = &dev->queue_lock; |
473 | err = -ENOMEM; | 507 | if (handle == 0) { |
474 | if (handle == 0) | 508 | handle = qdisc_alloc_handle(dev); |
475 | goto err_out3; | 509 | err = -ENOMEM; |
510 | if (handle == 0) | ||
511 | goto err_out3; | ||
512 | } | ||
476 | } | 513 | } |
477 | 514 | ||
478 | sch->handle = handle; | 515 | sch->handle = handle; |
@@ -621,9 +658,9 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
621 | return err; | 658 | return err; |
622 | if (q) { | 659 | if (q) { |
623 | qdisc_notify(skb, n, clid, q, NULL); | 660 | qdisc_notify(skb, n, clid, q, NULL); |
624 | spin_lock_bh(&dev->queue_lock); | 661 | qdisc_lock_tree(dev); |
625 | qdisc_destroy(q); | 662 | qdisc_destroy(q); |
626 | spin_unlock_bh(&dev->queue_lock); | 663 | qdisc_unlock_tree(dev); |
627 | } | 664 | } |
628 | } else { | 665 | } else { |
629 | qdisc_notify(skb, n, clid, NULL, q); | 666 | qdisc_notify(skb, n, clid, NULL, q); |
@@ -756,17 +793,17 @@ graft: | |||
756 | err = qdisc_graft(dev, p, clid, q, &old_q); | 793 | err = qdisc_graft(dev, p, clid, q, &old_q); |
757 | if (err) { | 794 | if (err) { |
758 | if (q) { | 795 | if (q) { |
759 | spin_lock_bh(&dev->queue_lock); | 796 | qdisc_lock_tree(dev); |
760 | qdisc_destroy(q); | 797 | qdisc_destroy(q); |
761 | spin_unlock_bh(&dev->queue_lock); | 798 | qdisc_unlock_tree(dev); |
762 | } | 799 | } |
763 | return err; | 800 | return err; |
764 | } | 801 | } |
765 | qdisc_notify(skb, n, clid, old_q, q); | 802 | qdisc_notify(skb, n, clid, old_q, q); |
766 | if (old_q) { | 803 | if (old_q) { |
767 | spin_lock_bh(&dev->queue_lock); | 804 | qdisc_lock_tree(dev); |
768 | qdisc_destroy(old_q); | 805 | qdisc_destroy(old_q); |
769 | spin_unlock_bh(&dev->queue_lock); | 806 | qdisc_unlock_tree(dev); |
770 | } | 807 | } |
771 | } | 808 | } |
772 | return 0; | 809 | return 0; |
@@ -777,7 +814,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
777 | { | 814 | { |
778 | struct tcmsg *tcm; | 815 | struct tcmsg *tcm; |
779 | struct nlmsghdr *nlh; | 816 | struct nlmsghdr *nlh; |
780 | unsigned char *b = skb->tail; | 817 | unsigned char *b = skb_tail_pointer(skb); |
781 | struct gnet_dump d; | 818 | struct gnet_dump d; |
782 | 819 | ||
783 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); | 820 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
@@ -811,12 +848,12 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
811 | if (gnet_stats_finish_copy(&d) < 0) | 848 | if (gnet_stats_finish_copy(&d) < 0) |
812 | goto rtattr_failure; | 849 | goto rtattr_failure; |
813 | 850 | ||
814 | nlh->nlmsg_len = skb->tail - b; | 851 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
815 | return skb->len; | 852 | return skb->len; |
816 | 853 | ||
817 | nlmsg_failure: | 854 | nlmsg_failure: |
818 | rtattr_failure: | 855 | rtattr_failure: |
819 | skb_trim(skb, b - skb->data); | 856 | nlmsg_trim(skb, b); |
820 | return -1; | 857 | return -1; |
821 | } | 858 | } |
822 | 859 | ||
@@ -862,7 +899,6 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) | |||
862 | continue; | 899 | continue; |
863 | if (idx > s_idx) | 900 | if (idx > s_idx) |
864 | s_q_idx = 0; | 901 | s_q_idx = 0; |
865 | read_lock(&qdisc_tree_lock); | ||
866 | q_idx = 0; | 902 | q_idx = 0; |
867 | list_for_each_entry(q, &dev->qdisc_list, list) { | 903 | list_for_each_entry(q, &dev->qdisc_list, list) { |
868 | if (q_idx < s_q_idx) { | 904 | if (q_idx < s_q_idx) { |
@@ -870,13 +906,10 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) | |||
870 | continue; | 906 | continue; |
871 | } | 907 | } |
872 | if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, | 908 | if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, |
873 | cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) { | 909 | cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) |
874 | read_unlock(&qdisc_tree_lock); | ||
875 | goto done; | 910 | goto done; |
876 | } | ||
877 | q_idx++; | 911 | q_idx++; |
878 | } | 912 | } |
879 | read_unlock(&qdisc_tree_lock); | ||
880 | } | 913 | } |
881 | 914 | ||
882 | done: | 915 | done: |
@@ -1015,7 +1048,7 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, | |||
1015 | { | 1048 | { |
1016 | struct tcmsg *tcm; | 1049 | struct tcmsg *tcm; |
1017 | struct nlmsghdr *nlh; | 1050 | struct nlmsghdr *nlh; |
1018 | unsigned char *b = skb->tail; | 1051 | unsigned char *b = skb_tail_pointer(skb); |
1019 | struct gnet_dump d; | 1052 | struct gnet_dump d; |
1020 | struct Qdisc_class_ops *cl_ops = q->ops->cl_ops; | 1053 | struct Qdisc_class_ops *cl_ops = q->ops->cl_ops; |
1021 | 1054 | ||
@@ -1040,12 +1073,12 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, | |||
1040 | if (gnet_stats_finish_copy(&d) < 0) | 1073 | if (gnet_stats_finish_copy(&d) < 0) |
1041 | goto rtattr_failure; | 1074 | goto rtattr_failure; |
1042 | 1075 | ||
1043 | nlh->nlmsg_len = skb->tail - b; | 1076 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
1044 | return skb->len; | 1077 | return skb->len; |
1045 | 1078 | ||
1046 | nlmsg_failure: | 1079 | nlmsg_failure: |
1047 | rtattr_failure: | 1080 | rtattr_failure: |
1048 | skb_trim(skb, b - skb->data); | 1081 | nlmsg_trim(skb, b); |
1049 | return -1; | 1082 | return -1; |
1050 | } | 1083 | } |
1051 | 1084 | ||
@@ -1099,7 +1132,6 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1099 | s_t = cb->args[0]; | 1132 | s_t = cb->args[0]; |
1100 | t = 0; | 1133 | t = 0; |
1101 | 1134 | ||
1102 | read_lock(&qdisc_tree_lock); | ||
1103 | list_for_each_entry(q, &dev->qdisc_list, list) { | 1135 | list_for_each_entry(q, &dev->qdisc_list, list) { |
1104 | if (t < s_t || !q->ops->cl_ops || | 1136 | if (t < s_t || !q->ops->cl_ops || |
1105 | (tcm->tcm_parent && | 1137 | (tcm->tcm_parent && |
@@ -1121,7 +1153,6 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1121 | break; | 1153 | break; |
1122 | t++; | 1154 | t++; |
1123 | } | 1155 | } |
1124 | read_unlock(&qdisc_tree_lock); | ||
1125 | 1156 | ||
1126 | cb->args[0] = t; | 1157 | cb->args[0] = t; |
1127 | 1158 | ||
@@ -1146,7 +1177,7 @@ reclassify: | |||
1146 | 1177 | ||
1147 | for ( ; tp; tp = tp->next) { | 1178 | for ( ; tp; tp = tp->next) { |
1148 | if ((tp->protocol == protocol || | 1179 | if ((tp->protocol == protocol || |
1149 | tp->protocol == __constant_htons(ETH_P_ALL)) && | 1180 | tp->protocol == htons(ETH_P_ALL)) && |
1150 | (err = tp->classify(skb, tp, res)) >= 0) { | 1181 | (err = tp->classify(skb, tp, res)) >= 0) { |
1151 | #ifdef CONFIG_NET_CLS_ACT | 1182 | #ifdef CONFIG_NET_CLS_ACT |
1152 | if ( TC_ACT_RECLASSIFY == err) { | 1183 | if ( TC_ACT_RECLASSIFY == err) { |
@@ -1175,15 +1206,31 @@ reclassify: | |||
1175 | return -1; | 1206 | return -1; |
1176 | } | 1207 | } |
1177 | 1208 | ||
1178 | static int psched_us_per_tick = 1; | 1209 | void tcf_destroy(struct tcf_proto *tp) |
1179 | static int psched_tick_per_us = 1; | 1210 | { |
1211 | tp->ops->destroy(tp); | ||
1212 | module_put(tp->ops->owner); | ||
1213 | kfree(tp); | ||
1214 | } | ||
1215 | |||
1216 | void tcf_destroy_chain(struct tcf_proto *fl) | ||
1217 | { | ||
1218 | struct tcf_proto *tp; | ||
1219 | |||
1220 | while ((tp = fl) != NULL) { | ||
1221 | fl = tp->next; | ||
1222 | tcf_destroy(tp); | ||
1223 | } | ||
1224 | } | ||
1225 | EXPORT_SYMBOL(tcf_destroy_chain); | ||
1180 | 1226 | ||
1181 | #ifdef CONFIG_PROC_FS | 1227 | #ifdef CONFIG_PROC_FS |
1182 | static int psched_show(struct seq_file *seq, void *v) | 1228 | static int psched_show(struct seq_file *seq, void *v) |
1183 | { | 1229 | { |
1184 | seq_printf(seq, "%08x %08x %08x %08x\n", | 1230 | seq_printf(seq, "%08x %08x %08x %08x\n", |
1185 | psched_tick_per_us, psched_us_per_tick, | 1231 | (u32)NSEC_PER_USEC, (u32)PSCHED_US2NS(1), |
1186 | 1000000, HZ); | 1232 | 1000000, |
1233 | (u32)NSEC_PER_SEC/(u32)ktime_to_ns(KTIME_MONOTONIC_RES)); | ||
1187 | 1234 | ||
1188 | return 0; | 1235 | return 0; |
1189 | } | 1236 | } |
@@ -1202,101 +1249,19 @@ static const struct file_operations psched_fops = { | |||
1202 | }; | 1249 | }; |
1203 | #endif | 1250 | #endif |
1204 | 1251 | ||
1205 | #ifdef CONFIG_NET_SCH_CLK_CPU | ||
1206 | psched_tdiff_t psched_clock_per_hz; | ||
1207 | int psched_clock_scale; | ||
1208 | EXPORT_SYMBOL(psched_clock_per_hz); | ||
1209 | EXPORT_SYMBOL(psched_clock_scale); | ||
1210 | |||
1211 | psched_time_t psched_time_base; | ||
1212 | cycles_t psched_time_mark; | ||
1213 | EXPORT_SYMBOL(psched_time_mark); | ||
1214 | EXPORT_SYMBOL(psched_time_base); | ||
1215 | |||
1216 | /* | ||
1217 | * Periodically adjust psched_time_base to avoid overflow | ||
1218 | * with 32-bit get_cycles(). Safe up to 4GHz CPU. | ||
1219 | */ | ||
1220 | static void psched_tick(unsigned long); | ||
1221 | static DEFINE_TIMER(psched_timer, psched_tick, 0, 0); | ||
1222 | |||
1223 | static void psched_tick(unsigned long dummy) | ||
1224 | { | ||
1225 | if (sizeof(cycles_t) == sizeof(u32)) { | ||
1226 | psched_time_t dummy_stamp; | ||
1227 | PSCHED_GET_TIME(dummy_stamp); | ||
1228 | psched_timer.expires = jiffies + 1*HZ; | ||
1229 | add_timer(&psched_timer); | ||
1230 | } | ||
1231 | } | ||
1232 | |||
1233 | int __init psched_calibrate_clock(void) | ||
1234 | { | ||
1235 | psched_time_t stamp, stamp1; | ||
1236 | struct timeval tv, tv1; | ||
1237 | psched_tdiff_t delay; | ||
1238 | long rdelay; | ||
1239 | unsigned long stop; | ||
1240 | |||
1241 | psched_tick(0); | ||
1242 | stop = jiffies + HZ/10; | ||
1243 | PSCHED_GET_TIME(stamp); | ||
1244 | do_gettimeofday(&tv); | ||
1245 | while (time_before(jiffies, stop)) { | ||
1246 | barrier(); | ||
1247 | cpu_relax(); | ||
1248 | } | ||
1249 | PSCHED_GET_TIME(stamp1); | ||
1250 | do_gettimeofday(&tv1); | ||
1251 | |||
1252 | delay = PSCHED_TDIFF(stamp1, stamp); | ||
1253 | rdelay = tv1.tv_usec - tv.tv_usec; | ||
1254 | rdelay += (tv1.tv_sec - tv.tv_sec)*1000000; | ||
1255 | if (rdelay > delay) | ||
1256 | return -1; | ||
1257 | delay /= rdelay; | ||
1258 | psched_tick_per_us = delay; | ||
1259 | while ((delay>>=1) != 0) | ||
1260 | psched_clock_scale++; | ||
1261 | psched_us_per_tick = 1<<psched_clock_scale; | ||
1262 | psched_clock_per_hz = (psched_tick_per_us*(1000000/HZ))>>psched_clock_scale; | ||
1263 | return 0; | ||
1264 | } | ||
1265 | #endif | ||
1266 | |||
1267 | static int __init pktsched_init(void) | 1252 | static int __init pktsched_init(void) |
1268 | { | 1253 | { |
1269 | struct rtnetlink_link *link_p; | ||
1270 | |||
1271 | #ifdef CONFIG_NET_SCH_CLK_CPU | ||
1272 | if (psched_calibrate_clock() < 0) | ||
1273 | return -1; | ||
1274 | #elif defined(CONFIG_NET_SCH_CLK_JIFFIES) | ||
1275 | psched_tick_per_us = HZ<<PSCHED_JSCALE; | ||
1276 | psched_us_per_tick = 1000000; | ||
1277 | #endif | ||
1278 | |||
1279 | link_p = rtnetlink_links[PF_UNSPEC]; | ||
1280 | |||
1281 | /* Setup rtnetlink links. It is made here to avoid | ||
1282 | exporting large number of public symbols. | ||
1283 | */ | ||
1284 | |||
1285 | if (link_p) { | ||
1286 | link_p[RTM_NEWQDISC-RTM_BASE].doit = tc_modify_qdisc; | ||
1287 | link_p[RTM_DELQDISC-RTM_BASE].doit = tc_get_qdisc; | ||
1288 | link_p[RTM_GETQDISC-RTM_BASE].doit = tc_get_qdisc; | ||
1289 | link_p[RTM_GETQDISC-RTM_BASE].dumpit = tc_dump_qdisc; | ||
1290 | link_p[RTM_NEWTCLASS-RTM_BASE].doit = tc_ctl_tclass; | ||
1291 | link_p[RTM_DELTCLASS-RTM_BASE].doit = tc_ctl_tclass; | ||
1292 | link_p[RTM_GETTCLASS-RTM_BASE].doit = tc_ctl_tclass; | ||
1293 | link_p[RTM_GETTCLASS-RTM_BASE].dumpit = tc_dump_tclass; | ||
1294 | } | ||
1295 | |||
1296 | register_qdisc(&pfifo_qdisc_ops); | 1254 | register_qdisc(&pfifo_qdisc_ops); |
1297 | register_qdisc(&bfifo_qdisc_ops); | 1255 | register_qdisc(&bfifo_qdisc_ops); |
1298 | proc_net_fops_create("psched", 0, &psched_fops); | 1256 | proc_net_fops_create("psched", 0, &psched_fops); |
1299 | 1257 | ||
1258 | rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL); | ||
1259 | rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL); | ||
1260 | rtnl_register(PF_UNSPEC, RTM_GETQDISC, tc_get_qdisc, tc_dump_qdisc); | ||
1261 | rtnl_register(PF_UNSPEC, RTM_NEWTCLASS, tc_ctl_tclass, NULL); | ||
1262 | rtnl_register(PF_UNSPEC, RTM_DELTCLASS, tc_ctl_tclass, NULL); | ||
1263 | rtnl_register(PF_UNSPEC, RTM_GETTCLASS, tc_ctl_tclass, tc_dump_tclass); | ||
1264 | |||
1300 | return 0; | 1265 | return 0; |
1301 | } | 1266 | } |
1302 | 1267 | ||
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index afb3bbd571f2..be7d299acd73 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
15 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
16 | #include <linux/file.h> /* for fput */ | 16 | #include <linux/file.h> /* for fput */ |
17 | #include <net/netlink.h> | ||
17 | #include <net/pkt_sched.h> | 18 | #include <net/pkt_sched.h> |
18 | #include <net/sock.h> | 19 | #include <net/sock.h> |
19 | 20 | ||
@@ -157,19 +158,6 @@ static unsigned long atm_tc_bind_filter(struct Qdisc *sch, | |||
157 | return atm_tc_get(sch,classid); | 158 | return atm_tc_get(sch,classid); |
158 | } | 159 | } |
159 | 160 | ||
160 | |||
161 | static void destroy_filters(struct atm_flow_data *flow) | ||
162 | { | ||
163 | struct tcf_proto *filter; | ||
164 | |||
165 | while ((filter = flow->filter_list)) { | ||
166 | DPRINTK("destroy_filters: destroying filter %p\n",filter); | ||
167 | flow->filter_list = filter->next; | ||
168 | tcf_destroy(filter); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | |||
173 | /* | 161 | /* |
174 | * atm_tc_put handles all destructions, including the ones that are explicitly | 162 | * atm_tc_put handles all destructions, including the ones that are explicitly |
175 | * requested (atm_tc_destroy, etc.). The assumption here is that we never drop | 163 | * requested (atm_tc_destroy, etc.). The assumption here is that we never drop |
@@ -194,7 +182,7 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl) | |||
194 | *prev = flow->next; | 182 | *prev = flow->next; |
195 | DPRINTK("atm_tc_put: qdisc %p\n",flow->q); | 183 | DPRINTK("atm_tc_put: qdisc %p\n",flow->q); |
196 | qdisc_destroy(flow->q); | 184 | qdisc_destroy(flow->q); |
197 | destroy_filters(flow); | 185 | tcf_destroy_chain(flow->filter_list); |
198 | if (flow->sock) { | 186 | if (flow->sock) { |
199 | DPRINTK("atm_tc_put: f_count %d\n", | 187 | DPRINTK("atm_tc_put: f_count %d\n", |
200 | file_count(flow->sock->file)); | 188 | file_count(flow->sock->file)); |
@@ -503,7 +491,7 @@ static void sch_atm_dequeue(unsigned long data) | |||
503 | } | 491 | } |
504 | D2PRINTK("atm_tc_dequeue: sending on class %p\n",flow); | 492 | D2PRINTK("atm_tc_dequeue: sending on class %p\n",flow); |
505 | /* remove any LL header somebody else has attached */ | 493 | /* remove any LL header somebody else has attached */ |
506 | skb_pull(skb,(char *) skb->nh.iph-(char *) skb->data); | 494 | skb_pull(skb, skb_network_offset(skb)); |
507 | if (skb_headroom(skb) < flow->hdr_len) { | 495 | if (skb_headroom(skb) < flow->hdr_len) { |
508 | struct sk_buff *new; | 496 | struct sk_buff *new; |
509 | 497 | ||
@@ -513,7 +501,7 @@ static void sch_atm_dequeue(unsigned long data) | |||
513 | skb = new; | 501 | skb = new; |
514 | } | 502 | } |
515 | D2PRINTK("sch_atm_dequeue: ip %p, data %p\n", | 503 | D2PRINTK("sch_atm_dequeue: ip %p, data %p\n", |
516 | skb->nh.iph,skb->data); | 504 | skb_network_header(skb), skb->data); |
517 | ATM_SKB(skb)->vcc = flow->vcc; | 505 | ATM_SKB(skb)->vcc = flow->vcc; |
518 | memcpy(skb_push(skb,flow->hdr_len),flow->hdr, | 506 | memcpy(skb_push(skb,flow->hdr_len),flow->hdr, |
519 | flow->hdr_len); | 507 | flow->hdr_len); |
@@ -610,7 +598,7 @@ static void atm_tc_destroy(struct Qdisc *sch) | |||
610 | DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p); | 598 | DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p); |
611 | /* races ? */ | 599 | /* races ? */ |
612 | while ((flow = p->flows)) { | 600 | while ((flow = p->flows)) { |
613 | destroy_filters(flow); | 601 | tcf_destroy_chain(flow->filter_list); |
614 | if (flow->ref > 1) | 602 | if (flow->ref > 1) |
615 | printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow, | 603 | printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow, |
616 | flow->ref); | 604 | flow->ref); |
@@ -631,7 +619,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, | |||
631 | { | 619 | { |
632 | struct atm_qdisc_data *p = PRIV(sch); | 620 | struct atm_qdisc_data *p = PRIV(sch); |
633 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; | 621 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; |
634 | unsigned char *b = skb->tail; | 622 | unsigned char *b = skb_tail_pointer(skb); |
635 | struct rtattr *rta; | 623 | struct rtattr *rta; |
636 | 624 | ||
637 | DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n", | 625 | DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n", |
@@ -661,11 +649,11 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, | |||
661 | 649 | ||
662 | RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(zero),&zero); | 650 | RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(zero),&zero); |
663 | } | 651 | } |
664 | rta->rta_len = skb->tail-b; | 652 | rta->rta_len = skb_tail_pointer(skb) - b; |
665 | return skb->len; | 653 | return skb->len; |
666 | 654 | ||
667 | rtattr_failure: | 655 | rtattr_failure: |
668 | skb_trim(skb,b-skb->data); | 656 | nlmsg_trim(skb, b); |
669 | return -1; | 657 | return -1; |
670 | } | 658 | } |
671 | static int | 659 | static int |
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 76c92e710a33..a294542cb8e4 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
30 | #include <linux/notifier.h> | 30 | #include <linux/notifier.h> |
31 | #include <net/ip.h> | 31 | #include <net/ip.h> |
32 | #include <net/netlink.h> | ||
32 | #include <net/route.h> | 33 | #include <net/route.h> |
33 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
34 | #include <net/sock.h> | 35 | #include <net/sock.h> |
@@ -112,7 +113,7 @@ struct cbq_class | |||
112 | 113 | ||
113 | /* Overlimit strategy parameters */ | 114 | /* Overlimit strategy parameters */ |
114 | void (*overlimit)(struct cbq_class *cl); | 115 | void (*overlimit)(struct cbq_class *cl); |
115 | long penalty; | 116 | psched_tdiff_t penalty; |
116 | 117 | ||
117 | /* General scheduler (WRR) parameters */ | 118 | /* General scheduler (WRR) parameters */ |
118 | long allot; | 119 | long allot; |
@@ -143,7 +144,7 @@ struct cbq_class | |||
143 | psched_time_t undertime; | 144 | psched_time_t undertime; |
144 | long avgidle; | 145 | long avgidle; |
145 | long deficit; /* Saved deficit for WRR */ | 146 | long deficit; /* Saved deficit for WRR */ |
146 | unsigned long penalized; | 147 | psched_time_t penalized; |
147 | struct gnet_stats_basic bstats; | 148 | struct gnet_stats_basic bstats; |
148 | struct gnet_stats_queue qstats; | 149 | struct gnet_stats_queue qstats; |
149 | struct gnet_stats_rate_est rate_est; | 150 | struct gnet_stats_rate_est rate_est; |
@@ -180,12 +181,12 @@ struct cbq_sched_data | |||
180 | psched_time_t now_rt; /* Cached real time */ | 181 | psched_time_t now_rt; /* Cached real time */ |
181 | unsigned pmask; | 182 | unsigned pmask; |
182 | 183 | ||
183 | struct timer_list delay_timer; | 184 | struct hrtimer delay_timer; |
184 | struct timer_list wd_timer; /* Watchdog timer, | 185 | struct qdisc_watchdog watchdog; /* Watchdog timer, |
185 | started when CBQ has | 186 | started when CBQ has |
186 | backlog, but cannot | 187 | backlog, but cannot |
187 | transmit just now */ | 188 | transmit just now */ |
188 | long wd_expires; | 189 | psched_tdiff_t wd_expires; |
189 | int toplevel; | 190 | int toplevel; |
190 | u32 hgenerator; | 191 | u32 hgenerator; |
191 | }; | 192 | }; |
@@ -384,12 +385,12 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl) | |||
384 | psched_time_t now; | 385 | psched_time_t now; |
385 | psched_tdiff_t incr; | 386 | psched_tdiff_t incr; |
386 | 387 | ||
387 | PSCHED_GET_TIME(now); | 388 | now = psched_get_time(); |
388 | incr = PSCHED_TDIFF(now, q->now_rt); | 389 | incr = now - q->now_rt; |
389 | PSCHED_TADD2(q->now, incr, now); | 390 | now = q->now + incr; |
390 | 391 | ||
391 | do { | 392 | do { |
392 | if (PSCHED_TLESS(cl->undertime, now)) { | 393 | if (cl->undertime < now) { |
393 | q->toplevel = cl->level; | 394 | q->toplevel = cl->level; |
394 | return; | 395 | return; |
395 | } | 396 | } |
@@ -473,7 +474,7 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch) | |||
473 | static void cbq_ovl_classic(struct cbq_class *cl) | 474 | static void cbq_ovl_classic(struct cbq_class *cl) |
474 | { | 475 | { |
475 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); | 476 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); |
476 | psched_tdiff_t delay = PSCHED_TDIFF(cl->undertime, q->now); | 477 | psched_tdiff_t delay = cl->undertime - q->now; |
477 | 478 | ||
478 | if (!cl->delayed) { | 479 | if (!cl->delayed) { |
479 | delay += cl->offtime; | 480 | delay += cl->offtime; |
@@ -491,7 +492,7 @@ static void cbq_ovl_classic(struct cbq_class *cl) | |||
491 | cl->avgidle = cl->minidle; | 492 | cl->avgidle = cl->minidle; |
492 | if (delay <= 0) | 493 | if (delay <= 0) |
493 | delay = 1; | 494 | delay = 1; |
494 | PSCHED_TADD2(q->now, delay, cl->undertime); | 495 | cl->undertime = q->now + delay; |
495 | 496 | ||
496 | cl->xstats.overactions++; | 497 | cl->xstats.overactions++; |
497 | cl->delayed = 1; | 498 | cl->delayed = 1; |
@@ -508,7 +509,7 @@ static void cbq_ovl_classic(struct cbq_class *cl) | |||
508 | psched_tdiff_t base_delay = q->wd_expires; | 509 | psched_tdiff_t base_delay = q->wd_expires; |
509 | 510 | ||
510 | for (b = cl->borrow; b; b = b->borrow) { | 511 | for (b = cl->borrow; b; b = b->borrow) { |
511 | delay = PSCHED_TDIFF(b->undertime, q->now); | 512 | delay = b->undertime - q->now; |
512 | if (delay < base_delay) { | 513 | if (delay < base_delay) { |
513 | if (delay <= 0) | 514 | if (delay <= 0) |
514 | delay = 1; | 515 | delay = 1; |
@@ -546,27 +547,32 @@ static void cbq_ovl_rclassic(struct cbq_class *cl) | |||
546 | static void cbq_ovl_delay(struct cbq_class *cl) | 547 | static void cbq_ovl_delay(struct cbq_class *cl) |
547 | { | 548 | { |
548 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); | 549 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); |
549 | psched_tdiff_t delay = PSCHED_TDIFF(cl->undertime, q->now); | 550 | psched_tdiff_t delay = cl->undertime - q->now; |
550 | 551 | ||
551 | if (!cl->delayed) { | 552 | if (!cl->delayed) { |
552 | unsigned long sched = jiffies; | 553 | psched_time_t sched = q->now; |
554 | ktime_t expires; | ||
553 | 555 | ||
554 | delay += cl->offtime; | 556 | delay += cl->offtime; |
555 | if (cl->avgidle < 0) | 557 | if (cl->avgidle < 0) |
556 | delay -= (-cl->avgidle) - ((-cl->avgidle) >> cl->ewma_log); | 558 | delay -= (-cl->avgidle) - ((-cl->avgidle) >> cl->ewma_log); |
557 | if (cl->avgidle < cl->minidle) | 559 | if (cl->avgidle < cl->minidle) |
558 | cl->avgidle = cl->minidle; | 560 | cl->avgidle = cl->minidle; |
559 | PSCHED_TADD2(q->now, delay, cl->undertime); | 561 | cl->undertime = q->now + delay; |
560 | 562 | ||
561 | if (delay > 0) { | 563 | if (delay > 0) { |
562 | sched += PSCHED_US2JIFFIE(delay) + cl->penalty; | 564 | sched += delay + cl->penalty; |
563 | cl->penalized = sched; | 565 | cl->penalized = sched; |
564 | cl->cpriority = TC_CBQ_MAXPRIO; | 566 | cl->cpriority = TC_CBQ_MAXPRIO; |
565 | q->pmask |= (1<<TC_CBQ_MAXPRIO); | 567 | q->pmask |= (1<<TC_CBQ_MAXPRIO); |
566 | if (del_timer(&q->delay_timer) && | 568 | |
567 | (long)(q->delay_timer.expires - sched) > 0) | 569 | expires = ktime_set(0, 0); |
568 | q->delay_timer.expires = sched; | 570 | expires = ktime_add_ns(expires, PSCHED_US2NS(sched)); |
569 | add_timer(&q->delay_timer); | 571 | if (hrtimer_try_to_cancel(&q->delay_timer) && |
572 | ktime_to_ns(ktime_sub(q->delay_timer.expires, | ||
573 | expires)) > 0) | ||
574 | q->delay_timer.expires = expires; | ||
575 | hrtimer_restart(&q->delay_timer); | ||
570 | cl->delayed = 1; | 576 | cl->delayed = 1; |
571 | cl->xstats.overactions++; | 577 | cl->xstats.overactions++; |
572 | return; | 578 | return; |
@@ -583,7 +589,7 @@ static void cbq_ovl_lowprio(struct cbq_class *cl) | |||
583 | { | 589 | { |
584 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); | 590 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); |
585 | 591 | ||
586 | cl->penalized = jiffies + cl->penalty; | 592 | cl->penalized = q->now + cl->penalty; |
587 | 593 | ||
588 | if (cl->cpriority != cl->priority2) { | 594 | if (cl->cpriority != cl->priority2) { |
589 | cl->cpriority = cl->priority2; | 595 | cl->cpriority = cl->priority2; |
@@ -604,27 +610,19 @@ static void cbq_ovl_drop(struct cbq_class *cl) | |||
604 | cbq_ovl_classic(cl); | 610 | cbq_ovl_classic(cl); |
605 | } | 611 | } |
606 | 612 | ||
607 | static void cbq_watchdog(unsigned long arg) | 613 | static psched_tdiff_t cbq_undelay_prio(struct cbq_sched_data *q, int prio, |
608 | { | 614 | psched_time_t now) |
609 | struct Qdisc *sch = (struct Qdisc*)arg; | ||
610 | |||
611 | sch->flags &= ~TCQ_F_THROTTLED; | ||
612 | netif_schedule(sch->dev); | ||
613 | } | ||
614 | |||
615 | static unsigned long cbq_undelay_prio(struct cbq_sched_data *q, int prio) | ||
616 | { | 615 | { |
617 | struct cbq_class *cl; | 616 | struct cbq_class *cl; |
618 | struct cbq_class *cl_prev = q->active[prio]; | 617 | struct cbq_class *cl_prev = q->active[prio]; |
619 | unsigned long now = jiffies; | 618 | psched_time_t sched = now; |
620 | unsigned long sched = now; | ||
621 | 619 | ||
622 | if (cl_prev == NULL) | 620 | if (cl_prev == NULL) |
623 | return now; | 621 | return 0; |
624 | 622 | ||
625 | do { | 623 | do { |
626 | cl = cl_prev->next_alive; | 624 | cl = cl_prev->next_alive; |
627 | if ((long)(now - cl->penalized) > 0) { | 625 | if (now - cl->penalized > 0) { |
628 | cl_prev->next_alive = cl->next_alive; | 626 | cl_prev->next_alive = cl->next_alive; |
629 | cl->next_alive = NULL; | 627 | cl->next_alive = NULL; |
630 | cl->cpriority = cl->priority; | 628 | cl->cpriority = cl->priority; |
@@ -640,30 +638,34 @@ static unsigned long cbq_undelay_prio(struct cbq_sched_data *q, int prio) | |||
640 | } | 638 | } |
641 | 639 | ||
642 | cl = cl_prev->next_alive; | 640 | cl = cl_prev->next_alive; |
643 | } else if ((long)(sched - cl->penalized) > 0) | 641 | } else if (sched - cl->penalized > 0) |
644 | sched = cl->penalized; | 642 | sched = cl->penalized; |
645 | } while ((cl_prev = cl) != q->active[prio]); | 643 | } while ((cl_prev = cl) != q->active[prio]); |
646 | 644 | ||
647 | return (long)(sched - now); | 645 | return sched - now; |
648 | } | 646 | } |
649 | 647 | ||
650 | static void cbq_undelay(unsigned long arg) | 648 | static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) |
651 | { | 649 | { |
652 | struct Qdisc *sch = (struct Qdisc*)arg; | 650 | struct cbq_sched_data *q = container_of(timer, struct cbq_sched_data, |
653 | struct cbq_sched_data *q = qdisc_priv(sch); | 651 | delay_timer); |
654 | long delay = 0; | 652 | struct Qdisc *sch = q->watchdog.qdisc; |
653 | psched_time_t now; | ||
654 | psched_tdiff_t delay = 0; | ||
655 | unsigned pmask; | 655 | unsigned pmask; |
656 | 656 | ||
657 | now = psched_get_time(); | ||
658 | |||
657 | pmask = q->pmask; | 659 | pmask = q->pmask; |
658 | q->pmask = 0; | 660 | q->pmask = 0; |
659 | 661 | ||
660 | while (pmask) { | 662 | while (pmask) { |
661 | int prio = ffz(~pmask); | 663 | int prio = ffz(~pmask); |
662 | long tmp; | 664 | psched_tdiff_t tmp; |
663 | 665 | ||
664 | pmask &= ~(1<<prio); | 666 | pmask &= ~(1<<prio); |
665 | 667 | ||
666 | tmp = cbq_undelay_prio(q, prio); | 668 | tmp = cbq_undelay_prio(q, prio, now); |
667 | if (tmp > 0) { | 669 | if (tmp > 0) { |
668 | q->pmask |= 1<<prio; | 670 | q->pmask |= 1<<prio; |
669 | if (tmp < delay || delay == 0) | 671 | if (tmp < delay || delay == 0) |
@@ -672,12 +674,16 @@ static void cbq_undelay(unsigned long arg) | |||
672 | } | 674 | } |
673 | 675 | ||
674 | if (delay) { | 676 | if (delay) { |
675 | q->delay_timer.expires = jiffies + delay; | 677 | ktime_t time; |
676 | add_timer(&q->delay_timer); | 678 | |
679 | time = ktime_set(0, 0); | ||
680 | time = ktime_add_ns(time, PSCHED_US2NS(now + delay)); | ||
681 | hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS); | ||
677 | } | 682 | } |
678 | 683 | ||
679 | sch->flags &= ~TCQ_F_THROTTLED; | 684 | sch->flags &= ~TCQ_F_THROTTLED; |
680 | netif_schedule(sch->dev); | 685 | netif_schedule(sch->dev); |
686 | return HRTIMER_NORESTART; | ||
681 | } | 687 | } |
682 | 688 | ||
683 | 689 | ||
@@ -732,7 +738,7 @@ cbq_update_toplevel(struct cbq_sched_data *q, struct cbq_class *cl, | |||
732 | if (cl && q->toplevel >= borrowed->level) { | 738 | if (cl && q->toplevel >= borrowed->level) { |
733 | if (cl->q->q.qlen > 1) { | 739 | if (cl->q->q.qlen > 1) { |
734 | do { | 740 | do { |
735 | if (PSCHED_IS_PASTPERFECT(borrowed->undertime)) { | 741 | if (borrowed->undertime == PSCHED_PASTPERFECT) { |
736 | q->toplevel = borrowed->level; | 742 | q->toplevel = borrowed->level; |
737 | return; | 743 | return; |
738 | } | 744 | } |
@@ -770,7 +776,7 @@ cbq_update(struct cbq_sched_data *q) | |||
770 | idle = (now - last) - last_pktlen/rate | 776 | idle = (now - last) - last_pktlen/rate |
771 | */ | 777 | */ |
772 | 778 | ||
773 | idle = PSCHED_TDIFF(q->now, cl->last); | 779 | idle = q->now - cl->last; |
774 | if ((unsigned long)idle > 128*1024*1024) { | 780 | if ((unsigned long)idle > 128*1024*1024) { |
775 | avgidle = cl->maxidle; | 781 | avgidle = cl->maxidle; |
776 | } else { | 782 | } else { |
@@ -814,13 +820,11 @@ cbq_update(struct cbq_sched_data *q) | |||
814 | idle -= L2T(&q->link, len); | 820 | idle -= L2T(&q->link, len); |
815 | idle += L2T(cl, len); | 821 | idle += L2T(cl, len); |
816 | 822 | ||
817 | PSCHED_AUDIT_TDIFF(idle); | 823 | cl->undertime = q->now + idle; |
818 | |||
819 | PSCHED_TADD2(q->now, idle, cl->undertime); | ||
820 | } else { | 824 | } else { |
821 | /* Underlimit */ | 825 | /* Underlimit */ |
822 | 826 | ||
823 | PSCHED_SET_PASTPERFECT(cl->undertime); | 827 | cl->undertime = PSCHED_PASTPERFECT; |
824 | if (avgidle > cl->maxidle) | 828 | if (avgidle > cl->maxidle) |
825 | cl->avgidle = cl->maxidle; | 829 | cl->avgidle = cl->maxidle; |
826 | else | 830 | else |
@@ -841,8 +845,7 @@ cbq_under_limit(struct cbq_class *cl) | |||
841 | if (cl->tparent == NULL) | 845 | if (cl->tparent == NULL) |
842 | return cl; | 846 | return cl; |
843 | 847 | ||
844 | if (PSCHED_IS_PASTPERFECT(cl->undertime) || | 848 | if (cl->undertime == PSCHED_PASTPERFECT || q->now >= cl->undertime) { |
845 | !PSCHED_TLESS(q->now, cl->undertime)) { | ||
846 | cl->delayed = 0; | 849 | cl->delayed = 0; |
847 | return cl; | 850 | return cl; |
848 | } | 851 | } |
@@ -865,8 +868,7 @@ cbq_under_limit(struct cbq_class *cl) | |||
865 | } | 868 | } |
866 | if (cl->level > q->toplevel) | 869 | if (cl->level > q->toplevel) |
867 | return NULL; | 870 | return NULL; |
868 | } while (!PSCHED_IS_PASTPERFECT(cl->undertime) && | 871 | } while (cl->undertime != PSCHED_PASTPERFECT && q->now < cl->undertime); |
869 | PSCHED_TLESS(q->now, cl->undertime)); | ||
870 | 872 | ||
871 | cl->delayed = 0; | 873 | cl->delayed = 0; |
872 | return cl; | 874 | return cl; |
@@ -1001,8 +1003,8 @@ cbq_dequeue(struct Qdisc *sch) | |||
1001 | psched_time_t now; | 1003 | psched_time_t now; |
1002 | psched_tdiff_t incr; | 1004 | psched_tdiff_t incr; |
1003 | 1005 | ||
1004 | PSCHED_GET_TIME(now); | 1006 | now = psched_get_time(); |
1005 | incr = PSCHED_TDIFF(now, q->now_rt); | 1007 | incr = now - q->now_rt; |
1006 | 1008 | ||
1007 | if (q->tx_class) { | 1009 | if (q->tx_class) { |
1008 | psched_tdiff_t incr2; | 1010 | psched_tdiff_t incr2; |
@@ -1014,12 +1016,12 @@ cbq_dequeue(struct Qdisc *sch) | |||
1014 | cbq_time = max(real_time, work); | 1016 | cbq_time = max(real_time, work); |
1015 | */ | 1017 | */ |
1016 | incr2 = L2T(&q->link, q->tx_len); | 1018 | incr2 = L2T(&q->link, q->tx_len); |
1017 | PSCHED_TADD(q->now, incr2); | 1019 | q->now += incr2; |
1018 | cbq_update(q); | 1020 | cbq_update(q); |
1019 | if ((incr -= incr2) < 0) | 1021 | if ((incr -= incr2) < 0) |
1020 | incr = 0; | 1022 | incr = 0; |
1021 | } | 1023 | } |
1022 | PSCHED_TADD(q->now, incr); | 1024 | q->now += incr; |
1023 | q->now_rt = now; | 1025 | q->now_rt = now; |
1024 | 1026 | ||
1025 | for (;;) { | 1027 | for (;;) { |
@@ -1051,11 +1053,11 @@ cbq_dequeue(struct Qdisc *sch) | |||
1051 | */ | 1053 | */ |
1052 | 1054 | ||
1053 | if (q->toplevel == TC_CBQ_MAXLEVEL && | 1055 | if (q->toplevel == TC_CBQ_MAXLEVEL && |
1054 | PSCHED_IS_PASTPERFECT(q->link.undertime)) | 1056 | q->link.undertime == PSCHED_PASTPERFECT) |
1055 | break; | 1057 | break; |
1056 | 1058 | ||
1057 | q->toplevel = TC_CBQ_MAXLEVEL; | 1059 | q->toplevel = TC_CBQ_MAXLEVEL; |
1058 | PSCHED_SET_PASTPERFECT(q->link.undertime); | 1060 | q->link.undertime = PSCHED_PASTPERFECT; |
1059 | } | 1061 | } |
1060 | 1062 | ||
1061 | /* No packets in scheduler or nobody wants to give them to us :-( | 1063 | /* No packets in scheduler or nobody wants to give them to us :-( |
@@ -1063,13 +1065,9 @@ cbq_dequeue(struct Qdisc *sch) | |||
1063 | 1065 | ||
1064 | if (sch->q.qlen) { | 1066 | if (sch->q.qlen) { |
1065 | sch->qstats.overlimits++; | 1067 | sch->qstats.overlimits++; |
1066 | if (q->wd_expires) { | 1068 | if (q->wd_expires) |
1067 | long delay = PSCHED_US2JIFFIE(q->wd_expires); | 1069 | qdisc_watchdog_schedule(&q->watchdog, |
1068 | if (delay <= 0) | 1070 | now + q->wd_expires); |
1069 | delay = 1; | ||
1070 | mod_timer(&q->wd_timer, jiffies + delay); | ||
1071 | sch->flags |= TCQ_F_THROTTLED; | ||
1072 | } | ||
1073 | } | 1071 | } |
1074 | return NULL; | 1072 | return NULL; |
1075 | } | 1073 | } |
@@ -1276,10 +1274,10 @@ cbq_reset(struct Qdisc* sch) | |||
1276 | q->pmask = 0; | 1274 | q->pmask = 0; |
1277 | q->tx_class = NULL; | 1275 | q->tx_class = NULL; |
1278 | q->tx_borrowed = NULL; | 1276 | q->tx_borrowed = NULL; |
1279 | del_timer(&q->wd_timer); | 1277 | qdisc_watchdog_cancel(&q->watchdog); |
1280 | del_timer(&q->delay_timer); | 1278 | hrtimer_cancel(&q->delay_timer); |
1281 | q->toplevel = TC_CBQ_MAXLEVEL; | 1279 | q->toplevel = TC_CBQ_MAXLEVEL; |
1282 | PSCHED_GET_TIME(q->now); | 1280 | q->now = psched_get_time(); |
1283 | q->now_rt = q->now; | 1281 | q->now_rt = q->now; |
1284 | 1282 | ||
1285 | for (prio = 0; prio <= TC_CBQ_MAXPRIO; prio++) | 1283 | for (prio = 0; prio <= TC_CBQ_MAXPRIO; prio++) |
@@ -1290,7 +1288,7 @@ cbq_reset(struct Qdisc* sch) | |||
1290 | qdisc_reset(cl->q); | 1288 | qdisc_reset(cl->q); |
1291 | 1289 | ||
1292 | cl->next_alive = NULL; | 1290 | cl->next_alive = NULL; |
1293 | PSCHED_SET_PASTPERFECT(cl->undertime); | 1291 | cl->undertime = PSCHED_PASTPERFECT; |
1294 | cl->avgidle = cl->maxidle; | 1292 | cl->avgidle = cl->maxidle; |
1295 | cl->deficit = cl->quantum; | 1293 | cl->deficit = cl->quantum; |
1296 | cl->cpriority = cl->priority; | 1294 | cl->cpriority = cl->priority; |
@@ -1379,7 +1377,7 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl) | |||
1379 | default: | 1377 | default: |
1380 | return -EINVAL; | 1378 | return -EINVAL; |
1381 | } | 1379 | } |
1382 | cl->penalty = (ovl->penalty*HZ)/1000; | 1380 | cl->penalty = ovl->penalty; |
1383 | return 0; | 1381 | return 0; |
1384 | } | 1382 | } |
1385 | 1383 | ||
@@ -1446,14 +1444,11 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt) | |||
1446 | q->link.minidle = -0x7FFFFFFF; | 1444 | q->link.minidle = -0x7FFFFFFF; |
1447 | q->link.stats_lock = &sch->dev->queue_lock; | 1445 | q->link.stats_lock = &sch->dev->queue_lock; |
1448 | 1446 | ||
1449 | init_timer(&q->wd_timer); | 1447 | qdisc_watchdog_init(&q->watchdog, sch); |
1450 | q->wd_timer.data = (unsigned long)sch; | 1448 | hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
1451 | q->wd_timer.function = cbq_watchdog; | ||
1452 | init_timer(&q->delay_timer); | ||
1453 | q->delay_timer.data = (unsigned long)sch; | ||
1454 | q->delay_timer.function = cbq_undelay; | 1449 | q->delay_timer.function = cbq_undelay; |
1455 | q->toplevel = TC_CBQ_MAXLEVEL; | 1450 | q->toplevel = TC_CBQ_MAXLEVEL; |
1456 | PSCHED_GET_TIME(q->now); | 1451 | q->now = psched_get_time(); |
1457 | q->now_rt = q->now; | 1452 | q->now_rt = q->now; |
1458 | 1453 | ||
1459 | cbq_link_class(&q->link); | 1454 | cbq_link_class(&q->link); |
@@ -1467,19 +1462,19 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt) | |||
1467 | 1462 | ||
1468 | static __inline__ int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl) | 1463 | static __inline__ int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl) |
1469 | { | 1464 | { |
1470 | unsigned char *b = skb->tail; | 1465 | unsigned char *b = skb_tail_pointer(skb); |
1471 | 1466 | ||
1472 | RTA_PUT(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate); | 1467 | RTA_PUT(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate); |
1473 | return skb->len; | 1468 | return skb->len; |
1474 | 1469 | ||
1475 | rtattr_failure: | 1470 | rtattr_failure: |
1476 | skb_trim(skb, b - skb->data); | 1471 | nlmsg_trim(skb, b); |
1477 | return -1; | 1472 | return -1; |
1478 | } | 1473 | } |
1479 | 1474 | ||
1480 | static __inline__ int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl) | 1475 | static __inline__ int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl) |
1481 | { | 1476 | { |
1482 | unsigned char *b = skb->tail; | 1477 | unsigned char *b = skb_tail_pointer(skb); |
1483 | struct tc_cbq_lssopt opt; | 1478 | struct tc_cbq_lssopt opt; |
1484 | 1479 | ||
1485 | opt.flags = 0; | 1480 | opt.flags = 0; |
@@ -1498,13 +1493,13 @@ static __inline__ int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl) | |||
1498 | return skb->len; | 1493 | return skb->len; |
1499 | 1494 | ||
1500 | rtattr_failure: | 1495 | rtattr_failure: |
1501 | skb_trim(skb, b - skb->data); | 1496 | nlmsg_trim(skb, b); |
1502 | return -1; | 1497 | return -1; |
1503 | } | 1498 | } |
1504 | 1499 | ||
1505 | static __inline__ int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl) | 1500 | static __inline__ int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl) |
1506 | { | 1501 | { |
1507 | unsigned char *b = skb->tail; | 1502 | unsigned char *b = skb_tail_pointer(skb); |
1508 | struct tc_cbq_wrropt opt; | 1503 | struct tc_cbq_wrropt opt; |
1509 | 1504 | ||
1510 | opt.flags = 0; | 1505 | opt.flags = 0; |
@@ -1516,30 +1511,30 @@ static __inline__ int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl) | |||
1516 | return skb->len; | 1511 | return skb->len; |
1517 | 1512 | ||
1518 | rtattr_failure: | 1513 | rtattr_failure: |
1519 | skb_trim(skb, b - skb->data); | 1514 | nlmsg_trim(skb, b); |
1520 | return -1; | 1515 | return -1; |
1521 | } | 1516 | } |
1522 | 1517 | ||
1523 | static __inline__ int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl) | 1518 | static __inline__ int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl) |
1524 | { | 1519 | { |
1525 | unsigned char *b = skb->tail; | 1520 | unsigned char *b = skb_tail_pointer(skb); |
1526 | struct tc_cbq_ovl opt; | 1521 | struct tc_cbq_ovl opt; |
1527 | 1522 | ||
1528 | opt.strategy = cl->ovl_strategy; | 1523 | opt.strategy = cl->ovl_strategy; |
1529 | opt.priority2 = cl->priority2+1; | 1524 | opt.priority2 = cl->priority2+1; |
1530 | opt.pad = 0; | 1525 | opt.pad = 0; |
1531 | opt.penalty = (cl->penalty*1000)/HZ; | 1526 | opt.penalty = cl->penalty; |
1532 | RTA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt); | 1527 | RTA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt); |
1533 | return skb->len; | 1528 | return skb->len; |
1534 | 1529 | ||
1535 | rtattr_failure: | 1530 | rtattr_failure: |
1536 | skb_trim(skb, b - skb->data); | 1531 | nlmsg_trim(skb, b); |
1537 | return -1; | 1532 | return -1; |
1538 | } | 1533 | } |
1539 | 1534 | ||
1540 | static __inline__ int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl) | 1535 | static __inline__ int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl) |
1541 | { | 1536 | { |
1542 | unsigned char *b = skb->tail; | 1537 | unsigned char *b = skb_tail_pointer(skb); |
1543 | struct tc_cbq_fopt opt; | 1538 | struct tc_cbq_fopt opt; |
1544 | 1539 | ||
1545 | if (cl->split || cl->defmap) { | 1540 | if (cl->split || cl->defmap) { |
@@ -1551,14 +1546,14 @@ static __inline__ int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl) | |||
1551 | return skb->len; | 1546 | return skb->len; |
1552 | 1547 | ||
1553 | rtattr_failure: | 1548 | rtattr_failure: |
1554 | skb_trim(skb, b - skb->data); | 1549 | nlmsg_trim(skb, b); |
1555 | return -1; | 1550 | return -1; |
1556 | } | 1551 | } |
1557 | 1552 | ||
1558 | #ifdef CONFIG_NET_CLS_POLICE | 1553 | #ifdef CONFIG_NET_CLS_POLICE |
1559 | static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) | 1554 | static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) |
1560 | { | 1555 | { |
1561 | unsigned char *b = skb->tail; | 1556 | unsigned char *b = skb_tail_pointer(skb); |
1562 | struct tc_cbq_police opt; | 1557 | struct tc_cbq_police opt; |
1563 | 1558 | ||
1564 | if (cl->police) { | 1559 | if (cl->police) { |
@@ -1570,7 +1565,7 @@ static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) | |||
1570 | return skb->len; | 1565 | return skb->len; |
1571 | 1566 | ||
1572 | rtattr_failure: | 1567 | rtattr_failure: |
1573 | skb_trim(skb, b - skb->data); | 1568 | nlmsg_trim(skb, b); |
1574 | return -1; | 1569 | return -1; |
1575 | } | 1570 | } |
1576 | #endif | 1571 | #endif |
@@ -1592,18 +1587,18 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl) | |||
1592 | static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb) | 1587 | static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb) |
1593 | { | 1588 | { |
1594 | struct cbq_sched_data *q = qdisc_priv(sch); | 1589 | struct cbq_sched_data *q = qdisc_priv(sch); |
1595 | unsigned char *b = skb->tail; | 1590 | unsigned char *b = skb_tail_pointer(skb); |
1596 | struct rtattr *rta; | 1591 | struct rtattr *rta; |
1597 | 1592 | ||
1598 | rta = (struct rtattr*)b; | 1593 | rta = (struct rtattr*)b; |
1599 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); | 1594 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
1600 | if (cbq_dump_attr(skb, &q->link) < 0) | 1595 | if (cbq_dump_attr(skb, &q->link) < 0) |
1601 | goto rtattr_failure; | 1596 | goto rtattr_failure; |
1602 | rta->rta_len = skb->tail - b; | 1597 | rta->rta_len = skb_tail_pointer(skb) - b; |
1603 | return skb->len; | 1598 | return skb->len; |
1604 | 1599 | ||
1605 | rtattr_failure: | 1600 | rtattr_failure: |
1606 | skb_trim(skb, b - skb->data); | 1601 | nlmsg_trim(skb, b); |
1607 | return -1; | 1602 | return -1; |
1608 | } | 1603 | } |
1609 | 1604 | ||
@@ -1621,7 +1616,7 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg, | |||
1621 | struct sk_buff *skb, struct tcmsg *tcm) | 1616 | struct sk_buff *skb, struct tcmsg *tcm) |
1622 | { | 1617 | { |
1623 | struct cbq_class *cl = (struct cbq_class*)arg; | 1618 | struct cbq_class *cl = (struct cbq_class*)arg; |
1624 | unsigned char *b = skb->tail; | 1619 | unsigned char *b = skb_tail_pointer(skb); |
1625 | struct rtattr *rta; | 1620 | struct rtattr *rta; |
1626 | 1621 | ||
1627 | if (cl->tparent) | 1622 | if (cl->tparent) |
@@ -1635,11 +1630,11 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg, | |||
1635 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); | 1630 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
1636 | if (cbq_dump_attr(skb, cl) < 0) | 1631 | if (cbq_dump_attr(skb, cl) < 0) |
1637 | goto rtattr_failure; | 1632 | goto rtattr_failure; |
1638 | rta->rta_len = skb->tail - b; | 1633 | rta->rta_len = skb_tail_pointer(skb) - b; |
1639 | return skb->len; | 1634 | return skb->len; |
1640 | 1635 | ||
1641 | rtattr_failure: | 1636 | rtattr_failure: |
1642 | skb_trim(skb, b - skb->data); | 1637 | nlmsg_trim(skb, b); |
1643 | return -1; | 1638 | return -1; |
1644 | } | 1639 | } |
1645 | 1640 | ||
@@ -1654,8 +1649,8 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg, | |||
1654 | cl->xstats.avgidle = cl->avgidle; | 1649 | cl->xstats.avgidle = cl->avgidle; |
1655 | cl->xstats.undertime = 0; | 1650 | cl->xstats.undertime = 0; |
1656 | 1651 | ||
1657 | if (!PSCHED_IS_PASTPERFECT(cl->undertime)) | 1652 | if (cl->undertime != PSCHED_PASTPERFECT) |
1658 | cl->xstats.undertime = PSCHED_TDIFF(cl->undertime, q->now); | 1653 | cl->xstats.undertime = cl->undertime - q->now; |
1659 | 1654 | ||
1660 | if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || | 1655 | if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || |
1661 | #ifdef CONFIG_NET_ESTIMATOR | 1656 | #ifdef CONFIG_NET_ESTIMATOR |
@@ -1722,23 +1717,13 @@ static unsigned long cbq_get(struct Qdisc *sch, u32 classid) | |||
1722 | return 0; | 1717 | return 0; |
1723 | } | 1718 | } |
1724 | 1719 | ||
1725 | static void cbq_destroy_filters(struct cbq_class *cl) | ||
1726 | { | ||
1727 | struct tcf_proto *tp; | ||
1728 | |||
1729 | while ((tp = cl->filter_list) != NULL) { | ||
1730 | cl->filter_list = tp->next; | ||
1731 | tcf_destroy(tp); | ||
1732 | } | ||
1733 | } | ||
1734 | |||
1735 | static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl) | 1720 | static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl) |
1736 | { | 1721 | { |
1737 | struct cbq_sched_data *q = qdisc_priv(sch); | 1722 | struct cbq_sched_data *q = qdisc_priv(sch); |
1738 | 1723 | ||
1739 | BUG_TRAP(!cl->filters); | 1724 | BUG_TRAP(!cl->filters); |
1740 | 1725 | ||
1741 | cbq_destroy_filters(cl); | 1726 | tcf_destroy_chain(cl->filter_list); |
1742 | qdisc_destroy(cl->q); | 1727 | qdisc_destroy(cl->q); |
1743 | qdisc_put_rtab(cl->R_tab); | 1728 | qdisc_put_rtab(cl->R_tab); |
1744 | #ifdef CONFIG_NET_ESTIMATOR | 1729 | #ifdef CONFIG_NET_ESTIMATOR |
@@ -1765,7 +1750,7 @@ cbq_destroy(struct Qdisc* sch) | |||
1765 | */ | 1750 | */ |
1766 | for (h = 0; h < 16; h++) | 1751 | for (h = 0; h < 16; h++) |
1767 | for (cl = q->classes[h]; cl; cl = cl->next) | 1752 | for (cl = q->classes[h]; cl; cl = cl->next) |
1768 | cbq_destroy_filters(cl); | 1753 | tcf_destroy_chain(cl->filter_list); |
1769 | 1754 | ||
1770 | for (h = 0; h < 16; h++) { | 1755 | for (h = 0; h < 16; h++) { |
1771 | struct cbq_class *next; | 1756 | struct cbq_class *next; |
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 96324cf4e6a9..3c6fd181263f 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c | |||
@@ -216,17 +216,17 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
216 | /* FIXME: Safe with non-linear skbs? --RR */ | 216 | /* FIXME: Safe with non-linear skbs? --RR */ |
217 | switch (skb->protocol) { | 217 | switch (skb->protocol) { |
218 | case __constant_htons(ETH_P_IP): | 218 | case __constant_htons(ETH_P_IP): |
219 | skb->tc_index = ipv4_get_dsfield(skb->nh.iph) | 219 | skb->tc_index = ipv4_get_dsfield(ip_hdr(skb)) |
220 | & ~INET_ECN_MASK; | 220 | & ~INET_ECN_MASK; |
221 | break; | 221 | break; |
222 | case __constant_htons(ETH_P_IPV6): | 222 | case __constant_htons(ETH_P_IPV6): |
223 | skb->tc_index = ipv6_get_dsfield(skb->nh.ipv6h) | 223 | skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb)) |
224 | & ~INET_ECN_MASK; | 224 | & ~INET_ECN_MASK; |
225 | break; | 225 | break; |
226 | default: | 226 | default: |
227 | skb->tc_index = 0; | 227 | skb->tc_index = 0; |
228 | break; | 228 | break; |
229 | }; | 229 | } |
230 | } | 230 | } |
231 | 231 | ||
232 | if (TC_H_MAJ(skb->priority) == sch->handle) | 232 | if (TC_H_MAJ(skb->priority) == sch->handle) |
@@ -257,7 +257,7 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
257 | if (p->default_index != NO_DEFAULT_INDEX) | 257 | if (p->default_index != NO_DEFAULT_INDEX) |
258 | skb->tc_index = p->default_index; | 258 | skb->tc_index = p->default_index; |
259 | break; | 259 | break; |
260 | }; | 260 | } |
261 | } | 261 | } |
262 | 262 | ||
263 | err = p->q->enqueue(skb,p->q); | 263 | err = p->q->enqueue(skb,p->q); |
@@ -292,11 +292,11 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) | |||
292 | 292 | ||
293 | switch (skb->protocol) { | 293 | switch (skb->protocol) { |
294 | case __constant_htons(ETH_P_IP): | 294 | case __constant_htons(ETH_P_IP): |
295 | ipv4_change_dsfield(skb->nh.iph, p->mask[index], | 295 | ipv4_change_dsfield(ip_hdr(skb), p->mask[index], |
296 | p->value[index]); | 296 | p->value[index]); |
297 | break; | 297 | break; |
298 | case __constant_htons(ETH_P_IPV6): | 298 | case __constant_htons(ETH_P_IPV6): |
299 | ipv6_change_dsfield(skb->nh.ipv6h, p->mask[index], | 299 | ipv6_change_dsfield(ipv6_hdr(skb), p->mask[index], |
300 | p->value[index]); | 300 | p->value[index]); |
301 | break; | 301 | break; |
302 | default: | 302 | default: |
@@ -310,7 +310,7 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) | |||
310 | "unsupported protocol %d\n", | 310 | "unsupported protocol %d\n", |
311 | ntohs(skb->protocol)); | 311 | ntohs(skb->protocol)); |
312 | break; | 312 | break; |
313 | }; | 313 | } |
314 | 314 | ||
315 | return skb; | 315 | return skb; |
316 | } | 316 | } |
@@ -412,16 +412,10 @@ static void dsmark_reset(struct Qdisc *sch) | |||
412 | static void dsmark_destroy(struct Qdisc *sch) | 412 | static void dsmark_destroy(struct Qdisc *sch) |
413 | { | 413 | { |
414 | struct dsmark_qdisc_data *p = PRIV(sch); | 414 | struct dsmark_qdisc_data *p = PRIV(sch); |
415 | struct tcf_proto *tp; | ||
416 | 415 | ||
417 | DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n", sch, p); | 416 | DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n", sch, p); |
418 | 417 | ||
419 | while (p->filter_list) { | 418 | tcf_destroy_chain(p->filter_list); |
420 | tp = p->filter_list; | ||
421 | p->filter_list = tp->next; | ||
422 | tcf_destroy(tp); | ||
423 | } | ||
424 | |||
425 | qdisc_destroy(p->q); | 419 | qdisc_destroy(p->q); |
426 | kfree(p->mask); | 420 | kfree(p->mask); |
427 | } | 421 | } |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 52eb3439d7c6..3385ee592541 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -36,34 +36,27 @@ | |||
36 | 36 | ||
37 | /* Main transmission queue. */ | 37 | /* Main transmission queue. */ |
38 | 38 | ||
39 | /* Main qdisc structure lock. | 39 | /* Modifications to data participating in scheduling must be protected with |
40 | 40 | * dev->queue_lock spinlock. | |
41 | However, modifications | 41 | * |
42 | to data, participating in scheduling must be additionally | 42 | * The idea is the following: |
43 | protected with dev->queue_lock spinlock. | 43 | * - enqueue, dequeue are serialized via top level device |
44 | 44 | * spinlock dev->queue_lock. | |
45 | The idea is the following: | 45 | * - ingress filtering is serialized via top level device |
46 | - enqueue, dequeue are serialized via top level device | 46 | * spinlock dev->ingress_lock. |
47 | spinlock dev->queue_lock. | 47 | * - updates to tree and tree walking are only done under the rtnl mutex. |
48 | - tree walking is protected by read_lock(qdisc_tree_lock) | ||
49 | and this lock is used only in process context. | ||
50 | - updates to tree are made only under rtnl semaphore, | ||
51 | hence this lock may be made without local bh disabling. | ||
52 | |||
53 | qdisc_tree_lock must be grabbed BEFORE dev->queue_lock! | ||
54 | */ | 48 | */ |
55 | DEFINE_RWLOCK(qdisc_tree_lock); | ||
56 | 49 | ||
57 | void qdisc_lock_tree(struct net_device *dev) | 50 | void qdisc_lock_tree(struct net_device *dev) |
58 | { | 51 | { |
59 | write_lock(&qdisc_tree_lock); | ||
60 | spin_lock_bh(&dev->queue_lock); | 52 | spin_lock_bh(&dev->queue_lock); |
53 | spin_lock(&dev->ingress_lock); | ||
61 | } | 54 | } |
62 | 55 | ||
63 | void qdisc_unlock_tree(struct net_device *dev) | 56 | void qdisc_unlock_tree(struct net_device *dev) |
64 | { | 57 | { |
58 | spin_unlock(&dev->ingress_lock); | ||
65 | spin_unlock_bh(&dev->queue_lock); | 59 | spin_unlock_bh(&dev->queue_lock); |
66 | write_unlock(&qdisc_tree_lock); | ||
67 | } | 60 | } |
68 | 61 | ||
69 | /* | 62 | /* |
@@ -442,7 +435,6 @@ struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops) | |||
442 | sch->dequeue = ops->dequeue; | 435 | sch->dequeue = ops->dequeue; |
443 | sch->dev = dev; | 436 | sch->dev = dev; |
444 | dev_hold(dev); | 437 | dev_hold(dev); |
445 | sch->stats_lock = &dev->queue_lock; | ||
446 | atomic_set(&sch->refcnt, 1); | 438 | atomic_set(&sch->refcnt, 1); |
447 | 439 | ||
448 | return sch; | 440 | return sch; |
@@ -458,6 +450,7 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops, | |||
458 | sch = qdisc_alloc(dev, ops); | 450 | sch = qdisc_alloc(dev, ops); |
459 | if (IS_ERR(sch)) | 451 | if (IS_ERR(sch)) |
460 | goto errout; | 452 | goto errout; |
453 | sch->stats_lock = &dev->queue_lock; | ||
461 | sch->parent = parentid; | 454 | sch->parent = parentid; |
462 | 455 | ||
463 | if (!ops->init || ops->init(sch, NULL) == 0) | 456 | if (!ops->init || ops->init(sch, NULL) == 0) |
@@ -528,15 +521,11 @@ void dev_activate(struct net_device *dev) | |||
528 | printk(KERN_INFO "%s: activation failed\n", dev->name); | 521 | printk(KERN_INFO "%s: activation failed\n", dev->name); |
529 | return; | 522 | return; |
530 | } | 523 | } |
531 | write_lock(&qdisc_tree_lock); | ||
532 | list_add_tail(&qdisc->list, &dev->qdisc_list); | 524 | list_add_tail(&qdisc->list, &dev->qdisc_list); |
533 | write_unlock(&qdisc_tree_lock); | ||
534 | } else { | 525 | } else { |
535 | qdisc = &noqueue_qdisc; | 526 | qdisc = &noqueue_qdisc; |
536 | } | 527 | } |
537 | write_lock(&qdisc_tree_lock); | ||
538 | dev->qdisc_sleeping = qdisc; | 528 | dev->qdisc_sleeping = qdisc; |
539 | write_unlock(&qdisc_tree_lock); | ||
540 | } | 529 | } |
541 | 530 | ||
542 | if (!netif_carrier_ok(dev)) | 531 | if (!netif_carrier_ok(dev)) |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 407c6fb1ba14..9d124c4ee3a7 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -59,13 +59,13 @@ | |||
59 | #include <linux/skbuff.h> | 59 | #include <linux/skbuff.h> |
60 | #include <linux/string.h> | 60 | #include <linux/string.h> |
61 | #include <linux/slab.h> | 61 | #include <linux/slab.h> |
62 | #include <linux/timer.h> | ||
63 | #include <linux/list.h> | 62 | #include <linux/list.h> |
64 | #include <linux/rbtree.h> | 63 | #include <linux/rbtree.h> |
65 | #include <linux/init.h> | 64 | #include <linux/init.h> |
66 | #include <linux/netdevice.h> | 65 | #include <linux/netdevice.h> |
67 | #include <linux/rtnetlink.h> | 66 | #include <linux/rtnetlink.h> |
68 | #include <linux/pkt_sched.h> | 67 | #include <linux/pkt_sched.h> |
68 | #include <net/netlink.h> | ||
69 | #include <net/pkt_sched.h> | 69 | #include <net/pkt_sched.h> |
70 | #include <net/pkt_cls.h> | 70 | #include <net/pkt_cls.h> |
71 | #include <asm/system.h> | 71 | #include <asm/system.h> |
@@ -192,23 +192,9 @@ struct hfsc_sched | |||
192 | struct list_head droplist; /* active leaf class list (for | 192 | struct list_head droplist; /* active leaf class list (for |
193 | dropping) */ | 193 | dropping) */ |
194 | struct sk_buff_head requeue; /* requeued packet */ | 194 | struct sk_buff_head requeue; /* requeued packet */ |
195 | struct timer_list wd_timer; /* watchdog timer */ | 195 | struct qdisc_watchdog watchdog; /* watchdog timer */ |
196 | }; | 196 | }; |
197 | 197 | ||
198 | /* | ||
199 | * macros | ||
200 | */ | ||
201 | #ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY | ||
202 | #include <linux/time.h> | ||
203 | #undef PSCHED_GET_TIME | ||
204 | #define PSCHED_GET_TIME(stamp) \ | ||
205 | do { \ | ||
206 | struct timeval tv; \ | ||
207 | do_gettimeofday(&tv); \ | ||
208 | (stamp) = 1ULL * USEC_PER_SEC * tv.tv_sec + tv.tv_usec; \ | ||
209 | } while (0) | ||
210 | #endif | ||
211 | |||
212 | #define HT_INFINITY 0xffffffffffffffffULL /* infinite time value */ | 198 | #define HT_INFINITY 0xffffffffffffffffULL /* infinite time value */ |
213 | 199 | ||
214 | 200 | ||
@@ -394,28 +380,17 @@ cftree_update(struct hfsc_class *cl) | |||
394 | * ism: (psched_us/byte) << ISM_SHIFT | 380 | * ism: (psched_us/byte) << ISM_SHIFT |
395 | * dx: psched_us | 381 | * dx: psched_us |
396 | * | 382 | * |
397 | * Clock source resolution (CONFIG_NET_SCH_CLK_*) | 383 | * The clock source resolution with ktime is 1.024us. |
398 | * JIFFIES: for 48<=HZ<=1534 resolution is between 0.63us and 1.27us. | ||
399 | * CPU: resolution is between 0.5us and 1us. | ||
400 | * GETTIMEOFDAY: resolution is exactly 1us. | ||
401 | * | 384 | * |
402 | * sm and ism are scaled in order to keep effective digits. | 385 | * sm and ism are scaled in order to keep effective digits. |
403 | * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective | 386 | * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective |
404 | * digits in decimal using the following table. | 387 | * digits in decimal using the following table. |
405 | * | 388 | * |
406 | * Note: We can afford the additional accuracy (altq hfsc keeps at most | ||
407 | * 3 effective digits) thanks to the fact that linux clock is bounded | ||
408 | * much more tightly. | ||
409 | * | ||
410 | * bits/sec 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps | 389 | * bits/sec 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps |
411 | * ------------+------------------------------------------------------- | 390 | * ------------+------------------------------------------------------- |
412 | * bytes/0.5us 6.25e-3 62.5e-3 625e-3 6250e-e 62500e-3 | 391 | * bytes/1.024us 12.8e-3 128e-3 1280e-3 12800e-3 128000e-3 |
413 | * bytes/us 12.5e-3 125e-3 1250e-3 12500e-3 125000e-3 | ||
414 | * bytes/1.27us 15.875e-3 158.75e-3 1587.5e-3 15875e-3 158750e-3 | ||
415 | * | 392 | * |
416 | * 0.5us/byte 160 16 1.6 0.16 0.016 | 393 | * 1.024us/byte 78.125 7.8125 0.78125 0.078125 0.0078125 |
417 | * us/byte 80 8 0.8 0.08 0.008 | ||
418 | * 1.27us/byte 63 6.3 0.63 0.063 0.0063 | ||
419 | */ | 394 | */ |
420 | #define SM_SHIFT 20 | 395 | #define SM_SHIFT 20 |
421 | #define ISM_SHIFT 18 | 396 | #define ISM_SHIFT 18 |
@@ -460,8 +435,8 @@ m2sm(u32 m) | |||
460 | u64 sm; | 435 | u64 sm; |
461 | 436 | ||
462 | sm = ((u64)m << SM_SHIFT); | 437 | sm = ((u64)m << SM_SHIFT); |
463 | sm += PSCHED_JIFFIE2US(HZ) - 1; | 438 | sm += PSCHED_TICKS_PER_SEC - 1; |
464 | do_div(sm, PSCHED_JIFFIE2US(HZ)); | 439 | do_div(sm, PSCHED_TICKS_PER_SEC); |
465 | return sm; | 440 | return sm; |
466 | } | 441 | } |
467 | 442 | ||
@@ -474,7 +449,7 @@ m2ism(u32 m) | |||
474 | if (m == 0) | 449 | if (m == 0) |
475 | ism = HT_INFINITY; | 450 | ism = HT_INFINITY; |
476 | else { | 451 | else { |
477 | ism = ((u64)PSCHED_JIFFIE2US(HZ) << ISM_SHIFT); | 452 | ism = ((u64)PSCHED_TICKS_PER_SEC << ISM_SHIFT); |
478 | ism += m - 1; | 453 | ism += m - 1; |
479 | do_div(ism, m); | 454 | do_div(ism, m); |
480 | } | 455 | } |
@@ -487,7 +462,7 @@ d2dx(u32 d) | |||
487 | { | 462 | { |
488 | u64 dx; | 463 | u64 dx; |
489 | 464 | ||
490 | dx = ((u64)d * PSCHED_JIFFIE2US(HZ)); | 465 | dx = ((u64)d * PSCHED_TICKS_PER_SEC); |
491 | dx += USEC_PER_SEC - 1; | 466 | dx += USEC_PER_SEC - 1; |
492 | do_div(dx, USEC_PER_SEC); | 467 | do_div(dx, USEC_PER_SEC); |
493 | return dx; | 468 | return dx; |
@@ -499,7 +474,7 @@ sm2m(u64 sm) | |||
499 | { | 474 | { |
500 | u64 m; | 475 | u64 m; |
501 | 476 | ||
502 | m = (sm * PSCHED_JIFFIE2US(HZ)) >> SM_SHIFT; | 477 | m = (sm * PSCHED_TICKS_PER_SEC) >> SM_SHIFT; |
503 | return (u32)m; | 478 | return (u32)m; |
504 | } | 479 | } |
505 | 480 | ||
@@ -510,7 +485,7 @@ dx2d(u64 dx) | |||
510 | u64 d; | 485 | u64 d; |
511 | 486 | ||
512 | d = dx * USEC_PER_SEC; | 487 | d = dx * USEC_PER_SEC; |
513 | do_div(d, PSCHED_JIFFIE2US(HZ)); | 488 | do_div(d, PSCHED_TICKS_PER_SEC); |
514 | return (u32)d; | 489 | return (u32)d; |
515 | } | 490 | } |
516 | 491 | ||
@@ -654,9 +629,7 @@ rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, u64 y) | |||
654 | static void | 629 | static void |
655 | init_ed(struct hfsc_class *cl, unsigned int next_len) | 630 | init_ed(struct hfsc_class *cl, unsigned int next_len) |
656 | { | 631 | { |
657 | u64 cur_time; | 632 | u64 cur_time = psched_get_time(); |
658 | |||
659 | PSCHED_GET_TIME(cur_time); | ||
660 | 633 | ||
661 | /* update the deadline curve */ | 634 | /* update the deadline curve */ |
662 | rtsc_min(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul); | 635 | rtsc_min(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul); |
@@ -779,7 +752,7 @@ init_vf(struct hfsc_class *cl, unsigned int len) | |||
779 | if (cl->cl_flags & HFSC_USC) { | 752 | if (cl->cl_flags & HFSC_USC) { |
780 | /* class has upper limit curve */ | 753 | /* class has upper limit curve */ |
781 | if (cur_time == 0) | 754 | if (cur_time == 0) |
782 | PSCHED_GET_TIME(cur_time); | 755 | cur_time = psched_get_time(); |
783 | 756 | ||
784 | /* update the ulimit curve */ | 757 | /* update the ulimit curve */ |
785 | rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time, | 758 | rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time, |
@@ -1063,7 +1036,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1063 | if (cl->cl_parent == NULL && parentid != TC_H_ROOT) | 1036 | if (cl->cl_parent == NULL && parentid != TC_H_ROOT) |
1064 | return -EINVAL; | 1037 | return -EINVAL; |
1065 | } | 1038 | } |
1066 | PSCHED_GET_TIME(cur_time); | 1039 | cur_time = psched_get_time(); |
1067 | 1040 | ||
1068 | sch_tree_lock(sch); | 1041 | sch_tree_lock(sch); |
1069 | if (rsc != NULL) | 1042 | if (rsc != NULL) |
@@ -1149,22 +1122,11 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1149 | } | 1122 | } |
1150 | 1123 | ||
1151 | static void | 1124 | static void |
1152 | hfsc_destroy_filters(struct tcf_proto **fl) | ||
1153 | { | ||
1154 | struct tcf_proto *tp; | ||
1155 | |||
1156 | while ((tp = *fl) != NULL) { | ||
1157 | *fl = tp->next; | ||
1158 | tcf_destroy(tp); | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | static void | ||
1163 | hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl) | 1125 | hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl) |
1164 | { | 1126 | { |
1165 | struct hfsc_sched *q = qdisc_priv(sch); | 1127 | struct hfsc_sched *q = qdisc_priv(sch); |
1166 | 1128 | ||
1167 | hfsc_destroy_filters(&cl->filter_list); | 1129 | tcf_destroy_chain(cl->filter_list); |
1168 | qdisc_destroy(cl->qdisc); | 1130 | qdisc_destroy(cl->qdisc); |
1169 | #ifdef CONFIG_NET_ESTIMATOR | 1131 | #ifdef CONFIG_NET_ESTIMATOR |
1170 | gen_kill_estimator(&cl->bstats, &cl->rate_est); | 1132 | gen_kill_estimator(&cl->bstats, &cl->rate_est); |
@@ -1389,7 +1351,7 @@ hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, | |||
1389 | struct tcmsg *tcm) | 1351 | struct tcmsg *tcm) |
1390 | { | 1352 | { |
1391 | struct hfsc_class *cl = (struct hfsc_class *)arg; | 1353 | struct hfsc_class *cl = (struct hfsc_class *)arg; |
1392 | unsigned char *b = skb->tail; | 1354 | unsigned char *b = skb_tail_pointer(skb); |
1393 | struct rtattr *rta = (struct rtattr *)b; | 1355 | struct rtattr *rta = (struct rtattr *)b; |
1394 | 1356 | ||
1395 | tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT; | 1357 | tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT; |
@@ -1400,11 +1362,11 @@ hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, | |||
1400 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); | 1362 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
1401 | if (hfsc_dump_curves(skb, cl) < 0) | 1363 | if (hfsc_dump_curves(skb, cl) < 0) |
1402 | goto rtattr_failure; | 1364 | goto rtattr_failure; |
1403 | rta->rta_len = skb->tail - b; | 1365 | rta->rta_len = skb_tail_pointer(skb) - b; |
1404 | return skb->len; | 1366 | return skb->len; |
1405 | 1367 | ||
1406 | rtattr_failure: | 1368 | rtattr_failure: |
1407 | skb_trim(skb, b - skb->data); | 1369 | nlmsg_trim(skb, b); |
1408 | return -1; | 1370 | return -1; |
1409 | } | 1371 | } |
1410 | 1372 | ||
@@ -1459,21 +1421,11 @@ hfsc_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
1459 | } | 1421 | } |
1460 | 1422 | ||
1461 | static void | 1423 | static void |
1462 | hfsc_watchdog(unsigned long arg) | 1424 | hfsc_schedule_watchdog(struct Qdisc *sch) |
1463 | { | ||
1464 | struct Qdisc *sch = (struct Qdisc *)arg; | ||
1465 | |||
1466 | sch->flags &= ~TCQ_F_THROTTLED; | ||
1467 | netif_schedule(sch->dev); | ||
1468 | } | ||
1469 | |||
1470 | static void | ||
1471 | hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time) | ||
1472 | { | 1425 | { |
1473 | struct hfsc_sched *q = qdisc_priv(sch); | 1426 | struct hfsc_sched *q = qdisc_priv(sch); |
1474 | struct hfsc_class *cl; | 1427 | struct hfsc_class *cl; |
1475 | u64 next_time = 0; | 1428 | u64 next_time = 0; |
1476 | long delay; | ||
1477 | 1429 | ||
1478 | if ((cl = eltree_get_minel(q)) != NULL) | 1430 | if ((cl = eltree_get_minel(q)) != NULL) |
1479 | next_time = cl->cl_e; | 1431 | next_time = cl->cl_e; |
@@ -1482,11 +1434,7 @@ hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time) | |||
1482 | next_time = q->root.cl_cfmin; | 1434 | next_time = q->root.cl_cfmin; |
1483 | } | 1435 | } |
1484 | WARN_ON(next_time == 0); | 1436 | WARN_ON(next_time == 0); |
1485 | delay = next_time - cur_time; | 1437 | qdisc_watchdog_schedule(&q->watchdog, next_time); |
1486 | delay = PSCHED_US2JIFFIE(delay); | ||
1487 | |||
1488 | sch->flags |= TCQ_F_THROTTLED; | ||
1489 | mod_timer(&q->wd_timer, jiffies + delay); | ||
1490 | } | 1438 | } |
1491 | 1439 | ||
1492 | static int | 1440 | static int |
@@ -1523,9 +1471,7 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) | |||
1523 | 1471 | ||
1524 | list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]); | 1472 | list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]); |
1525 | 1473 | ||
1526 | init_timer(&q->wd_timer); | 1474 | qdisc_watchdog_init(&q->watchdog, sch); |
1527 | q->wd_timer.function = hfsc_watchdog; | ||
1528 | q->wd_timer.data = (unsigned long)sch; | ||
1529 | 1475 | ||
1530 | return 0; | 1476 | return 0; |
1531 | } | 1477 | } |
@@ -1595,8 +1541,7 @@ hfsc_reset_qdisc(struct Qdisc *sch) | |||
1595 | __skb_queue_purge(&q->requeue); | 1541 | __skb_queue_purge(&q->requeue); |
1596 | q->eligible = RB_ROOT; | 1542 | q->eligible = RB_ROOT; |
1597 | INIT_LIST_HEAD(&q->droplist); | 1543 | INIT_LIST_HEAD(&q->droplist); |
1598 | del_timer(&q->wd_timer); | 1544 | qdisc_watchdog_cancel(&q->watchdog); |
1599 | sch->flags &= ~TCQ_F_THROTTLED; | ||
1600 | sch->q.qlen = 0; | 1545 | sch->q.qlen = 0; |
1601 | } | 1546 | } |
1602 | 1547 | ||
@@ -1612,14 +1557,14 @@ hfsc_destroy_qdisc(struct Qdisc *sch) | |||
1612 | hfsc_destroy_class(sch, cl); | 1557 | hfsc_destroy_class(sch, cl); |
1613 | } | 1558 | } |
1614 | __skb_queue_purge(&q->requeue); | 1559 | __skb_queue_purge(&q->requeue); |
1615 | del_timer(&q->wd_timer); | 1560 | qdisc_watchdog_cancel(&q->watchdog); |
1616 | } | 1561 | } |
1617 | 1562 | ||
1618 | static int | 1563 | static int |
1619 | hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb) | 1564 | hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb) |
1620 | { | 1565 | { |
1621 | struct hfsc_sched *q = qdisc_priv(sch); | 1566 | struct hfsc_sched *q = qdisc_priv(sch); |
1622 | unsigned char *b = skb->tail; | 1567 | unsigned char *b = skb_tail_pointer(skb); |
1623 | struct tc_hfsc_qopt qopt; | 1568 | struct tc_hfsc_qopt qopt; |
1624 | 1569 | ||
1625 | qopt.defcls = q->defcls; | 1570 | qopt.defcls = q->defcls; |
@@ -1627,7 +1572,7 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb) | |||
1627 | return skb->len; | 1572 | return skb->len; |
1628 | 1573 | ||
1629 | rtattr_failure: | 1574 | rtattr_failure: |
1630 | skb_trim(skb, b - skb->data); | 1575 | nlmsg_trim(skb, b); |
1631 | return -1; | 1576 | return -1; |
1632 | } | 1577 | } |
1633 | 1578 | ||
@@ -1681,7 +1626,7 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1681 | if ((skb = __skb_dequeue(&q->requeue))) | 1626 | if ((skb = __skb_dequeue(&q->requeue))) |
1682 | goto out; | 1627 | goto out; |
1683 | 1628 | ||
1684 | PSCHED_GET_TIME(cur_time); | 1629 | cur_time = psched_get_time(); |
1685 | 1630 | ||
1686 | /* | 1631 | /* |
1687 | * if there are eligible classes, use real-time criteria. | 1632 | * if there are eligible classes, use real-time criteria. |
@@ -1698,7 +1643,7 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1698 | cl = vttree_get_minvt(&q->root, cur_time); | 1643 | cl = vttree_get_minvt(&q->root, cur_time); |
1699 | if (cl == NULL) { | 1644 | if (cl == NULL) { |
1700 | sch->qstats.overlimits++; | 1645 | sch->qstats.overlimits++; |
1701 | hfsc_schedule_watchdog(sch, cur_time); | 1646 | hfsc_schedule_watchdog(sch); |
1702 | return NULL; | 1647 | return NULL; |
1703 | } | 1648 | } |
1704 | } | 1649 | } |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 3c3294d01041..99bcec8dd04c 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/skbuff.h> | 50 | #include <linux/skbuff.h> |
51 | #include <linux/list.h> | 51 | #include <linux/list.h> |
52 | #include <linux/compiler.h> | 52 | #include <linux/compiler.h> |
53 | #include <net/netlink.h> | ||
53 | #include <net/sock.h> | 54 | #include <net/sock.h> |
54 | #include <net/pkt_sched.h> | 55 | #include <net/pkt_sched.h> |
55 | #include <linux/rbtree.h> | 56 | #include <linux/rbtree.h> |
@@ -128,7 +129,7 @@ struct htb_class { | |||
128 | } un; | 129 | } un; |
129 | struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ | 130 | struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ |
130 | struct rb_node pq_node; /* node for event queue */ | 131 | struct rb_node pq_node; /* node for event queue */ |
131 | unsigned long pq_key; /* the same type as jiffies global */ | 132 | psched_time_t pq_key; |
132 | 133 | ||
133 | int prio_activity; /* for which prios are we active */ | 134 | int prio_activity; /* for which prios are we active */ |
134 | enum htb_cmode cmode; /* current mode of the class */ | 135 | enum htb_cmode cmode; /* current mode of the class */ |
@@ -179,10 +180,7 @@ struct htb_sched { | |||
179 | struct rb_root wait_pq[TC_HTB_MAXDEPTH]; | 180 | struct rb_root wait_pq[TC_HTB_MAXDEPTH]; |
180 | 181 | ||
181 | /* time of nearest event per level (row) */ | 182 | /* time of nearest event per level (row) */ |
182 | unsigned long near_ev_cache[TC_HTB_MAXDEPTH]; | 183 | psched_time_t near_ev_cache[TC_HTB_MAXDEPTH]; |
183 | |||
184 | /* cached value of jiffies in dequeue */ | ||
185 | unsigned long jiffies; | ||
186 | 184 | ||
187 | /* whether we hit non-work conserving class during this dequeue; we use */ | 185 | /* whether we hit non-work conserving class during this dequeue; we use */ |
188 | int nwc_hit; /* this to disable mindelay complaint in dequeue */ | 186 | int nwc_hit; /* this to disable mindelay complaint in dequeue */ |
@@ -195,7 +193,7 @@ struct htb_sched { | |||
195 | 193 | ||
196 | int rate2quantum; /* quant = rate / rate2quantum */ | 194 | int rate2quantum; /* quant = rate / rate2quantum */ |
197 | psched_time_t now; /* cached dequeue time */ | 195 | psched_time_t now; /* cached dequeue time */ |
198 | struct timer_list timer; /* send delay timer */ | 196 | struct qdisc_watchdog watchdog; |
199 | #ifdef HTB_RATECM | 197 | #ifdef HTB_RATECM |
200 | struct timer_list rttim; /* rate computer timer */ | 198 | struct timer_list rttim; /* rate computer timer */ |
201 | int recmp_bucket; /* which hash bucket to recompute next */ | 199 | int recmp_bucket; /* which hash bucket to recompute next */ |
@@ -342,19 +340,19 @@ static void htb_add_to_wait_tree(struct htb_sched *q, | |||
342 | { | 340 | { |
343 | struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL; | 341 | struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL; |
344 | 342 | ||
345 | cl->pq_key = q->jiffies + PSCHED_US2JIFFIE(delay); | 343 | cl->pq_key = q->now + delay; |
346 | if (cl->pq_key == q->jiffies) | 344 | if (cl->pq_key == q->now) |
347 | cl->pq_key++; | 345 | cl->pq_key++; |
348 | 346 | ||
349 | /* update the nearest event cache */ | 347 | /* update the nearest event cache */ |
350 | if (time_after(q->near_ev_cache[cl->level], cl->pq_key)) | 348 | if (q->near_ev_cache[cl->level] > cl->pq_key) |
351 | q->near_ev_cache[cl->level] = cl->pq_key; | 349 | q->near_ev_cache[cl->level] = cl->pq_key; |
352 | 350 | ||
353 | while (*p) { | 351 | while (*p) { |
354 | struct htb_class *c; | 352 | struct htb_class *c; |
355 | parent = *p; | 353 | parent = *p; |
356 | c = rb_entry(parent, struct htb_class, pq_node); | 354 | c = rb_entry(parent, struct htb_class, pq_node); |
357 | if (time_after_eq(cl->pq_key, c->pq_key)) | 355 | if (cl->pq_key >= c->pq_key) |
358 | p = &parent->rb_right; | 356 | p = &parent->rb_right; |
359 | else | 357 | else |
360 | p = &parent->rb_left; | 358 | p = &parent->rb_left; |
@@ -679,14 +677,6 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) | |||
679 | return NET_XMIT_SUCCESS; | 677 | return NET_XMIT_SUCCESS; |
680 | } | 678 | } |
681 | 679 | ||
682 | static void htb_timer(unsigned long arg) | ||
683 | { | ||
684 | struct Qdisc *sch = (struct Qdisc *)arg; | ||
685 | sch->flags &= ~TCQ_F_THROTTLED; | ||
686 | wmb(); | ||
687 | netif_schedule(sch->dev); | ||
688 | } | ||
689 | |||
690 | #ifdef HTB_RATECM | 680 | #ifdef HTB_RATECM |
691 | #define RT_GEN(D,R) R+=D-(R/HTB_EWMAC);D=0 | 681 | #define RT_GEN(D,R) R+=D-(R/HTB_EWMAC);D=0 |
692 | static void htb_rate_timer(unsigned long arg) | 682 | static void htb_rate_timer(unsigned long arg) |
@@ -739,7 +729,7 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, | |||
739 | cl->T = toks | 729 | cl->T = toks |
740 | 730 | ||
741 | while (cl) { | 731 | while (cl) { |
742 | diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32) cl->mbuffer); | 732 | diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer); |
743 | if (cl->level >= level) { | 733 | if (cl->level >= level) { |
744 | if (cl->level == level) | 734 | if (cl->level == level) |
745 | cl->xstats.lends++; | 735 | cl->xstats.lends++; |
@@ -778,11 +768,11 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, | |||
778 | /** | 768 | /** |
779 | * htb_do_events - make mode changes to classes at the level | 769 | * htb_do_events - make mode changes to classes at the level |
780 | * | 770 | * |
781 | * Scans event queue for pending events and applies them. Returns jiffies to | 771 | * Scans event queue for pending events and applies them. Returns time of |
782 | * next pending event (0 for no event in pq). | 772 | * next pending event (0 for no event in pq). |
783 | * Note: Aplied are events whose have cl->pq_key <= jiffies. | 773 | * Note: Applied are events whose have cl->pq_key <= q->now. |
784 | */ | 774 | */ |
785 | static long htb_do_events(struct htb_sched *q, int level) | 775 | static psched_time_t htb_do_events(struct htb_sched *q, int level) |
786 | { | 776 | { |
787 | int i; | 777 | int i; |
788 | 778 | ||
@@ -795,18 +785,18 @@ static long htb_do_events(struct htb_sched *q, int level) | |||
795 | return 0; | 785 | return 0; |
796 | 786 | ||
797 | cl = rb_entry(p, struct htb_class, pq_node); | 787 | cl = rb_entry(p, struct htb_class, pq_node); |
798 | if (time_after(cl->pq_key, q->jiffies)) { | 788 | if (cl->pq_key > q->now) |
799 | return cl->pq_key - q->jiffies; | 789 | return cl->pq_key; |
800 | } | 790 | |
801 | htb_safe_rb_erase(p, q->wait_pq + level); | 791 | htb_safe_rb_erase(p, q->wait_pq + level); |
802 | diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32) cl->mbuffer); | 792 | diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer); |
803 | htb_change_class_mode(q, cl, &diff); | 793 | htb_change_class_mode(q, cl, &diff); |
804 | if (cl->cmode != HTB_CAN_SEND) | 794 | if (cl->cmode != HTB_CAN_SEND) |
805 | htb_add_to_wait_tree(q, cl, diff); | 795 | htb_add_to_wait_tree(q, cl, diff); |
806 | } | 796 | } |
807 | if (net_ratelimit()) | 797 | if (net_ratelimit()) |
808 | printk(KERN_WARNING "htb: too many events !\n"); | 798 | printk(KERN_WARNING "htb: too many events !\n"); |
809 | return HZ / 10; | 799 | return q->now + PSCHED_TICKS_PER_SEC / 10; |
810 | } | 800 | } |
811 | 801 | ||
812 | /* Returns class->node+prio from id-tree where classe's id is >= id. NULL | 802 | /* Returns class->node+prio from id-tree where classe's id is >= id. NULL |
@@ -958,30 +948,12 @@ next: | |||
958 | return skb; | 948 | return skb; |
959 | } | 949 | } |
960 | 950 | ||
961 | static void htb_delay_by(struct Qdisc *sch, long delay) | ||
962 | { | ||
963 | struct htb_sched *q = qdisc_priv(sch); | ||
964 | if (delay <= 0) | ||
965 | delay = 1; | ||
966 | if (unlikely(delay > 5 * HZ)) { | ||
967 | if (net_ratelimit()) | ||
968 | printk(KERN_INFO "HTB delay %ld > 5sec\n", delay); | ||
969 | delay = 5 * HZ; | ||
970 | } | ||
971 | /* why don't use jiffies here ? because expires can be in past */ | ||
972 | mod_timer(&q->timer, q->jiffies + delay); | ||
973 | sch->flags |= TCQ_F_THROTTLED; | ||
974 | sch->qstats.overlimits++; | ||
975 | } | ||
976 | |||
977 | static struct sk_buff *htb_dequeue(struct Qdisc *sch) | 951 | static struct sk_buff *htb_dequeue(struct Qdisc *sch) |
978 | { | 952 | { |
979 | struct sk_buff *skb = NULL; | 953 | struct sk_buff *skb = NULL; |
980 | struct htb_sched *q = qdisc_priv(sch); | 954 | struct htb_sched *q = qdisc_priv(sch); |
981 | int level; | 955 | int level; |
982 | long min_delay; | 956 | psched_time_t next_event; |
983 | |||
984 | q->jiffies = jiffies; | ||
985 | 957 | ||
986 | /* try to dequeue direct packets as high prio (!) to minimize cpu work */ | 958 | /* try to dequeue direct packets as high prio (!) to minimize cpu work */ |
987 | skb = __skb_dequeue(&q->direct_queue); | 959 | skb = __skb_dequeue(&q->direct_queue); |
@@ -993,23 +965,25 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) | |||
993 | 965 | ||
994 | if (!sch->q.qlen) | 966 | if (!sch->q.qlen) |
995 | goto fin; | 967 | goto fin; |
996 | PSCHED_GET_TIME(q->now); | 968 | q->now = psched_get_time(); |
997 | 969 | ||
998 | min_delay = LONG_MAX; | 970 | next_event = q->now + 5 * PSCHED_TICKS_PER_SEC; |
999 | q->nwc_hit = 0; | 971 | q->nwc_hit = 0; |
1000 | for (level = 0; level < TC_HTB_MAXDEPTH; level++) { | 972 | for (level = 0; level < TC_HTB_MAXDEPTH; level++) { |
1001 | /* common case optimization - skip event handler quickly */ | 973 | /* common case optimization - skip event handler quickly */ |
1002 | int m; | 974 | int m; |
1003 | long delay; | 975 | psched_time_t event; |
1004 | if (time_after_eq(q->jiffies, q->near_ev_cache[level])) { | 976 | |
1005 | delay = htb_do_events(q, level); | 977 | if (q->now >= q->near_ev_cache[level]) { |
1006 | q->near_ev_cache[level] = | 978 | event = htb_do_events(q, level); |
1007 | q->jiffies + (delay ? delay : HZ); | 979 | q->near_ev_cache[level] = event ? event : |
980 | PSCHED_TICKS_PER_SEC; | ||
1008 | } else | 981 | } else |
1009 | delay = q->near_ev_cache[level] - q->jiffies; | 982 | event = q->near_ev_cache[level]; |
983 | |||
984 | if (event && next_event > event) | ||
985 | next_event = event; | ||
1010 | 986 | ||
1011 | if (delay && min_delay > delay) | ||
1012 | min_delay = delay; | ||
1013 | m = ~q->row_mask[level]; | 987 | m = ~q->row_mask[level]; |
1014 | while (m != (int)(-1)) { | 988 | while (m != (int)(-1)) { |
1015 | int prio = ffz(m); | 989 | int prio = ffz(m); |
@@ -1022,7 +996,8 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) | |||
1022 | } | 996 | } |
1023 | } | 997 | } |
1024 | } | 998 | } |
1025 | htb_delay_by(sch, min_delay > 5 * HZ ? 5 * HZ : min_delay); | 999 | sch->qstats.overlimits++; |
1000 | qdisc_watchdog_schedule(&q->watchdog, next_event); | ||
1026 | fin: | 1001 | fin: |
1027 | return skb; | 1002 | return skb; |
1028 | } | 1003 | } |
@@ -1075,8 +1050,7 @@ static void htb_reset(struct Qdisc *sch) | |||
1075 | 1050 | ||
1076 | } | 1051 | } |
1077 | } | 1052 | } |
1078 | sch->flags &= ~TCQ_F_THROTTLED; | 1053 | qdisc_watchdog_cancel(&q->watchdog); |
1079 | del_timer(&q->timer); | ||
1080 | __skb_queue_purge(&q->direct_queue); | 1054 | __skb_queue_purge(&q->direct_queue); |
1081 | sch->q.qlen = 0; | 1055 | sch->q.qlen = 0; |
1082 | memset(q->row, 0, sizeof(q->row)); | 1056 | memset(q->row, 0, sizeof(q->row)); |
@@ -1113,14 +1087,12 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt) | |||
1113 | for (i = 0; i < TC_HTB_NUMPRIO; i++) | 1087 | for (i = 0; i < TC_HTB_NUMPRIO; i++) |
1114 | INIT_LIST_HEAD(q->drops + i); | 1088 | INIT_LIST_HEAD(q->drops + i); |
1115 | 1089 | ||
1116 | init_timer(&q->timer); | 1090 | qdisc_watchdog_init(&q->watchdog, sch); |
1117 | skb_queue_head_init(&q->direct_queue); | 1091 | skb_queue_head_init(&q->direct_queue); |
1118 | 1092 | ||
1119 | q->direct_qlen = sch->dev->tx_queue_len; | 1093 | q->direct_qlen = sch->dev->tx_queue_len; |
1120 | if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */ | 1094 | if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */ |
1121 | q->direct_qlen = 2; | 1095 | q->direct_qlen = 2; |
1122 | q->timer.function = htb_timer; | ||
1123 | q->timer.data = (unsigned long)sch; | ||
1124 | 1096 | ||
1125 | #ifdef HTB_RATECM | 1097 | #ifdef HTB_RATECM |
1126 | init_timer(&q->rttim); | 1098 | init_timer(&q->rttim); |
@@ -1139,7 +1111,7 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt) | |||
1139 | static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) | 1111 | static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) |
1140 | { | 1112 | { |
1141 | struct htb_sched *q = qdisc_priv(sch); | 1113 | struct htb_sched *q = qdisc_priv(sch); |
1142 | unsigned char *b = skb->tail; | 1114 | unsigned char *b = skb_tail_pointer(skb); |
1143 | struct rtattr *rta; | 1115 | struct rtattr *rta; |
1144 | struct tc_htb_glob gopt; | 1116 | struct tc_htb_glob gopt; |
1145 | spin_lock_bh(&sch->dev->queue_lock); | 1117 | spin_lock_bh(&sch->dev->queue_lock); |
@@ -1152,12 +1124,12 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
1152 | rta = (struct rtattr *)b; | 1124 | rta = (struct rtattr *)b; |
1153 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); | 1125 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
1154 | RTA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt); | 1126 | RTA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt); |
1155 | rta->rta_len = skb->tail - b; | 1127 | rta->rta_len = skb_tail_pointer(skb) - b; |
1156 | spin_unlock_bh(&sch->dev->queue_lock); | 1128 | spin_unlock_bh(&sch->dev->queue_lock); |
1157 | return skb->len; | 1129 | return skb->len; |
1158 | rtattr_failure: | 1130 | rtattr_failure: |
1159 | spin_unlock_bh(&sch->dev->queue_lock); | 1131 | spin_unlock_bh(&sch->dev->queue_lock); |
1160 | skb_trim(skb, skb->tail - skb->data); | 1132 | nlmsg_trim(skb, skb_tail_pointer(skb)); |
1161 | return -1; | 1133 | return -1; |
1162 | } | 1134 | } |
1163 | 1135 | ||
@@ -1165,7 +1137,7 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, | |||
1165 | struct sk_buff *skb, struct tcmsg *tcm) | 1137 | struct sk_buff *skb, struct tcmsg *tcm) |
1166 | { | 1138 | { |
1167 | struct htb_class *cl = (struct htb_class *)arg; | 1139 | struct htb_class *cl = (struct htb_class *)arg; |
1168 | unsigned char *b = skb->tail; | 1140 | unsigned char *b = skb_tail_pointer(skb); |
1169 | struct rtattr *rta; | 1141 | struct rtattr *rta; |
1170 | struct tc_htb_opt opt; | 1142 | struct tc_htb_opt opt; |
1171 | 1143 | ||
@@ -1188,12 +1160,12 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, | |||
1188 | opt.prio = cl->un.leaf.prio; | 1160 | opt.prio = cl->un.leaf.prio; |
1189 | opt.level = cl->level; | 1161 | opt.level = cl->level; |
1190 | RTA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt); | 1162 | RTA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt); |
1191 | rta->rta_len = skb->tail - b; | 1163 | rta->rta_len = skb_tail_pointer(skb) - b; |
1192 | spin_unlock_bh(&sch->dev->queue_lock); | 1164 | spin_unlock_bh(&sch->dev->queue_lock); |
1193 | return skb->len; | 1165 | return skb->len; |
1194 | rtattr_failure: | 1166 | rtattr_failure: |
1195 | spin_unlock_bh(&sch->dev->queue_lock); | 1167 | spin_unlock_bh(&sch->dev->queue_lock); |
1196 | skb_trim(skb, b - skb->data); | 1168 | nlmsg_trim(skb, b); |
1197 | return -1; | 1169 | return -1; |
1198 | } | 1170 | } |
1199 | 1171 | ||
@@ -1264,16 +1236,6 @@ static unsigned long htb_get(struct Qdisc *sch, u32 classid) | |||
1264 | return (unsigned long)cl; | 1236 | return (unsigned long)cl; |
1265 | } | 1237 | } |
1266 | 1238 | ||
1267 | static void htb_destroy_filters(struct tcf_proto **fl) | ||
1268 | { | ||
1269 | struct tcf_proto *tp; | ||
1270 | |||
1271 | while ((tp = *fl) != NULL) { | ||
1272 | *fl = tp->next; | ||
1273 | tcf_destroy(tp); | ||
1274 | } | ||
1275 | } | ||
1276 | |||
1277 | static inline int htb_parent_last_child(struct htb_class *cl) | 1239 | static inline int htb_parent_last_child(struct htb_class *cl) |
1278 | { | 1240 | { |
1279 | if (!cl->parent) | 1241 | if (!cl->parent) |
@@ -1302,7 +1264,7 @@ static void htb_parent_to_leaf(struct htb_class *cl, struct Qdisc *new_q) | |||
1302 | parent->un.leaf.prio = parent->prio; | 1264 | parent->un.leaf.prio = parent->prio; |
1303 | parent->tokens = parent->buffer; | 1265 | parent->tokens = parent->buffer; |
1304 | parent->ctokens = parent->cbuffer; | 1266 | parent->ctokens = parent->cbuffer; |
1305 | PSCHED_GET_TIME(parent->t_c); | 1267 | parent->t_c = psched_get_time(); |
1306 | parent->cmode = HTB_CAN_SEND; | 1268 | parent->cmode = HTB_CAN_SEND; |
1307 | } | 1269 | } |
1308 | 1270 | ||
@@ -1317,7 +1279,7 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) | |||
1317 | qdisc_put_rtab(cl->rate); | 1279 | qdisc_put_rtab(cl->rate); |
1318 | qdisc_put_rtab(cl->ceil); | 1280 | qdisc_put_rtab(cl->ceil); |
1319 | 1281 | ||
1320 | htb_destroy_filters(&cl->filter_list); | 1282 | tcf_destroy_chain(cl->filter_list); |
1321 | 1283 | ||
1322 | while (!list_empty(&cl->children)) | 1284 | while (!list_empty(&cl->children)) |
1323 | htb_destroy_class(sch, list_entry(cl->children.next, | 1285 | htb_destroy_class(sch, list_entry(cl->children.next, |
@@ -1341,7 +1303,7 @@ static void htb_destroy(struct Qdisc *sch) | |||
1341 | { | 1303 | { |
1342 | struct htb_sched *q = qdisc_priv(sch); | 1304 | struct htb_sched *q = qdisc_priv(sch); |
1343 | 1305 | ||
1344 | del_timer_sync(&q->timer); | 1306 | qdisc_watchdog_cancel(&q->watchdog); |
1345 | #ifdef HTB_RATECM | 1307 | #ifdef HTB_RATECM |
1346 | del_timer_sync(&q->rttim); | 1308 | del_timer_sync(&q->rttim); |
1347 | #endif | 1309 | #endif |
@@ -1349,7 +1311,7 @@ static void htb_destroy(struct Qdisc *sch) | |||
1349 | and surprisingly it worked in 2.4. But it must precede it | 1311 | and surprisingly it worked in 2.4. But it must precede it |
1350 | because filter need its target class alive to be able to call | 1312 | because filter need its target class alive to be able to call |
1351 | unbind_filter on it (without Oops). */ | 1313 | unbind_filter on it (without Oops). */ |
1352 | htb_destroy_filters(&q->filter_list); | 1314 | tcf_destroy_chain(q->filter_list); |
1353 | 1315 | ||
1354 | while (!list_empty(&q->root)) | 1316 | while (!list_empty(&q->root)) |
1355 | htb_destroy_class(sch, list_entry(q->root.next, | 1317 | htb_destroy_class(sch, list_entry(q->root.next, |
@@ -1498,8 +1460,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1498 | /* set class to be in HTB_CAN_SEND state */ | 1460 | /* set class to be in HTB_CAN_SEND state */ |
1499 | cl->tokens = hopt->buffer; | 1461 | cl->tokens = hopt->buffer; |
1500 | cl->ctokens = hopt->cbuffer; | 1462 | cl->ctokens = hopt->cbuffer; |
1501 | cl->mbuffer = PSCHED_JIFFIE2US(HZ * 60); /* 1min */ | 1463 | cl->mbuffer = 60 * PSCHED_TICKS_PER_SEC; /* 1min */ |
1502 | PSCHED_GET_TIME(cl->t_c); | 1464 | cl->t_c = psched_get_time(); |
1503 | cl->cmode = HTB_CAN_SEND; | 1465 | cl->cmode = HTB_CAN_SEND; |
1504 | 1466 | ||
1505 | /* attach to the hash list and parent's family */ | 1467 | /* attach to the hash list and parent's family */ |
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index cfe070ee6ee3..f8b9f1cdf738 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/netfilter_ipv6.h> | 16 | #include <linux/netfilter_ipv6.h> |
17 | #include <linux/netfilter.h> | 17 | #include <linux/netfilter.h> |
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <net/netlink.h> | ||
19 | #include <net/pkt_sched.h> | 20 | #include <net/pkt_sched.h> |
20 | #include <asm/byteorder.h> | 21 | #include <asm/byteorder.h> |
21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
@@ -169,7 +170,7 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
169 | skb->tc_index = TC_H_MIN(res.classid); | 170 | skb->tc_index = TC_H_MIN(res.classid); |
170 | result = TC_ACT_OK; | 171 | result = TC_ACT_OK; |
171 | break; | 172 | break; |
172 | }; | 173 | } |
173 | /* backward compat */ | 174 | /* backward compat */ |
174 | #else | 175 | #else |
175 | #ifdef CONFIG_NET_CLS_POLICE | 176 | #ifdef CONFIG_NET_CLS_POLICE |
@@ -186,7 +187,7 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
186 | sch->bstats.bytes += skb->len; | 187 | sch->bstats.bytes += skb->len; |
187 | result = NF_ACCEPT; | 188 | result = NF_ACCEPT; |
188 | break; | 189 | break; |
189 | }; | 190 | } |
190 | 191 | ||
191 | #else | 192 | #else |
192 | D2PRINTK("Overriding result to ACCEPT\n"); | 193 | D2PRINTK("Overriding result to ACCEPT\n"); |
@@ -247,16 +248,11 @@ ing_hook(unsigned int hook, struct sk_buff **pskb, | |||
247 | skb->dev ? (*pskb)->dev->name : "(no dev)", | 248 | skb->dev ? (*pskb)->dev->name : "(no dev)", |
248 | skb->len); | 249 | skb->len); |
249 | 250 | ||
250 | /* | ||
251 | revisit later: Use a private since lock dev->queue_lock is also | ||
252 | used on the egress (might slow things for an iota) | ||
253 | */ | ||
254 | |||
255 | if (dev->qdisc_ingress) { | 251 | if (dev->qdisc_ingress) { |
256 | spin_lock(&dev->queue_lock); | 252 | spin_lock(&dev->ingress_lock); |
257 | if ((q = dev->qdisc_ingress) != NULL) | 253 | if ((q = dev->qdisc_ingress) != NULL) |
258 | fwres = q->enqueue(skb, q); | 254 | fwres = q->enqueue(skb, q); |
259 | spin_unlock(&dev->queue_lock); | 255 | spin_unlock(&dev->ingress_lock); |
260 | } | 256 | } |
261 | 257 | ||
262 | return fwres; | 258 | return fwres; |
@@ -345,14 +341,9 @@ static void ingress_reset(struct Qdisc *sch) | |||
345 | static void ingress_destroy(struct Qdisc *sch) | 341 | static void ingress_destroy(struct Qdisc *sch) |
346 | { | 342 | { |
347 | struct ingress_qdisc_data *p = PRIV(sch); | 343 | struct ingress_qdisc_data *p = PRIV(sch); |
348 | struct tcf_proto *tp; | ||
349 | 344 | ||
350 | DPRINTK("ingress_destroy(sch %p,[qdisc %p])\n", sch, p); | 345 | DPRINTK("ingress_destroy(sch %p,[qdisc %p])\n", sch, p); |
351 | while (p->filter_list) { | 346 | tcf_destroy_chain(p->filter_list); |
352 | tp = p->filter_list; | ||
353 | p->filter_list = tp->next; | ||
354 | tcf_destroy(tp); | ||
355 | } | ||
356 | #if 0 | 347 | #if 0 |
357 | /* for future use */ | 348 | /* for future use */ |
358 | qdisc_destroy(p->q); | 349 | qdisc_destroy(p->q); |
@@ -362,16 +353,16 @@ static void ingress_destroy(struct Qdisc *sch) | |||
362 | 353 | ||
363 | static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb) | 354 | static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb) |
364 | { | 355 | { |
365 | unsigned char *b = skb->tail; | 356 | unsigned char *b = skb_tail_pointer(skb); |
366 | struct rtattr *rta; | 357 | struct rtattr *rta; |
367 | 358 | ||
368 | rta = (struct rtattr *) b; | 359 | rta = (struct rtattr *) b; |
369 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); | 360 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
370 | rta->rta_len = skb->tail - b; | 361 | rta->rta_len = skb_tail_pointer(skb) - b; |
371 | return skb->len; | 362 | return skb->len; |
372 | 363 | ||
373 | rtattr_failure: | 364 | rtattr_failure: |
374 | skb_trim(skb, b - skb->data); | 365 | nlmsg_trim(skb, b); |
375 | return -1; | 366 | return -1; |
376 | } | 367 | } |
377 | 368 | ||
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 1ccbfb55b0b8..5d9d8bc9cc3a 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/skbuff.h> | 22 | #include <linux/skbuff.h> |
23 | #include <linux/rtnetlink.h> | 23 | #include <linux/rtnetlink.h> |
24 | 24 | ||
25 | #include <net/netlink.h> | ||
25 | #include <net/pkt_sched.h> | 26 | #include <net/pkt_sched.h> |
26 | 27 | ||
27 | #define VERSION "1.2" | 28 | #define VERSION "1.2" |
@@ -54,21 +55,22 @@ | |||
54 | 55 | ||
55 | struct netem_sched_data { | 56 | struct netem_sched_data { |
56 | struct Qdisc *qdisc; | 57 | struct Qdisc *qdisc; |
57 | struct timer_list timer; | 58 | struct qdisc_watchdog watchdog; |
59 | |||
60 | psched_tdiff_t latency; | ||
61 | psched_tdiff_t jitter; | ||
58 | 62 | ||
59 | u32 latency; | ||
60 | u32 loss; | 63 | u32 loss; |
61 | u32 limit; | 64 | u32 limit; |
62 | u32 counter; | 65 | u32 counter; |
63 | u32 gap; | 66 | u32 gap; |
64 | u32 jitter; | ||
65 | u32 duplicate; | 67 | u32 duplicate; |
66 | u32 reorder; | 68 | u32 reorder; |
67 | u32 corrupt; | 69 | u32 corrupt; |
68 | 70 | ||
69 | struct crndstate { | 71 | struct crndstate { |
70 | unsigned long last; | 72 | u32 last; |
71 | unsigned long rho; | 73 | u32 rho; |
72 | } delay_cor, loss_cor, dup_cor, reorder_cor, corrupt_cor; | 74 | } delay_cor, loss_cor, dup_cor, reorder_cor, corrupt_cor; |
73 | 75 | ||
74 | struct disttable { | 76 | struct disttable { |
@@ -95,12 +97,12 @@ static void init_crandom(struct crndstate *state, unsigned long rho) | |||
95 | * Next number depends on last value. | 97 | * Next number depends on last value. |
96 | * rho is scaled to avoid floating point. | 98 | * rho is scaled to avoid floating point. |
97 | */ | 99 | */ |
98 | static unsigned long get_crandom(struct crndstate *state) | 100 | static u32 get_crandom(struct crndstate *state) |
99 | { | 101 | { |
100 | u64 value, rho; | 102 | u64 value, rho; |
101 | unsigned long answer; | 103 | unsigned long answer; |
102 | 104 | ||
103 | if (state->rho == 0) /* no correllation */ | 105 | if (state->rho == 0) /* no correlation */ |
104 | return net_random(); | 106 | return net_random(); |
105 | 107 | ||
106 | value = net_random(); | 108 | value = net_random(); |
@@ -114,11 +116,13 @@ static unsigned long get_crandom(struct crndstate *state) | |||
114 | * std deviation sigma. Uses table lookup to approximate the desired | 116 | * std deviation sigma. Uses table lookup to approximate the desired |
115 | * distribution, and a uniformly-distributed pseudo-random source. | 117 | * distribution, and a uniformly-distributed pseudo-random source. |
116 | */ | 118 | */ |
117 | static long tabledist(unsigned long mu, long sigma, | 119 | static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma, |
118 | struct crndstate *state, const struct disttable *dist) | 120 | struct crndstate *state, |
121 | const struct disttable *dist) | ||
119 | { | 122 | { |
120 | long t, x; | 123 | psched_tdiff_t x; |
121 | unsigned long rnd; | 124 | long t; |
125 | u32 rnd; | ||
122 | 126 | ||
123 | if (sigma == 0) | 127 | if (sigma == 0) |
124 | return mu; | 128 | return mu; |
@@ -213,8 +217,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
213 | delay = tabledist(q->latency, q->jitter, | 217 | delay = tabledist(q->latency, q->jitter, |
214 | &q->delay_cor, q->delay_dist); | 218 | &q->delay_cor, q->delay_dist); |
215 | 219 | ||
216 | PSCHED_GET_TIME(now); | 220 | now = psched_get_time(); |
217 | PSCHED_TADD2(now, delay, cb->time_to_send); | 221 | cb->time_to_send = now + delay; |
218 | ++q->counter; | 222 | ++q->counter; |
219 | ret = q->qdisc->enqueue(skb, q->qdisc); | 223 | ret = q->qdisc->enqueue(skb, q->qdisc); |
220 | } else { | 224 | } else { |
@@ -222,7 +226,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
222 | * Do re-ordering by putting one out of N packets at the front | 226 | * Do re-ordering by putting one out of N packets at the front |
223 | * of the queue. | 227 | * of the queue. |
224 | */ | 228 | */ |
225 | PSCHED_GET_TIME(cb->time_to_send); | 229 | cb->time_to_send = psched_get_time(); |
226 | q->counter = 0; | 230 | q->counter = 0; |
227 | ret = q->qdisc->ops->requeue(skb, q->qdisc); | 231 | ret = q->qdisc->ops->requeue(skb, q->qdisc); |
228 | } | 232 | } |
@@ -269,55 +273,43 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) | |||
269 | struct netem_sched_data *q = qdisc_priv(sch); | 273 | struct netem_sched_data *q = qdisc_priv(sch); |
270 | struct sk_buff *skb; | 274 | struct sk_buff *skb; |
271 | 275 | ||
276 | smp_mb(); | ||
277 | if (sch->flags & TCQ_F_THROTTLED) | ||
278 | return NULL; | ||
279 | |||
272 | skb = q->qdisc->dequeue(q->qdisc); | 280 | skb = q->qdisc->dequeue(q->qdisc); |
273 | if (skb) { | 281 | if (skb) { |
274 | const struct netem_skb_cb *cb | 282 | const struct netem_skb_cb *cb |
275 | = (const struct netem_skb_cb *)skb->cb; | 283 | = (const struct netem_skb_cb *)skb->cb; |
276 | psched_time_t now; | 284 | psched_time_t now = psched_get_time(); |
277 | 285 | ||
278 | /* if more time remaining? */ | 286 | /* if more time remaining? */ |
279 | PSCHED_GET_TIME(now); | 287 | if (cb->time_to_send <= now) { |
280 | |||
281 | if (PSCHED_TLESS(cb->time_to_send, now)) { | ||
282 | pr_debug("netem_dequeue: return skb=%p\n", skb); | 288 | pr_debug("netem_dequeue: return skb=%p\n", skb); |
283 | sch->q.qlen--; | 289 | sch->q.qlen--; |
284 | sch->flags &= ~TCQ_F_THROTTLED; | ||
285 | return skb; | 290 | return skb; |
286 | } else { | 291 | } |
287 | psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, now); | ||
288 | |||
289 | if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) { | ||
290 | qdisc_tree_decrease_qlen(q->qdisc, 1); | ||
291 | sch->qstats.drops++; | ||
292 | printk(KERN_ERR "netem: queue discpline %s could not requeue\n", | ||
293 | q->qdisc->ops->id); | ||
294 | } | ||
295 | 292 | ||
296 | mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay)); | 293 | if (unlikely(q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS)) { |
297 | sch->flags |= TCQ_F_THROTTLED; | 294 | qdisc_tree_decrease_qlen(q->qdisc, 1); |
295 | sch->qstats.drops++; | ||
296 | printk(KERN_ERR "netem: %s could not requeue\n", | ||
297 | q->qdisc->ops->id); | ||
298 | } | 298 | } |
299 | |||
300 | qdisc_watchdog_schedule(&q->watchdog, cb->time_to_send); | ||
299 | } | 301 | } |
300 | 302 | ||
301 | return NULL; | 303 | return NULL; |
302 | } | 304 | } |
303 | 305 | ||
304 | static void netem_watchdog(unsigned long arg) | ||
305 | { | ||
306 | struct Qdisc *sch = (struct Qdisc *)arg; | ||
307 | |||
308 | pr_debug("netem_watchdog qlen=%d\n", sch->q.qlen); | ||
309 | sch->flags &= ~TCQ_F_THROTTLED; | ||
310 | netif_schedule(sch->dev); | ||
311 | } | ||
312 | |||
313 | static void netem_reset(struct Qdisc *sch) | 306 | static void netem_reset(struct Qdisc *sch) |
314 | { | 307 | { |
315 | struct netem_sched_data *q = qdisc_priv(sch); | 308 | struct netem_sched_data *q = qdisc_priv(sch); |
316 | 309 | ||
317 | qdisc_reset(q->qdisc); | 310 | qdisc_reset(q->qdisc); |
318 | sch->q.qlen = 0; | 311 | sch->q.qlen = 0; |
319 | sch->flags &= ~TCQ_F_THROTTLED; | 312 | qdisc_watchdog_cancel(&q->watchdog); |
320 | del_timer_sync(&q->timer); | ||
321 | } | 313 | } |
322 | 314 | ||
323 | /* Pass size change message down to embedded FIFO */ | 315 | /* Pass size change message down to embedded FIFO */ |
@@ -438,10 +430,11 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt) | |||
438 | q->loss = qopt->loss; | 430 | q->loss = qopt->loss; |
439 | q->duplicate = qopt->duplicate; | 431 | q->duplicate = qopt->duplicate; |
440 | 432 | ||
441 | /* for compatiablity with earlier versions. | 433 | /* for compatibility with earlier versions. |
442 | * if gap is set, need to assume 100% probablity | 434 | * if gap is set, need to assume 100% probability |
443 | */ | 435 | */ |
444 | q->reorder = ~0; | 436 | if (q->gap) |
437 | q->reorder = ~0; | ||
445 | 438 | ||
446 | /* Handle nested options after initial queue options. | 439 | /* Handle nested options after initial queue options. |
447 | * Should have put all options in nested format but too late now. | 440 | * Should have put all options in nested format but too late now. |
@@ -487,22 +480,28 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt) | |||
487 | */ | 480 | */ |
488 | struct fifo_sched_data { | 481 | struct fifo_sched_data { |
489 | u32 limit; | 482 | u32 limit; |
483 | psched_time_t oldest; | ||
490 | }; | 484 | }; |
491 | 485 | ||
492 | static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) | 486 | static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) |
493 | { | 487 | { |
494 | struct fifo_sched_data *q = qdisc_priv(sch); | 488 | struct fifo_sched_data *q = qdisc_priv(sch); |
495 | struct sk_buff_head *list = &sch->q; | 489 | struct sk_buff_head *list = &sch->q; |
496 | const struct netem_skb_cb *ncb | 490 | psched_time_t tnext = ((struct netem_skb_cb *)nskb->cb)->time_to_send; |
497 | = (const struct netem_skb_cb *)nskb->cb; | ||
498 | struct sk_buff *skb; | 491 | struct sk_buff *skb; |
499 | 492 | ||
500 | if (likely(skb_queue_len(list) < q->limit)) { | 493 | if (likely(skb_queue_len(list) < q->limit)) { |
494 | /* Optimize for add at tail */ | ||
495 | if (likely(skb_queue_empty(list) || tnext >= q->oldest)) { | ||
496 | q->oldest = tnext; | ||
497 | return qdisc_enqueue_tail(nskb, sch); | ||
498 | } | ||
499 | |||
501 | skb_queue_reverse_walk(list, skb) { | 500 | skb_queue_reverse_walk(list, skb) { |
502 | const struct netem_skb_cb *cb | 501 | const struct netem_skb_cb *cb |
503 | = (const struct netem_skb_cb *)skb->cb; | 502 | = (const struct netem_skb_cb *)skb->cb; |
504 | 503 | ||
505 | if (!PSCHED_TLESS(ncb->time_to_send, cb->time_to_send)) | 504 | if (tnext >= cb->time_to_send) |
506 | break; | 505 | break; |
507 | } | 506 | } |
508 | 507 | ||
@@ -515,7 +514,7 @@ static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) | |||
515 | return NET_XMIT_SUCCESS; | 514 | return NET_XMIT_SUCCESS; |
516 | } | 515 | } |
517 | 516 | ||
518 | return qdisc_drop(nskb, sch); | 517 | return qdisc_reshape_fail(nskb, sch); |
519 | } | 518 | } |
520 | 519 | ||
521 | static int tfifo_init(struct Qdisc *sch, struct rtattr *opt) | 520 | static int tfifo_init(struct Qdisc *sch, struct rtattr *opt) |
@@ -531,6 +530,7 @@ static int tfifo_init(struct Qdisc *sch, struct rtattr *opt) | |||
531 | } else | 530 | } else |
532 | q->limit = max_t(u32, sch->dev->tx_queue_len, 1); | 531 | q->limit = max_t(u32, sch->dev->tx_queue_len, 1); |
533 | 532 | ||
533 | q->oldest = PSCHED_PASTPERFECT; | ||
534 | return 0; | 534 | return 0; |
535 | } | 535 | } |
536 | 536 | ||
@@ -567,9 +567,7 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt) | |||
567 | if (!opt) | 567 | if (!opt) |
568 | return -EINVAL; | 568 | return -EINVAL; |
569 | 569 | ||
570 | init_timer(&q->timer); | 570 | qdisc_watchdog_init(&q->watchdog, sch); |
571 | q->timer.function = netem_watchdog; | ||
572 | q->timer.data = (unsigned long) sch; | ||
573 | 571 | ||
574 | q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops, | 572 | q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops, |
575 | TC_H_MAKE(sch->handle, 1)); | 573 | TC_H_MAKE(sch->handle, 1)); |
@@ -590,7 +588,7 @@ static void netem_destroy(struct Qdisc *sch) | |||
590 | { | 588 | { |
591 | struct netem_sched_data *q = qdisc_priv(sch); | 589 | struct netem_sched_data *q = qdisc_priv(sch); |
592 | 590 | ||
593 | del_timer_sync(&q->timer); | 591 | qdisc_watchdog_cancel(&q->watchdog); |
594 | qdisc_destroy(q->qdisc); | 592 | qdisc_destroy(q->qdisc); |
595 | kfree(q->delay_dist); | 593 | kfree(q->delay_dist); |
596 | } | 594 | } |
@@ -598,7 +596,7 @@ static void netem_destroy(struct Qdisc *sch) | |||
598 | static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) | 596 | static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) |
599 | { | 597 | { |
600 | const struct netem_sched_data *q = qdisc_priv(sch); | 598 | const struct netem_sched_data *q = qdisc_priv(sch); |
601 | unsigned char *b = skb->tail; | 599 | unsigned char *b = skb_tail_pointer(skb); |
602 | struct rtattr *rta = (struct rtattr *) b; | 600 | struct rtattr *rta = (struct rtattr *) b; |
603 | struct tc_netem_qopt qopt; | 601 | struct tc_netem_qopt qopt; |
604 | struct tc_netem_corr cor; | 602 | struct tc_netem_corr cor; |
@@ -626,12 +624,12 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
626 | corrupt.correlation = q->corrupt_cor.rho; | 624 | corrupt.correlation = q->corrupt_cor.rho; |
627 | RTA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt); | 625 | RTA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt); |
628 | 626 | ||
629 | rta->rta_len = skb->tail - b; | 627 | rta->rta_len = skb_tail_pointer(skb) - b; |
630 | 628 | ||
631 | return skb->len; | 629 | return skb->len; |
632 | 630 | ||
633 | rtattr_failure: | 631 | rtattr_failure: |
634 | skb_trim(skb, b - skb->data); | 632 | nlmsg_trim(skb, b); |
635 | return -1; | 633 | return -1; |
636 | } | 634 | } |
637 | 635 | ||
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index de889f23f22a..269a6e17c6c4 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <net/ip.h> | 32 | #include <net/ip.h> |
33 | #include <net/route.h> | 33 | #include <net/route.h> |
34 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
35 | #include <net/netlink.h> | ||
35 | #include <net/sock.h> | 36 | #include <net/sock.h> |
36 | #include <net/pkt_sched.h> | 37 | #include <net/pkt_sched.h> |
37 | 38 | ||
@@ -61,7 +62,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
61 | *qerr = NET_XMIT_SUCCESS; | 62 | *qerr = NET_XMIT_SUCCESS; |
62 | case TC_ACT_SHOT: | 63 | case TC_ACT_SHOT: |
63 | return NULL; | 64 | return NULL; |
64 | }; | 65 | } |
65 | 66 | ||
66 | if (!q->filter_list ) { | 67 | if (!q->filter_list ) { |
67 | #else | 68 | #else |
@@ -188,13 +189,8 @@ prio_destroy(struct Qdisc* sch) | |||
188 | { | 189 | { |
189 | int prio; | 190 | int prio; |
190 | struct prio_sched_data *q = qdisc_priv(sch); | 191 | struct prio_sched_data *q = qdisc_priv(sch); |
191 | struct tcf_proto *tp; | ||
192 | |||
193 | while ((tp = q->filter_list) != NULL) { | ||
194 | q->filter_list = tp->next; | ||
195 | tcf_destroy(tp); | ||
196 | } | ||
197 | 192 | ||
193 | tcf_destroy_chain(q->filter_list); | ||
198 | for (prio=0; prio<q->bands; prio++) | 194 | for (prio=0; prio<q->bands; prio++) |
199 | qdisc_destroy(q->queues[prio]); | 195 | qdisc_destroy(q->queues[prio]); |
200 | } | 196 | } |
@@ -271,7 +267,7 @@ static int prio_init(struct Qdisc *sch, struct rtattr *opt) | |||
271 | static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) | 267 | static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) |
272 | { | 268 | { |
273 | struct prio_sched_data *q = qdisc_priv(sch); | 269 | struct prio_sched_data *q = qdisc_priv(sch); |
274 | unsigned char *b = skb->tail; | 270 | unsigned char *b = skb_tail_pointer(skb); |
275 | struct tc_prio_qopt opt; | 271 | struct tc_prio_qopt opt; |
276 | 272 | ||
277 | opt.bands = q->bands; | 273 | opt.bands = q->bands; |
@@ -280,7 +276,7 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
280 | return skb->len; | 276 | return skb->len; |
281 | 277 | ||
282 | rtattr_failure: | 278 | rtattr_failure: |
283 | skb_trim(skb, b - skb->data); | 279 | nlmsg_trim(skb, b); |
284 | return -1; | 280 | return -1; |
285 | } | 281 | } |
286 | 282 | ||
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 66f32051a99b..96dfdf78d32c 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/notifier.h> | 30 | #include <linux/notifier.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <net/ip.h> | 32 | #include <net/ip.h> |
33 | #include <net/netlink.h> | ||
33 | #include <linux/ipv6.h> | 34 | #include <linux/ipv6.h> |
34 | #include <net/route.h> | 35 | #include <net/route.h> |
35 | #include <linux/skbuff.h> | 36 | #include <linux/skbuff.h> |
@@ -137,7 +138,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
137 | switch (skb->protocol) { | 138 | switch (skb->protocol) { |
138 | case __constant_htons(ETH_P_IP): | 139 | case __constant_htons(ETH_P_IP): |
139 | { | 140 | { |
140 | struct iphdr *iph = skb->nh.iph; | 141 | const struct iphdr *iph = ip_hdr(skb); |
141 | h = iph->daddr; | 142 | h = iph->daddr; |
142 | h2 = iph->saddr^iph->protocol; | 143 | h2 = iph->saddr^iph->protocol; |
143 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && | 144 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && |
@@ -152,7 +153,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
152 | } | 153 | } |
153 | case __constant_htons(ETH_P_IPV6): | 154 | case __constant_htons(ETH_P_IPV6): |
154 | { | 155 | { |
155 | struct ipv6hdr *iph = skb->nh.ipv6h; | 156 | struct ipv6hdr *iph = ipv6_hdr(skb); |
156 | h = iph->daddr.s6_addr32[3]; | 157 | h = iph->daddr.s6_addr32[3]; |
157 | h2 = iph->saddr.s6_addr32[3]^iph->nexthdr; | 158 | h2 = iph->saddr.s6_addr32[3]^iph->nexthdr; |
158 | if (iph->nexthdr == IPPROTO_TCP || | 159 | if (iph->nexthdr == IPPROTO_TCP || |
@@ -461,7 +462,7 @@ static void sfq_destroy(struct Qdisc *sch) | |||
461 | static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) | 462 | static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) |
462 | { | 463 | { |
463 | struct sfq_sched_data *q = qdisc_priv(sch); | 464 | struct sfq_sched_data *q = qdisc_priv(sch); |
464 | unsigned char *b = skb->tail; | 465 | unsigned char *b = skb_tail_pointer(skb); |
465 | struct tc_sfq_qopt opt; | 466 | struct tc_sfq_qopt opt; |
466 | 467 | ||
467 | opt.quantum = q->quantum; | 468 | opt.quantum = q->quantum; |
@@ -476,7 +477,7 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
476 | return skb->len; | 477 | return skb->len; |
477 | 478 | ||
478 | rtattr_failure: | 479 | rtattr_failure: |
479 | skb_trim(skb, b - skb->data); | 480 | nlmsg_trim(skb, b); |
480 | return -1; | 481 | return -1; |
481 | } | 482 | } |
482 | 483 | ||
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 85da8daa61d2..53862953baaf 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/etherdevice.h> | 32 | #include <linux/etherdevice.h> |
33 | #include <linux/notifier.h> | 33 | #include <linux/notifier.h> |
34 | #include <net/ip.h> | 34 | #include <net/ip.h> |
35 | #include <net/netlink.h> | ||
35 | #include <net/route.h> | 36 | #include <net/route.h> |
36 | #include <linux/skbuff.h> | 37 | #include <linux/skbuff.h> |
37 | #include <net/sock.h> | 38 | #include <net/sock.h> |
@@ -127,8 +128,8 @@ struct tbf_sched_data | |||
127 | long tokens; /* Current number of B tokens */ | 128 | long tokens; /* Current number of B tokens */ |
128 | long ptokens; /* Current number of P tokens */ | 129 | long ptokens; /* Current number of P tokens */ |
129 | psched_time_t t_c; /* Time check-point */ | 130 | psched_time_t t_c; /* Time check-point */ |
130 | struct timer_list wd_timer; /* Watchdog timer */ | ||
131 | struct Qdisc *qdisc; /* Inner qdisc, default - bfifo queue */ | 131 | struct Qdisc *qdisc; /* Inner qdisc, default - bfifo queue */ |
132 | struct qdisc_watchdog watchdog; /* Watchdog timer */ | ||
132 | }; | 133 | }; |
133 | 134 | ||
134 | #define L2T(q,L) ((q)->R_tab->data[(L)>>(q)->R_tab->rate.cell_log]) | 135 | #define L2T(q,L) ((q)->R_tab->data[(L)>>(q)->R_tab->rate.cell_log]) |
@@ -185,14 +186,6 @@ static unsigned int tbf_drop(struct Qdisc* sch) | |||
185 | return len; | 186 | return len; |
186 | } | 187 | } |
187 | 188 | ||
188 | static void tbf_watchdog(unsigned long arg) | ||
189 | { | ||
190 | struct Qdisc *sch = (struct Qdisc*)arg; | ||
191 | |||
192 | sch->flags &= ~TCQ_F_THROTTLED; | ||
193 | netif_schedule(sch->dev); | ||
194 | } | ||
195 | |||
196 | static struct sk_buff *tbf_dequeue(struct Qdisc* sch) | 189 | static struct sk_buff *tbf_dequeue(struct Qdisc* sch) |
197 | { | 190 | { |
198 | struct tbf_sched_data *q = qdisc_priv(sch); | 191 | struct tbf_sched_data *q = qdisc_priv(sch); |
@@ -202,13 +195,12 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) | |||
202 | 195 | ||
203 | if (skb) { | 196 | if (skb) { |
204 | psched_time_t now; | 197 | psched_time_t now; |
205 | long toks, delay; | 198 | long toks; |
206 | long ptoks = 0; | 199 | long ptoks = 0; |
207 | unsigned int len = skb->len; | 200 | unsigned int len = skb->len; |
208 | 201 | ||
209 | PSCHED_GET_TIME(now); | 202 | now = psched_get_time(); |
210 | 203 | toks = psched_tdiff_bounded(now, q->t_c, q->buffer); | |
211 | toks = PSCHED_TDIFF_SAFE(now, q->t_c, q->buffer); | ||
212 | 204 | ||
213 | if (q->P_tab) { | 205 | if (q->P_tab) { |
214 | ptoks = toks + q->ptokens; | 206 | ptoks = toks + q->ptokens; |
@@ -230,12 +222,8 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) | |||
230 | return skb; | 222 | return skb; |
231 | } | 223 | } |
232 | 224 | ||
233 | delay = PSCHED_US2JIFFIE(max_t(long, -toks, -ptoks)); | 225 | qdisc_watchdog_schedule(&q->watchdog, |
234 | 226 | now + max_t(long, -toks, -ptoks)); | |
235 | if (delay == 0) | ||
236 | delay = 1; | ||
237 | |||
238 | mod_timer(&q->wd_timer, jiffies+delay); | ||
239 | 227 | ||
240 | /* Maybe we have a shorter packet in the queue, | 228 | /* Maybe we have a shorter packet in the queue, |
241 | which can be sent now. It sounds cool, | 229 | which can be sent now. It sounds cool, |
@@ -254,7 +242,6 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) | |||
254 | sch->qstats.drops++; | 242 | sch->qstats.drops++; |
255 | } | 243 | } |
256 | 244 | ||
257 | sch->flags |= TCQ_F_THROTTLED; | ||
258 | sch->qstats.overlimits++; | 245 | sch->qstats.overlimits++; |
259 | } | 246 | } |
260 | return NULL; | 247 | return NULL; |
@@ -266,11 +253,10 @@ static void tbf_reset(struct Qdisc* sch) | |||
266 | 253 | ||
267 | qdisc_reset(q->qdisc); | 254 | qdisc_reset(q->qdisc); |
268 | sch->q.qlen = 0; | 255 | sch->q.qlen = 0; |
269 | PSCHED_GET_TIME(q->t_c); | 256 | q->t_c = psched_get_time(); |
270 | q->tokens = q->buffer; | 257 | q->tokens = q->buffer; |
271 | q->ptokens = q->mtu; | 258 | q->ptokens = q->mtu; |
272 | sch->flags &= ~TCQ_F_THROTTLED; | 259 | qdisc_watchdog_cancel(&q->watchdog); |
273 | del_timer(&q->wd_timer); | ||
274 | } | 260 | } |
275 | 261 | ||
276 | static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit) | 262 | static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit) |
@@ -377,11 +363,8 @@ static int tbf_init(struct Qdisc* sch, struct rtattr *opt) | |||
377 | if (opt == NULL) | 363 | if (opt == NULL) |
378 | return -EINVAL; | 364 | return -EINVAL; |
379 | 365 | ||
380 | PSCHED_GET_TIME(q->t_c); | 366 | q->t_c = psched_get_time(); |
381 | init_timer(&q->wd_timer); | 367 | qdisc_watchdog_init(&q->watchdog, sch); |
382 | q->wd_timer.function = tbf_watchdog; | ||
383 | q->wd_timer.data = (unsigned long)sch; | ||
384 | |||
385 | q->qdisc = &noop_qdisc; | 368 | q->qdisc = &noop_qdisc; |
386 | 369 | ||
387 | return tbf_change(sch, opt); | 370 | return tbf_change(sch, opt); |
@@ -391,7 +374,7 @@ static void tbf_destroy(struct Qdisc *sch) | |||
391 | { | 374 | { |
392 | struct tbf_sched_data *q = qdisc_priv(sch); | 375 | struct tbf_sched_data *q = qdisc_priv(sch); |
393 | 376 | ||
394 | del_timer(&q->wd_timer); | 377 | qdisc_watchdog_cancel(&q->watchdog); |
395 | 378 | ||
396 | if (q->P_tab) | 379 | if (q->P_tab) |
397 | qdisc_put_rtab(q->P_tab); | 380 | qdisc_put_rtab(q->P_tab); |
@@ -404,7 +387,7 @@ static void tbf_destroy(struct Qdisc *sch) | |||
404 | static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) | 387 | static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) |
405 | { | 388 | { |
406 | struct tbf_sched_data *q = qdisc_priv(sch); | 389 | struct tbf_sched_data *q = qdisc_priv(sch); |
407 | unsigned char *b = skb->tail; | 390 | unsigned char *b = skb_tail_pointer(skb); |
408 | struct rtattr *rta; | 391 | struct rtattr *rta; |
409 | struct tc_tbf_qopt opt; | 392 | struct tc_tbf_qopt opt; |
410 | 393 | ||
@@ -420,12 +403,12 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
420 | opt.mtu = q->mtu; | 403 | opt.mtu = q->mtu; |
421 | opt.buffer = q->buffer; | 404 | opt.buffer = q->buffer; |
422 | RTA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt); | 405 | RTA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt); |
423 | rta->rta_len = skb->tail - b; | 406 | rta->rta_len = skb_tail_pointer(skb) - b; |
424 | 407 | ||
425 | return skb->len; | 408 | return skb->len; |
426 | 409 | ||
427 | rtattr_failure: | 410 | rtattr_failure: |
428 | skb_trim(skb, b - skb->data); | 411 | nlmsg_trim(skb, b); |
429 | return -1; | 412 | return -1; |
430 | } | 413 | } |
431 | 414 | ||
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 587123c61af9..d24914db7861 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c | |||
@@ -323,7 +323,7 @@ restart: | |||
323 | nores = 1; | 323 | nores = 1; |
324 | break; | 324 | break; |
325 | } | 325 | } |
326 | __skb_pull(skb, skb->nh.raw - skb->data); | 326 | __skb_pull(skb, skb_network_offset(skb)); |
327 | } while ((q = NEXT_SLAVE(q)) != start); | 327 | } while ((q = NEXT_SLAVE(q)) != start); |
328 | 328 | ||
329 | if (nores && skb_res == NULL) { | 329 | if (nores && skb_res == NULL) { |