diff options
Diffstat (limited to 'net/sched')
47 files changed, 3189 insertions, 912 deletions
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index f04d4a484d53..a7a5583d4f68 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -126,6 +126,17 @@ config NET_SCH_RED | |||
126 | To compile this code as a module, choose M here: the | 126 | To compile this code as a module, choose M here: the |
127 | module will be called sch_red. | 127 | module will be called sch_red. |
128 | 128 | ||
129 | config NET_SCH_SFB | ||
130 | tristate "Stochastic Fair Blue (SFB)" | ||
131 | ---help--- | ||
132 | Say Y here if you want to use the Stochastic Fair Blue (SFB) | ||
133 | packet scheduling algorithm. | ||
134 | |||
135 | See the top of <file:net/sched/sch_sfb.c> for more details. | ||
136 | |||
137 | To compile this code as a module, choose M here: the | ||
138 | module will be called sch_sfb. | ||
139 | |||
129 | config NET_SCH_SFQ | 140 | config NET_SCH_SFQ |
130 | tristate "Stochastic Fairness Queueing (SFQ)" | 141 | tristate "Stochastic Fairness Queueing (SFQ)" |
131 | ---help--- | 142 | ---help--- |
@@ -205,6 +216,29 @@ config NET_SCH_DRR | |||
205 | 216 | ||
206 | If unsure, say N. | 217 | If unsure, say N. |
207 | 218 | ||
219 | config NET_SCH_MQPRIO | ||
220 | tristate "Multi-queue priority scheduler (MQPRIO)" | ||
221 | help | ||
222 | Say Y here if you want to use the Multi-queue Priority scheduler. | ||
223 | This scheduler allows QOS to be offloaded on NICs that have support | ||
224 | for offloading QOS schedulers. | ||
225 | |||
226 | To compile this driver as a module, choose M here: the module will | ||
227 | be called sch_mqprio. | ||
228 | |||
229 | If unsure, say N. | ||
230 | |||
231 | config NET_SCH_CHOKE | ||
232 | tristate "CHOose and Keep responsive flow scheduler (CHOKE)" | ||
233 | help | ||
234 | Say Y here if you want to use the CHOKe packet scheduler (CHOose | ||
235 | and Keep for responsive flows, CHOose and Kill for unresponsive | ||
236 | flows). This is a variation of RED which trys to penalize flows | ||
237 | that monopolize the queue. | ||
238 | |||
239 | To compile this code as a module, choose M here: the | ||
240 | module will be called sch_choke. | ||
241 | |||
208 | config NET_SCH_INGRESS | 242 | config NET_SCH_INGRESS |
209 | tristate "Ingress Qdisc" | 243 | tristate "Ingress Qdisc" |
210 | depends on NET_CLS_ACT | 244 | depends on NET_CLS_ACT |
@@ -243,7 +277,7 @@ config NET_CLS_TCINDEX | |||
243 | 277 | ||
244 | config NET_CLS_ROUTE4 | 278 | config NET_CLS_ROUTE4 |
245 | tristate "Routing decision (ROUTE)" | 279 | tristate "Routing decision (ROUTE)" |
246 | select NET_CLS_ROUTE | 280 | select IP_ROUTE_CLASSID |
247 | select NET_CLS | 281 | select NET_CLS |
248 | ---help--- | 282 | ---help--- |
249 | If you say Y here, you will be able to classify packets | 283 | If you say Y here, you will be able to classify packets |
@@ -252,9 +286,6 @@ config NET_CLS_ROUTE4 | |||
252 | To compile this code as a module, choose M here: the | 286 | To compile this code as a module, choose M here: the |
253 | module will be called cls_route. | 287 | module will be called cls_route. |
254 | 288 | ||
255 | config NET_CLS_ROUTE | ||
256 | bool | ||
257 | |||
258 | config NET_CLS_FW | 289 | config NET_CLS_FW |
259 | tristate "Netfilter mark (FW)" | 290 | tristate "Netfilter mark (FW)" |
260 | select NET_CLS | 291 | select NET_CLS |
diff --git a/net/sched/Makefile b/net/sched/Makefile index 960f5dba6304..2e77b8dba22e 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile | |||
@@ -24,6 +24,7 @@ obj-$(CONFIG_NET_SCH_RED) += sch_red.o | |||
24 | obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o | 24 | obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o |
25 | obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o | 25 | obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o |
26 | obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o | 26 | obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o |
27 | obj-$(CONFIG_NET_SCH_SFB) += sch_sfb.o | ||
27 | obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o | 28 | obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o |
28 | obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o | 29 | obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o |
29 | obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o | 30 | obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o |
@@ -32,6 +33,9 @@ obj-$(CONFIG_NET_SCH_MULTIQ) += sch_multiq.o | |||
32 | obj-$(CONFIG_NET_SCH_ATM) += sch_atm.o | 33 | obj-$(CONFIG_NET_SCH_ATM) += sch_atm.o |
33 | obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o | 34 | obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o |
34 | obj-$(CONFIG_NET_SCH_DRR) += sch_drr.o | 35 | obj-$(CONFIG_NET_SCH_DRR) += sch_drr.o |
36 | obj-$(CONFIG_NET_SCH_MQPRIO) += sch_mqprio.o | ||
37 | obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o | ||
38 | |||
35 | obj-$(CONFIG_NET_CLS_U32) += cls_u32.o | 39 | obj-$(CONFIG_NET_CLS_U32) += cls_u32.o |
36 | obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o | 40 | obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o |
37 | obj-$(CONFIG_NET_CLS_FW) += cls_fw.o | 41 | obj-$(CONFIG_NET_CLS_FW) += cls_fw.o |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 23b25f89e7e0..14b42f4ad791 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -78,7 +78,7 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, | |||
78 | struct tc_action *a, struct tcf_hashinfo *hinfo) | 78 | struct tc_action *a, struct tcf_hashinfo *hinfo) |
79 | { | 79 | { |
80 | struct tcf_common *p; | 80 | struct tcf_common *p; |
81 | int err = 0, index = -1,i = 0, s_i = 0, n_i = 0; | 81 | int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; |
82 | struct nlattr *nest; | 82 | struct nlattr *nest; |
83 | 83 | ||
84 | read_lock_bh(hinfo->lock); | 84 | read_lock_bh(hinfo->lock); |
@@ -126,7 +126,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a, | |||
126 | { | 126 | { |
127 | struct tcf_common *p, *s_p; | 127 | struct tcf_common *p, *s_p; |
128 | struct nlattr *nest; | 128 | struct nlattr *nest; |
129 | int i= 0, n_i = 0; | 129 | int i = 0, n_i = 0; |
130 | 130 | ||
131 | nest = nla_nest_start(skb, a->order); | 131 | nest = nla_nest_start(skb, a->order); |
132 | if (nest == NULL) | 132 | if (nest == NULL) |
@@ -138,7 +138,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a, | |||
138 | while (p != NULL) { | 138 | while (p != NULL) { |
139 | s_p = p->tcfc_next; | 139 | s_p = p->tcfc_next; |
140 | if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo)) | 140 | if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo)) |
141 | module_put(a->ops->owner); | 141 | module_put(a->ops->owner); |
142 | n_i++; | 142 | n_i++; |
143 | p = s_p; | 143 | p = s_p; |
144 | } | 144 | } |
@@ -447,7 +447,8 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | |||
447 | nest = nla_nest_start(skb, TCA_OPTIONS); | 447 | nest = nla_nest_start(skb, TCA_OPTIONS); |
448 | if (nest == NULL) | 448 | if (nest == NULL) |
449 | goto nla_put_failure; | 449 | goto nla_put_failure; |
450 | if ((err = tcf_action_dump_old(skb, a, bind, ref)) > 0) { | 450 | err = tcf_action_dump_old(skb, a, bind, ref); |
451 | if (err > 0) { | ||
451 | nla_nest_end(skb, nest); | 452 | nla_nest_end(skb, nest); |
452 | return err; | 453 | return err; |
453 | } | 454 | } |
@@ -491,7 +492,7 @@ struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, | |||
491 | struct tc_action *a; | 492 | struct tc_action *a; |
492 | struct tc_action_ops *a_o; | 493 | struct tc_action_ops *a_o; |
493 | char act_name[IFNAMSIZ]; | 494 | char act_name[IFNAMSIZ]; |
494 | struct nlattr *tb[TCA_ACT_MAX+1]; | 495 | struct nlattr *tb[TCA_ACT_MAX + 1]; |
495 | struct nlattr *kind; | 496 | struct nlattr *kind; |
496 | int err; | 497 | int err; |
497 | 498 | ||
@@ -549,9 +550,9 @@ struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, | |||
549 | goto err_free; | 550 | goto err_free; |
550 | 551 | ||
551 | /* module count goes up only when brand new policy is created | 552 | /* module count goes up only when brand new policy is created |
552 | if it exists and is only bound to in a_o->init() then | 553 | * if it exists and is only bound to in a_o->init() then |
553 | ACT_P_CREATED is not returned (a zero is). | 554 | * ACT_P_CREATED is not returned (a zero is). |
554 | */ | 555 | */ |
555 | if (err != ACT_P_CREATED) | 556 | if (err != ACT_P_CREATED) |
556 | module_put(a_o->owner); | 557 | module_put(a_o->owner); |
557 | a->ops = a_o; | 558 | a->ops = a_o; |
@@ -569,7 +570,7 @@ err_out: | |||
569 | struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, | 570 | struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, |
570 | char *name, int ovr, int bind) | 571 | char *name, int ovr, int bind) |
571 | { | 572 | { |
572 | struct nlattr *tb[TCA_ACT_MAX_PRIO+1]; | 573 | struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; |
573 | struct tc_action *head = NULL, *act, *act_prev = NULL; | 574 | struct tc_action *head = NULL, *act, *act_prev = NULL; |
574 | int err; | 575 | int err; |
575 | int i; | 576 | int i; |
@@ -697,7 +698,7 @@ act_get_notify(struct net *net, u32 pid, struct nlmsghdr *n, | |||
697 | static struct tc_action * | 698 | static struct tc_action * |
698 | tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid) | 699 | tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid) |
699 | { | 700 | { |
700 | struct nlattr *tb[TCA_ACT_MAX+1]; | 701 | struct nlattr *tb[TCA_ACT_MAX + 1]; |
701 | struct tc_action *a; | 702 | struct tc_action *a; |
702 | int index; | 703 | int index; |
703 | int err; | 704 | int err; |
@@ -770,7 +771,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
770 | struct tcamsg *t; | 771 | struct tcamsg *t; |
771 | struct netlink_callback dcb; | 772 | struct netlink_callback dcb; |
772 | struct nlattr *nest; | 773 | struct nlattr *nest; |
773 | struct nlattr *tb[TCA_ACT_MAX+1]; | 774 | struct nlattr *tb[TCA_ACT_MAX + 1]; |
774 | struct nlattr *kind; | 775 | struct nlattr *kind; |
775 | struct tc_action *a = create_a(0); | 776 | struct tc_action *a = create_a(0); |
776 | int err = -ENOMEM; | 777 | int err = -ENOMEM; |
@@ -821,7 +822,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
821 | nlh->nlmsg_flags |= NLM_F_ROOT; | 822 | nlh->nlmsg_flags |= NLM_F_ROOT; |
822 | module_put(a->ops->owner); | 823 | module_put(a->ops->owner); |
823 | kfree(a); | 824 | kfree(a); |
824 | err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 825 | err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
826 | n->nlmsg_flags & NLM_F_ECHO); | ||
825 | if (err > 0) | 827 | if (err > 0) |
826 | return 0; | 828 | return 0; |
827 | 829 | ||
@@ -842,14 +844,14 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, | |||
842 | u32 pid, int event) | 844 | u32 pid, int event) |
843 | { | 845 | { |
844 | int i, ret; | 846 | int i, ret; |
845 | struct nlattr *tb[TCA_ACT_MAX_PRIO+1]; | 847 | struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; |
846 | struct tc_action *head = NULL, *act, *act_prev = NULL; | 848 | struct tc_action *head = NULL, *act, *act_prev = NULL; |
847 | 849 | ||
848 | ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL); | 850 | ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL); |
849 | if (ret < 0) | 851 | if (ret < 0) |
850 | return ret; | 852 | return ret; |
851 | 853 | ||
852 | if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) { | 854 | if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) { |
853 | if (tb[1] != NULL) | 855 | if (tb[1] != NULL) |
854 | return tca_action_flush(net, tb[1], n, pid); | 856 | return tca_action_flush(net, tb[1], n, pid); |
855 | else | 857 | else |
@@ -892,7 +894,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, | |||
892 | /* now do the delete */ | 894 | /* now do the delete */ |
893 | tcf_action_destroy(head, 0); | 895 | tcf_action_destroy(head, 0); |
894 | ret = rtnetlink_send(skb, net, pid, RTNLGRP_TC, | 896 | ret = rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
895 | n->nlmsg_flags&NLM_F_ECHO); | 897 | n->nlmsg_flags & NLM_F_ECHO); |
896 | if (ret > 0) | 898 | if (ret > 0) |
897 | return 0; | 899 | return 0; |
898 | return ret; | 900 | return ret; |
@@ -936,7 +938,7 @@ static int tcf_add_notify(struct net *net, struct tc_action *a, | |||
936 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; | 938 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
937 | NETLINK_CB(skb).dst_group = RTNLGRP_TC; | 939 | NETLINK_CB(skb).dst_group = RTNLGRP_TC; |
938 | 940 | ||
939 | err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, flags&NLM_F_ECHO); | 941 | err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, flags & NLM_F_ECHO); |
940 | if (err > 0) | 942 | if (err > 0) |
941 | err = 0; | 943 | err = 0; |
942 | return err; | 944 | return err; |
@@ -967,7 +969,7 @@ tcf_action_add(struct net *net, struct nlattr *nla, struct nlmsghdr *n, | |||
967 | 969 | ||
968 | /* dump then free all the actions after update; inserted policy | 970 | /* dump then free all the actions after update; inserted policy |
969 | * stays intact | 971 | * stays intact |
970 | * */ | 972 | */ |
971 | ret = tcf_add_notify(net, act, pid, seq, RTM_NEWACTION, n->nlmsg_flags); | 973 | ret = tcf_add_notify(net, act, pid, seq, RTM_NEWACTION, n->nlmsg_flags); |
972 | for (a = act; a; a = act) { | 974 | for (a = act; a; a = act) { |
973 | act = a->next; | 975 | act = a->next; |
@@ -993,17 +995,16 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
993 | return -EINVAL; | 995 | return -EINVAL; |
994 | } | 996 | } |
995 | 997 | ||
996 | /* n->nlmsg_flags&NLM_F_CREATE | 998 | /* n->nlmsg_flags & NLM_F_CREATE */ |
997 | * */ | ||
998 | switch (n->nlmsg_type) { | 999 | switch (n->nlmsg_type) { |
999 | case RTM_NEWACTION: | 1000 | case RTM_NEWACTION: |
1000 | /* we are going to assume all other flags | 1001 | /* we are going to assume all other flags |
1001 | * imply create only if it doesnt exist | 1002 | * imply create only if it doesn't exist |
1002 | * Note that CREATE | EXCL implies that | 1003 | * Note that CREATE | EXCL implies that |
1003 | * but since we want avoid ambiguity (eg when flags | 1004 | * but since we want avoid ambiguity (eg when flags |
1004 | * is zero) then just set this | 1005 | * is zero) then just set this |
1005 | */ | 1006 | */ |
1006 | if (n->nlmsg_flags&NLM_F_REPLACE) | 1007 | if (n->nlmsg_flags & NLM_F_REPLACE) |
1007 | ovr = 1; | 1008 | ovr = 1; |
1008 | replay: | 1009 | replay: |
1009 | ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, pid, ovr); | 1010 | ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, pid, ovr); |
@@ -1028,7 +1029,7 @@ replay: | |||
1028 | static struct nlattr * | 1029 | static struct nlattr * |
1029 | find_dump_kind(const struct nlmsghdr *n) | 1030 | find_dump_kind(const struct nlmsghdr *n) |
1030 | { | 1031 | { |
1031 | struct nlattr *tb1, *tb2[TCA_ACT_MAX+1]; | 1032 | struct nlattr *tb1, *tb2[TCA_ACT_MAX + 1]; |
1032 | struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; | 1033 | struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; |
1033 | struct nlattr *nla[TCAA_MAX + 1]; | 1034 | struct nlattr *nla[TCAA_MAX + 1]; |
1034 | struct nlattr *kind; | 1035 | struct nlattr *kind; |
@@ -1071,9 +1072,8 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1071 | } | 1072 | } |
1072 | 1073 | ||
1073 | a_o = tc_lookup_action(kind); | 1074 | a_o = tc_lookup_action(kind); |
1074 | if (a_o == NULL) { | 1075 | if (a_o == NULL) |
1075 | return 0; | 1076 | return 0; |
1076 | } | ||
1077 | 1077 | ||
1078 | memset(&a, 0, sizeof(struct tc_action)); | 1078 | memset(&a, 0, sizeof(struct tc_action)); |
1079 | a.ops = a_o; | 1079 | a.ops = a_o; |
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index 83ddfc07e45d..6cdf9abe475f 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c | |||
@@ -63,7 +63,7 @@ static int tcf_csum_init(struct nlattr *nla, struct nlattr *est, | |||
63 | if (nla == NULL) | 63 | if (nla == NULL) |
64 | return -EINVAL; | 64 | return -EINVAL; |
65 | 65 | ||
66 | err = nla_parse_nested(tb, TCA_CSUM_MAX, nla,csum_policy); | 66 | err = nla_parse_nested(tb, TCA_CSUM_MAX, nla, csum_policy); |
67 | if (err < 0) | 67 | if (err < 0) |
68 | return err; | 68 | return err; |
69 | 69 | ||
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index c2ed90a4c0b4..2b4ab4b05ce8 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
@@ -50,7 +50,7 @@ static int gact_determ(struct tcf_gact *gact) | |||
50 | } | 50 | } |
51 | 51 | ||
52 | typedef int (*g_rand)(struct tcf_gact *gact); | 52 | typedef int (*g_rand)(struct tcf_gact *gact); |
53 | static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ }; | 53 | static g_rand gact_rand[MAX_RAND] = { NULL, gact_net_rand, gact_determ }; |
54 | #endif /* CONFIG_GACT_PROB */ | 54 | #endif /* CONFIG_GACT_PROB */ |
55 | 55 | ||
56 | static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = { | 56 | static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = { |
@@ -89,7 +89,7 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, | |||
89 | pc = tcf_hash_create(parm->index, est, a, sizeof(*gact), | 89 | pc = tcf_hash_create(parm->index, est, a, sizeof(*gact), |
90 | bind, &gact_idx_gen, &gact_hash_info); | 90 | bind, &gact_idx_gen, &gact_hash_info); |
91 | if (IS_ERR(pc)) | 91 | if (IS_ERR(pc)) |
92 | return PTR_ERR(pc); | 92 | return PTR_ERR(pc); |
93 | ret = ACT_P_CREATED; | 93 | ret = ACT_P_CREATED; |
94 | } else { | 94 | } else { |
95 | if (!ovr) { | 95 | if (!ovr) { |
@@ -205,9 +205,9 @@ MODULE_LICENSE("GPL"); | |||
205 | static int __init gact_init_module(void) | 205 | static int __init gact_init_module(void) |
206 | { | 206 | { |
207 | #ifdef CONFIG_GACT_PROB | 207 | #ifdef CONFIG_GACT_PROB |
208 | printk(KERN_INFO "GACT probability on\n"); | 208 | pr_info("GACT probability on\n"); |
209 | #else | 209 | #else |
210 | printk(KERN_INFO "GACT probability NOT on\n"); | 210 | pr_info("GACT probability NOT on\n"); |
211 | #endif | 211 | #endif |
212 | return tcf_register_action(&act_gact_ops); | 212 | return tcf_register_action(&act_gact_ops); |
213 | } | 213 | } |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index c2a7c20e81c1..9fc211a1b20e 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -138,7 +138,7 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est, | |||
138 | pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind, | 138 | pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind, |
139 | &ipt_idx_gen, &ipt_hash_info); | 139 | &ipt_idx_gen, &ipt_hash_info); |
140 | if (IS_ERR(pc)) | 140 | if (IS_ERR(pc)) |
141 | return PTR_ERR(pc); | 141 | return PTR_ERR(pc); |
142 | ret = ACT_P_CREATED; | 142 | ret = ACT_P_CREATED; |
143 | } else { | 143 | } else { |
144 | if (!ovr) { | 144 | if (!ovr) { |
@@ -162,7 +162,8 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est, | |||
162 | if (unlikely(!t)) | 162 | if (unlikely(!t)) |
163 | goto err2; | 163 | goto err2; |
164 | 164 | ||
165 | if ((err = ipt_init_target(t, tname, hook)) < 0) | 165 | err = ipt_init_target(t, tname, hook); |
166 | if (err < 0) | ||
166 | goto err3; | 167 | goto err3; |
167 | 168 | ||
168 | spin_lock_bh(&ipt->tcf_lock); | 169 | spin_lock_bh(&ipt->tcf_lock); |
@@ -212,8 +213,9 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, | |||
212 | bstats_update(&ipt->tcf_bstats, skb); | 213 | bstats_update(&ipt->tcf_bstats, skb); |
213 | 214 | ||
214 | /* yes, we have to worry about both in and out dev | 215 | /* yes, we have to worry about both in and out dev |
215 | worry later - danger - this API seems to have changed | 216 | * worry later - danger - this API seems to have changed |
216 | from earlier kernels */ | 217 | * from earlier kernels |
218 | */ | ||
217 | par.in = skb->dev; | 219 | par.in = skb->dev; |
218 | par.out = NULL; | 220 | par.out = NULL; |
219 | par.hooknum = ipt->tcfi_hook; | 221 | par.hooknum = ipt->tcfi_hook; |
@@ -253,9 +255,9 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int | |||
253 | struct tc_cnt c; | 255 | struct tc_cnt c; |
254 | 256 | ||
255 | /* for simple targets kernel size == user size | 257 | /* for simple targets kernel size == user size |
256 | ** user name = target name | 258 | * user name = target name |
257 | ** for foolproof you need to not assume this | 259 | * for foolproof you need to not assume this |
258 | */ | 260 | */ |
259 | 261 | ||
260 | t = kmemdup(ipt->tcfi_t, ipt->tcfi_t->u.user.target_size, GFP_ATOMIC); | 262 | t = kmemdup(ipt->tcfi_t, ipt->tcfi_t->u.user.target_size, GFP_ATOMIC); |
261 | if (unlikely(!t)) | 263 | if (unlikely(!t)) |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index d765067e99db..961386e2f2c0 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -41,13 +41,13 @@ static struct tcf_hashinfo mirred_hash_info = { | |||
41 | .lock = &mirred_lock, | 41 | .lock = &mirred_lock, |
42 | }; | 42 | }; |
43 | 43 | ||
44 | static inline int tcf_mirred_release(struct tcf_mirred *m, int bind) | 44 | static int tcf_mirred_release(struct tcf_mirred *m, int bind) |
45 | { | 45 | { |
46 | if (m) { | 46 | if (m) { |
47 | if (bind) | 47 | if (bind) |
48 | m->tcf_bindcnt--; | 48 | m->tcf_bindcnt--; |
49 | m->tcf_refcnt--; | 49 | m->tcf_refcnt--; |
50 | if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) { | 50 | if (!m->tcf_bindcnt && m->tcf_refcnt <= 0) { |
51 | list_del(&m->tcfm_list); | 51 | list_del(&m->tcfm_list); |
52 | if (m->tcfm_dev) | 52 | if (m->tcfm_dev) |
53 | dev_put(m->tcfm_dev); | 53 | dev_put(m->tcfm_dev); |
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 178a4bd7b7cb..762b027650a9 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c | |||
@@ -69,7 +69,7 @@ static int tcf_nat_init(struct nlattr *nla, struct nlattr *est, | |||
69 | pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, | 69 | pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, |
70 | &nat_idx_gen, &nat_hash_info); | 70 | &nat_idx_gen, &nat_hash_info); |
71 | if (IS_ERR(pc)) | 71 | if (IS_ERR(pc)) |
72 | return PTR_ERR(pc); | 72 | return PTR_ERR(pc); |
73 | p = to_tcf_nat(pc); | 73 | p = to_tcf_nat(pc); |
74 | ret = ACT_P_CREATED; | 74 | ret = ACT_P_CREATED; |
75 | } else { | 75 | } else { |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 445bef716f77..7affe9a92757 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
@@ -70,7 +70,7 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est, | |||
70 | pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, | 70 | pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, |
71 | &pedit_idx_gen, &pedit_hash_info); | 71 | &pedit_idx_gen, &pedit_hash_info); |
72 | if (IS_ERR(pc)) | 72 | if (IS_ERR(pc)) |
73 | return PTR_ERR(pc); | 73 | return PTR_ERR(pc); |
74 | p = to_pedit(pc); | 74 | p = to_pedit(pc); |
75 | keys = kmalloc(ksize, GFP_KERNEL); | 75 | keys = kmalloc(ksize, GFP_KERNEL); |
76 | if (keys == NULL) { | 76 | if (keys == NULL) { |
@@ -127,11 +127,9 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, | |||
127 | int i, munged = 0; | 127 | int i, munged = 0; |
128 | unsigned int off; | 128 | unsigned int off; |
129 | 129 | ||
130 | if (skb_cloned(skb)) { | 130 | if (skb_cloned(skb) && |
131 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { | 131 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
132 | return p->tcf_action; | 132 | return p->tcf_action; |
133 | } | ||
134 | } | ||
135 | 133 | ||
136 | off = skb_network_offset(skb); | 134 | off = skb_network_offset(skb); |
137 | 135 | ||
@@ -163,7 +161,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, | |||
163 | } | 161 | } |
164 | if (offset > 0 && offset > skb->len) { | 162 | if (offset > 0 && offset > skb->len) { |
165 | pr_info("tc filter pedit" | 163 | pr_info("tc filter pedit" |
166 | " offset %d cant exceed pkt length %d\n", | 164 | " offset %d can't exceed pkt length %d\n", |
167 | offset, skb->len); | 165 | offset, skb->len); |
168 | goto bad; | 166 | goto bad; |
169 | } | 167 | } |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index e2f08b1e2e58..8a1630774fd6 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -22,8 +22,8 @@ | |||
22 | #include <net/act_api.h> | 22 | #include <net/act_api.h> |
23 | #include <net/netlink.h> | 23 | #include <net/netlink.h> |
24 | 24 | ||
25 | #define L2T(p,L) qdisc_l2t((p)->tcfp_R_tab, L) | 25 | #define L2T(p, L) qdisc_l2t((p)->tcfp_R_tab, L) |
26 | #define L2T_P(p,L) qdisc_l2t((p)->tcfp_P_tab, L) | 26 | #define L2T_P(p, L) qdisc_l2t((p)->tcfp_P_tab, L) |
27 | 27 | ||
28 | #define POL_TAB_MASK 15 | 28 | #define POL_TAB_MASK 15 |
29 | static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1]; | 29 | static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1]; |
@@ -37,8 +37,7 @@ static struct tcf_hashinfo police_hash_info = { | |||
37 | }; | 37 | }; |
38 | 38 | ||
39 | /* old policer structure from before tc actions */ | 39 | /* old policer structure from before tc actions */ |
40 | struct tc_police_compat | 40 | struct tc_police_compat { |
41 | { | ||
42 | u32 index; | 41 | u32 index; |
43 | int action; | 42 | int action; |
44 | u32 limit; | 43 | u32 limit; |
@@ -139,7 +138,7 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { | |||
139 | static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est, | 138 | static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est, |
140 | struct tc_action *a, int ovr, int bind) | 139 | struct tc_action *a, int ovr, int bind) |
141 | { | 140 | { |
142 | unsigned h; | 141 | unsigned int h; |
143 | int ret = 0, err; | 142 | int ret = 0, err; |
144 | struct nlattr *tb[TCA_POLICE_MAX + 1]; | 143 | struct nlattr *tb[TCA_POLICE_MAX + 1]; |
145 | struct tc_police *parm; | 144 | struct tc_police *parm; |
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 7287cff7af3e..a34a22de60b3 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
@@ -47,7 +47,7 @@ static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result | |||
47 | /* print policy string followed by _ then packet count | 47 | /* print policy string followed by _ then packet count |
48 | * Example if this was the 3rd packet and the string was "hello" | 48 | * Example if this was the 3rd packet and the string was "hello" |
49 | * then it would look like "hello_3" (without quotes) | 49 | * then it would look like "hello_3" (without quotes) |
50 | **/ | 50 | */ |
51 | pr_info("simple: %s_%d\n", | 51 | pr_info("simple: %s_%d\n", |
52 | (char *)d->tcfd_defdata, d->tcf_bstats.packets); | 52 | (char *)d->tcfd_defdata, d->tcf_bstats.packets); |
53 | spin_unlock(&d->tcf_lock); | 53 | spin_unlock(&d->tcf_lock); |
@@ -125,7 +125,7 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est, | |||
125 | pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, | 125 | pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, |
126 | &simp_idx_gen, &simp_hash_info); | 126 | &simp_idx_gen, &simp_hash_info); |
127 | if (IS_ERR(pc)) | 127 | if (IS_ERR(pc)) |
128 | return PTR_ERR(pc); | 128 | return PTR_ERR(pc); |
129 | 129 | ||
130 | d = to_defact(pc); | 130 | d = to_defact(pc); |
131 | ret = alloc_defdata(d, defdata); | 131 | ret = alloc_defdata(d, defdata); |
@@ -149,7 +149,7 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est, | |||
149 | return ret; | 149 | return ret; |
150 | } | 150 | } |
151 | 151 | ||
152 | static inline int tcf_simp_cleanup(struct tc_action *a, int bind) | 152 | static int tcf_simp_cleanup(struct tc_action *a, int bind) |
153 | { | 153 | { |
154 | struct tcf_defact *d = a->priv; | 154 | struct tcf_defact *d = a->priv; |
155 | 155 | ||
@@ -158,8 +158,8 @@ static inline int tcf_simp_cleanup(struct tc_action *a, int bind) | |||
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | 160 | ||
161 | static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, | 161 | static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, |
162 | int bind, int ref) | 162 | int bind, int ref) |
163 | { | 163 | { |
164 | unsigned char *b = skb_tail_pointer(skb); | 164 | unsigned char *b = skb_tail_pointer(skb); |
165 | struct tcf_defact *d = a->priv; | 165 | struct tcf_defact *d = a->priv; |
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index 836f5fee9e58..5f6f0c7c3905 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c | |||
@@ -113,7 +113,7 @@ static int tcf_skbedit_init(struct nlattr *nla, struct nlattr *est, | |||
113 | pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, | 113 | pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, |
114 | &skbedit_idx_gen, &skbedit_hash_info); | 114 | &skbedit_idx_gen, &skbedit_hash_info); |
115 | if (IS_ERR(pc)) | 115 | if (IS_ERR(pc)) |
116 | return PTR_ERR(pc); | 116 | return PTR_ERR(pc); |
117 | 117 | ||
118 | d = to_skbedit(pc); | 118 | d = to_skbedit(pc); |
119 | ret = ACT_P_CREATED; | 119 | ret = ACT_P_CREATED; |
@@ -144,7 +144,7 @@ static int tcf_skbedit_init(struct nlattr *nla, struct nlattr *est, | |||
144 | return ret; | 144 | return ret; |
145 | } | 145 | } |
146 | 146 | ||
147 | static inline int tcf_skbedit_cleanup(struct tc_action *a, int bind) | 147 | static int tcf_skbedit_cleanup(struct tc_action *a, int bind) |
148 | { | 148 | { |
149 | struct tcf_skbedit *d = a->priv; | 149 | struct tcf_skbedit *d = a->priv; |
150 | 150 | ||
@@ -153,8 +153,8 @@ static inline int tcf_skbedit_cleanup(struct tc_action *a, int bind) | |||
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | static inline int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, | 156 | static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, |
157 | int bind, int ref) | 157 | int bind, int ref) |
158 | { | 158 | { |
159 | unsigned char *b = skb_tail_pointer(skb); | 159 | unsigned char *b = skb_tail_pointer(skb); |
160 | struct tcf_skbedit *d = a->priv; | 160 | struct tcf_skbedit *d = a->priv; |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 5fd0c28ef79a..bb2c523f8158 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -85,7 +85,7 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops) | |||
85 | int rc = -ENOENT; | 85 | int rc = -ENOENT; |
86 | 86 | ||
87 | write_lock(&cls_mod_lock); | 87 | write_lock(&cls_mod_lock); |
88 | for (tp = &tcf_proto_base; (t=*tp) != NULL; tp = &t->next) | 88 | for (tp = &tcf_proto_base; (t = *tp) != NULL; tp = &t->next) |
89 | if (t == ops) | 89 | if (t == ops) |
90 | break; | 90 | break; |
91 | 91 | ||
@@ -111,7 +111,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp) | |||
111 | u32 first = TC_H_MAKE(0xC0000000U, 0U); | 111 | u32 first = TC_H_MAKE(0xC0000000U, 0U); |
112 | 112 | ||
113 | if (tp) | 113 | if (tp) |
114 | first = tp->prio-1; | 114 | first = tp->prio - 1; |
115 | 115 | ||
116 | return first; | 116 | return first; |
117 | } | 117 | } |
@@ -149,7 +149,8 @@ replay: | |||
149 | 149 | ||
150 | if (prio == 0) { | 150 | if (prio == 0) { |
151 | /* If no priority is given, user wants we allocated it. */ | 151 | /* If no priority is given, user wants we allocated it. */ |
152 | if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE)) | 152 | if (n->nlmsg_type != RTM_NEWTFILTER || |
153 | !(n->nlmsg_flags & NLM_F_CREATE)) | ||
153 | return -ENOENT; | 154 | return -ENOENT; |
154 | prio = TC_H_MAKE(0x80000000U, 0U); | 155 | prio = TC_H_MAKE(0x80000000U, 0U); |
155 | } | 156 | } |
@@ -176,7 +177,8 @@ replay: | |||
176 | } | 177 | } |
177 | 178 | ||
178 | /* Is it classful? */ | 179 | /* Is it classful? */ |
179 | if ((cops = q->ops->cl_ops) == NULL) | 180 | cops = q->ops->cl_ops; |
181 | if (!cops) | ||
180 | return -EINVAL; | 182 | return -EINVAL; |
181 | 183 | ||
182 | if (cops->tcf_chain == NULL) | 184 | if (cops->tcf_chain == NULL) |
@@ -196,10 +198,11 @@ replay: | |||
196 | goto errout; | 198 | goto errout; |
197 | 199 | ||
198 | /* Check the chain for existence of proto-tcf with this priority */ | 200 | /* Check the chain for existence of proto-tcf with this priority */ |
199 | for (back = chain; (tp=*back) != NULL; back = &tp->next) { | 201 | for (back = chain; (tp = *back) != NULL; back = &tp->next) { |
200 | if (tp->prio >= prio) { | 202 | if (tp->prio >= prio) { |
201 | if (tp->prio == prio) { | 203 | if (tp->prio == prio) { |
202 | if (!nprio || (tp->protocol != protocol && protocol)) | 204 | if (!nprio || |
205 | (tp->protocol != protocol && protocol)) | ||
203 | goto errout; | 206 | goto errout; |
204 | } else | 207 | } else |
205 | tp = NULL; | 208 | tp = NULL; |
@@ -216,7 +219,8 @@ replay: | |||
216 | goto errout; | 219 | goto errout; |
217 | 220 | ||
218 | err = -ENOENT; | 221 | err = -ENOENT; |
219 | if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE)) | 222 | if (n->nlmsg_type != RTM_NEWTFILTER || |
223 | !(n->nlmsg_flags & NLM_F_CREATE)) | ||
220 | goto errout; | 224 | goto errout; |
221 | 225 | ||
222 | 226 | ||
@@ -420,7 +424,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) | |||
420 | 424 | ||
421 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) | 425 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) |
422 | return skb->len; | 426 | return skb->len; |
423 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) | 427 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); |
428 | if (!dev) | ||
424 | return skb->len; | 429 | return skb->len; |
425 | 430 | ||
426 | if (!tcm->tcm_parent) | 431 | if (!tcm->tcm_parent) |
@@ -429,7 +434,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) | |||
429 | q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent)); | 434 | q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent)); |
430 | if (!q) | 435 | if (!q) |
431 | goto out; | 436 | goto out; |
432 | if ((cops = q->ops->cl_ops) == NULL) | 437 | cops = q->ops->cl_ops; |
438 | if (!cops) | ||
433 | goto errout; | 439 | goto errout; |
434 | if (cops->tcf_chain == NULL) | 440 | if (cops->tcf_chain == NULL) |
435 | goto errout; | 441 | goto errout; |
@@ -444,8 +450,9 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) | |||
444 | 450 | ||
445 | s_t = cb->args[0]; | 451 | s_t = cb->args[0]; |
446 | 452 | ||
447 | for (tp=*chain, t=0; tp; tp = tp->next, t++) { | 453 | for (tp = *chain, t = 0; tp; tp = tp->next, t++) { |
448 | if (t < s_t) continue; | 454 | if (t < s_t) |
455 | continue; | ||
449 | if (TC_H_MAJ(tcm->tcm_info) && | 456 | if (TC_H_MAJ(tcm->tcm_info) && |
450 | TC_H_MAJ(tcm->tcm_info) != tp->prio) | 457 | TC_H_MAJ(tcm->tcm_info) != tp->prio) |
451 | continue; | 458 | continue; |
@@ -468,10 +475,10 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) | |||
468 | arg.skb = skb; | 475 | arg.skb = skb; |
469 | arg.cb = cb; | 476 | arg.cb = cb; |
470 | arg.w.stop = 0; | 477 | arg.w.stop = 0; |
471 | arg.w.skip = cb->args[1]-1; | 478 | arg.w.skip = cb->args[1] - 1; |
472 | arg.w.count = 0; | 479 | arg.w.count = 0; |
473 | tp->ops->walk(tp, &arg.w); | 480 | tp->ops->walk(tp, &arg.w); |
474 | cb->args[1] = arg.w.count+1; | 481 | cb->args[1] = arg.w.count + 1; |
475 | if (arg.w.stop) | 482 | if (arg.w.stop) |
476 | break; | 483 | break; |
477 | } | 484 | } |
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index f23d9155b1ef..8be8872dd571 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -21,14 +21,12 @@ | |||
21 | #include <net/act_api.h> | 21 | #include <net/act_api.h> |
22 | #include <net/pkt_cls.h> | 22 | #include <net/pkt_cls.h> |
23 | 23 | ||
24 | struct basic_head | 24 | struct basic_head { |
25 | { | ||
26 | u32 hgenerator; | 25 | u32 hgenerator; |
27 | struct list_head flist; | 26 | struct list_head flist; |
28 | }; | 27 | }; |
29 | 28 | ||
30 | struct basic_filter | 29 | struct basic_filter { |
31 | { | ||
32 | u32 handle; | 30 | u32 handle; |
33 | struct tcf_exts exts; | 31 | struct tcf_exts exts; |
34 | struct tcf_ematch_tree ematches; | 32 | struct tcf_ematch_tree ematches; |
@@ -92,8 +90,7 @@ static int basic_init(struct tcf_proto *tp) | |||
92 | return 0; | 90 | return 0; |
93 | } | 91 | } |
94 | 92 | ||
95 | static inline void basic_delete_filter(struct tcf_proto *tp, | 93 | static void basic_delete_filter(struct tcf_proto *tp, struct basic_filter *f) |
96 | struct basic_filter *f) | ||
97 | { | 94 | { |
98 | tcf_unbind_filter(tp, &f->res); | 95 | tcf_unbind_filter(tp, &f->res); |
99 | tcf_exts_destroy(tp, &f->exts); | 96 | tcf_exts_destroy(tp, &f->exts); |
@@ -135,9 +132,9 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = { | |||
135 | [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED }, | 132 | [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED }, |
136 | }; | 133 | }; |
137 | 134 | ||
138 | static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f, | 135 | static int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f, |
139 | unsigned long base, struct nlattr **tb, | 136 | unsigned long base, struct nlattr **tb, |
140 | struct nlattr *est) | 137 | struct nlattr *est) |
141 | { | 138 | { |
142 | int err = -EINVAL; | 139 | int err = -EINVAL; |
143 | struct tcf_exts e; | 140 | struct tcf_exts e; |
@@ -203,7 +200,7 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle, | |||
203 | } while (--i > 0 && basic_get(tp, head->hgenerator)); | 200 | } while (--i > 0 && basic_get(tp, head->hgenerator)); |
204 | 201 | ||
205 | if (i <= 0) { | 202 | if (i <= 0) { |
206 | printk(KERN_ERR "Insufficient number of handles\n"); | 203 | pr_err("Insufficient number of handles\n"); |
207 | goto errout; | 204 | goto errout; |
208 | } | 205 | } |
209 | 206 | ||
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index d49c40fb7e09..32a335194ca5 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c | |||
@@ -56,7 +56,8 @@ static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss, | |||
56 | { | 56 | { |
57 | struct cgroup_cls_state *cs; | 57 | struct cgroup_cls_state *cs; |
58 | 58 | ||
59 | if (!(cs = kzalloc(sizeof(*cs), GFP_KERNEL))) | 59 | cs = kzalloc(sizeof(*cs), GFP_KERNEL); |
60 | if (!cs) | ||
60 | return ERR_PTR(-ENOMEM); | 61 | return ERR_PTR(-ENOMEM); |
61 | 62 | ||
62 | if (cgrp->parent) | 63 | if (cgrp->parent) |
@@ -94,8 +95,7 @@ static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp) | |||
94 | return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files)); | 95 | return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files)); |
95 | } | 96 | } |
96 | 97 | ||
97 | struct cls_cgroup_head | 98 | struct cls_cgroup_head { |
98 | { | ||
99 | u32 handle; | 99 | u32 handle; |
100 | struct tcf_exts exts; | 100 | struct tcf_exts exts; |
101 | struct tcf_ematch_tree ematches; | 101 | struct tcf_ematch_tree ematches; |
@@ -166,7 +166,7 @@ static int cls_cgroup_change(struct tcf_proto *tp, unsigned long base, | |||
166 | u32 handle, struct nlattr **tca, | 166 | u32 handle, struct nlattr **tca, |
167 | unsigned long *arg) | 167 | unsigned long *arg) |
168 | { | 168 | { |
169 | struct nlattr *tb[TCA_CGROUP_MAX+1]; | 169 | struct nlattr *tb[TCA_CGROUP_MAX + 1]; |
170 | struct cls_cgroup_head *head = tp->root; | 170 | struct cls_cgroup_head *head = tp->root; |
171 | struct tcf_ematch_tree t; | 171 | struct tcf_ematch_tree t; |
172 | struct tcf_exts e; | 172 | struct tcf_exts e; |
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 5b271a18bc3a..8ec01391d988 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c | |||
@@ -121,7 +121,7 @@ static u32 flow_get_proto_src(struct sk_buff *skb) | |||
121 | if (!pskb_network_may_pull(skb, sizeof(*iph))) | 121 | if (!pskb_network_may_pull(skb, sizeof(*iph))) |
122 | break; | 122 | break; |
123 | iph = ip_hdr(skb); | 123 | iph = ip_hdr(skb); |
124 | if (iph->frag_off & htons(IP_MF|IP_OFFSET)) | 124 | if (iph->frag_off & htons(IP_MF | IP_OFFSET)) |
125 | break; | 125 | break; |
126 | poff = proto_ports_offset(iph->protocol); | 126 | poff = proto_ports_offset(iph->protocol); |
127 | if (poff >= 0 && | 127 | if (poff >= 0 && |
@@ -163,7 +163,7 @@ static u32 flow_get_proto_dst(struct sk_buff *skb) | |||
163 | if (!pskb_network_may_pull(skb, sizeof(*iph))) | 163 | if (!pskb_network_may_pull(skb, sizeof(*iph))) |
164 | break; | 164 | break; |
165 | iph = ip_hdr(skb); | 165 | iph = ip_hdr(skb); |
166 | if (iph->frag_off & htons(IP_MF|IP_OFFSET)) | 166 | if (iph->frag_off & htons(IP_MF | IP_OFFSET)) |
167 | break; | 167 | break; |
168 | poff = proto_ports_offset(iph->protocol); | 168 | poff = proto_ports_offset(iph->protocol); |
169 | if (poff >= 0 && | 169 | if (poff >= 0 && |
@@ -276,7 +276,7 @@ fallback: | |||
276 | 276 | ||
277 | static u32 flow_get_rtclassid(const struct sk_buff *skb) | 277 | static u32 flow_get_rtclassid(const struct sk_buff *skb) |
278 | { | 278 | { |
279 | #ifdef CONFIG_NET_CLS_ROUTE | 279 | #ifdef CONFIG_IP_ROUTE_CLASSID |
280 | if (skb_dst(skb)) | 280 | if (skb_dst(skb)) |
281 | return skb_dst(skb)->tclassid; | 281 | return skb_dst(skb)->tclassid; |
282 | #endif | 282 | #endif |
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 93b0a7b6f9b4..26e7bc4ffb79 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
@@ -31,14 +31,12 @@ | |||
31 | 31 | ||
32 | #define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *)) | 32 | #define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *)) |
33 | 33 | ||
34 | struct fw_head | 34 | struct fw_head { |
35 | { | ||
36 | struct fw_filter *ht[HTSIZE]; | 35 | struct fw_filter *ht[HTSIZE]; |
37 | u32 mask; | 36 | u32 mask; |
38 | }; | 37 | }; |
39 | 38 | ||
40 | struct fw_filter | 39 | struct fw_filter { |
41 | { | ||
42 | struct fw_filter *next; | 40 | struct fw_filter *next; |
43 | u32 id; | 41 | u32 id; |
44 | struct tcf_result res; | 42 | struct tcf_result res; |
@@ -53,7 +51,7 @@ static const struct tcf_ext_map fw_ext_map = { | |||
53 | .police = TCA_FW_POLICE | 51 | .police = TCA_FW_POLICE |
54 | }; | 52 | }; |
55 | 53 | ||
56 | static __inline__ int fw_hash(u32 handle) | 54 | static inline int fw_hash(u32 handle) |
57 | { | 55 | { |
58 | if (HTSIZE == 4096) | 56 | if (HTSIZE == 4096) |
59 | return ((handle >> 24) & 0xFFF) ^ | 57 | return ((handle >> 24) & 0xFFF) ^ |
@@ -82,14 +80,14 @@ static __inline__ int fw_hash(u32 handle) | |||
82 | static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, | 80 | static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, |
83 | struct tcf_result *res) | 81 | struct tcf_result *res) |
84 | { | 82 | { |
85 | struct fw_head *head = (struct fw_head*)tp->root; | 83 | struct fw_head *head = (struct fw_head *)tp->root; |
86 | struct fw_filter *f; | 84 | struct fw_filter *f; |
87 | int r; | 85 | int r; |
88 | u32 id = skb->mark; | 86 | u32 id = skb->mark; |
89 | 87 | ||
90 | if (head != NULL) { | 88 | if (head != NULL) { |
91 | id &= head->mask; | 89 | id &= head->mask; |
92 | for (f=head->ht[fw_hash(id)]; f; f=f->next) { | 90 | for (f = head->ht[fw_hash(id)]; f; f = f->next) { |
93 | if (f->id == id) { | 91 | if (f->id == id) { |
94 | *res = f->res; | 92 | *res = f->res; |
95 | #ifdef CONFIG_NET_CLS_IND | 93 | #ifdef CONFIG_NET_CLS_IND |
@@ -105,7 +103,8 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, | |||
105 | } | 103 | } |
106 | } else { | 104 | } else { |
107 | /* old method */ | 105 | /* old method */ |
108 | if (id && (TC_H_MAJ(id) == 0 || !(TC_H_MAJ(id^tp->q->handle)))) { | 106 | if (id && (TC_H_MAJ(id) == 0 || |
107 | !(TC_H_MAJ(id ^ tp->q->handle)))) { | ||
109 | res->classid = id; | 108 | res->classid = id; |
110 | res->class = 0; | 109 | res->class = 0; |
111 | return 0; | 110 | return 0; |
@@ -117,13 +116,13 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, | |||
117 | 116 | ||
118 | static unsigned long fw_get(struct tcf_proto *tp, u32 handle) | 117 | static unsigned long fw_get(struct tcf_proto *tp, u32 handle) |
119 | { | 118 | { |
120 | struct fw_head *head = (struct fw_head*)tp->root; | 119 | struct fw_head *head = (struct fw_head *)tp->root; |
121 | struct fw_filter *f; | 120 | struct fw_filter *f; |
122 | 121 | ||
123 | if (head == NULL) | 122 | if (head == NULL) |
124 | return 0; | 123 | return 0; |
125 | 124 | ||
126 | for (f=head->ht[fw_hash(handle)]; f; f=f->next) { | 125 | for (f = head->ht[fw_hash(handle)]; f; f = f->next) { |
127 | if (f->id == handle) | 126 | if (f->id == handle) |
128 | return (unsigned long)f; | 127 | return (unsigned long)f; |
129 | } | 128 | } |
@@ -139,8 +138,7 @@ static int fw_init(struct tcf_proto *tp) | |||
139 | return 0; | 138 | return 0; |
140 | } | 139 | } |
141 | 140 | ||
142 | static inline void | 141 | static void fw_delete_filter(struct tcf_proto *tp, struct fw_filter *f) |
143 | fw_delete_filter(struct tcf_proto *tp, struct fw_filter *f) | ||
144 | { | 142 | { |
145 | tcf_unbind_filter(tp, &f->res); | 143 | tcf_unbind_filter(tp, &f->res); |
146 | tcf_exts_destroy(tp, &f->exts); | 144 | tcf_exts_destroy(tp, &f->exts); |
@@ -156,8 +154,8 @@ static void fw_destroy(struct tcf_proto *tp) | |||
156 | if (head == NULL) | 154 | if (head == NULL) |
157 | return; | 155 | return; |
158 | 156 | ||
159 | for (h=0; h<HTSIZE; h++) { | 157 | for (h = 0; h < HTSIZE; h++) { |
160 | while ((f=head->ht[h]) != NULL) { | 158 | while ((f = head->ht[h]) != NULL) { |
161 | head->ht[h] = f->next; | 159 | head->ht[h] = f->next; |
162 | fw_delete_filter(tp, f); | 160 | fw_delete_filter(tp, f); |
163 | } | 161 | } |
@@ -167,14 +165,14 @@ static void fw_destroy(struct tcf_proto *tp) | |||
167 | 165 | ||
168 | static int fw_delete(struct tcf_proto *tp, unsigned long arg) | 166 | static int fw_delete(struct tcf_proto *tp, unsigned long arg) |
169 | { | 167 | { |
170 | struct fw_head *head = (struct fw_head*)tp->root; | 168 | struct fw_head *head = (struct fw_head *)tp->root; |
171 | struct fw_filter *f = (struct fw_filter*)arg; | 169 | struct fw_filter *f = (struct fw_filter *)arg; |
172 | struct fw_filter **fp; | 170 | struct fw_filter **fp; |
173 | 171 | ||
174 | if (head == NULL || f == NULL) | 172 | if (head == NULL || f == NULL) |
175 | goto out; | 173 | goto out; |
176 | 174 | ||
177 | for (fp=&head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) { | 175 | for (fp = &head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) { |
178 | if (*fp == f) { | 176 | if (*fp == f) { |
179 | tcf_tree_lock(tp); | 177 | tcf_tree_lock(tp); |
180 | *fp = f->next; | 178 | *fp = f->next; |
@@ -240,7 +238,7 @@ static int fw_change(struct tcf_proto *tp, unsigned long base, | |||
240 | struct nlattr **tca, | 238 | struct nlattr **tca, |
241 | unsigned long *arg) | 239 | unsigned long *arg) |
242 | { | 240 | { |
243 | struct fw_head *head = (struct fw_head*)tp->root; | 241 | struct fw_head *head = (struct fw_head *)tp->root; |
244 | struct fw_filter *f = (struct fw_filter *) *arg; | 242 | struct fw_filter *f = (struct fw_filter *) *arg; |
245 | struct nlattr *opt = tca[TCA_OPTIONS]; | 243 | struct nlattr *opt = tca[TCA_OPTIONS]; |
246 | struct nlattr *tb[TCA_FW_MAX + 1]; | 244 | struct nlattr *tb[TCA_FW_MAX + 1]; |
@@ -302,7 +300,7 @@ errout: | |||
302 | 300 | ||
303 | static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) | 301 | static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) |
304 | { | 302 | { |
305 | struct fw_head *head = (struct fw_head*)tp->root; | 303 | struct fw_head *head = (struct fw_head *)tp->root; |
306 | int h; | 304 | int h; |
307 | 305 | ||
308 | if (head == NULL) | 306 | if (head == NULL) |
@@ -332,7 +330,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, | |||
332 | struct sk_buff *skb, struct tcmsg *t) | 330 | struct sk_buff *skb, struct tcmsg *t) |
333 | { | 331 | { |
334 | struct fw_head *head = (struct fw_head *)tp->root; | 332 | struct fw_head *head = (struct fw_head *)tp->root; |
335 | struct fw_filter *f = (struct fw_filter*)fh; | 333 | struct fw_filter *f = (struct fw_filter *)fh; |
336 | unsigned char *b = skb_tail_pointer(skb); | 334 | unsigned char *b = skb_tail_pointer(skb); |
337 | struct nlattr *nest; | 335 | struct nlattr *nest; |
338 | 336 | ||
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 694dcd85dec8..a907905376df 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c | |||
@@ -23,34 +23,30 @@ | |||
23 | #include <net/pkt_cls.h> | 23 | #include <net/pkt_cls.h> |
24 | 24 | ||
25 | /* | 25 | /* |
26 | 1. For now we assume that route tags < 256. | 26 | * 1. For now we assume that route tags < 256. |
27 | It allows to use direct table lookups, instead of hash tables. | 27 | * It allows to use direct table lookups, instead of hash tables. |
28 | 2. For now we assume that "from TAG" and "fromdev DEV" statements | 28 | * 2. For now we assume that "from TAG" and "fromdev DEV" statements |
29 | are mutually exclusive. | 29 | * are mutually exclusive. |
30 | 3. "to TAG from ANY" has higher priority, than "to ANY from XXX" | 30 | * 3. "to TAG from ANY" has higher priority, than "to ANY from XXX" |
31 | */ | 31 | */ |
32 | 32 | ||
33 | struct route4_fastmap | 33 | struct route4_fastmap { |
34 | { | ||
35 | struct route4_filter *filter; | 34 | struct route4_filter *filter; |
36 | u32 id; | 35 | u32 id; |
37 | int iif; | 36 | int iif; |
38 | }; | 37 | }; |
39 | 38 | ||
40 | struct route4_head | 39 | struct route4_head { |
41 | { | ||
42 | struct route4_fastmap fastmap[16]; | 40 | struct route4_fastmap fastmap[16]; |
43 | struct route4_bucket *table[256+1]; | 41 | struct route4_bucket *table[256 + 1]; |
44 | }; | 42 | }; |
45 | 43 | ||
46 | struct route4_bucket | 44 | struct route4_bucket { |
47 | { | ||
48 | /* 16 FROM buckets + 16 IIF buckets + 1 wildcard bucket */ | 45 | /* 16 FROM buckets + 16 IIF buckets + 1 wildcard bucket */ |
49 | struct route4_filter *ht[16+16+1]; | 46 | struct route4_filter *ht[16 + 16 + 1]; |
50 | }; | 47 | }; |
51 | 48 | ||
52 | struct route4_filter | 49 | struct route4_filter { |
53 | { | ||
54 | struct route4_filter *next; | 50 | struct route4_filter *next; |
55 | u32 id; | 51 | u32 id; |
56 | int iif; | 52 | int iif; |
@@ -61,20 +57,20 @@ struct route4_filter | |||
61 | struct route4_bucket *bkt; | 57 | struct route4_bucket *bkt; |
62 | }; | 58 | }; |
63 | 59 | ||
64 | #define ROUTE4_FAILURE ((struct route4_filter*)(-1L)) | 60 | #define ROUTE4_FAILURE ((struct route4_filter *)(-1L)) |
65 | 61 | ||
66 | static const struct tcf_ext_map route_ext_map = { | 62 | static const struct tcf_ext_map route_ext_map = { |
67 | .police = TCA_ROUTE4_POLICE, | 63 | .police = TCA_ROUTE4_POLICE, |
68 | .action = TCA_ROUTE4_ACT | 64 | .action = TCA_ROUTE4_ACT |
69 | }; | 65 | }; |
70 | 66 | ||
71 | static __inline__ int route4_fastmap_hash(u32 id, int iif) | 67 | static inline int route4_fastmap_hash(u32 id, int iif) |
72 | { | 68 | { |
73 | return id&0xF; | 69 | return id & 0xF; |
74 | } | 70 | } |
75 | 71 | ||
76 | static inline | 72 | static void |
77 | void route4_reset_fastmap(struct Qdisc *q, struct route4_head *head, u32 id) | 73 | route4_reset_fastmap(struct Qdisc *q, struct route4_head *head, u32 id) |
78 | { | 74 | { |
79 | spinlock_t *root_lock = qdisc_root_sleeping_lock(q); | 75 | spinlock_t *root_lock = qdisc_root_sleeping_lock(q); |
80 | 76 | ||
@@ -83,32 +79,33 @@ void route4_reset_fastmap(struct Qdisc *q, struct route4_head *head, u32 id) | |||
83 | spin_unlock_bh(root_lock); | 79 | spin_unlock_bh(root_lock); |
84 | } | 80 | } |
85 | 81 | ||
86 | static inline void | 82 | static void |
87 | route4_set_fastmap(struct route4_head *head, u32 id, int iif, | 83 | route4_set_fastmap(struct route4_head *head, u32 id, int iif, |
88 | struct route4_filter *f) | 84 | struct route4_filter *f) |
89 | { | 85 | { |
90 | int h = route4_fastmap_hash(id, iif); | 86 | int h = route4_fastmap_hash(id, iif); |
87 | |||
91 | head->fastmap[h].id = id; | 88 | head->fastmap[h].id = id; |
92 | head->fastmap[h].iif = iif; | 89 | head->fastmap[h].iif = iif; |
93 | head->fastmap[h].filter = f; | 90 | head->fastmap[h].filter = f; |
94 | } | 91 | } |
95 | 92 | ||
96 | static __inline__ int route4_hash_to(u32 id) | 93 | static inline int route4_hash_to(u32 id) |
97 | { | 94 | { |
98 | return id&0xFF; | 95 | return id & 0xFF; |
99 | } | 96 | } |
100 | 97 | ||
101 | static __inline__ int route4_hash_from(u32 id) | 98 | static inline int route4_hash_from(u32 id) |
102 | { | 99 | { |
103 | return (id>>16)&0xF; | 100 | return (id >> 16) & 0xF; |
104 | } | 101 | } |
105 | 102 | ||
106 | static __inline__ int route4_hash_iif(int iif) | 103 | static inline int route4_hash_iif(int iif) |
107 | { | 104 | { |
108 | return 16 + ((iif>>16)&0xF); | 105 | return 16 + ((iif >> 16) & 0xF); |
109 | } | 106 | } |
110 | 107 | ||
111 | static __inline__ int route4_hash_wild(void) | 108 | static inline int route4_hash_wild(void) |
112 | { | 109 | { |
113 | return 32; | 110 | return 32; |
114 | } | 111 | } |
@@ -131,21 +128,22 @@ static __inline__ int route4_hash_wild(void) | |||
131 | static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp, | 128 | static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp, |
132 | struct tcf_result *res) | 129 | struct tcf_result *res) |
133 | { | 130 | { |
134 | struct route4_head *head = (struct route4_head*)tp->root; | 131 | struct route4_head *head = (struct route4_head *)tp->root; |
135 | struct dst_entry *dst; | 132 | struct dst_entry *dst; |
136 | struct route4_bucket *b; | 133 | struct route4_bucket *b; |
137 | struct route4_filter *f; | 134 | struct route4_filter *f; |
138 | u32 id, h; | 135 | u32 id, h; |
139 | int iif, dont_cache = 0; | 136 | int iif, dont_cache = 0; |
140 | 137 | ||
141 | if ((dst = skb_dst(skb)) == NULL) | 138 | dst = skb_dst(skb); |
139 | if (!dst) | ||
142 | goto failure; | 140 | goto failure; |
143 | 141 | ||
144 | id = dst->tclassid; | 142 | id = dst->tclassid; |
145 | if (head == NULL) | 143 | if (head == NULL) |
146 | goto old_method; | 144 | goto old_method; |
147 | 145 | ||
148 | iif = ((struct rtable*)dst)->fl.iif; | 146 | iif = ((struct rtable *)dst)->rt_iif; |
149 | 147 | ||
150 | h = route4_fastmap_hash(id, iif); | 148 | h = route4_fastmap_hash(id, iif); |
151 | if (id == head->fastmap[h].id && | 149 | if (id == head->fastmap[h].id && |
@@ -161,7 +159,8 @@ static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp, | |||
161 | h = route4_hash_to(id); | 159 | h = route4_hash_to(id); |
162 | 160 | ||
163 | restart: | 161 | restart: |
164 | if ((b = head->table[h]) != NULL) { | 162 | b = head->table[h]; |
163 | if (b) { | ||
165 | for (f = b->ht[route4_hash_from(id)]; f; f = f->next) | 164 | for (f = b->ht[route4_hash_from(id)]; f; f = f->next) |
166 | if (f->id == id) | 165 | if (f->id == id) |
167 | ROUTE4_APPLY_RESULT(); | 166 | ROUTE4_APPLY_RESULT(); |
@@ -197,8 +196,9 @@ old_method: | |||
197 | 196 | ||
198 | static inline u32 to_hash(u32 id) | 197 | static inline u32 to_hash(u32 id) |
199 | { | 198 | { |
200 | u32 h = id&0xFF; | 199 | u32 h = id & 0xFF; |
201 | if (id&0x8000) | 200 | |
201 | if (id & 0x8000) | ||
202 | h += 256; | 202 | h += 256; |
203 | return h; | 203 | return h; |
204 | } | 204 | } |
@@ -211,17 +211,17 @@ static inline u32 from_hash(u32 id) | |||
211 | if (!(id & 0x8000)) { | 211 | if (!(id & 0x8000)) { |
212 | if (id > 255) | 212 | if (id > 255) |
213 | return 256; | 213 | return 256; |
214 | return id&0xF; | 214 | return id & 0xF; |
215 | } | 215 | } |
216 | return 16 + (id&0xF); | 216 | return 16 + (id & 0xF); |
217 | } | 217 | } |
218 | 218 | ||
219 | static unsigned long route4_get(struct tcf_proto *tp, u32 handle) | 219 | static unsigned long route4_get(struct tcf_proto *tp, u32 handle) |
220 | { | 220 | { |
221 | struct route4_head *head = (struct route4_head*)tp->root; | 221 | struct route4_head *head = (struct route4_head *)tp->root; |
222 | struct route4_bucket *b; | 222 | struct route4_bucket *b; |
223 | struct route4_filter *f; | 223 | struct route4_filter *f; |
224 | unsigned h1, h2; | 224 | unsigned int h1, h2; |
225 | 225 | ||
226 | if (!head) | 226 | if (!head) |
227 | return 0; | 227 | return 0; |
@@ -230,11 +230,12 @@ static unsigned long route4_get(struct tcf_proto *tp, u32 handle) | |||
230 | if (h1 > 256) | 230 | if (h1 > 256) |
231 | return 0; | 231 | return 0; |
232 | 232 | ||
233 | h2 = from_hash(handle>>16); | 233 | h2 = from_hash(handle >> 16); |
234 | if (h2 > 32) | 234 | if (h2 > 32) |
235 | return 0; | 235 | return 0; |
236 | 236 | ||
237 | if ((b = head->table[h1]) != NULL) { | 237 | b = head->table[h1]; |
238 | if (b) { | ||
238 | for (f = b->ht[h2]; f; f = f->next) | 239 | for (f = b->ht[h2]; f; f = f->next) |
239 | if (f->handle == handle) | 240 | if (f->handle == handle) |
240 | return (unsigned long)f; | 241 | return (unsigned long)f; |
@@ -251,7 +252,7 @@ static int route4_init(struct tcf_proto *tp) | |||
251 | return 0; | 252 | return 0; |
252 | } | 253 | } |
253 | 254 | ||
254 | static inline void | 255 | static void |
255 | route4_delete_filter(struct tcf_proto *tp, struct route4_filter *f) | 256 | route4_delete_filter(struct tcf_proto *tp, struct route4_filter *f) |
256 | { | 257 | { |
257 | tcf_unbind_filter(tp, &f->res); | 258 | tcf_unbind_filter(tp, &f->res); |
@@ -267,11 +268,12 @@ static void route4_destroy(struct tcf_proto *tp) | |||
267 | if (head == NULL) | 268 | if (head == NULL) |
268 | return; | 269 | return; |
269 | 270 | ||
270 | for (h1=0; h1<=256; h1++) { | 271 | for (h1 = 0; h1 <= 256; h1++) { |
271 | struct route4_bucket *b; | 272 | struct route4_bucket *b; |
272 | 273 | ||
273 | if ((b = head->table[h1]) != NULL) { | 274 | b = head->table[h1]; |
274 | for (h2=0; h2<=32; h2++) { | 275 | if (b) { |
276 | for (h2 = 0; h2 <= 32; h2++) { | ||
275 | struct route4_filter *f; | 277 | struct route4_filter *f; |
276 | 278 | ||
277 | while ((f = b->ht[h2]) != NULL) { | 279 | while ((f = b->ht[h2]) != NULL) { |
@@ -287,9 +289,9 @@ static void route4_destroy(struct tcf_proto *tp) | |||
287 | 289 | ||
288 | static int route4_delete(struct tcf_proto *tp, unsigned long arg) | 290 | static int route4_delete(struct tcf_proto *tp, unsigned long arg) |
289 | { | 291 | { |
290 | struct route4_head *head = (struct route4_head*)tp->root; | 292 | struct route4_head *head = (struct route4_head *)tp->root; |
291 | struct route4_filter **fp, *f = (struct route4_filter*)arg; | 293 | struct route4_filter **fp, *f = (struct route4_filter *)arg; |
292 | unsigned h = 0; | 294 | unsigned int h = 0; |
293 | struct route4_bucket *b; | 295 | struct route4_bucket *b; |
294 | int i; | 296 | int i; |
295 | 297 | ||
@@ -299,7 +301,7 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg) | |||
299 | h = f->handle; | 301 | h = f->handle; |
300 | b = f->bkt; | 302 | b = f->bkt; |
301 | 303 | ||
302 | for (fp = &b->ht[from_hash(h>>16)]; *fp; fp = &(*fp)->next) { | 304 | for (fp = &b->ht[from_hash(h >> 16)]; *fp; fp = &(*fp)->next) { |
303 | if (*fp == f) { | 305 | if (*fp == f) { |
304 | tcf_tree_lock(tp); | 306 | tcf_tree_lock(tp); |
305 | *fp = f->next; | 307 | *fp = f->next; |
@@ -310,7 +312,7 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg) | |||
310 | 312 | ||
311 | /* Strip tree */ | 313 | /* Strip tree */ |
312 | 314 | ||
313 | for (i=0; i<=32; i++) | 315 | for (i = 0; i <= 32; i++) |
314 | if (b->ht[i]) | 316 | if (b->ht[i]) |
315 | return 0; | 317 | return 0; |
316 | 318 | ||
@@ -380,7 +382,8 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base, | |||
380 | } | 382 | } |
381 | 383 | ||
382 | h1 = to_hash(nhandle); | 384 | h1 = to_hash(nhandle); |
383 | if ((b = head->table[h1]) == NULL) { | 385 | b = head->table[h1]; |
386 | if (!b) { | ||
384 | err = -ENOBUFS; | 387 | err = -ENOBUFS; |
385 | b = kzalloc(sizeof(struct route4_bucket), GFP_KERNEL); | 388 | b = kzalloc(sizeof(struct route4_bucket), GFP_KERNEL); |
386 | if (b == NULL) | 389 | if (b == NULL) |
@@ -391,6 +394,7 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base, | |||
391 | tcf_tree_unlock(tp); | 394 | tcf_tree_unlock(tp); |
392 | } else { | 395 | } else { |
393 | unsigned int h2 = from_hash(nhandle >> 16); | 396 | unsigned int h2 = from_hash(nhandle >> 16); |
397 | |||
394 | err = -EEXIST; | 398 | err = -EEXIST; |
395 | for (fp = b->ht[h2]; fp; fp = fp->next) | 399 | for (fp = b->ht[h2]; fp; fp = fp->next) |
396 | if (fp->handle == f->handle) | 400 | if (fp->handle == f->handle) |
@@ -444,7 +448,8 @@ static int route4_change(struct tcf_proto *tp, unsigned long base, | |||
444 | if (err < 0) | 448 | if (err < 0) |
445 | return err; | 449 | return err; |
446 | 450 | ||
447 | if ((f = (struct route4_filter*)*arg) != NULL) { | 451 | f = (struct route4_filter *)*arg; |
452 | if (f) { | ||
448 | if (f->handle != handle && handle) | 453 | if (f->handle != handle && handle) |
449 | return -EINVAL; | 454 | return -EINVAL; |
450 | 455 | ||
@@ -481,7 +486,7 @@ static int route4_change(struct tcf_proto *tp, unsigned long base, | |||
481 | 486 | ||
482 | reinsert: | 487 | reinsert: |
483 | h = from_hash(f->handle >> 16); | 488 | h = from_hash(f->handle >> 16); |
484 | for (fp = &f->bkt->ht[h]; (f1=*fp) != NULL; fp = &f1->next) | 489 | for (fp = &f->bkt->ht[h]; (f1 = *fp) != NULL; fp = &f1->next) |
485 | if (f->handle < f1->handle) | 490 | if (f->handle < f1->handle) |
486 | break; | 491 | break; |
487 | 492 | ||
@@ -492,7 +497,8 @@ reinsert: | |||
492 | if (old_handle && f->handle != old_handle) { | 497 | if (old_handle && f->handle != old_handle) { |
493 | th = to_hash(old_handle); | 498 | th = to_hash(old_handle); |
494 | h = from_hash(old_handle >> 16); | 499 | h = from_hash(old_handle >> 16); |
495 | if ((b = head->table[th]) != NULL) { | 500 | b = head->table[th]; |
501 | if (b) { | ||
496 | for (fp = &b->ht[h]; *fp; fp = &(*fp)->next) { | 502 | for (fp = &b->ht[h]; *fp; fp = &(*fp)->next) { |
497 | if (*fp == f) { | 503 | if (*fp == f) { |
498 | *fp = f->next; | 504 | *fp = f->next; |
@@ -515,7 +521,7 @@ errout: | |||
515 | static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg) | 521 | static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg) |
516 | { | 522 | { |
517 | struct route4_head *head = tp->root; | 523 | struct route4_head *head = tp->root; |
518 | unsigned h, h1; | 524 | unsigned int h, h1; |
519 | 525 | ||
520 | if (head == NULL) | 526 | if (head == NULL) |
521 | arg->stop = 1; | 527 | arg->stop = 1; |
@@ -549,7 +555,7 @@ static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg) | |||
549 | static int route4_dump(struct tcf_proto *tp, unsigned long fh, | 555 | static int route4_dump(struct tcf_proto *tp, unsigned long fh, |
550 | struct sk_buff *skb, struct tcmsg *t) | 556 | struct sk_buff *skb, struct tcmsg *t) |
551 | { | 557 | { |
552 | struct route4_filter *f = (struct route4_filter*)fh; | 558 | struct route4_filter *f = (struct route4_filter *)fh; |
553 | unsigned char *b = skb_tail_pointer(skb); | 559 | unsigned char *b = skb_tail_pointer(skb); |
554 | struct nlattr *nest; | 560 | struct nlattr *nest; |
555 | u32 id; | 561 | u32 id; |
@@ -563,15 +569,15 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh, | |||
563 | if (nest == NULL) | 569 | if (nest == NULL) |
564 | goto nla_put_failure; | 570 | goto nla_put_failure; |
565 | 571 | ||
566 | if (!(f->handle&0x8000)) { | 572 | if (!(f->handle & 0x8000)) { |
567 | id = f->id&0xFF; | 573 | id = f->id & 0xFF; |
568 | NLA_PUT_U32(skb, TCA_ROUTE4_TO, id); | 574 | NLA_PUT_U32(skb, TCA_ROUTE4_TO, id); |
569 | } | 575 | } |
570 | if (f->handle&0x80000000) { | 576 | if (f->handle & 0x80000000) { |
571 | if ((f->handle>>16) != 0xFFFF) | 577 | if ((f->handle >> 16) != 0xFFFF) |
572 | NLA_PUT_U32(skb, TCA_ROUTE4_IIF, f->iif); | 578 | NLA_PUT_U32(skb, TCA_ROUTE4_IIF, f->iif); |
573 | } else { | 579 | } else { |
574 | id = f->id>>16; | 580 | id = f->id >> 16; |
575 | NLA_PUT_U32(skb, TCA_ROUTE4_FROM, id); | 581 | NLA_PUT_U32(skb, TCA_ROUTE4_FROM, id); |
576 | } | 582 | } |
577 | if (f->res.classid) | 583 | if (f->res.classid) |
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 425a1790b048..402c44b241a3 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h | |||
@@ -66,28 +66,25 @@ | |||
66 | powerful classification engine. */ | 66 | powerful classification engine. */ |
67 | 67 | ||
68 | 68 | ||
69 | struct rsvp_head | 69 | struct rsvp_head { |
70 | { | ||
71 | u32 tmap[256/32]; | 70 | u32 tmap[256/32]; |
72 | u32 hgenerator; | 71 | u32 hgenerator; |
73 | u8 tgenerator; | 72 | u8 tgenerator; |
74 | struct rsvp_session *ht[256]; | 73 | struct rsvp_session *ht[256]; |
75 | }; | 74 | }; |
76 | 75 | ||
77 | struct rsvp_session | 76 | struct rsvp_session { |
78 | { | ||
79 | struct rsvp_session *next; | 77 | struct rsvp_session *next; |
80 | __be32 dst[RSVP_DST_LEN]; | 78 | __be32 dst[RSVP_DST_LEN]; |
81 | struct tc_rsvp_gpi dpi; | 79 | struct tc_rsvp_gpi dpi; |
82 | u8 protocol; | 80 | u8 protocol; |
83 | u8 tunnelid; | 81 | u8 tunnelid; |
84 | /* 16 (src,sport) hash slots, and one wildcard source slot */ | 82 | /* 16 (src,sport) hash slots, and one wildcard source slot */ |
85 | struct rsvp_filter *ht[16+1]; | 83 | struct rsvp_filter *ht[16 + 1]; |
86 | }; | 84 | }; |
87 | 85 | ||
88 | 86 | ||
89 | struct rsvp_filter | 87 | struct rsvp_filter { |
90 | { | ||
91 | struct rsvp_filter *next; | 88 | struct rsvp_filter *next; |
92 | __be32 src[RSVP_DST_LEN]; | 89 | __be32 src[RSVP_DST_LEN]; |
93 | struct tc_rsvp_gpi spi; | 90 | struct tc_rsvp_gpi spi; |
@@ -100,17 +97,19 @@ struct rsvp_filter | |||
100 | struct rsvp_session *sess; | 97 | struct rsvp_session *sess; |
101 | }; | 98 | }; |
102 | 99 | ||
103 | static __inline__ unsigned hash_dst(__be32 *dst, u8 protocol, u8 tunnelid) | 100 | static inline unsigned int hash_dst(__be32 *dst, u8 protocol, u8 tunnelid) |
104 | { | 101 | { |
105 | unsigned h = (__force __u32)dst[RSVP_DST_LEN-1]; | 102 | unsigned int h = (__force __u32)dst[RSVP_DST_LEN - 1]; |
103 | |||
106 | h ^= h>>16; | 104 | h ^= h>>16; |
107 | h ^= h>>8; | 105 | h ^= h>>8; |
108 | return (h ^ protocol ^ tunnelid) & 0xFF; | 106 | return (h ^ protocol ^ tunnelid) & 0xFF; |
109 | } | 107 | } |
110 | 108 | ||
111 | static __inline__ unsigned hash_src(__be32 *src) | 109 | static inline unsigned int hash_src(__be32 *src) |
112 | { | 110 | { |
113 | unsigned h = (__force __u32)src[RSVP_DST_LEN-1]; | 111 | unsigned int h = (__force __u32)src[RSVP_DST_LEN-1]; |
112 | |||
114 | h ^= h>>16; | 113 | h ^= h>>16; |
115 | h ^= h>>8; | 114 | h ^= h>>8; |
116 | h ^= h>>4; | 115 | h ^= h>>4; |
@@ -134,10 +133,10 @@ static struct tcf_ext_map rsvp_ext_map = { | |||
134 | static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp, | 133 | static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp, |
135 | struct tcf_result *res) | 134 | struct tcf_result *res) |
136 | { | 135 | { |
137 | struct rsvp_session **sht = ((struct rsvp_head*)tp->root)->ht; | 136 | struct rsvp_session **sht = ((struct rsvp_head *)tp->root)->ht; |
138 | struct rsvp_session *s; | 137 | struct rsvp_session *s; |
139 | struct rsvp_filter *f; | 138 | struct rsvp_filter *f; |
140 | unsigned h1, h2; | 139 | unsigned int h1, h2; |
141 | __be32 *dst, *src; | 140 | __be32 *dst, *src; |
142 | u8 protocol; | 141 | u8 protocol; |
143 | u8 tunnelid = 0; | 142 | u8 tunnelid = 0; |
@@ -162,13 +161,13 @@ restart: | |||
162 | src = &nhptr->saddr.s6_addr32[0]; | 161 | src = &nhptr->saddr.s6_addr32[0]; |
163 | dst = &nhptr->daddr.s6_addr32[0]; | 162 | dst = &nhptr->daddr.s6_addr32[0]; |
164 | protocol = nhptr->nexthdr; | 163 | protocol = nhptr->nexthdr; |
165 | xprt = ((u8*)nhptr) + sizeof(struct ipv6hdr); | 164 | xprt = ((u8 *)nhptr) + sizeof(struct ipv6hdr); |
166 | #else | 165 | #else |
167 | src = &nhptr->saddr; | 166 | src = &nhptr->saddr; |
168 | dst = &nhptr->daddr; | 167 | dst = &nhptr->daddr; |
169 | protocol = nhptr->protocol; | 168 | protocol = nhptr->protocol; |
170 | xprt = ((u8*)nhptr) + (nhptr->ihl<<2); | 169 | xprt = ((u8 *)nhptr) + (nhptr->ihl<<2); |
171 | if (nhptr->frag_off & htons(IP_MF|IP_OFFSET)) | 170 | if (nhptr->frag_off & htons(IP_MF | IP_OFFSET)) |
172 | return -1; | 171 | return -1; |
173 | #endif | 172 | #endif |
174 | 173 | ||
@@ -176,10 +175,10 @@ restart: | |||
176 | h2 = hash_src(src); | 175 | h2 = hash_src(src); |
177 | 176 | ||
178 | for (s = sht[h1]; s; s = s->next) { | 177 | for (s = sht[h1]; s; s = s->next) { |
179 | if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN-1] && | 178 | if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN - 1] && |
180 | protocol == s->protocol && | 179 | protocol == s->protocol && |
181 | !(s->dpi.mask & | 180 | !(s->dpi.mask & |
182 | (*(u32*)(xprt+s->dpi.offset)^s->dpi.key)) && | 181 | (*(u32 *)(xprt + s->dpi.offset) ^ s->dpi.key)) && |
183 | #if RSVP_DST_LEN == 4 | 182 | #if RSVP_DST_LEN == 4 |
184 | dst[0] == s->dst[0] && | 183 | dst[0] == s->dst[0] && |
185 | dst[1] == s->dst[1] && | 184 | dst[1] == s->dst[1] && |
@@ -188,8 +187,8 @@ restart: | |||
188 | tunnelid == s->tunnelid) { | 187 | tunnelid == s->tunnelid) { |
189 | 188 | ||
190 | for (f = s->ht[h2]; f; f = f->next) { | 189 | for (f = s->ht[h2]; f; f = f->next) { |
191 | if (src[RSVP_DST_LEN-1] == f->src[RSVP_DST_LEN-1] && | 190 | if (src[RSVP_DST_LEN-1] == f->src[RSVP_DST_LEN - 1] && |
192 | !(f->spi.mask & (*(u32*)(xprt+f->spi.offset)^f->spi.key)) | 191 | !(f->spi.mask & (*(u32 *)(xprt + f->spi.offset) ^ f->spi.key)) |
193 | #if RSVP_DST_LEN == 4 | 192 | #if RSVP_DST_LEN == 4 |
194 | && | 193 | && |
195 | src[0] == f->src[0] && | 194 | src[0] == f->src[0] && |
@@ -205,7 +204,7 @@ matched: | |||
205 | return 0; | 204 | return 0; |
206 | 205 | ||
207 | tunnelid = f->res.classid; | 206 | tunnelid = f->res.classid; |
208 | nhptr = (void*)(xprt + f->tunnelhdr - sizeof(*nhptr)); | 207 | nhptr = (void *)(xprt + f->tunnelhdr - sizeof(*nhptr)); |
209 | goto restart; | 208 | goto restart; |
210 | } | 209 | } |
211 | } | 210 | } |
@@ -224,11 +223,11 @@ matched: | |||
224 | 223 | ||
225 | static unsigned long rsvp_get(struct tcf_proto *tp, u32 handle) | 224 | static unsigned long rsvp_get(struct tcf_proto *tp, u32 handle) |
226 | { | 225 | { |
227 | struct rsvp_session **sht = ((struct rsvp_head*)tp->root)->ht; | 226 | struct rsvp_session **sht = ((struct rsvp_head *)tp->root)->ht; |
228 | struct rsvp_session *s; | 227 | struct rsvp_session *s; |
229 | struct rsvp_filter *f; | 228 | struct rsvp_filter *f; |
230 | unsigned h1 = handle&0xFF; | 229 | unsigned int h1 = handle & 0xFF; |
231 | unsigned h2 = (handle>>8)&0xFF; | 230 | unsigned int h2 = (handle >> 8) & 0xFF; |
232 | 231 | ||
233 | if (h2 > 16) | 232 | if (h2 > 16) |
234 | return 0; | 233 | return 0; |
@@ -258,7 +257,7 @@ static int rsvp_init(struct tcf_proto *tp) | |||
258 | return -ENOBUFS; | 257 | return -ENOBUFS; |
259 | } | 258 | } |
260 | 259 | ||
261 | static inline void | 260 | static void |
262 | rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f) | 261 | rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f) |
263 | { | 262 | { |
264 | tcf_unbind_filter(tp, &f->res); | 263 | tcf_unbind_filter(tp, &f->res); |
@@ -277,13 +276,13 @@ static void rsvp_destroy(struct tcf_proto *tp) | |||
277 | 276 | ||
278 | sht = data->ht; | 277 | sht = data->ht; |
279 | 278 | ||
280 | for (h1=0; h1<256; h1++) { | 279 | for (h1 = 0; h1 < 256; h1++) { |
281 | struct rsvp_session *s; | 280 | struct rsvp_session *s; |
282 | 281 | ||
283 | while ((s = sht[h1]) != NULL) { | 282 | while ((s = sht[h1]) != NULL) { |
284 | sht[h1] = s->next; | 283 | sht[h1] = s->next; |
285 | 284 | ||
286 | for (h2=0; h2<=16; h2++) { | 285 | for (h2 = 0; h2 <= 16; h2++) { |
287 | struct rsvp_filter *f; | 286 | struct rsvp_filter *f; |
288 | 287 | ||
289 | while ((f = s->ht[h2]) != NULL) { | 288 | while ((f = s->ht[h2]) != NULL) { |
@@ -299,13 +298,13 @@ static void rsvp_destroy(struct tcf_proto *tp) | |||
299 | 298 | ||
300 | static int rsvp_delete(struct tcf_proto *tp, unsigned long arg) | 299 | static int rsvp_delete(struct tcf_proto *tp, unsigned long arg) |
301 | { | 300 | { |
302 | struct rsvp_filter **fp, *f = (struct rsvp_filter*)arg; | 301 | struct rsvp_filter **fp, *f = (struct rsvp_filter *)arg; |
303 | unsigned h = f->handle; | 302 | unsigned int h = f->handle; |
304 | struct rsvp_session **sp; | 303 | struct rsvp_session **sp; |
305 | struct rsvp_session *s = f->sess; | 304 | struct rsvp_session *s = f->sess; |
306 | int i; | 305 | int i; |
307 | 306 | ||
308 | for (fp = &s->ht[(h>>8)&0xFF]; *fp; fp = &(*fp)->next) { | 307 | for (fp = &s->ht[(h >> 8) & 0xFF]; *fp; fp = &(*fp)->next) { |
309 | if (*fp == f) { | 308 | if (*fp == f) { |
310 | tcf_tree_lock(tp); | 309 | tcf_tree_lock(tp); |
311 | *fp = f->next; | 310 | *fp = f->next; |
@@ -314,12 +313,12 @@ static int rsvp_delete(struct tcf_proto *tp, unsigned long arg) | |||
314 | 313 | ||
315 | /* Strip tree */ | 314 | /* Strip tree */ |
316 | 315 | ||
317 | for (i=0; i<=16; i++) | 316 | for (i = 0; i <= 16; i++) |
318 | if (s->ht[i]) | 317 | if (s->ht[i]) |
319 | return 0; | 318 | return 0; |
320 | 319 | ||
321 | /* OK, session has no flows */ | 320 | /* OK, session has no flows */ |
322 | for (sp = &((struct rsvp_head*)tp->root)->ht[h&0xFF]; | 321 | for (sp = &((struct rsvp_head *)tp->root)->ht[h & 0xFF]; |
323 | *sp; sp = &(*sp)->next) { | 322 | *sp; sp = &(*sp)->next) { |
324 | if (*sp == s) { | 323 | if (*sp == s) { |
325 | tcf_tree_lock(tp); | 324 | tcf_tree_lock(tp); |
@@ -337,13 +336,14 @@ static int rsvp_delete(struct tcf_proto *tp, unsigned long arg) | |||
337 | return 0; | 336 | return 0; |
338 | } | 337 | } |
339 | 338 | ||
340 | static unsigned gen_handle(struct tcf_proto *tp, unsigned salt) | 339 | static unsigned int gen_handle(struct tcf_proto *tp, unsigned salt) |
341 | { | 340 | { |
342 | struct rsvp_head *data = tp->root; | 341 | struct rsvp_head *data = tp->root; |
343 | int i = 0xFFFF; | 342 | int i = 0xFFFF; |
344 | 343 | ||
345 | while (i-- > 0) { | 344 | while (i-- > 0) { |
346 | u32 h; | 345 | u32 h; |
346 | |||
347 | if ((data->hgenerator += 0x10000) == 0) | 347 | if ((data->hgenerator += 0x10000) == 0) |
348 | data->hgenerator = 0x10000; | 348 | data->hgenerator = 0x10000; |
349 | h = data->hgenerator|salt; | 349 | h = data->hgenerator|salt; |
@@ -355,10 +355,10 @@ static unsigned gen_handle(struct tcf_proto *tp, unsigned salt) | |||
355 | 355 | ||
356 | static int tunnel_bts(struct rsvp_head *data) | 356 | static int tunnel_bts(struct rsvp_head *data) |
357 | { | 357 | { |
358 | int n = data->tgenerator>>5; | 358 | int n = data->tgenerator >> 5; |
359 | u32 b = 1<<(data->tgenerator&0x1F); | 359 | u32 b = 1 << (data->tgenerator & 0x1F); |
360 | 360 | ||
361 | if (data->tmap[n]&b) | 361 | if (data->tmap[n] & b) |
362 | return 0; | 362 | return 0; |
363 | data->tmap[n] |= b; | 363 | data->tmap[n] |= b; |
364 | return 1; | 364 | return 1; |
@@ -372,10 +372,10 @@ static void tunnel_recycle(struct rsvp_head *data) | |||
372 | 372 | ||
373 | memset(tmap, 0, sizeof(tmap)); | 373 | memset(tmap, 0, sizeof(tmap)); |
374 | 374 | ||
375 | for (h1=0; h1<256; h1++) { | 375 | for (h1 = 0; h1 < 256; h1++) { |
376 | struct rsvp_session *s; | 376 | struct rsvp_session *s; |
377 | for (s = sht[h1]; s; s = s->next) { | 377 | for (s = sht[h1]; s; s = s->next) { |
378 | for (h2=0; h2<=16; h2++) { | 378 | for (h2 = 0; h2 <= 16; h2++) { |
379 | struct rsvp_filter *f; | 379 | struct rsvp_filter *f; |
380 | 380 | ||
381 | for (f = s->ht[h2]; f; f = f->next) { | 381 | for (f = s->ht[h2]; f; f = f->next) { |
@@ -395,8 +395,8 @@ static u32 gen_tunnel(struct rsvp_head *data) | |||
395 | { | 395 | { |
396 | int i, k; | 396 | int i, k; |
397 | 397 | ||
398 | for (k=0; k<2; k++) { | 398 | for (k = 0; k < 2; k++) { |
399 | for (i=255; i>0; i--) { | 399 | for (i = 255; i > 0; i--) { |
400 | if (++data->tgenerator == 0) | 400 | if (++data->tgenerator == 0) |
401 | data->tgenerator = 1; | 401 | data->tgenerator = 1; |
402 | if (tunnel_bts(data)) | 402 | if (tunnel_bts(data)) |
@@ -428,7 +428,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base, | |||
428 | struct nlattr *opt = tca[TCA_OPTIONS-1]; | 428 | struct nlattr *opt = tca[TCA_OPTIONS-1]; |
429 | struct nlattr *tb[TCA_RSVP_MAX + 1]; | 429 | struct nlattr *tb[TCA_RSVP_MAX + 1]; |
430 | struct tcf_exts e; | 430 | struct tcf_exts e; |
431 | unsigned h1, h2; | 431 | unsigned int h1, h2; |
432 | __be32 *dst; | 432 | __be32 *dst; |
433 | int err; | 433 | int err; |
434 | 434 | ||
@@ -443,7 +443,8 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base, | |||
443 | if (err < 0) | 443 | if (err < 0) |
444 | return err; | 444 | return err; |
445 | 445 | ||
446 | if ((f = (struct rsvp_filter*)*arg) != NULL) { | 446 | f = (struct rsvp_filter *)*arg; |
447 | if (f) { | ||
447 | /* Node exists: adjust only classid */ | 448 | /* Node exists: adjust only classid */ |
448 | 449 | ||
449 | if (f->handle != handle && handle) | 450 | if (f->handle != handle && handle) |
@@ -500,7 +501,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base, | |||
500 | goto errout; | 501 | goto errout; |
501 | } | 502 | } |
502 | 503 | ||
503 | for (sp = &data->ht[h1]; (s=*sp) != NULL; sp = &s->next) { | 504 | for (sp = &data->ht[h1]; (s = *sp) != NULL; sp = &s->next) { |
504 | if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN-1] && | 505 | if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN-1] && |
505 | pinfo && pinfo->protocol == s->protocol && | 506 | pinfo && pinfo->protocol == s->protocol && |
506 | memcmp(&pinfo->dpi, &s->dpi, sizeof(s->dpi)) == 0 && | 507 | memcmp(&pinfo->dpi, &s->dpi, sizeof(s->dpi)) == 0 && |
@@ -523,7 +524,7 @@ insert: | |||
523 | tcf_exts_change(tp, &f->exts, &e); | 524 | tcf_exts_change(tp, &f->exts, &e); |
524 | 525 | ||
525 | for (fp = &s->ht[h2]; *fp; fp = &(*fp)->next) | 526 | for (fp = &s->ht[h2]; *fp; fp = &(*fp)->next) |
526 | if (((*fp)->spi.mask&f->spi.mask) != f->spi.mask) | 527 | if (((*fp)->spi.mask & f->spi.mask) != f->spi.mask) |
527 | break; | 528 | break; |
528 | f->next = *fp; | 529 | f->next = *fp; |
529 | wmb(); | 530 | wmb(); |
@@ -567,7 +568,7 @@ errout2: | |||
567 | static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg) | 568 | static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg) |
568 | { | 569 | { |
569 | struct rsvp_head *head = tp->root; | 570 | struct rsvp_head *head = tp->root; |
570 | unsigned h, h1; | 571 | unsigned int h, h1; |
571 | 572 | ||
572 | if (arg->stop) | 573 | if (arg->stop) |
573 | return; | 574 | return; |
@@ -598,7 +599,7 @@ static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg) | |||
598 | static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, | 599 | static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, |
599 | struct sk_buff *skb, struct tcmsg *t) | 600 | struct sk_buff *skb, struct tcmsg *t) |
600 | { | 601 | { |
601 | struct rsvp_filter *f = (struct rsvp_filter*)fh; | 602 | struct rsvp_filter *f = (struct rsvp_filter *)fh; |
602 | struct rsvp_session *s; | 603 | struct rsvp_session *s; |
603 | unsigned char *b = skb_tail_pointer(skb); | 604 | unsigned char *b = skb_tail_pointer(skb); |
604 | struct nlattr *nest; | 605 | struct nlattr *nest; |
@@ -624,7 +625,7 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, | |||
624 | NLA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo); | 625 | NLA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo); |
625 | if (f->res.classid) | 626 | if (f->res.classid) |
626 | NLA_PUT_U32(skb, TCA_RSVP_CLASSID, f->res.classid); | 627 | NLA_PUT_U32(skb, TCA_RSVP_CLASSID, f->res.classid); |
627 | if (((f->handle>>8)&0xFF) != 16) | 628 | if (((f->handle >> 8) & 0xFF) != 16) |
628 | NLA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src); | 629 | NLA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src); |
629 | 630 | ||
630 | if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0) | 631 | if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0) |
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 20ef330bb918..36667fa64237 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -249,7 +249,7 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle, | |||
249 | * of the hashing index is below the threshold. | 249 | * of the hashing index is below the threshold. |
250 | */ | 250 | */ |
251 | if ((cp.mask >> cp.shift) < PERFECT_HASH_THRESHOLD) | 251 | if ((cp.mask >> cp.shift) < PERFECT_HASH_THRESHOLD) |
252 | cp.hash = (cp.mask >> cp.shift)+1; | 252 | cp.hash = (cp.mask >> cp.shift) + 1; |
253 | else | 253 | else |
254 | cp.hash = DEFAULT_HASH_SIZE; | 254 | cp.hash = DEFAULT_HASH_SIZE; |
255 | } | 255 | } |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index b0c2a82178af..3b93fc0c8955 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -42,8 +42,7 @@ | |||
42 | #include <net/act_api.h> | 42 | #include <net/act_api.h> |
43 | #include <net/pkt_cls.h> | 43 | #include <net/pkt_cls.h> |
44 | 44 | ||
45 | struct tc_u_knode | 45 | struct tc_u_knode { |
46 | { | ||
47 | struct tc_u_knode *next; | 46 | struct tc_u_knode *next; |
48 | u32 handle; | 47 | u32 handle; |
49 | struct tc_u_hnode *ht_up; | 48 | struct tc_u_hnode *ht_up; |
@@ -63,19 +62,17 @@ struct tc_u_knode | |||
63 | struct tc_u32_sel sel; | 62 | struct tc_u32_sel sel; |
64 | }; | 63 | }; |
65 | 64 | ||
66 | struct tc_u_hnode | 65 | struct tc_u_hnode { |
67 | { | ||
68 | struct tc_u_hnode *next; | 66 | struct tc_u_hnode *next; |
69 | u32 handle; | 67 | u32 handle; |
70 | u32 prio; | 68 | u32 prio; |
71 | struct tc_u_common *tp_c; | 69 | struct tc_u_common *tp_c; |
72 | int refcnt; | 70 | int refcnt; |
73 | unsigned divisor; | 71 | unsigned int divisor; |
74 | struct tc_u_knode *ht[1]; | 72 | struct tc_u_knode *ht[1]; |
75 | }; | 73 | }; |
76 | 74 | ||
77 | struct tc_u_common | 75 | struct tc_u_common { |
78 | { | ||
79 | struct tc_u_hnode *hlist; | 76 | struct tc_u_hnode *hlist; |
80 | struct Qdisc *q; | 77 | struct Qdisc *q; |
81 | int refcnt; | 78 | int refcnt; |
@@ -87,9 +84,11 @@ static const struct tcf_ext_map u32_ext_map = { | |||
87 | .police = TCA_U32_POLICE | 84 | .police = TCA_U32_POLICE |
88 | }; | 85 | }; |
89 | 86 | ||
90 | static __inline__ unsigned u32_hash_fold(__be32 key, struct tc_u32_sel *sel, u8 fshift) | 87 | static inline unsigned int u32_hash_fold(__be32 key, |
88 | const struct tc_u32_sel *sel, | ||
89 | u8 fshift) | ||
91 | { | 90 | { |
92 | unsigned h = ntohl(key & sel->hmask)>>fshift; | 91 | unsigned int h = ntohl(key & sel->hmask) >> fshift; |
93 | 92 | ||
94 | return h; | 93 | return h; |
95 | } | 94 | } |
@@ -101,7 +100,7 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re | |||
101 | unsigned int off; | 100 | unsigned int off; |
102 | } stack[TC_U32_MAXDEPTH]; | 101 | } stack[TC_U32_MAXDEPTH]; |
103 | 102 | ||
104 | struct tc_u_hnode *ht = (struct tc_u_hnode*)tp->root; | 103 | struct tc_u_hnode *ht = (struct tc_u_hnode *)tp->root; |
105 | unsigned int off = skb_network_offset(skb); | 104 | unsigned int off = skb_network_offset(skb); |
106 | struct tc_u_knode *n; | 105 | struct tc_u_knode *n; |
107 | int sdepth = 0; | 106 | int sdepth = 0; |
@@ -120,7 +119,7 @@ next_knode: | |||
120 | struct tc_u32_key *key = n->sel.keys; | 119 | struct tc_u32_key *key = n->sel.keys; |
121 | 120 | ||
122 | #ifdef CONFIG_CLS_U32_PERF | 121 | #ifdef CONFIG_CLS_U32_PERF |
123 | n->pf->rcnt +=1; | 122 | n->pf->rcnt += 1; |
124 | j = 0; | 123 | j = 0; |
125 | #endif | 124 | #endif |
126 | 125 | ||
@@ -133,14 +132,14 @@ next_knode: | |||
133 | } | 132 | } |
134 | #endif | 133 | #endif |
135 | 134 | ||
136 | for (i = n->sel.nkeys; i>0; i--, key++) { | 135 | for (i = n->sel.nkeys; i > 0; i--, key++) { |
137 | int toff = off + key->off + (off2 & key->offmask); | 136 | int toff = off + key->off + (off2 & key->offmask); |
138 | __be32 *data, _data; | 137 | __be32 *data, hdata; |
139 | 138 | ||
140 | if (skb_headroom(skb) + toff > INT_MAX) | 139 | if (skb_headroom(skb) + toff > INT_MAX) |
141 | goto out; | 140 | goto out; |
142 | 141 | ||
143 | data = skb_header_pointer(skb, toff, 4, &_data); | 142 | data = skb_header_pointer(skb, toff, 4, &hdata); |
144 | if (!data) | 143 | if (!data) |
145 | goto out; | 144 | goto out; |
146 | if ((*data ^ key->val) & key->mask) { | 145 | if ((*data ^ key->val) & key->mask) { |
@@ -148,13 +147,13 @@ next_knode: | |||
148 | goto next_knode; | 147 | goto next_knode; |
149 | } | 148 | } |
150 | #ifdef CONFIG_CLS_U32_PERF | 149 | #ifdef CONFIG_CLS_U32_PERF |
151 | n->pf->kcnts[j] +=1; | 150 | n->pf->kcnts[j] += 1; |
152 | j++; | 151 | j++; |
153 | #endif | 152 | #endif |
154 | } | 153 | } |
155 | if (n->ht_down == NULL) { | 154 | if (n->ht_down == NULL) { |
156 | check_terminal: | 155 | check_terminal: |
157 | if (n->sel.flags&TC_U32_TERMINAL) { | 156 | if (n->sel.flags & TC_U32_TERMINAL) { |
158 | 157 | ||
159 | *res = n->res; | 158 | *res = n->res; |
160 | #ifdef CONFIG_NET_CLS_IND | 159 | #ifdef CONFIG_NET_CLS_IND |
@@ -164,7 +163,7 @@ check_terminal: | |||
164 | } | 163 | } |
165 | #endif | 164 | #endif |
166 | #ifdef CONFIG_CLS_U32_PERF | 165 | #ifdef CONFIG_CLS_U32_PERF |
167 | n->pf->rhit +=1; | 166 | n->pf->rhit += 1; |
168 | #endif | 167 | #endif |
169 | r = tcf_exts_exec(skb, &n->exts, res); | 168 | r = tcf_exts_exec(skb, &n->exts, res); |
170 | if (r < 0) { | 169 | if (r < 0) { |
@@ -188,26 +187,26 @@ check_terminal: | |||
188 | ht = n->ht_down; | 187 | ht = n->ht_down; |
189 | sel = 0; | 188 | sel = 0; |
190 | if (ht->divisor) { | 189 | if (ht->divisor) { |
191 | __be32 *data, _data; | 190 | __be32 *data, hdata; |
192 | 191 | ||
193 | data = skb_header_pointer(skb, off + n->sel.hoff, 4, | 192 | data = skb_header_pointer(skb, off + n->sel.hoff, 4, |
194 | &_data); | 193 | &hdata); |
195 | if (!data) | 194 | if (!data) |
196 | goto out; | 195 | goto out; |
197 | sel = ht->divisor & u32_hash_fold(*data, &n->sel, | 196 | sel = ht->divisor & u32_hash_fold(*data, &n->sel, |
198 | n->fshift); | 197 | n->fshift); |
199 | } | 198 | } |
200 | if (!(n->sel.flags&(TC_U32_VAROFFSET|TC_U32_OFFSET|TC_U32_EAT))) | 199 | if (!(n->sel.flags & (TC_U32_VAROFFSET | TC_U32_OFFSET | TC_U32_EAT))) |
201 | goto next_ht; | 200 | goto next_ht; |
202 | 201 | ||
203 | if (n->sel.flags&(TC_U32_OFFSET|TC_U32_VAROFFSET)) { | 202 | if (n->sel.flags & (TC_U32_OFFSET | TC_U32_VAROFFSET)) { |
204 | off2 = n->sel.off + 3; | 203 | off2 = n->sel.off + 3; |
205 | if (n->sel.flags & TC_U32_VAROFFSET) { | 204 | if (n->sel.flags & TC_U32_VAROFFSET) { |
206 | __be16 *data, _data; | 205 | __be16 *data, hdata; |
207 | 206 | ||
208 | data = skb_header_pointer(skb, | 207 | data = skb_header_pointer(skb, |
209 | off + n->sel.offoff, | 208 | off + n->sel.offoff, |
210 | 2, &_data); | 209 | 2, &hdata); |
211 | if (!data) | 210 | if (!data) |
212 | goto out; | 211 | goto out; |
213 | off2 += ntohs(n->sel.offmask & *data) >> | 212 | off2 += ntohs(n->sel.offmask & *data) >> |
@@ -215,7 +214,7 @@ check_terminal: | |||
215 | } | 214 | } |
216 | off2 &= ~3; | 215 | off2 &= ~3; |
217 | } | 216 | } |
218 | if (n->sel.flags&TC_U32_EAT) { | 217 | if (n->sel.flags & TC_U32_EAT) { |
219 | off += off2; | 218 | off += off2; |
220 | off2 = 0; | 219 | off2 = 0; |
221 | } | 220 | } |
@@ -236,11 +235,11 @@ out: | |||
236 | 235 | ||
237 | deadloop: | 236 | deadloop: |
238 | if (net_ratelimit()) | 237 | if (net_ratelimit()) |
239 | printk(KERN_WARNING "cls_u32: dead loop\n"); | 238 | pr_warning("cls_u32: dead loop\n"); |
240 | return -1; | 239 | return -1; |
241 | } | 240 | } |
242 | 241 | ||
243 | static __inline__ struct tc_u_hnode * | 242 | static struct tc_u_hnode * |
244 | u32_lookup_ht(struct tc_u_common *tp_c, u32 handle) | 243 | u32_lookup_ht(struct tc_u_common *tp_c, u32 handle) |
245 | { | 244 | { |
246 | struct tc_u_hnode *ht; | 245 | struct tc_u_hnode *ht; |
@@ -252,10 +251,10 @@ u32_lookup_ht(struct tc_u_common *tp_c, u32 handle) | |||
252 | return ht; | 251 | return ht; |
253 | } | 252 | } |
254 | 253 | ||
255 | static __inline__ struct tc_u_knode * | 254 | static struct tc_u_knode * |
256 | u32_lookup_key(struct tc_u_hnode *ht, u32 handle) | 255 | u32_lookup_key(struct tc_u_hnode *ht, u32 handle) |
257 | { | 256 | { |
258 | unsigned sel; | 257 | unsigned int sel; |
259 | struct tc_u_knode *n = NULL; | 258 | struct tc_u_knode *n = NULL; |
260 | 259 | ||
261 | sel = TC_U32_HASH(handle); | 260 | sel = TC_U32_HASH(handle); |
@@ -300,7 +299,7 @@ static u32 gen_new_htid(struct tc_u_common *tp_c) | |||
300 | do { | 299 | do { |
301 | if (++tp_c->hgenerator == 0x7FF) | 300 | if (++tp_c->hgenerator == 0x7FF) |
302 | tp_c->hgenerator = 1; | 301 | tp_c->hgenerator = 1; |
303 | } while (--i>0 && u32_lookup_ht(tp_c, (tp_c->hgenerator|0x800)<<20)); | 302 | } while (--i > 0 && u32_lookup_ht(tp_c, (tp_c->hgenerator|0x800)<<20)); |
304 | 303 | ||
305 | return i > 0 ? (tp_c->hgenerator|0x800)<<20 : 0; | 304 | return i > 0 ? (tp_c->hgenerator|0x800)<<20 : 0; |
306 | } | 305 | } |
@@ -378,9 +377,9 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode* key) | |||
378 | static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht) | 377 | static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht) |
379 | { | 378 | { |
380 | struct tc_u_knode *n; | 379 | struct tc_u_knode *n; |
381 | unsigned h; | 380 | unsigned int h; |
382 | 381 | ||
383 | for (h=0; h<=ht->divisor; h++) { | 382 | for (h = 0; h <= ht->divisor; h++) { |
384 | while ((n = ht->ht[h]) != NULL) { | 383 | while ((n = ht->ht[h]) != NULL) { |
385 | ht->ht[h] = n->next; | 384 | ht->ht[h] = n->next; |
386 | 385 | ||
@@ -446,13 +445,13 @@ static void u32_destroy(struct tcf_proto *tp) | |||
446 | 445 | ||
447 | static int u32_delete(struct tcf_proto *tp, unsigned long arg) | 446 | static int u32_delete(struct tcf_proto *tp, unsigned long arg) |
448 | { | 447 | { |
449 | struct tc_u_hnode *ht = (struct tc_u_hnode*)arg; | 448 | struct tc_u_hnode *ht = (struct tc_u_hnode *)arg; |
450 | 449 | ||
451 | if (ht == NULL) | 450 | if (ht == NULL) |
452 | return 0; | 451 | return 0; |
453 | 452 | ||
454 | if (TC_U32_KEY(ht->handle)) | 453 | if (TC_U32_KEY(ht->handle)) |
455 | return u32_delete_key(tp, (struct tc_u_knode*)ht); | 454 | return u32_delete_key(tp, (struct tc_u_knode *)ht); |
456 | 455 | ||
457 | if (tp->root == ht) | 456 | if (tp->root == ht) |
458 | return -EINVAL; | 457 | return -EINVAL; |
@@ -470,14 +469,14 @@ static int u32_delete(struct tcf_proto *tp, unsigned long arg) | |||
470 | static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle) | 469 | static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle) |
471 | { | 470 | { |
472 | struct tc_u_knode *n; | 471 | struct tc_u_knode *n; |
473 | unsigned i = 0x7FF; | 472 | unsigned int i = 0x7FF; |
474 | 473 | ||
475 | for (n=ht->ht[TC_U32_HASH(handle)]; n; n = n->next) | 474 | for (n = ht->ht[TC_U32_HASH(handle)]; n; n = n->next) |
476 | if (i < TC_U32_NODE(n->handle)) | 475 | if (i < TC_U32_NODE(n->handle)) |
477 | i = TC_U32_NODE(n->handle); | 476 | i = TC_U32_NODE(n->handle); |
478 | i++; | 477 | i++; |
479 | 478 | ||
480 | return handle|(i>0xFFF ? 0xFFF : i); | 479 | return handle | (i > 0xFFF ? 0xFFF : i); |
481 | } | 480 | } |
482 | 481 | ||
483 | static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = { | 482 | static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = { |
@@ -566,7 +565,8 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, | |||
566 | if (err < 0) | 565 | if (err < 0) |
567 | return err; | 566 | return err; |
568 | 567 | ||
569 | if ((n = (struct tc_u_knode*)*arg) != NULL) { | 568 | n = (struct tc_u_knode *)*arg; |
569 | if (n) { | ||
570 | if (TC_U32_KEY(n->handle) == 0) | 570 | if (TC_U32_KEY(n->handle) == 0) |
571 | return -EINVAL; | 571 | return -EINVAL; |
572 | 572 | ||
@@ -574,7 +574,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, | |||
574 | } | 574 | } |
575 | 575 | ||
576 | if (tb[TCA_U32_DIVISOR]) { | 576 | if (tb[TCA_U32_DIVISOR]) { |
577 | unsigned divisor = nla_get_u32(tb[TCA_U32_DIVISOR]); | 577 | unsigned int divisor = nla_get_u32(tb[TCA_U32_DIVISOR]); |
578 | 578 | ||
579 | if (--divisor > 0x100) | 579 | if (--divisor > 0x100) |
580 | return -EINVAL; | 580 | return -EINVAL; |
@@ -585,7 +585,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, | |||
585 | if (handle == 0) | 585 | if (handle == 0) |
586 | return -ENOMEM; | 586 | return -ENOMEM; |
587 | } | 587 | } |
588 | ht = kzalloc(sizeof(*ht) + divisor*sizeof(void*), GFP_KERNEL); | 588 | ht = kzalloc(sizeof(*ht) + divisor*sizeof(void *), GFP_KERNEL); |
589 | if (ht == NULL) | 589 | if (ht == NULL) |
590 | return -ENOBUFS; | 590 | return -ENOBUFS; |
591 | ht->tp_c = tp_c; | 591 | ht->tp_c = tp_c; |
@@ -683,7 +683,7 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg) | |||
683 | struct tc_u_common *tp_c = tp->data; | 683 | struct tc_u_common *tp_c = tp->data; |
684 | struct tc_u_hnode *ht; | 684 | struct tc_u_hnode *ht; |
685 | struct tc_u_knode *n; | 685 | struct tc_u_knode *n; |
686 | unsigned h; | 686 | unsigned int h; |
687 | 687 | ||
688 | if (arg->stop) | 688 | if (arg->stop) |
689 | return; | 689 | return; |
@@ -717,7 +717,7 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg) | |||
717 | static int u32_dump(struct tcf_proto *tp, unsigned long fh, | 717 | static int u32_dump(struct tcf_proto *tp, unsigned long fh, |
718 | struct sk_buff *skb, struct tcmsg *t) | 718 | struct sk_buff *skb, struct tcmsg *t) |
719 | { | 719 | { |
720 | struct tc_u_knode *n = (struct tc_u_knode*)fh; | 720 | struct tc_u_knode *n = (struct tc_u_knode *)fh; |
721 | struct nlattr *nest; | 721 | struct nlattr *nest; |
722 | 722 | ||
723 | if (n == NULL) | 723 | if (n == NULL) |
@@ -730,8 +730,9 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, | |||
730 | goto nla_put_failure; | 730 | goto nla_put_failure; |
731 | 731 | ||
732 | if (TC_U32_KEY(n->handle) == 0) { | 732 | if (TC_U32_KEY(n->handle) == 0) { |
733 | struct tc_u_hnode *ht = (struct tc_u_hnode*)fh; | 733 | struct tc_u_hnode *ht = (struct tc_u_hnode *)fh; |
734 | u32 divisor = ht->divisor+1; | 734 | u32 divisor = ht->divisor + 1; |
735 | |||
735 | NLA_PUT_U32(skb, TCA_U32_DIVISOR, divisor); | 736 | NLA_PUT_U32(skb, TCA_U32_DIVISOR, divisor); |
736 | } else { | 737 | } else { |
737 | NLA_PUT(skb, TCA_U32_SEL, | 738 | NLA_PUT(skb, TCA_U32_SEL, |
@@ -755,7 +756,7 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, | |||
755 | goto nla_put_failure; | 756 | goto nla_put_failure; |
756 | 757 | ||
757 | #ifdef CONFIG_NET_CLS_IND | 758 | #ifdef CONFIG_NET_CLS_IND |
758 | if(strlen(n->indev)) | 759 | if (strlen(n->indev)) |
759 | NLA_PUT_STRING(skb, TCA_U32_INDEV, n->indev); | 760 | NLA_PUT_STRING(skb, TCA_U32_INDEV, n->indev); |
760 | #endif | 761 | #endif |
761 | #ifdef CONFIG_CLS_U32_PERF | 762 | #ifdef CONFIG_CLS_U32_PERF |
diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c index bc450397487a..1c8360a2752a 100644 --- a/net/sched/em_cmp.c +++ b/net/sched/em_cmp.c | |||
@@ -33,40 +33,41 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em, | |||
33 | return 0; | 33 | return 0; |
34 | 34 | ||
35 | switch (cmp->align) { | 35 | switch (cmp->align) { |
36 | case TCF_EM_ALIGN_U8: | 36 | case TCF_EM_ALIGN_U8: |
37 | val = *ptr; | 37 | val = *ptr; |
38 | break; | 38 | break; |
39 | 39 | ||
40 | case TCF_EM_ALIGN_U16: | 40 | case TCF_EM_ALIGN_U16: |
41 | val = get_unaligned_be16(ptr); | 41 | val = get_unaligned_be16(ptr); |
42 | 42 | ||
43 | if (cmp_needs_transformation(cmp)) | 43 | if (cmp_needs_transformation(cmp)) |
44 | val = be16_to_cpu(val); | 44 | val = be16_to_cpu(val); |
45 | break; | 45 | break; |
46 | 46 | ||
47 | case TCF_EM_ALIGN_U32: | 47 | case TCF_EM_ALIGN_U32: |
48 | /* Worth checking boundries? The branching seems | 48 | /* Worth checking boundries? The branching seems |
49 | * to get worse. Visit again. */ | 49 | * to get worse. Visit again. |
50 | val = get_unaligned_be32(ptr); | 50 | */ |
51 | val = get_unaligned_be32(ptr); | ||
51 | 52 | ||
52 | if (cmp_needs_transformation(cmp)) | 53 | if (cmp_needs_transformation(cmp)) |
53 | val = be32_to_cpu(val); | 54 | val = be32_to_cpu(val); |
54 | break; | 55 | break; |
55 | 56 | ||
56 | default: | 57 | default: |
57 | return 0; | 58 | return 0; |
58 | } | 59 | } |
59 | 60 | ||
60 | if (cmp->mask) | 61 | if (cmp->mask) |
61 | val &= cmp->mask; | 62 | val &= cmp->mask; |
62 | 63 | ||
63 | switch (cmp->opnd) { | 64 | switch (cmp->opnd) { |
64 | case TCF_EM_OPND_EQ: | 65 | case TCF_EM_OPND_EQ: |
65 | return val == cmp->val; | 66 | return val == cmp->val; |
66 | case TCF_EM_OPND_LT: | 67 | case TCF_EM_OPND_LT: |
67 | return val < cmp->val; | 68 | return val < cmp->val; |
68 | case TCF_EM_OPND_GT: | 69 | case TCF_EM_OPND_GT: |
69 | return val > cmp->val; | 70 | return val > cmp->val; |
70 | } | 71 | } |
71 | 72 | ||
72 | return 0; | 73 | return 0; |
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 34da5e29ea1a..49130e8abff0 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c | |||
@@ -47,7 +47,7 @@ | |||
47 | * on the meta type. Obviously, the length of the data must also | 47 | * on the meta type. Obviously, the length of the data must also |
48 | * be provided for non-numeric types. | 48 | * be provided for non-numeric types. |
49 | * | 49 | * |
50 | * Additionaly, type dependant modifiers such as shift operators | 50 | * Additionally, type dependent modifiers such as shift operators |
51 | * or mask may be applied to extend the functionaliy. As of now, | 51 | * or mask may be applied to extend the functionaliy. As of now, |
52 | * the variable length type supports shifting the byte string to | 52 | * the variable length type supports shifting the byte string to |
53 | * the right, eating up any number of octets and thus supporting | 53 | * the right, eating up any number of octets and thus supporting |
@@ -73,21 +73,18 @@ | |||
73 | #include <net/pkt_cls.h> | 73 | #include <net/pkt_cls.h> |
74 | #include <net/sock.h> | 74 | #include <net/sock.h> |
75 | 75 | ||
76 | struct meta_obj | 76 | struct meta_obj { |
77 | { | ||
78 | unsigned long value; | 77 | unsigned long value; |
79 | unsigned int len; | 78 | unsigned int len; |
80 | }; | 79 | }; |
81 | 80 | ||
82 | struct meta_value | 81 | struct meta_value { |
83 | { | ||
84 | struct tcf_meta_val hdr; | 82 | struct tcf_meta_val hdr; |
85 | unsigned long val; | 83 | unsigned long val; |
86 | unsigned int len; | 84 | unsigned int len; |
87 | }; | 85 | }; |
88 | 86 | ||
89 | struct meta_match | 87 | struct meta_match { |
90 | { | ||
91 | struct meta_value lvalue; | 88 | struct meta_value lvalue; |
92 | struct meta_value rvalue; | 89 | struct meta_value rvalue; |
93 | }; | 90 | }; |
@@ -255,7 +252,7 @@ META_COLLECTOR(int_rtclassid) | |||
255 | if (unlikely(skb_dst(skb) == NULL)) | 252 | if (unlikely(skb_dst(skb) == NULL)) |
256 | *err = -1; | 253 | *err = -1; |
257 | else | 254 | else |
258 | #ifdef CONFIG_NET_CLS_ROUTE | 255 | #ifdef CONFIG_IP_ROUTE_CLASSID |
259 | dst->value = skb_dst(skb)->tclassid; | 256 | dst->value = skb_dst(skb)->tclassid; |
260 | #else | 257 | #else |
261 | dst->value = 0; | 258 | dst->value = 0; |
@@ -267,7 +264,7 @@ META_COLLECTOR(int_rtiif) | |||
267 | if (unlikely(skb_rtable(skb) == NULL)) | 264 | if (unlikely(skb_rtable(skb) == NULL)) |
268 | *err = -1; | 265 | *err = -1; |
269 | else | 266 | else |
270 | dst->value = skb_rtable(skb)->fl.iif; | 267 | dst->value = skb_rtable(skb)->rt_iif; |
271 | } | 268 | } |
272 | 269 | ||
273 | /************************************************************************** | 270 | /************************************************************************** |
@@ -404,7 +401,7 @@ META_COLLECTOR(int_sk_sndbuf) | |||
404 | META_COLLECTOR(int_sk_alloc) | 401 | META_COLLECTOR(int_sk_alloc) |
405 | { | 402 | { |
406 | SKIP_NONLOCAL(skb); | 403 | SKIP_NONLOCAL(skb); |
407 | dst->value = skb->sk->sk_allocation; | 404 | dst->value = (__force int) skb->sk->sk_allocation; |
408 | } | 405 | } |
409 | 406 | ||
410 | META_COLLECTOR(int_sk_route_caps) | 407 | META_COLLECTOR(int_sk_route_caps) |
@@ -483,8 +480,7 @@ META_COLLECTOR(int_sk_write_pend) | |||
483 | * Meta value collectors assignment table | 480 | * Meta value collectors assignment table |
484 | **************************************************************************/ | 481 | **************************************************************************/ |
485 | 482 | ||
486 | struct meta_ops | 483 | struct meta_ops { |
487 | { | ||
488 | void (*get)(struct sk_buff *, struct tcf_pkt_info *, | 484 | void (*get)(struct sk_buff *, struct tcf_pkt_info *, |
489 | struct meta_value *, struct meta_obj *, int *); | 485 | struct meta_value *, struct meta_obj *, int *); |
490 | }; | 486 | }; |
@@ -494,7 +490,7 @@ struct meta_ops | |||
494 | 490 | ||
495 | /* Meta value operations table listing all meta value collectors and | 491 | /* Meta value operations table listing all meta value collectors and |
496 | * assigns them to a type and meta id. */ | 492 | * assigns them to a type and meta id. */ |
497 | static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { | 493 | static struct meta_ops __meta_ops[TCF_META_TYPE_MAX + 1][TCF_META_ID_MAX + 1] = { |
498 | [TCF_META_TYPE_VAR] = { | 494 | [TCF_META_TYPE_VAR] = { |
499 | [META_ID(DEV)] = META_FUNC(var_dev), | 495 | [META_ID(DEV)] = META_FUNC(var_dev), |
500 | [META_ID(SK_BOUND_IF)] = META_FUNC(var_sk_bound_if), | 496 | [META_ID(SK_BOUND_IF)] = META_FUNC(var_sk_bound_if), |
@@ -550,7 +546,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { | |||
550 | } | 546 | } |
551 | }; | 547 | }; |
552 | 548 | ||
553 | static inline struct meta_ops * meta_ops(struct meta_value *val) | 549 | static inline struct meta_ops *meta_ops(struct meta_value *val) |
554 | { | 550 | { |
555 | return &__meta_ops[meta_type(val)][meta_id(val)]; | 551 | return &__meta_ops[meta_type(val)][meta_id(val)]; |
556 | } | 552 | } |
@@ -649,9 +645,8 @@ static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv) | |||
649 | { | 645 | { |
650 | if (v->len == sizeof(unsigned long)) | 646 | if (v->len == sizeof(unsigned long)) |
651 | NLA_PUT(skb, tlv, sizeof(unsigned long), &v->val); | 647 | NLA_PUT(skb, tlv, sizeof(unsigned long), &v->val); |
652 | else if (v->len == sizeof(u32)) { | 648 | else if (v->len == sizeof(u32)) |
653 | NLA_PUT_U32(skb, tlv, v->val); | 649 | NLA_PUT_U32(skb, tlv, v->val); |
654 | } | ||
655 | 650 | ||
656 | return 0; | 651 | return 0; |
657 | 652 | ||
@@ -663,8 +658,7 @@ nla_put_failure: | |||
663 | * Type specific operations table | 658 | * Type specific operations table |
664 | **************************************************************************/ | 659 | **************************************************************************/ |
665 | 660 | ||
666 | struct meta_type_ops | 661 | struct meta_type_ops { |
667 | { | ||
668 | void (*destroy)(struct meta_value *); | 662 | void (*destroy)(struct meta_value *); |
669 | int (*compare)(struct meta_obj *, struct meta_obj *); | 663 | int (*compare)(struct meta_obj *, struct meta_obj *); |
670 | int (*change)(struct meta_value *, struct nlattr *); | 664 | int (*change)(struct meta_value *, struct nlattr *); |
@@ -672,7 +666,7 @@ struct meta_type_ops | |||
672 | int (*dump)(struct sk_buff *, struct meta_value *, int); | 666 | int (*dump)(struct sk_buff *, struct meta_value *, int); |
673 | }; | 667 | }; |
674 | 668 | ||
675 | static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX+1] = { | 669 | static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX + 1] = { |
676 | [TCF_META_TYPE_VAR] = { | 670 | [TCF_META_TYPE_VAR] = { |
677 | .destroy = meta_var_destroy, | 671 | .destroy = meta_var_destroy, |
678 | .compare = meta_var_compare, | 672 | .compare = meta_var_compare, |
@@ -688,7 +682,7 @@ static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX+1] = { | |||
688 | } | 682 | } |
689 | }; | 683 | }; |
690 | 684 | ||
691 | static inline struct meta_type_ops * meta_type_ops(struct meta_value *v) | 685 | static inline struct meta_type_ops *meta_type_ops(struct meta_value *v) |
692 | { | 686 | { |
693 | return &__meta_type_ops[meta_type(v)]; | 687 | return &__meta_type_ops[meta_type(v)]; |
694 | } | 688 | } |
@@ -713,7 +707,7 @@ static int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info, | |||
713 | return err; | 707 | return err; |
714 | 708 | ||
715 | if (meta_type_ops(v)->apply_extras) | 709 | if (meta_type_ops(v)->apply_extras) |
716 | meta_type_ops(v)->apply_extras(v, dst); | 710 | meta_type_ops(v)->apply_extras(v, dst); |
717 | 711 | ||
718 | return 0; | 712 | return 0; |
719 | } | 713 | } |
@@ -732,12 +726,12 @@ static int em_meta_match(struct sk_buff *skb, struct tcf_ematch *m, | |||
732 | r = meta_type_ops(&meta->lvalue)->compare(&l_value, &r_value); | 726 | r = meta_type_ops(&meta->lvalue)->compare(&l_value, &r_value); |
733 | 727 | ||
734 | switch (meta->lvalue.hdr.op) { | 728 | switch (meta->lvalue.hdr.op) { |
735 | case TCF_EM_OPND_EQ: | 729 | case TCF_EM_OPND_EQ: |
736 | return !r; | 730 | return !r; |
737 | case TCF_EM_OPND_LT: | 731 | case TCF_EM_OPND_LT: |
738 | return r < 0; | 732 | return r < 0; |
739 | case TCF_EM_OPND_GT: | 733 | case TCF_EM_OPND_GT: |
740 | return r > 0; | 734 | return r > 0; |
741 | } | 735 | } |
742 | 736 | ||
743 | return 0; | 737 | return 0; |
@@ -771,7 +765,7 @@ static inline int meta_change_data(struct meta_value *dst, struct nlattr *nla) | |||
771 | 765 | ||
772 | static inline int meta_is_supported(struct meta_value *val) | 766 | static inline int meta_is_supported(struct meta_value *val) |
773 | { | 767 | { |
774 | return (!meta_id(val) || meta_ops(val)->get); | 768 | return !meta_id(val) || meta_ops(val)->get; |
775 | } | 769 | } |
776 | 770 | ||
777 | static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = { | 771 | static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = { |
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c index 1a4176aee6e5..a3bed07a008b 100644 --- a/net/sched/em_nbyte.c +++ b/net/sched/em_nbyte.c | |||
@@ -18,8 +18,7 @@ | |||
18 | #include <linux/tc_ematch/tc_em_nbyte.h> | 18 | #include <linux/tc_ematch/tc_em_nbyte.h> |
19 | #include <net/pkt_cls.h> | 19 | #include <net/pkt_cls.h> |
20 | 20 | ||
21 | struct nbyte_data | 21 | struct nbyte_data { |
22 | { | ||
23 | struct tcf_em_nbyte hdr; | 22 | struct tcf_em_nbyte hdr; |
24 | char pattern[0]; | 23 | char pattern[0]; |
25 | }; | 24 | }; |
diff --git a/net/sched/em_text.c b/net/sched/em_text.c index ea8f566e720c..15d353d2e4be 100644 --- a/net/sched/em_text.c +++ b/net/sched/em_text.c | |||
@@ -19,8 +19,7 @@ | |||
19 | #include <linux/tc_ematch/tc_em_text.h> | 19 | #include <linux/tc_ematch/tc_em_text.h> |
20 | #include <net/pkt_cls.h> | 20 | #include <net/pkt_cls.h> |
21 | 21 | ||
22 | struct text_match | 22 | struct text_match { |
23 | { | ||
24 | u16 from_offset; | 23 | u16 from_offset; |
25 | u16 to_offset; | 24 | u16 to_offset; |
26 | u8 from_layer; | 25 | u8 from_layer; |
diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c index 953f1479f7da..797bdb88c010 100644 --- a/net/sched/em_u32.c +++ b/net/sched/em_u32.c | |||
@@ -35,7 +35,7 @@ static int em_u32_match(struct sk_buff *skb, struct tcf_ematch *em, | |||
35 | if (!tcf_valid_offset(skb, ptr, sizeof(u32))) | 35 | if (!tcf_valid_offset(skb, ptr, sizeof(u32))) |
36 | return 0; | 36 | return 0; |
37 | 37 | ||
38 | return !(((*(__be32*) ptr) ^ key->val) & key->mask); | 38 | return !(((*(__be32 *) ptr) ^ key->val) & key->mask); |
39 | } | 39 | } |
40 | 40 | ||
41 | static struct tcf_ematch_ops em_u32_ops = { | 41 | static struct tcf_ematch_ops em_u32_ops = { |
diff --git a/net/sched/ematch.c b/net/sched/ematch.c index 5e37da961f80..88d93eb92507 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c | |||
@@ -93,7 +93,7 @@ | |||
93 | static LIST_HEAD(ematch_ops); | 93 | static LIST_HEAD(ematch_ops); |
94 | static DEFINE_RWLOCK(ematch_mod_lock); | 94 | static DEFINE_RWLOCK(ematch_mod_lock); |
95 | 95 | ||
96 | static inline struct tcf_ematch_ops * tcf_em_lookup(u16 kind) | 96 | static struct tcf_ematch_ops *tcf_em_lookup(u16 kind) |
97 | { | 97 | { |
98 | struct tcf_ematch_ops *e = NULL; | 98 | struct tcf_ematch_ops *e = NULL; |
99 | 99 | ||
@@ -163,8 +163,8 @@ void tcf_em_unregister(struct tcf_ematch_ops *ops) | |||
163 | } | 163 | } |
164 | EXPORT_SYMBOL(tcf_em_unregister); | 164 | EXPORT_SYMBOL(tcf_em_unregister); |
165 | 165 | ||
166 | static inline struct tcf_ematch * tcf_em_get_match(struct tcf_ematch_tree *tree, | 166 | static inline struct tcf_ematch *tcf_em_get_match(struct tcf_ematch_tree *tree, |
167 | int index) | 167 | int index) |
168 | { | 168 | { |
169 | return &tree->matches[index]; | 169 | return &tree->matches[index]; |
170 | } | 170 | } |
@@ -184,7 +184,8 @@ static int tcf_em_validate(struct tcf_proto *tp, | |||
184 | 184 | ||
185 | if (em_hdr->kind == TCF_EM_CONTAINER) { | 185 | if (em_hdr->kind == TCF_EM_CONTAINER) { |
186 | /* Special ematch called "container", carries an index | 186 | /* Special ematch called "container", carries an index |
187 | * referencing an external ematch sequence. */ | 187 | * referencing an external ematch sequence. |
188 | */ | ||
188 | u32 ref; | 189 | u32 ref; |
189 | 190 | ||
190 | if (data_len < sizeof(ref)) | 191 | if (data_len < sizeof(ref)) |
@@ -195,7 +196,8 @@ static int tcf_em_validate(struct tcf_proto *tp, | |||
195 | goto errout; | 196 | goto errout; |
196 | 197 | ||
197 | /* We do not allow backward jumps to avoid loops and jumps | 198 | /* We do not allow backward jumps to avoid loops and jumps |
198 | * to our own position are of course illegal. */ | 199 | * to our own position are of course illegal. |
200 | */ | ||
199 | if (ref <= idx) | 201 | if (ref <= idx) |
200 | goto errout; | 202 | goto errout; |
201 | 203 | ||
@@ -208,7 +210,8 @@ static int tcf_em_validate(struct tcf_proto *tp, | |||
208 | * which automatically releases the reference again, therefore | 210 | * which automatically releases the reference again, therefore |
209 | * the module MUST not be given back under any circumstances | 211 | * the module MUST not be given back under any circumstances |
210 | * here. Be aware, the destroy function assumes that the | 212 | * here. Be aware, the destroy function assumes that the |
211 | * module is held if the ops field is non zero. */ | 213 | * module is held if the ops field is non zero. |
214 | */ | ||
212 | em->ops = tcf_em_lookup(em_hdr->kind); | 215 | em->ops = tcf_em_lookup(em_hdr->kind); |
213 | 216 | ||
214 | if (em->ops == NULL) { | 217 | if (em->ops == NULL) { |
@@ -221,7 +224,8 @@ static int tcf_em_validate(struct tcf_proto *tp, | |||
221 | if (em->ops) { | 224 | if (em->ops) { |
222 | /* We dropped the RTNL mutex in order to | 225 | /* We dropped the RTNL mutex in order to |
223 | * perform the module load. Tell the caller | 226 | * perform the module load. Tell the caller |
224 | * to replay the request. */ | 227 | * to replay the request. |
228 | */ | ||
225 | module_put(em->ops->owner); | 229 | module_put(em->ops->owner); |
226 | err = -EAGAIN; | 230 | err = -EAGAIN; |
227 | } | 231 | } |
@@ -230,7 +234,8 @@ static int tcf_em_validate(struct tcf_proto *tp, | |||
230 | } | 234 | } |
231 | 235 | ||
232 | /* ematch module provides expected length of data, so we | 236 | /* ematch module provides expected length of data, so we |
233 | * can do a basic sanity check. */ | 237 | * can do a basic sanity check. |
238 | */ | ||
234 | if (em->ops->datalen && data_len < em->ops->datalen) | 239 | if (em->ops->datalen && data_len < em->ops->datalen) |
235 | goto errout; | 240 | goto errout; |
236 | 241 | ||
@@ -246,7 +251,8 @@ static int tcf_em_validate(struct tcf_proto *tp, | |||
246 | * TCF_EM_SIMPLE may be specified stating that the | 251 | * TCF_EM_SIMPLE may be specified stating that the |
247 | * data only consists of a u32 integer and the module | 252 | * data only consists of a u32 integer and the module |
248 | * does not expected a memory reference but rather | 253 | * does not expected a memory reference but rather |
249 | * the value carried. */ | 254 | * the value carried. |
255 | */ | ||
250 | if (em_hdr->flags & TCF_EM_SIMPLE) { | 256 | if (em_hdr->flags & TCF_EM_SIMPLE) { |
251 | if (data_len < sizeof(u32)) | 257 | if (data_len < sizeof(u32)) |
252 | goto errout; | 258 | goto errout; |
@@ -334,7 +340,8 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla, | |||
334 | * The array of rt attributes is parsed in the order as they are | 340 | * The array of rt attributes is parsed in the order as they are |
335 | * provided, their type must be incremental from 1 to n. Even | 341 | * provided, their type must be incremental from 1 to n. Even |
336 | * if it does not serve any real purpose, a failure of sticking | 342 | * if it does not serve any real purpose, a failure of sticking |
337 | * to this policy will result in parsing failure. */ | 343 | * to this policy will result in parsing failure. |
344 | */ | ||
338 | for (idx = 0; nla_ok(rt_match, list_len); idx++) { | 345 | for (idx = 0; nla_ok(rt_match, list_len); idx++) { |
339 | err = -EINVAL; | 346 | err = -EINVAL; |
340 | 347 | ||
@@ -359,7 +366,8 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla, | |||
359 | /* Check if the number of matches provided by userspace actually | 366 | /* Check if the number of matches provided by userspace actually |
360 | * complies with the array of matches. The number was used for | 367 | * complies with the array of matches. The number was used for |
361 | * the validation of references and a mismatch could lead to | 368 | * the validation of references and a mismatch could lead to |
362 | * undefined references during the matching process. */ | 369 | * undefined references during the matching process. |
370 | */ | ||
363 | if (idx != tree_hdr->nmatches) { | 371 | if (idx != tree_hdr->nmatches) { |
364 | err = -EINVAL; | 372 | err = -EINVAL; |
365 | goto errout_abort; | 373 | goto errout_abort; |
@@ -449,7 +457,7 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv) | |||
449 | .flags = em->flags | 457 | .flags = em->flags |
450 | }; | 458 | }; |
451 | 459 | ||
452 | NLA_PUT(skb, i+1, sizeof(em_hdr), &em_hdr); | 460 | NLA_PUT(skb, i + 1, sizeof(em_hdr), &em_hdr); |
453 | 461 | ||
454 | if (em->ops && em->ops->dump) { | 462 | if (em->ops && em->ops->dump) { |
455 | if (em->ops->dump(skb, em) < 0) | 463 | if (em->ops->dump(skb, em) < 0) |
@@ -478,6 +486,7 @@ static inline int tcf_em_match(struct sk_buff *skb, struct tcf_ematch *em, | |||
478 | struct tcf_pkt_info *info) | 486 | struct tcf_pkt_info *info) |
479 | { | 487 | { |
480 | int r = em->ops->match(skb, em, info); | 488 | int r = em->ops->match(skb, em, info); |
489 | |||
481 | return tcf_em_is_inverted(em) ? !r : r; | 490 | return tcf_em_is_inverted(em) ? !r : r; |
482 | } | 491 | } |
483 | 492 | ||
@@ -527,8 +536,8 @@ pop_stack: | |||
527 | 536 | ||
528 | stack_overflow: | 537 | stack_overflow: |
529 | if (net_ratelimit()) | 538 | if (net_ratelimit()) |
530 | printk(KERN_WARNING "tc ematch: local stack overflow," | 539 | pr_warning("tc ematch: local stack overflow," |
531 | " increase NET_EMATCH_STACK\n"); | 540 | " increase NET_EMATCH_STACK\n"); |
532 | return -1; | 541 | return -1; |
533 | } | 542 | } |
534 | EXPORT_SYMBOL(__tcf_em_tree_match); | 543 | EXPORT_SYMBOL(__tcf_em_tree_match); |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index b22ca2d1cebc..7490f3f2db8b 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -187,7 +187,7 @@ int unregister_qdisc(struct Qdisc_ops *qops) | |||
187 | int err = -ENOENT; | 187 | int err = -ENOENT; |
188 | 188 | ||
189 | write_lock(&qdisc_mod_lock); | 189 | write_lock(&qdisc_mod_lock); |
190 | for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next) | 190 | for (qp = &qdisc_base; (q = *qp) != NULL; qp = &q->next) |
191 | if (q == qops) | 191 | if (q == qops) |
192 | break; | 192 | break; |
193 | if (q) { | 193 | if (q) { |
@@ -321,7 +321,9 @@ void qdisc_put_rtab(struct qdisc_rate_table *tab) | |||
321 | if (!tab || --tab->refcnt) | 321 | if (!tab || --tab->refcnt) |
322 | return; | 322 | return; |
323 | 323 | ||
324 | for (rtabp = &qdisc_rtab_list; (rtab=*rtabp) != NULL; rtabp = &rtab->next) { | 324 | for (rtabp = &qdisc_rtab_list; |
325 | (rtab = *rtabp) != NULL; | ||
326 | rtabp = &rtab->next) { | ||
325 | if (rtab == tab) { | 327 | if (rtab == tab) { |
326 | *rtabp = rtab->next; | 328 | *rtabp = rtab->next; |
327 | kfree(rtab); | 329 | kfree(rtab); |
@@ -396,6 +398,11 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt) | |||
396 | return stab; | 398 | return stab; |
397 | } | 399 | } |
398 | 400 | ||
401 | static void stab_kfree_rcu(struct rcu_head *head) | ||
402 | { | ||
403 | kfree(container_of(head, struct qdisc_size_table, rcu)); | ||
404 | } | ||
405 | |||
399 | void qdisc_put_stab(struct qdisc_size_table *tab) | 406 | void qdisc_put_stab(struct qdisc_size_table *tab) |
400 | { | 407 | { |
401 | if (!tab) | 408 | if (!tab) |
@@ -405,7 +412,7 @@ void qdisc_put_stab(struct qdisc_size_table *tab) | |||
405 | 412 | ||
406 | if (--tab->refcnt == 0) { | 413 | if (--tab->refcnt == 0) { |
407 | list_del(&tab->list); | 414 | list_del(&tab->list); |
408 | kfree(tab); | 415 | call_rcu_bh(&tab->rcu, stab_kfree_rcu); |
409 | } | 416 | } |
410 | 417 | ||
411 | spin_unlock(&qdisc_stab_lock); | 418 | spin_unlock(&qdisc_stab_lock); |
@@ -428,7 +435,7 @@ nla_put_failure: | |||
428 | return -1; | 435 | return -1; |
429 | } | 436 | } |
430 | 437 | ||
431 | void qdisc_calculate_pkt_len(struct sk_buff *skb, struct qdisc_size_table *stab) | 438 | void __qdisc_calculate_pkt_len(struct sk_buff *skb, const struct qdisc_size_table *stab) |
432 | { | 439 | { |
433 | int pkt_len, slot; | 440 | int pkt_len, slot; |
434 | 441 | ||
@@ -454,14 +461,13 @@ out: | |||
454 | pkt_len = 1; | 461 | pkt_len = 1; |
455 | qdisc_skb_cb(skb)->pkt_len = pkt_len; | 462 | qdisc_skb_cb(skb)->pkt_len = pkt_len; |
456 | } | 463 | } |
457 | EXPORT_SYMBOL(qdisc_calculate_pkt_len); | 464 | EXPORT_SYMBOL(__qdisc_calculate_pkt_len); |
458 | 465 | ||
459 | void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc) | 466 | void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc) |
460 | { | 467 | { |
461 | if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { | 468 | if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { |
462 | printk(KERN_WARNING | 469 | pr_warn("%s: %s qdisc %X: is non-work-conserving?\n", |
463 | "%s: %s qdisc %X: is non-work-conserving?\n", | 470 | txt, qdisc->ops->id, qdisc->handle >> 16); |
464 | txt, qdisc->ops->id, qdisc->handle >> 16); | ||
465 | qdisc->flags |= TCQ_F_WARN_NONWC; | 471 | qdisc->flags |= TCQ_F_WARN_NONWC; |
466 | } | 472 | } |
467 | } | 473 | } |
@@ -472,7 +478,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) | |||
472 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, | 478 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, |
473 | timer); | 479 | timer); |
474 | 480 | ||
475 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | 481 | qdisc_unthrottled(wd->qdisc); |
476 | __netif_schedule(qdisc_root(wd->qdisc)); | 482 | __netif_schedule(qdisc_root(wd->qdisc)); |
477 | 483 | ||
478 | return HRTIMER_NORESTART; | 484 | return HRTIMER_NORESTART; |
@@ -494,7 +500,7 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires) | |||
494 | &qdisc_root_sleeping(wd->qdisc)->state)) | 500 | &qdisc_root_sleeping(wd->qdisc)->state)) |
495 | return; | 501 | return; |
496 | 502 | ||
497 | wd->qdisc->flags |= TCQ_F_THROTTLED; | 503 | qdisc_throttled(wd->qdisc); |
498 | time = ktime_set(0, 0); | 504 | time = ktime_set(0, 0); |
499 | time = ktime_add_ns(time, PSCHED_TICKS2NS(expires)); | 505 | time = ktime_add_ns(time, PSCHED_TICKS2NS(expires)); |
500 | hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); | 506 | hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); |
@@ -504,7 +510,7 @@ EXPORT_SYMBOL(qdisc_watchdog_schedule); | |||
504 | void qdisc_watchdog_cancel(struct qdisc_watchdog *wd) | 510 | void qdisc_watchdog_cancel(struct qdisc_watchdog *wd) |
505 | { | 511 | { |
506 | hrtimer_cancel(&wd->timer); | 512 | hrtimer_cancel(&wd->timer); |
507 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | 513 | qdisc_unthrottled(wd->qdisc); |
508 | } | 514 | } |
509 | EXPORT_SYMBOL(qdisc_watchdog_cancel); | 515 | EXPORT_SYMBOL(qdisc_watchdog_cancel); |
510 | 516 | ||
@@ -625,7 +631,7 @@ static u32 qdisc_alloc_handle(struct net_device *dev) | |||
625 | autohandle = TC_H_MAKE(0x80000000U, 0); | 631 | autohandle = TC_H_MAKE(0x80000000U, 0); |
626 | } while (qdisc_lookup(dev, autohandle) && --i > 0); | 632 | } while (qdisc_lookup(dev, autohandle) && --i > 0); |
627 | 633 | ||
628 | return i>0 ? autohandle : 0; | 634 | return i > 0 ? autohandle : 0; |
629 | } | 635 | } |
630 | 636 | ||
631 | void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) | 637 | void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) |
@@ -834,7 +840,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, | |||
834 | err = PTR_ERR(stab); | 840 | err = PTR_ERR(stab); |
835 | goto err_out4; | 841 | goto err_out4; |
836 | } | 842 | } |
837 | sch->stab = stab; | 843 | rcu_assign_pointer(sch->stab, stab); |
838 | } | 844 | } |
839 | if (tca[TCA_RATE]) { | 845 | if (tca[TCA_RATE]) { |
840 | spinlock_t *root_lock; | 846 | spinlock_t *root_lock; |
@@ -874,7 +880,7 @@ err_out4: | |||
874 | * Any broken qdiscs that would require a ops->reset() here? | 880 | * Any broken qdiscs that would require a ops->reset() here? |
875 | * The qdisc was never in action so it shouldn't be necessary. | 881 | * The qdisc was never in action so it shouldn't be necessary. |
876 | */ | 882 | */ |
877 | qdisc_put_stab(sch->stab); | 883 | qdisc_put_stab(rtnl_dereference(sch->stab)); |
878 | if (ops->destroy) | 884 | if (ops->destroy) |
879 | ops->destroy(sch); | 885 | ops->destroy(sch); |
880 | goto err_out3; | 886 | goto err_out3; |
@@ -882,7 +888,7 @@ err_out4: | |||
882 | 888 | ||
883 | static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) | 889 | static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) |
884 | { | 890 | { |
885 | struct qdisc_size_table *stab = NULL; | 891 | struct qdisc_size_table *ostab, *stab = NULL; |
886 | int err = 0; | 892 | int err = 0; |
887 | 893 | ||
888 | if (tca[TCA_OPTIONS]) { | 894 | if (tca[TCA_OPTIONS]) { |
@@ -899,8 +905,9 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) | |||
899 | return PTR_ERR(stab); | 905 | return PTR_ERR(stab); |
900 | } | 906 | } |
901 | 907 | ||
902 | qdisc_put_stab(sch->stab); | 908 | ostab = rtnl_dereference(sch->stab); |
903 | sch->stab = stab; | 909 | rcu_assign_pointer(sch->stab, stab); |
910 | qdisc_put_stab(ostab); | ||
904 | 911 | ||
905 | if (tca[TCA_RATE]) { | 912 | if (tca[TCA_RATE]) { |
906 | /* NB: ignores errors from replace_estimator | 913 | /* NB: ignores errors from replace_estimator |
@@ -915,9 +922,8 @@ out: | |||
915 | return 0; | 922 | return 0; |
916 | } | 923 | } |
917 | 924 | ||
918 | struct check_loop_arg | 925 | struct check_loop_arg { |
919 | { | 926 | struct qdisc_walker w; |
920 | struct qdisc_walker w; | ||
921 | struct Qdisc *p; | 927 | struct Qdisc *p; |
922 | int depth; | 928 | int depth; |
923 | }; | 929 | }; |
@@ -970,7 +976,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
970 | struct Qdisc *p = NULL; | 976 | struct Qdisc *p = NULL; |
971 | int err; | 977 | int err; |
972 | 978 | ||
973 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) | 979 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); |
980 | if (!dev) | ||
974 | return -ENODEV; | 981 | return -ENODEV; |
975 | 982 | ||
976 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 983 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -980,12 +987,12 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
980 | if (clid) { | 987 | if (clid) { |
981 | if (clid != TC_H_ROOT) { | 988 | if (clid != TC_H_ROOT) { |
982 | if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) { | 989 | if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) { |
983 | if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL) | 990 | p = qdisc_lookup(dev, TC_H_MAJ(clid)); |
991 | if (!p) | ||
984 | return -ENOENT; | 992 | return -ENOENT; |
985 | q = qdisc_leaf(p, clid); | 993 | q = qdisc_leaf(p, clid); |
986 | } else { /* ingress */ | 994 | } else if (dev_ingress_queue(dev)) { |
987 | if (dev_ingress_queue(dev)) | 995 | q = dev_ingress_queue(dev)->qdisc_sleeping; |
988 | q = dev_ingress_queue(dev)->qdisc_sleeping; | ||
989 | } | 996 | } |
990 | } else { | 997 | } else { |
991 | q = dev->qdisc; | 998 | q = dev->qdisc; |
@@ -996,7 +1003,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
996 | if (tcm->tcm_handle && q->handle != tcm->tcm_handle) | 1003 | if (tcm->tcm_handle && q->handle != tcm->tcm_handle) |
997 | return -EINVAL; | 1004 | return -EINVAL; |
998 | } else { | 1005 | } else { |
999 | if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL) | 1006 | q = qdisc_lookup(dev, tcm->tcm_handle); |
1007 | if (!q) | ||
1000 | return -ENOENT; | 1008 | return -ENOENT; |
1001 | } | 1009 | } |
1002 | 1010 | ||
@@ -1008,7 +1016,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1008 | return -EINVAL; | 1016 | return -EINVAL; |
1009 | if (q->handle == 0) | 1017 | if (q->handle == 0) |
1010 | return -ENOENT; | 1018 | return -ENOENT; |
1011 | if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0) | 1019 | err = qdisc_graft(dev, p, skb, n, clid, NULL, q); |
1020 | if (err != 0) | ||
1012 | return err; | 1021 | return err; |
1013 | } else { | 1022 | } else { |
1014 | qdisc_notify(net, skb, n, clid, NULL, q); | 1023 | qdisc_notify(net, skb, n, clid, NULL, q); |
@@ -1017,7 +1026,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1017 | } | 1026 | } |
1018 | 1027 | ||
1019 | /* | 1028 | /* |
1020 | Create/change qdisc. | 1029 | * Create/change qdisc. |
1021 | */ | 1030 | */ |
1022 | 1031 | ||
1023 | static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | 1032 | static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) |
@@ -1036,7 +1045,8 @@ replay: | |||
1036 | clid = tcm->tcm_parent; | 1045 | clid = tcm->tcm_parent; |
1037 | q = p = NULL; | 1046 | q = p = NULL; |
1038 | 1047 | ||
1039 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) | 1048 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); |
1049 | if (!dev) | ||
1040 | return -ENODEV; | 1050 | return -ENODEV; |
1041 | 1051 | ||
1042 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1052 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1046,12 +1056,12 @@ replay: | |||
1046 | if (clid) { | 1056 | if (clid) { |
1047 | if (clid != TC_H_ROOT) { | 1057 | if (clid != TC_H_ROOT) { |
1048 | if (clid != TC_H_INGRESS) { | 1058 | if (clid != TC_H_INGRESS) { |
1049 | if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL) | 1059 | p = qdisc_lookup(dev, TC_H_MAJ(clid)); |
1060 | if (!p) | ||
1050 | return -ENOENT; | 1061 | return -ENOENT; |
1051 | q = qdisc_leaf(p, clid); | 1062 | q = qdisc_leaf(p, clid); |
1052 | } else { /* ingress */ | 1063 | } else if (dev_ingress_queue_create(dev)) { |
1053 | if (dev_ingress_queue_create(dev)) | 1064 | q = dev_ingress_queue(dev)->qdisc_sleeping; |
1054 | q = dev_ingress_queue(dev)->qdisc_sleeping; | ||
1055 | } | 1065 | } |
1056 | } else { | 1066 | } else { |
1057 | q = dev->qdisc; | 1067 | q = dev->qdisc; |
@@ -1063,13 +1073,14 @@ replay: | |||
1063 | 1073 | ||
1064 | if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) { | 1074 | if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) { |
1065 | if (tcm->tcm_handle) { | 1075 | if (tcm->tcm_handle) { |
1066 | if (q && !(n->nlmsg_flags&NLM_F_REPLACE)) | 1076 | if (q && !(n->nlmsg_flags & NLM_F_REPLACE)) |
1067 | return -EEXIST; | 1077 | return -EEXIST; |
1068 | if (TC_H_MIN(tcm->tcm_handle)) | 1078 | if (TC_H_MIN(tcm->tcm_handle)) |
1069 | return -EINVAL; | 1079 | return -EINVAL; |
1070 | if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL) | 1080 | q = qdisc_lookup(dev, tcm->tcm_handle); |
1081 | if (!q) | ||
1071 | goto create_n_graft; | 1082 | goto create_n_graft; |
1072 | if (n->nlmsg_flags&NLM_F_EXCL) | 1083 | if (n->nlmsg_flags & NLM_F_EXCL) |
1073 | return -EEXIST; | 1084 | return -EEXIST; |
1074 | if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) | 1085 | if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) |
1075 | return -EINVAL; | 1086 | return -EINVAL; |
@@ -1079,7 +1090,7 @@ replay: | |||
1079 | atomic_inc(&q->refcnt); | 1090 | atomic_inc(&q->refcnt); |
1080 | goto graft; | 1091 | goto graft; |
1081 | } else { | 1092 | } else { |
1082 | if (q == NULL) | 1093 | if (!q) |
1083 | goto create_n_graft; | 1094 | goto create_n_graft; |
1084 | 1095 | ||
1085 | /* This magic test requires explanation. | 1096 | /* This magic test requires explanation. |
@@ -1101,9 +1112,9 @@ replay: | |||
1101 | * For now we select create/graft, if | 1112 | * For now we select create/graft, if |
1102 | * user gave KIND, which does not match existing. | 1113 | * user gave KIND, which does not match existing. |
1103 | */ | 1114 | */ |
1104 | if ((n->nlmsg_flags&NLM_F_CREATE) && | 1115 | if ((n->nlmsg_flags & NLM_F_CREATE) && |
1105 | (n->nlmsg_flags&NLM_F_REPLACE) && | 1116 | (n->nlmsg_flags & NLM_F_REPLACE) && |
1106 | ((n->nlmsg_flags&NLM_F_EXCL) || | 1117 | ((n->nlmsg_flags & NLM_F_EXCL) || |
1107 | (tca[TCA_KIND] && | 1118 | (tca[TCA_KIND] && |
1108 | nla_strcmp(tca[TCA_KIND], q->ops->id)))) | 1119 | nla_strcmp(tca[TCA_KIND], q->ops->id)))) |
1109 | goto create_n_graft; | 1120 | goto create_n_graft; |
@@ -1118,7 +1129,7 @@ replay: | |||
1118 | /* Change qdisc parameters */ | 1129 | /* Change qdisc parameters */ |
1119 | if (q == NULL) | 1130 | if (q == NULL) |
1120 | return -ENOENT; | 1131 | return -ENOENT; |
1121 | if (n->nlmsg_flags&NLM_F_EXCL) | 1132 | if (n->nlmsg_flags & NLM_F_EXCL) |
1122 | return -EEXIST; | 1133 | return -EEXIST; |
1123 | if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) | 1134 | if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) |
1124 | return -EINVAL; | 1135 | return -EINVAL; |
@@ -1128,7 +1139,7 @@ replay: | |||
1128 | return err; | 1139 | return err; |
1129 | 1140 | ||
1130 | create_n_graft: | 1141 | create_n_graft: |
1131 | if (!(n->nlmsg_flags&NLM_F_CREATE)) | 1142 | if (!(n->nlmsg_flags & NLM_F_CREATE)) |
1132 | return -ENOENT; | 1143 | return -ENOENT; |
1133 | if (clid == TC_H_INGRESS) { | 1144 | if (clid == TC_H_INGRESS) { |
1134 | if (dev_ingress_queue(dev)) | 1145 | if (dev_ingress_queue(dev)) |
@@ -1175,6 +1186,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
1175 | struct nlmsghdr *nlh; | 1186 | struct nlmsghdr *nlh; |
1176 | unsigned char *b = skb_tail_pointer(skb); | 1187 | unsigned char *b = skb_tail_pointer(skb); |
1177 | struct gnet_dump d; | 1188 | struct gnet_dump d; |
1189 | struct qdisc_size_table *stab; | ||
1178 | 1190 | ||
1179 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); | 1191 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
1180 | tcm = NLMSG_DATA(nlh); | 1192 | tcm = NLMSG_DATA(nlh); |
@@ -1190,7 +1202,8 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
1190 | goto nla_put_failure; | 1202 | goto nla_put_failure; |
1191 | q->qstats.qlen = q->q.qlen; | 1203 | q->qstats.qlen = q->q.qlen; |
1192 | 1204 | ||
1193 | if (q->stab && qdisc_dump_stab(skb, q->stab) < 0) | 1205 | stab = rtnl_dereference(q->stab); |
1206 | if (stab && qdisc_dump_stab(skb, stab) < 0) | ||
1194 | goto nla_put_failure; | 1207 | goto nla_put_failure; |
1195 | 1208 | ||
1196 | if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, TCA_XSTATS, | 1209 | if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, TCA_XSTATS, |
@@ -1234,16 +1247,19 @@ static int qdisc_notify(struct net *net, struct sk_buff *oskb, | |||
1234 | return -ENOBUFS; | 1247 | return -ENOBUFS; |
1235 | 1248 | ||
1236 | if (old && !tc_qdisc_dump_ignore(old)) { | 1249 | if (old && !tc_qdisc_dump_ignore(old)) { |
1237 | if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, 0, RTM_DELQDISC) < 0) | 1250 | if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, |
1251 | 0, RTM_DELQDISC) < 0) | ||
1238 | goto err_out; | 1252 | goto err_out; |
1239 | } | 1253 | } |
1240 | if (new && !tc_qdisc_dump_ignore(new)) { | 1254 | if (new && !tc_qdisc_dump_ignore(new)) { |
1241 | if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0) | 1255 | if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, |
1256 | old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0) | ||
1242 | goto err_out; | 1257 | goto err_out; |
1243 | } | 1258 | } |
1244 | 1259 | ||
1245 | if (skb->len) | 1260 | if (skb->len) |
1246 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1261 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
1262 | n->nlmsg_flags & NLM_F_ECHO); | ||
1247 | 1263 | ||
1248 | err_out: | 1264 | err_out: |
1249 | kfree_skb(skb); | 1265 | kfree_skb(skb); |
@@ -1275,7 +1291,7 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb, | |||
1275 | q_idx++; | 1291 | q_idx++; |
1276 | continue; | 1292 | continue; |
1277 | } | 1293 | } |
1278 | if (!tc_qdisc_dump_ignore(q) && | 1294 | if (!tc_qdisc_dump_ignore(q) && |
1279 | tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, | 1295 | tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, |
1280 | cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) | 1296 | cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) |
1281 | goto done; | 1297 | goto done; |
@@ -1356,7 +1372,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1356 | u32 qid = TC_H_MAJ(clid); | 1372 | u32 qid = TC_H_MAJ(clid); |
1357 | int err; | 1373 | int err; |
1358 | 1374 | ||
1359 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) | 1375 | dev = __dev_get_by_index(net, tcm->tcm_ifindex); |
1376 | if (!dev) | ||
1360 | return -ENODEV; | 1377 | return -ENODEV; |
1361 | 1378 | ||
1362 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1379 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1391,9 +1408,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1391 | qid = dev->qdisc->handle; | 1408 | qid = dev->qdisc->handle; |
1392 | 1409 | ||
1393 | /* Now qid is genuine qdisc handle consistent | 1410 | /* Now qid is genuine qdisc handle consistent |
1394 | both with parent and child. | 1411 | * both with parent and child. |
1395 | 1412 | * | |
1396 | TC_H_MAJ(pid) still may be unspecified, complete it now. | 1413 | * TC_H_MAJ(pid) still may be unspecified, complete it now. |
1397 | */ | 1414 | */ |
1398 | if (pid) | 1415 | if (pid) |
1399 | pid = TC_H_MAKE(qid, pid); | 1416 | pid = TC_H_MAKE(qid, pid); |
@@ -1403,7 +1420,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1403 | } | 1420 | } |
1404 | 1421 | ||
1405 | /* OK. Locate qdisc */ | 1422 | /* OK. Locate qdisc */ |
1406 | if ((q = qdisc_lookup(dev, qid)) == NULL) | 1423 | q = qdisc_lookup(dev, qid); |
1424 | if (!q) | ||
1407 | return -ENOENT; | 1425 | return -ENOENT; |
1408 | 1426 | ||
1409 | /* An check that it supports classes */ | 1427 | /* An check that it supports classes */ |
@@ -1423,13 +1441,14 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1423 | 1441 | ||
1424 | if (cl == 0) { | 1442 | if (cl == 0) { |
1425 | err = -ENOENT; | 1443 | err = -ENOENT; |
1426 | if (n->nlmsg_type != RTM_NEWTCLASS || !(n->nlmsg_flags&NLM_F_CREATE)) | 1444 | if (n->nlmsg_type != RTM_NEWTCLASS || |
1445 | !(n->nlmsg_flags & NLM_F_CREATE)) | ||
1427 | goto out; | 1446 | goto out; |
1428 | } else { | 1447 | } else { |
1429 | switch (n->nlmsg_type) { | 1448 | switch (n->nlmsg_type) { |
1430 | case RTM_NEWTCLASS: | 1449 | case RTM_NEWTCLASS: |
1431 | err = -EEXIST; | 1450 | err = -EEXIST; |
1432 | if (n->nlmsg_flags&NLM_F_EXCL) | 1451 | if (n->nlmsg_flags & NLM_F_EXCL) |
1433 | goto out; | 1452 | goto out; |
1434 | break; | 1453 | break; |
1435 | case RTM_DELTCLASS: | 1454 | case RTM_DELTCLASS: |
@@ -1521,14 +1540,14 @@ static int tclass_notify(struct net *net, struct sk_buff *oskb, | |||
1521 | return -EINVAL; | 1540 | return -EINVAL; |
1522 | } | 1541 | } |
1523 | 1542 | ||
1524 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1543 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
1544 | n->nlmsg_flags & NLM_F_ECHO); | ||
1525 | } | 1545 | } |
1526 | 1546 | ||
1527 | struct qdisc_dump_args | 1547 | struct qdisc_dump_args { |
1528 | { | 1548 | struct qdisc_walker w; |
1529 | struct qdisc_walker w; | 1549 | struct sk_buff *skb; |
1530 | struct sk_buff *skb; | 1550 | struct netlink_callback *cb; |
1531 | struct netlink_callback *cb; | ||
1532 | }; | 1551 | }; |
1533 | 1552 | ||
1534 | static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walker *arg) | 1553 | static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walker *arg) |
@@ -1590,7 +1609,7 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb, | |||
1590 | 1609 | ||
1591 | static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | 1610 | static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) |
1592 | { | 1611 | { |
1593 | struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh); | 1612 | struct tcmsg *tcm = (struct tcmsg *)NLMSG_DATA(cb->nlh); |
1594 | struct net *net = sock_net(skb->sk); | 1613 | struct net *net = sock_net(skb->sk); |
1595 | struct netdev_queue *dev_queue; | 1614 | struct netdev_queue *dev_queue; |
1596 | struct net_device *dev; | 1615 | struct net_device *dev; |
@@ -1598,7 +1617,8 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1598 | 1617 | ||
1599 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) | 1618 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) |
1600 | return 0; | 1619 | return 0; |
1601 | if ((dev = dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) | 1620 | dev = dev_get_by_index(net, tcm->tcm_ifindex); |
1621 | if (!dev) | ||
1602 | return 0; | 1622 | return 0; |
1603 | 1623 | ||
1604 | s_t = cb->args[0]; | 1624 | s_t = cb->args[0]; |
@@ -1621,19 +1641,22 @@ done: | |||
1621 | } | 1641 | } |
1622 | 1642 | ||
1623 | /* Main classifier routine: scans classifier chain attached | 1643 | /* Main classifier routine: scans classifier chain attached |
1624 | to this qdisc, (optionally) tests for protocol and asks | 1644 | * to this qdisc, (optionally) tests for protocol and asks |
1625 | specific classifiers. | 1645 | * specific classifiers. |
1626 | */ | 1646 | */ |
1627 | int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, | 1647 | int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, |
1628 | struct tcf_result *res) | 1648 | struct tcf_result *res) |
1629 | { | 1649 | { |
1630 | __be16 protocol = skb->protocol; | 1650 | __be16 protocol = skb->protocol; |
1631 | int err = 0; | 1651 | int err; |
1632 | 1652 | ||
1633 | for (; tp; tp = tp->next) { | 1653 | for (; tp; tp = tp->next) { |
1634 | if ((tp->protocol == protocol || | 1654 | if (tp->protocol != protocol && |
1635 | tp->protocol == htons(ETH_P_ALL)) && | 1655 | tp->protocol != htons(ETH_P_ALL)) |
1636 | (err = tp->classify(skb, tp, res)) >= 0) { | 1656 | continue; |
1657 | err = tp->classify(skb, tp, res); | ||
1658 | |||
1659 | if (err >= 0) { | ||
1637 | #ifdef CONFIG_NET_CLS_ACT | 1660 | #ifdef CONFIG_NET_CLS_ACT |
1638 | if (err != TC_ACT_RECLASSIFY && skb->tc_verd) | 1661 | if (err != TC_ACT_RECLASSIFY && skb->tc_verd) |
1639 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0); | 1662 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0); |
@@ -1649,12 +1672,12 @@ int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, | |||
1649 | struct tcf_result *res) | 1672 | struct tcf_result *res) |
1650 | { | 1673 | { |
1651 | int err = 0; | 1674 | int err = 0; |
1652 | __be16 protocol; | ||
1653 | #ifdef CONFIG_NET_CLS_ACT | 1675 | #ifdef CONFIG_NET_CLS_ACT |
1676 | __be16 protocol; | ||
1654 | struct tcf_proto *otp = tp; | 1677 | struct tcf_proto *otp = tp; |
1655 | reclassify: | 1678 | reclassify: |
1656 | #endif | ||
1657 | protocol = skb->protocol; | 1679 | protocol = skb->protocol; |
1680 | #endif | ||
1658 | 1681 | ||
1659 | err = tc_classify_compat(skb, tp, res); | 1682 | err = tc_classify_compat(skb, tp, res); |
1660 | #ifdef CONFIG_NET_CLS_ACT | 1683 | #ifdef CONFIG_NET_CLS_ACT |
@@ -1664,11 +1687,11 @@ reclassify: | |||
1664 | 1687 | ||
1665 | if (verd++ >= MAX_REC_LOOP) { | 1688 | if (verd++ >= MAX_REC_LOOP) { |
1666 | if (net_ratelimit()) | 1689 | if (net_ratelimit()) |
1667 | printk(KERN_NOTICE | 1690 | pr_notice("%s: packet reclassify loop" |
1668 | "%s: packet reclassify loop" | ||
1669 | " rule prio %u protocol %02x\n", | 1691 | " rule prio %u protocol %02x\n", |
1670 | tp->q->ops->id, | 1692 | tp->q->ops->id, |
1671 | tp->prio & 0xffff, ntohs(tp->protocol)); | 1693 | tp->prio & 0xffff, |
1694 | ntohs(tp->protocol)); | ||
1672 | return TC_ACT_SHOT; | 1695 | return TC_ACT_SHOT; |
1673 | } | 1696 | } |
1674 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); | 1697 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); |
@@ -1761,7 +1784,7 @@ static int __init pktsched_init(void) | |||
1761 | 1784 | ||
1762 | err = register_pernet_subsys(&psched_net_ops); | 1785 | err = register_pernet_subsys(&psched_net_ops); |
1763 | if (err) { | 1786 | if (err) { |
1764 | printk(KERN_ERR "pktsched_init: " | 1787 | pr_err("pktsched_init: " |
1765 | "cannot initialize per netns operations\n"); | 1788 | "cannot initialize per netns operations\n"); |
1766 | return err; | 1789 | return err; |
1767 | } | 1790 | } |
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 943d733409d0..3f08158b8688 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
@@ -319,7 +319,7 @@ static int atm_tc_delete(struct Qdisc *sch, unsigned long arg) | |||
319 | * creation), and one for the reference held when calling delete. | 319 | * creation), and one for the reference held when calling delete. |
320 | */ | 320 | */ |
321 | if (flow->ref < 2) { | 321 | if (flow->ref < 2) { |
322 | printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n", flow->ref); | 322 | pr_err("atm_tc_delete: flow->ref == %d\n", flow->ref); |
323 | return -EINVAL; | 323 | return -EINVAL; |
324 | } | 324 | } |
325 | if (flow->ref > 2) | 325 | if (flow->ref > 2) |
@@ -384,12 +384,12 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
384 | } | 384 | } |
385 | } | 385 | } |
386 | flow = NULL; | 386 | flow = NULL; |
387 | done: | 387 | done: |
388 | ; | 388 | ; |
389 | } | 389 | } |
390 | if (!flow) | 390 | if (!flow) { |
391 | flow = &p->link; | 391 | flow = &p->link; |
392 | else { | 392 | } else { |
393 | if (flow->vcc) | 393 | if (flow->vcc) |
394 | ATM_SKB(skb)->atm_options = flow->vcc->atm_options; | 394 | ATM_SKB(skb)->atm_options = flow->vcc->atm_options; |
395 | /*@@@ looks good ... but it's not supposed to work :-) */ | 395 | /*@@@ looks good ... but it's not supposed to work :-) */ |
@@ -576,8 +576,7 @@ static void atm_tc_destroy(struct Qdisc *sch) | |||
576 | 576 | ||
577 | list_for_each_entry_safe(flow, tmp, &p->flows, list) { | 577 | list_for_each_entry_safe(flow, tmp, &p->flows, list) { |
578 | if (flow->ref > 1) | 578 | if (flow->ref > 1) |
579 | printk(KERN_ERR "atm_destroy: %p->ref = %d\n", flow, | 579 | pr_err("atm_destroy: %p->ref = %d\n", flow, flow->ref); |
580 | flow->ref); | ||
581 | atm_tc_put(sch, (unsigned long)flow); | 580 | atm_tc_put(sch, (unsigned long)flow); |
582 | } | 581 | } |
583 | tasklet_kill(&p->task); | 582 | tasklet_kill(&p->task); |
@@ -616,9 +615,8 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, | |||
616 | } | 615 | } |
617 | if (flow->excess) | 616 | if (flow->excess) |
618 | NLA_PUT_U32(skb, TCA_ATM_EXCESS, flow->classid); | 617 | NLA_PUT_U32(skb, TCA_ATM_EXCESS, flow->classid); |
619 | else { | 618 | else |
620 | NLA_PUT_U32(skb, TCA_ATM_EXCESS, 0); | 619 | NLA_PUT_U32(skb, TCA_ATM_EXCESS, 0); |
621 | } | ||
622 | 620 | ||
623 | nla_nest_end(skb, nest); | 621 | nla_nest_end(skb, nest); |
624 | return skb->len; | 622 | return skb->len; |
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 5f63ec58942c..24d94c097b35 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -72,8 +72,7 @@ | |||
72 | struct cbq_sched_data; | 72 | struct cbq_sched_data; |
73 | 73 | ||
74 | 74 | ||
75 | struct cbq_class | 75 | struct cbq_class { |
76 | { | ||
77 | struct Qdisc_class_common common; | 76 | struct Qdisc_class_common common; |
78 | struct cbq_class *next_alive; /* next class with backlog in this priority band */ | 77 | struct cbq_class *next_alive; /* next class with backlog in this priority band */ |
79 | 78 | ||
@@ -139,19 +138,18 @@ struct cbq_class | |||
139 | int refcnt; | 138 | int refcnt; |
140 | int filters; | 139 | int filters; |
141 | 140 | ||
142 | struct cbq_class *defaults[TC_PRIO_MAX+1]; | 141 | struct cbq_class *defaults[TC_PRIO_MAX + 1]; |
143 | }; | 142 | }; |
144 | 143 | ||
145 | struct cbq_sched_data | 144 | struct cbq_sched_data { |
146 | { | ||
147 | struct Qdisc_class_hash clhash; /* Hash table of all classes */ | 145 | struct Qdisc_class_hash clhash; /* Hash table of all classes */ |
148 | int nclasses[TC_CBQ_MAXPRIO+1]; | 146 | int nclasses[TC_CBQ_MAXPRIO + 1]; |
149 | unsigned quanta[TC_CBQ_MAXPRIO+1]; | 147 | unsigned int quanta[TC_CBQ_MAXPRIO + 1]; |
150 | 148 | ||
151 | struct cbq_class link; | 149 | struct cbq_class link; |
152 | 150 | ||
153 | unsigned activemask; | 151 | unsigned int activemask; |
154 | struct cbq_class *active[TC_CBQ_MAXPRIO+1]; /* List of all classes | 152 | struct cbq_class *active[TC_CBQ_MAXPRIO + 1]; /* List of all classes |
155 | with backlog */ | 153 | with backlog */ |
156 | 154 | ||
157 | #ifdef CONFIG_NET_CLS_ACT | 155 | #ifdef CONFIG_NET_CLS_ACT |
@@ -162,7 +160,7 @@ struct cbq_sched_data | |||
162 | int tx_len; | 160 | int tx_len; |
163 | psched_time_t now; /* Cached timestamp */ | 161 | psched_time_t now; /* Cached timestamp */ |
164 | psched_time_t now_rt; /* Cached real time */ | 162 | psched_time_t now_rt; /* Cached real time */ |
165 | unsigned pmask; | 163 | unsigned int pmask; |
166 | 164 | ||
167 | struct hrtimer delay_timer; | 165 | struct hrtimer delay_timer; |
168 | struct qdisc_watchdog watchdog; /* Watchdog timer, | 166 | struct qdisc_watchdog watchdog; /* Watchdog timer, |
@@ -175,9 +173,9 @@ struct cbq_sched_data | |||
175 | }; | 173 | }; |
176 | 174 | ||
177 | 175 | ||
178 | #define L2T(cl,len) qdisc_l2t((cl)->R_tab,len) | 176 | #define L2T(cl, len) qdisc_l2t((cl)->R_tab, len) |
179 | 177 | ||
180 | static __inline__ struct cbq_class * | 178 | static inline struct cbq_class * |
181 | cbq_class_lookup(struct cbq_sched_data *q, u32 classid) | 179 | cbq_class_lookup(struct cbq_sched_data *q, u32 classid) |
182 | { | 180 | { |
183 | struct Qdisc_class_common *clc; | 181 | struct Qdisc_class_common *clc; |
@@ -193,25 +191,27 @@ cbq_class_lookup(struct cbq_sched_data *q, u32 classid) | |||
193 | static struct cbq_class * | 191 | static struct cbq_class * |
194 | cbq_reclassify(struct sk_buff *skb, struct cbq_class *this) | 192 | cbq_reclassify(struct sk_buff *skb, struct cbq_class *this) |
195 | { | 193 | { |
196 | struct cbq_class *cl, *new; | 194 | struct cbq_class *cl; |
197 | 195 | ||
198 | for (cl = this->tparent; cl; cl = cl->tparent) | 196 | for (cl = this->tparent; cl; cl = cl->tparent) { |
199 | if ((new = cl->defaults[TC_PRIO_BESTEFFORT]) != NULL && new != this) | 197 | struct cbq_class *new = cl->defaults[TC_PRIO_BESTEFFORT]; |
200 | return new; | ||
201 | 198 | ||
199 | if (new != NULL && new != this) | ||
200 | return new; | ||
201 | } | ||
202 | return NULL; | 202 | return NULL; |
203 | } | 203 | } |
204 | 204 | ||
205 | #endif | 205 | #endif |
206 | 206 | ||
207 | /* Classify packet. The procedure is pretty complicated, but | 207 | /* Classify packet. The procedure is pretty complicated, but |
208 | it allows us to combine link sharing and priority scheduling | 208 | * it allows us to combine link sharing and priority scheduling |
209 | transparently. | 209 | * transparently. |
210 | 210 | * | |
211 | Namely, you can put link sharing rules (f.e. route based) at root of CBQ, | 211 | * Namely, you can put link sharing rules (f.e. route based) at root of CBQ, |
212 | so that it resolves to split nodes. Then packets are classified | 212 | * so that it resolves to split nodes. Then packets are classified |
213 | by logical priority, or a more specific classifier may be attached | 213 | * by logical priority, or a more specific classifier may be attached |
214 | to the split node. | 214 | * to the split node. |
215 | */ | 215 | */ |
216 | 216 | ||
217 | static struct cbq_class * | 217 | static struct cbq_class * |
@@ -227,7 +227,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
227 | /* | 227 | /* |
228 | * Step 1. If skb->priority points to one of our classes, use it. | 228 | * Step 1. If skb->priority points to one of our classes, use it. |
229 | */ | 229 | */ |
230 | if (TC_H_MAJ(prio^sch->handle) == 0 && | 230 | if (TC_H_MAJ(prio ^ sch->handle) == 0 && |
231 | (cl = cbq_class_lookup(q, prio)) != NULL) | 231 | (cl = cbq_class_lookup(q, prio)) != NULL) |
232 | return cl; | 232 | return cl; |
233 | 233 | ||
@@ -243,10 +243,11 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
243 | (result = tc_classify_compat(skb, head->filter_list, &res)) < 0) | 243 | (result = tc_classify_compat(skb, head->filter_list, &res)) < 0) |
244 | goto fallback; | 244 | goto fallback; |
245 | 245 | ||
246 | if ((cl = (void*)res.class) == NULL) { | 246 | cl = (void *)res.class; |
247 | if (!cl) { | ||
247 | if (TC_H_MAJ(res.classid)) | 248 | if (TC_H_MAJ(res.classid)) |
248 | cl = cbq_class_lookup(q, res.classid); | 249 | cl = cbq_class_lookup(q, res.classid); |
249 | else if ((cl = defmap[res.classid&TC_PRIO_MAX]) == NULL) | 250 | else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL) |
250 | cl = defmap[TC_PRIO_BESTEFFORT]; | 251 | cl = defmap[TC_PRIO_BESTEFFORT]; |
251 | 252 | ||
252 | if (cl == NULL || cl->level >= head->level) | 253 | if (cl == NULL || cl->level >= head->level) |
@@ -282,7 +283,7 @@ fallback: | |||
282 | * Step 4. No success... | 283 | * Step 4. No success... |
283 | */ | 284 | */ |
284 | if (TC_H_MAJ(prio) == 0 && | 285 | if (TC_H_MAJ(prio) == 0 && |
285 | !(cl = head->defaults[prio&TC_PRIO_MAX]) && | 286 | !(cl = head->defaults[prio & TC_PRIO_MAX]) && |
286 | !(cl = head->defaults[TC_PRIO_BESTEFFORT])) | 287 | !(cl = head->defaults[TC_PRIO_BESTEFFORT])) |
287 | return head; | 288 | return head; |
288 | 289 | ||
@@ -290,12 +291,12 @@ fallback: | |||
290 | } | 291 | } |
291 | 292 | ||
292 | /* | 293 | /* |
293 | A packet has just been enqueued on the empty class. | 294 | * A packet has just been enqueued on the empty class. |
294 | cbq_activate_class adds it to the tail of active class list | 295 | * cbq_activate_class adds it to the tail of active class list |
295 | of its priority band. | 296 | * of its priority band. |
296 | */ | 297 | */ |
297 | 298 | ||
298 | static __inline__ void cbq_activate_class(struct cbq_class *cl) | 299 | static inline void cbq_activate_class(struct cbq_class *cl) |
299 | { | 300 | { |
300 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); | 301 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); |
301 | int prio = cl->cpriority; | 302 | int prio = cl->cpriority; |
@@ -314,9 +315,9 @@ static __inline__ void cbq_activate_class(struct cbq_class *cl) | |||
314 | } | 315 | } |
315 | 316 | ||
316 | /* | 317 | /* |
317 | Unlink class from active chain. | 318 | * Unlink class from active chain. |
318 | Note that this same procedure is done directly in cbq_dequeue* | 319 | * Note that this same procedure is done directly in cbq_dequeue* |
319 | during round-robin procedure. | 320 | * during round-robin procedure. |
320 | */ | 321 | */ |
321 | 322 | ||
322 | static void cbq_deactivate_class(struct cbq_class *this) | 323 | static void cbq_deactivate_class(struct cbq_class *this) |
@@ -350,7 +351,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl) | |||
350 | { | 351 | { |
351 | int toplevel = q->toplevel; | 352 | int toplevel = q->toplevel; |
352 | 353 | ||
353 | if (toplevel > cl->level && !(cl->q->flags&TCQ_F_THROTTLED)) { | 354 | if (toplevel > cl->level && !(qdisc_is_throttled(cl->q))) { |
354 | psched_time_t now; | 355 | psched_time_t now; |
355 | psched_tdiff_t incr; | 356 | psched_tdiff_t incr; |
356 | 357 | ||
@@ -363,7 +364,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl) | |||
363 | q->toplevel = cl->level; | 364 | q->toplevel = cl->level; |
364 | return; | 365 | return; |
365 | } | 366 | } |
366 | } while ((cl=cl->borrow) != NULL && toplevel > cl->level); | 367 | } while ((cl = cl->borrow) != NULL && toplevel > cl->level); |
367 | } | 368 | } |
368 | } | 369 | } |
369 | 370 | ||
@@ -417,11 +418,11 @@ static void cbq_ovl_classic(struct cbq_class *cl) | |||
417 | delay += cl->offtime; | 418 | delay += cl->offtime; |
418 | 419 | ||
419 | /* | 420 | /* |
420 | Class goes to sleep, so that it will have no | 421 | * Class goes to sleep, so that it will have no |
421 | chance to work avgidle. Let's forgive it 8) | 422 | * chance to work avgidle. Let's forgive it 8) |
422 | 423 | * | |
423 | BTW cbq-2.0 has a crap in this | 424 | * BTW cbq-2.0 has a crap in this |
424 | place, apparently they forgot to shift it by cl->ewma_log. | 425 | * place, apparently they forgot to shift it by cl->ewma_log. |
425 | */ | 426 | */ |
426 | if (cl->avgidle < 0) | 427 | if (cl->avgidle < 0) |
427 | delay -= (-cl->avgidle) - ((-cl->avgidle) >> cl->ewma_log); | 428 | delay -= (-cl->avgidle) - ((-cl->avgidle) >> cl->ewma_log); |
@@ -438,8 +439,8 @@ static void cbq_ovl_classic(struct cbq_class *cl) | |||
438 | q->wd_expires = delay; | 439 | q->wd_expires = delay; |
439 | 440 | ||
440 | /* Dirty work! We must schedule wakeups based on | 441 | /* Dirty work! We must schedule wakeups based on |
441 | real available rate, rather than leaf rate, | 442 | * real available rate, rather than leaf rate, |
442 | which may be tiny (even zero). | 443 | * which may be tiny (even zero). |
443 | */ | 444 | */ |
444 | if (q->toplevel == TC_CBQ_MAXLEVEL) { | 445 | if (q->toplevel == TC_CBQ_MAXLEVEL) { |
445 | struct cbq_class *b; | 446 | struct cbq_class *b; |
@@ -459,7 +460,7 @@ static void cbq_ovl_classic(struct cbq_class *cl) | |||
459 | } | 460 | } |
460 | 461 | ||
461 | /* TC_CBQ_OVL_RCLASSIC: penalize by offtime classes in hierarchy, when | 462 | /* TC_CBQ_OVL_RCLASSIC: penalize by offtime classes in hierarchy, when |
462 | they go overlimit | 463 | * they go overlimit |
463 | */ | 464 | */ |
464 | 465 | ||
465 | static void cbq_ovl_rclassic(struct cbq_class *cl) | 466 | static void cbq_ovl_rclassic(struct cbq_class *cl) |
@@ -594,7 +595,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) | |||
594 | struct Qdisc *sch = q->watchdog.qdisc; | 595 | struct Qdisc *sch = q->watchdog.qdisc; |
595 | psched_time_t now; | 596 | psched_time_t now; |
596 | psched_tdiff_t delay = 0; | 597 | psched_tdiff_t delay = 0; |
597 | unsigned pmask; | 598 | unsigned int pmask; |
598 | 599 | ||
599 | now = psched_get_time(); | 600 | now = psched_get_time(); |
600 | 601 | ||
@@ -623,7 +624,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) | |||
623 | hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS); | 624 | hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS); |
624 | } | 625 | } |
625 | 626 | ||
626 | sch->flags &= ~TCQ_F_THROTTLED; | 627 | qdisc_unthrottled(sch); |
627 | __netif_schedule(qdisc_root(sch)); | 628 | __netif_schedule(qdisc_root(sch)); |
628 | return HRTIMER_NORESTART; | 629 | return HRTIMER_NORESTART; |
629 | } | 630 | } |
@@ -663,15 +664,15 @@ static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) | |||
663 | #endif | 664 | #endif |
664 | 665 | ||
665 | /* | 666 | /* |
666 | It is mission critical procedure. | 667 | * It is mission critical procedure. |
667 | 668 | * | |
668 | We "regenerate" toplevel cutoff, if transmitting class | 669 | * We "regenerate" toplevel cutoff, if transmitting class |
669 | has backlog and it is not regulated. It is not part of | 670 | * has backlog and it is not regulated. It is not part of |
670 | original CBQ description, but looks more reasonable. | 671 | * original CBQ description, but looks more reasonable. |
671 | Probably, it is wrong. This question needs further investigation. | 672 | * Probably, it is wrong. This question needs further investigation. |
672 | */ | 673 | */ |
673 | 674 | ||
674 | static __inline__ void | 675 | static inline void |
675 | cbq_update_toplevel(struct cbq_sched_data *q, struct cbq_class *cl, | 676 | cbq_update_toplevel(struct cbq_sched_data *q, struct cbq_class *cl, |
676 | struct cbq_class *borrowed) | 677 | struct cbq_class *borrowed) |
677 | { | 678 | { |
@@ -682,7 +683,7 @@ cbq_update_toplevel(struct cbq_sched_data *q, struct cbq_class *cl, | |||
682 | q->toplevel = borrowed->level; | 683 | q->toplevel = borrowed->level; |
683 | return; | 684 | return; |
684 | } | 685 | } |
685 | } while ((borrowed=borrowed->borrow) != NULL); | 686 | } while ((borrowed = borrowed->borrow) != NULL); |
686 | } | 687 | } |
687 | #if 0 | 688 | #if 0 |
688 | /* It is not necessary now. Uncommenting it | 689 | /* It is not necessary now. Uncommenting it |
@@ -710,10 +711,10 @@ cbq_update(struct cbq_sched_data *q) | |||
710 | cl->bstats.bytes += len; | 711 | cl->bstats.bytes += len; |
711 | 712 | ||
712 | /* | 713 | /* |
713 | (now - last) is total time between packet right edges. | 714 | * (now - last) is total time between packet right edges. |
714 | (last_pktlen/rate) is "virtual" busy time, so that | 715 | * (last_pktlen/rate) is "virtual" busy time, so that |
715 | 716 | * | |
716 | idle = (now - last) - last_pktlen/rate | 717 | * idle = (now - last) - last_pktlen/rate |
717 | */ | 718 | */ |
718 | 719 | ||
719 | idle = q->now - cl->last; | 720 | idle = q->now - cl->last; |
@@ -723,9 +724,9 @@ cbq_update(struct cbq_sched_data *q) | |||
723 | idle -= L2T(cl, len); | 724 | idle -= L2T(cl, len); |
724 | 725 | ||
725 | /* true_avgidle := (1-W)*true_avgidle + W*idle, | 726 | /* true_avgidle := (1-W)*true_avgidle + W*idle, |
726 | where W=2^{-ewma_log}. But cl->avgidle is scaled: | 727 | * where W=2^{-ewma_log}. But cl->avgidle is scaled: |
727 | cl->avgidle == true_avgidle/W, | 728 | * cl->avgidle == true_avgidle/W, |
728 | hence: | 729 | * hence: |
729 | */ | 730 | */ |
730 | avgidle += idle - (avgidle>>cl->ewma_log); | 731 | avgidle += idle - (avgidle>>cl->ewma_log); |
731 | } | 732 | } |
@@ -739,22 +740,22 @@ cbq_update(struct cbq_sched_data *q) | |||
739 | cl->avgidle = avgidle; | 740 | cl->avgidle = avgidle; |
740 | 741 | ||
741 | /* Calculate expected time, when this class | 742 | /* Calculate expected time, when this class |
742 | will be allowed to send. | 743 | * will be allowed to send. |
743 | It will occur, when: | 744 | * It will occur, when: |
744 | (1-W)*true_avgidle + W*delay = 0, i.e. | 745 | * (1-W)*true_avgidle + W*delay = 0, i.e. |
745 | idle = (1/W - 1)*(-true_avgidle) | 746 | * idle = (1/W - 1)*(-true_avgidle) |
746 | or | 747 | * or |
747 | idle = (1 - W)*(-cl->avgidle); | 748 | * idle = (1 - W)*(-cl->avgidle); |
748 | */ | 749 | */ |
749 | idle = (-avgidle) - ((-avgidle) >> cl->ewma_log); | 750 | idle = (-avgidle) - ((-avgidle) >> cl->ewma_log); |
750 | 751 | ||
751 | /* | 752 | /* |
752 | That is not all. | 753 | * That is not all. |
753 | To maintain the rate allocated to the class, | 754 | * To maintain the rate allocated to the class, |
754 | we add to undertime virtual clock, | 755 | * we add to undertime virtual clock, |
755 | necessary to complete transmitted packet. | 756 | * necessary to complete transmitted packet. |
756 | (len/phys_bandwidth has been already passed | 757 | * (len/phys_bandwidth has been already passed |
757 | to the moment of cbq_update) | 758 | * to the moment of cbq_update) |
758 | */ | 759 | */ |
759 | 760 | ||
760 | idle -= L2T(&q->link, len); | 761 | idle -= L2T(&q->link, len); |
@@ -776,7 +777,7 @@ cbq_update(struct cbq_sched_data *q) | |||
776 | cbq_update_toplevel(q, this, q->tx_borrowed); | 777 | cbq_update_toplevel(q, this, q->tx_borrowed); |
777 | } | 778 | } |
778 | 779 | ||
779 | static __inline__ struct cbq_class * | 780 | static inline struct cbq_class * |
780 | cbq_under_limit(struct cbq_class *cl) | 781 | cbq_under_limit(struct cbq_class *cl) |
781 | { | 782 | { |
782 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); | 783 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); |
@@ -792,16 +793,17 @@ cbq_under_limit(struct cbq_class *cl) | |||
792 | 793 | ||
793 | do { | 794 | do { |
794 | /* It is very suspicious place. Now overlimit | 795 | /* It is very suspicious place. Now overlimit |
795 | action is generated for not bounded classes | 796 | * action is generated for not bounded classes |
796 | only if link is completely congested. | 797 | * only if link is completely congested. |
797 | Though it is in agree with ancestor-only paradigm, | 798 | * Though it is in agree with ancestor-only paradigm, |
798 | it looks very stupid. Particularly, | 799 | * it looks very stupid. Particularly, |
799 | it means that this chunk of code will either | 800 | * it means that this chunk of code will either |
800 | never be called or result in strong amplification | 801 | * never be called or result in strong amplification |
801 | of burstiness. Dangerous, silly, and, however, | 802 | * of burstiness. Dangerous, silly, and, however, |
802 | no another solution exists. | 803 | * no another solution exists. |
803 | */ | 804 | */ |
804 | if ((cl = cl->borrow) == NULL) { | 805 | cl = cl->borrow; |
806 | if (!cl) { | ||
805 | this_cl->qstats.overlimits++; | 807 | this_cl->qstats.overlimits++; |
806 | this_cl->overlimit(this_cl); | 808 | this_cl->overlimit(this_cl); |
807 | return NULL; | 809 | return NULL; |
@@ -814,7 +816,7 @@ cbq_under_limit(struct cbq_class *cl) | |||
814 | return cl; | 816 | return cl; |
815 | } | 817 | } |
816 | 818 | ||
817 | static __inline__ struct sk_buff * | 819 | static inline struct sk_buff * |
818 | cbq_dequeue_prio(struct Qdisc *sch, int prio) | 820 | cbq_dequeue_prio(struct Qdisc *sch, int prio) |
819 | { | 821 | { |
820 | struct cbq_sched_data *q = qdisc_priv(sch); | 822 | struct cbq_sched_data *q = qdisc_priv(sch); |
@@ -838,7 +840,7 @@ cbq_dequeue_prio(struct Qdisc *sch, int prio) | |||
838 | 840 | ||
839 | if (cl->deficit <= 0) { | 841 | if (cl->deficit <= 0) { |
840 | /* Class exhausted its allotment per | 842 | /* Class exhausted its allotment per |
841 | this round. Switch to the next one. | 843 | * this round. Switch to the next one. |
842 | */ | 844 | */ |
843 | deficit = 1; | 845 | deficit = 1; |
844 | cl->deficit += cl->quantum; | 846 | cl->deficit += cl->quantum; |
@@ -848,8 +850,8 @@ cbq_dequeue_prio(struct Qdisc *sch, int prio) | |||
848 | skb = cl->q->dequeue(cl->q); | 850 | skb = cl->q->dequeue(cl->q); |
849 | 851 | ||
850 | /* Class did not give us any skb :-( | 852 | /* Class did not give us any skb :-( |
851 | It could occur even if cl->q->q.qlen != 0 | 853 | * It could occur even if cl->q->q.qlen != 0 |
852 | f.e. if cl->q == "tbf" | 854 | * f.e. if cl->q == "tbf" |
853 | */ | 855 | */ |
854 | if (skb == NULL) | 856 | if (skb == NULL) |
855 | goto skip_class; | 857 | goto skip_class; |
@@ -878,7 +880,7 @@ cbq_dequeue_prio(struct Qdisc *sch, int prio) | |||
878 | skip_class: | 880 | skip_class: |
879 | if (cl->q->q.qlen == 0 || prio != cl->cpriority) { | 881 | if (cl->q->q.qlen == 0 || prio != cl->cpriority) { |
880 | /* Class is empty or penalized. | 882 | /* Class is empty or penalized. |
881 | Unlink it from active chain. | 883 | * Unlink it from active chain. |
882 | */ | 884 | */ |
883 | cl_prev->next_alive = cl->next_alive; | 885 | cl_prev->next_alive = cl->next_alive; |
884 | cl->next_alive = NULL; | 886 | cl->next_alive = NULL; |
@@ -917,14 +919,14 @@ next_class: | |||
917 | return NULL; | 919 | return NULL; |
918 | } | 920 | } |
919 | 921 | ||
920 | static __inline__ struct sk_buff * | 922 | static inline struct sk_buff * |
921 | cbq_dequeue_1(struct Qdisc *sch) | 923 | cbq_dequeue_1(struct Qdisc *sch) |
922 | { | 924 | { |
923 | struct cbq_sched_data *q = qdisc_priv(sch); | 925 | struct cbq_sched_data *q = qdisc_priv(sch); |
924 | struct sk_buff *skb; | 926 | struct sk_buff *skb; |
925 | unsigned activemask; | 927 | unsigned int activemask; |
926 | 928 | ||
927 | activemask = q->activemask&0xFF; | 929 | activemask = q->activemask & 0xFF; |
928 | while (activemask) { | 930 | while (activemask) { |
929 | int prio = ffz(~activemask); | 931 | int prio = ffz(~activemask); |
930 | activemask &= ~(1<<prio); | 932 | activemask &= ~(1<<prio); |
@@ -949,11 +951,11 @@ cbq_dequeue(struct Qdisc *sch) | |||
949 | if (q->tx_class) { | 951 | if (q->tx_class) { |
950 | psched_tdiff_t incr2; | 952 | psched_tdiff_t incr2; |
951 | /* Time integrator. We calculate EOS time | 953 | /* Time integrator. We calculate EOS time |
952 | by adding expected packet transmission time. | 954 | * by adding expected packet transmission time. |
953 | If real time is greater, we warp artificial clock, | 955 | * If real time is greater, we warp artificial clock, |
954 | so that: | 956 | * so that: |
955 | 957 | * | |
956 | cbq_time = max(real_time, work); | 958 | * cbq_time = max(real_time, work); |
957 | */ | 959 | */ |
958 | incr2 = L2T(&q->link, q->tx_len); | 960 | incr2 = L2T(&q->link, q->tx_len); |
959 | q->now += incr2; | 961 | q->now += incr2; |
@@ -971,27 +973,27 @@ cbq_dequeue(struct Qdisc *sch) | |||
971 | if (skb) { | 973 | if (skb) { |
972 | qdisc_bstats_update(sch, skb); | 974 | qdisc_bstats_update(sch, skb); |
973 | sch->q.qlen--; | 975 | sch->q.qlen--; |
974 | sch->flags &= ~TCQ_F_THROTTLED; | 976 | qdisc_unthrottled(sch); |
975 | return skb; | 977 | return skb; |
976 | } | 978 | } |
977 | 979 | ||
978 | /* All the classes are overlimit. | 980 | /* All the classes are overlimit. |
979 | 981 | * | |
980 | It is possible, if: | 982 | * It is possible, if: |
981 | 983 | * | |
982 | 1. Scheduler is empty. | 984 | * 1. Scheduler is empty. |
983 | 2. Toplevel cutoff inhibited borrowing. | 985 | * 2. Toplevel cutoff inhibited borrowing. |
984 | 3. Root class is overlimit. | 986 | * 3. Root class is overlimit. |
985 | 987 | * | |
986 | Reset 2d and 3d conditions and retry. | 988 | * Reset 2d and 3d conditions and retry. |
987 | 989 | * | |
988 | Note, that NS and cbq-2.0 are buggy, peeking | 990 | * Note, that NS and cbq-2.0 are buggy, peeking |
989 | an arbitrary class is appropriate for ancestor-only | 991 | * an arbitrary class is appropriate for ancestor-only |
990 | sharing, but not for toplevel algorithm. | 992 | * sharing, but not for toplevel algorithm. |
991 | 993 | * | |
992 | Our version is better, but slower, because it requires | 994 | * Our version is better, but slower, because it requires |
993 | two passes, but it is unavoidable with top-level sharing. | 995 | * two passes, but it is unavoidable with top-level sharing. |
994 | */ | 996 | */ |
995 | 997 | ||
996 | if (q->toplevel == TC_CBQ_MAXLEVEL && | 998 | if (q->toplevel == TC_CBQ_MAXLEVEL && |
997 | q->link.undertime == PSCHED_PASTPERFECT) | 999 | q->link.undertime == PSCHED_PASTPERFECT) |
@@ -1002,7 +1004,8 @@ cbq_dequeue(struct Qdisc *sch) | |||
1002 | } | 1004 | } |
1003 | 1005 | ||
1004 | /* No packets in scheduler or nobody wants to give them to us :-( | 1006 | /* No packets in scheduler or nobody wants to give them to us :-( |
1005 | Sigh... start watchdog timer in the last case. */ | 1007 | * Sigh... start watchdog timer in the last case. |
1008 | */ | ||
1006 | 1009 | ||
1007 | if (sch->q.qlen) { | 1010 | if (sch->q.qlen) { |
1008 | sch->qstats.overlimits++; | 1011 | sch->qstats.overlimits++; |
@@ -1024,13 +1027,14 @@ static void cbq_adjust_levels(struct cbq_class *this) | |||
1024 | int level = 0; | 1027 | int level = 0; |
1025 | struct cbq_class *cl; | 1028 | struct cbq_class *cl; |
1026 | 1029 | ||
1027 | if ((cl = this->children) != NULL) { | 1030 | cl = this->children; |
1031 | if (cl) { | ||
1028 | do { | 1032 | do { |
1029 | if (cl->level > level) | 1033 | if (cl->level > level) |
1030 | level = cl->level; | 1034 | level = cl->level; |
1031 | } while ((cl = cl->sibling) != this->children); | 1035 | } while ((cl = cl->sibling) != this->children); |
1032 | } | 1036 | } |
1033 | this->level = level+1; | 1037 | this->level = level + 1; |
1034 | } while ((this = this->tparent) != NULL); | 1038 | } while ((this = this->tparent) != NULL); |
1035 | } | 1039 | } |
1036 | 1040 | ||
@@ -1046,14 +1050,15 @@ static void cbq_normalize_quanta(struct cbq_sched_data *q, int prio) | |||
1046 | for (h = 0; h < q->clhash.hashsize; h++) { | 1050 | for (h = 0; h < q->clhash.hashsize; h++) { |
1047 | hlist_for_each_entry(cl, n, &q->clhash.hash[h], common.hnode) { | 1051 | hlist_for_each_entry(cl, n, &q->clhash.hash[h], common.hnode) { |
1048 | /* BUGGGG... Beware! This expression suffer of | 1052 | /* BUGGGG... Beware! This expression suffer of |
1049 | arithmetic overflows! | 1053 | * arithmetic overflows! |
1050 | */ | 1054 | */ |
1051 | if (cl->priority == prio) { | 1055 | if (cl->priority == prio) { |
1052 | cl->quantum = (cl->weight*cl->allot*q->nclasses[prio])/ | 1056 | cl->quantum = (cl->weight*cl->allot*q->nclasses[prio])/ |
1053 | q->quanta[prio]; | 1057 | q->quanta[prio]; |
1054 | } | 1058 | } |
1055 | if (cl->quantum <= 0 || cl->quantum>32*qdisc_dev(cl->qdisc)->mtu) { | 1059 | if (cl->quantum <= 0 || cl->quantum>32*qdisc_dev(cl->qdisc)->mtu) { |
1056 | printk(KERN_WARNING "CBQ: class %08x has bad quantum==%ld, repaired.\n", cl->common.classid, cl->quantum); | 1060 | pr_warning("CBQ: class %08x has bad quantum==%ld, repaired.\n", |
1061 | cl->common.classid, cl->quantum); | ||
1057 | cl->quantum = qdisc_dev(cl->qdisc)->mtu/2 + 1; | 1062 | cl->quantum = qdisc_dev(cl->qdisc)->mtu/2 + 1; |
1058 | } | 1063 | } |
1059 | } | 1064 | } |
@@ -1064,18 +1069,18 @@ static void cbq_sync_defmap(struct cbq_class *cl) | |||
1064 | { | 1069 | { |
1065 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); | 1070 | struct cbq_sched_data *q = qdisc_priv(cl->qdisc); |
1066 | struct cbq_class *split = cl->split; | 1071 | struct cbq_class *split = cl->split; |
1067 | unsigned h; | 1072 | unsigned int h; |
1068 | int i; | 1073 | int i; |
1069 | 1074 | ||
1070 | if (split == NULL) | 1075 | if (split == NULL) |
1071 | return; | 1076 | return; |
1072 | 1077 | ||
1073 | for (i=0; i<=TC_PRIO_MAX; i++) { | 1078 | for (i = 0; i <= TC_PRIO_MAX; i++) { |
1074 | if (split->defaults[i] == cl && !(cl->defmap&(1<<i))) | 1079 | if (split->defaults[i] == cl && !(cl->defmap & (1<<i))) |
1075 | split->defaults[i] = NULL; | 1080 | split->defaults[i] = NULL; |
1076 | } | 1081 | } |
1077 | 1082 | ||
1078 | for (i=0; i<=TC_PRIO_MAX; i++) { | 1083 | for (i = 0; i <= TC_PRIO_MAX; i++) { |
1079 | int level = split->level; | 1084 | int level = split->level; |
1080 | 1085 | ||
1081 | if (split->defaults[i]) | 1086 | if (split->defaults[i]) |
@@ -1088,7 +1093,7 @@ static void cbq_sync_defmap(struct cbq_class *cl) | |||
1088 | hlist_for_each_entry(c, n, &q->clhash.hash[h], | 1093 | hlist_for_each_entry(c, n, &q->clhash.hash[h], |
1089 | common.hnode) { | 1094 | common.hnode) { |
1090 | if (c->split == split && c->level < level && | 1095 | if (c->split == split && c->level < level && |
1091 | c->defmap&(1<<i)) { | 1096 | c->defmap & (1<<i)) { |
1092 | split->defaults[i] = c; | 1097 | split->defaults[i] = c; |
1093 | level = c->level; | 1098 | level = c->level; |
1094 | } | 1099 | } |
@@ -1102,7 +1107,8 @@ static void cbq_change_defmap(struct cbq_class *cl, u32 splitid, u32 def, u32 ma | |||
1102 | struct cbq_class *split = NULL; | 1107 | struct cbq_class *split = NULL; |
1103 | 1108 | ||
1104 | if (splitid == 0) { | 1109 | if (splitid == 0) { |
1105 | if ((split = cl->split) == NULL) | 1110 | split = cl->split; |
1111 | if (!split) | ||
1106 | return; | 1112 | return; |
1107 | splitid = split->common.classid; | 1113 | splitid = split->common.classid; |
1108 | } | 1114 | } |
@@ -1120,9 +1126,9 @@ static void cbq_change_defmap(struct cbq_class *cl, u32 splitid, u32 def, u32 ma | |||
1120 | cl->defmap = 0; | 1126 | cl->defmap = 0; |
1121 | cbq_sync_defmap(cl); | 1127 | cbq_sync_defmap(cl); |
1122 | cl->split = split; | 1128 | cl->split = split; |
1123 | cl->defmap = def&mask; | 1129 | cl->defmap = def & mask; |
1124 | } else | 1130 | } else |
1125 | cl->defmap = (cl->defmap&~mask)|(def&mask); | 1131 | cl->defmap = (cl->defmap & ~mask) | (def & mask); |
1126 | 1132 | ||
1127 | cbq_sync_defmap(cl); | 1133 | cbq_sync_defmap(cl); |
1128 | } | 1134 | } |
@@ -1135,7 +1141,7 @@ static void cbq_unlink_class(struct cbq_class *this) | |||
1135 | qdisc_class_hash_remove(&q->clhash, &this->common); | 1141 | qdisc_class_hash_remove(&q->clhash, &this->common); |
1136 | 1142 | ||
1137 | if (this->tparent) { | 1143 | if (this->tparent) { |
1138 | clp=&this->sibling; | 1144 | clp = &this->sibling; |
1139 | cl = *clp; | 1145 | cl = *clp; |
1140 | do { | 1146 | do { |
1141 | if (cl == this) { | 1147 | if (cl == this) { |
@@ -1174,7 +1180,7 @@ static void cbq_link_class(struct cbq_class *this) | |||
1174 | } | 1180 | } |
1175 | } | 1181 | } |
1176 | 1182 | ||
1177 | static unsigned int cbq_drop(struct Qdisc* sch) | 1183 | static unsigned int cbq_drop(struct Qdisc *sch) |
1178 | { | 1184 | { |
1179 | struct cbq_sched_data *q = qdisc_priv(sch); | 1185 | struct cbq_sched_data *q = qdisc_priv(sch); |
1180 | struct cbq_class *cl, *cl_head; | 1186 | struct cbq_class *cl, *cl_head; |
@@ -1182,7 +1188,8 @@ static unsigned int cbq_drop(struct Qdisc* sch) | |||
1182 | unsigned int len; | 1188 | unsigned int len; |
1183 | 1189 | ||
1184 | for (prio = TC_CBQ_MAXPRIO; prio >= 0; prio--) { | 1190 | for (prio = TC_CBQ_MAXPRIO; prio >= 0; prio--) { |
1185 | if ((cl_head = q->active[prio]) == NULL) | 1191 | cl_head = q->active[prio]; |
1192 | if (!cl_head) | ||
1186 | continue; | 1193 | continue; |
1187 | 1194 | ||
1188 | cl = cl_head; | 1195 | cl = cl_head; |
@@ -1199,13 +1206,13 @@ static unsigned int cbq_drop(struct Qdisc* sch) | |||
1199 | } | 1206 | } |
1200 | 1207 | ||
1201 | static void | 1208 | static void |
1202 | cbq_reset(struct Qdisc* sch) | 1209 | cbq_reset(struct Qdisc *sch) |
1203 | { | 1210 | { |
1204 | struct cbq_sched_data *q = qdisc_priv(sch); | 1211 | struct cbq_sched_data *q = qdisc_priv(sch); |
1205 | struct cbq_class *cl; | 1212 | struct cbq_class *cl; |
1206 | struct hlist_node *n; | 1213 | struct hlist_node *n; |
1207 | int prio; | 1214 | int prio; |
1208 | unsigned h; | 1215 | unsigned int h; |
1209 | 1216 | ||
1210 | q->activemask = 0; | 1217 | q->activemask = 0; |
1211 | q->pmask = 0; | 1218 | q->pmask = 0; |
@@ -1237,21 +1244,21 @@ cbq_reset(struct Qdisc* sch) | |||
1237 | 1244 | ||
1238 | static int cbq_set_lss(struct cbq_class *cl, struct tc_cbq_lssopt *lss) | 1245 | static int cbq_set_lss(struct cbq_class *cl, struct tc_cbq_lssopt *lss) |
1239 | { | 1246 | { |
1240 | if (lss->change&TCF_CBQ_LSS_FLAGS) { | 1247 | if (lss->change & TCF_CBQ_LSS_FLAGS) { |
1241 | cl->share = (lss->flags&TCF_CBQ_LSS_ISOLATED) ? NULL : cl->tparent; | 1248 | cl->share = (lss->flags & TCF_CBQ_LSS_ISOLATED) ? NULL : cl->tparent; |
1242 | cl->borrow = (lss->flags&TCF_CBQ_LSS_BOUNDED) ? NULL : cl->tparent; | 1249 | cl->borrow = (lss->flags & TCF_CBQ_LSS_BOUNDED) ? NULL : cl->tparent; |
1243 | } | 1250 | } |
1244 | if (lss->change&TCF_CBQ_LSS_EWMA) | 1251 | if (lss->change & TCF_CBQ_LSS_EWMA) |
1245 | cl->ewma_log = lss->ewma_log; | 1252 | cl->ewma_log = lss->ewma_log; |
1246 | if (lss->change&TCF_CBQ_LSS_AVPKT) | 1253 | if (lss->change & TCF_CBQ_LSS_AVPKT) |
1247 | cl->avpkt = lss->avpkt; | 1254 | cl->avpkt = lss->avpkt; |
1248 | if (lss->change&TCF_CBQ_LSS_MINIDLE) | 1255 | if (lss->change & TCF_CBQ_LSS_MINIDLE) |
1249 | cl->minidle = -(long)lss->minidle; | 1256 | cl->minidle = -(long)lss->minidle; |
1250 | if (lss->change&TCF_CBQ_LSS_MAXIDLE) { | 1257 | if (lss->change & TCF_CBQ_LSS_MAXIDLE) { |
1251 | cl->maxidle = lss->maxidle; | 1258 | cl->maxidle = lss->maxidle; |
1252 | cl->avgidle = lss->maxidle; | 1259 | cl->avgidle = lss->maxidle; |
1253 | } | 1260 | } |
1254 | if (lss->change&TCF_CBQ_LSS_OFFTIME) | 1261 | if (lss->change & TCF_CBQ_LSS_OFFTIME) |
1255 | cl->offtime = lss->offtime; | 1262 | cl->offtime = lss->offtime; |
1256 | return 0; | 1263 | return 0; |
1257 | } | 1264 | } |
@@ -1279,10 +1286,10 @@ static int cbq_set_wrr(struct cbq_class *cl, struct tc_cbq_wrropt *wrr) | |||
1279 | if (wrr->weight) | 1286 | if (wrr->weight) |
1280 | cl->weight = wrr->weight; | 1287 | cl->weight = wrr->weight; |
1281 | if (wrr->priority) { | 1288 | if (wrr->priority) { |
1282 | cl->priority = wrr->priority-1; | 1289 | cl->priority = wrr->priority - 1; |
1283 | cl->cpriority = cl->priority; | 1290 | cl->cpriority = cl->priority; |
1284 | if (cl->priority >= cl->priority2) | 1291 | if (cl->priority >= cl->priority2) |
1285 | cl->priority2 = TC_CBQ_MAXPRIO-1; | 1292 | cl->priority2 = TC_CBQ_MAXPRIO - 1; |
1286 | } | 1293 | } |
1287 | 1294 | ||
1288 | cbq_addprio(q, cl); | 1295 | cbq_addprio(q, cl); |
@@ -1299,10 +1306,10 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl) | |||
1299 | cl->overlimit = cbq_ovl_delay; | 1306 | cl->overlimit = cbq_ovl_delay; |
1300 | break; | 1307 | break; |
1301 | case TC_CBQ_OVL_LOWPRIO: | 1308 | case TC_CBQ_OVL_LOWPRIO: |
1302 | if (ovl->priority2-1 >= TC_CBQ_MAXPRIO || | 1309 | if (ovl->priority2 - 1 >= TC_CBQ_MAXPRIO || |
1303 | ovl->priority2-1 <= cl->priority) | 1310 | ovl->priority2 - 1 <= cl->priority) |
1304 | return -EINVAL; | 1311 | return -EINVAL; |
1305 | cl->priority2 = ovl->priority2-1; | 1312 | cl->priority2 = ovl->priority2 - 1; |
1306 | cl->overlimit = cbq_ovl_lowprio; | 1313 | cl->overlimit = cbq_ovl_lowprio; |
1307 | break; | 1314 | break; |
1308 | case TC_CBQ_OVL_DROP: | 1315 | case TC_CBQ_OVL_DROP: |
@@ -1381,9 +1388,9 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt) | |||
1381 | if (!q->link.q) | 1388 | if (!q->link.q) |
1382 | q->link.q = &noop_qdisc; | 1389 | q->link.q = &noop_qdisc; |
1383 | 1390 | ||
1384 | q->link.priority = TC_CBQ_MAXPRIO-1; | 1391 | q->link.priority = TC_CBQ_MAXPRIO - 1; |
1385 | q->link.priority2 = TC_CBQ_MAXPRIO-1; | 1392 | q->link.priority2 = TC_CBQ_MAXPRIO - 1; |
1386 | q->link.cpriority = TC_CBQ_MAXPRIO-1; | 1393 | q->link.cpriority = TC_CBQ_MAXPRIO - 1; |
1387 | q->link.ovl_strategy = TC_CBQ_OVL_CLASSIC; | 1394 | q->link.ovl_strategy = TC_CBQ_OVL_CLASSIC; |
1388 | q->link.overlimit = cbq_ovl_classic; | 1395 | q->link.overlimit = cbq_ovl_classic; |
1389 | q->link.allot = psched_mtu(qdisc_dev(sch)); | 1396 | q->link.allot = psched_mtu(qdisc_dev(sch)); |
@@ -1414,7 +1421,7 @@ put_rtab: | |||
1414 | return err; | 1421 | return err; |
1415 | } | 1422 | } |
1416 | 1423 | ||
1417 | static __inline__ int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl) | 1424 | static int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl) |
1418 | { | 1425 | { |
1419 | unsigned char *b = skb_tail_pointer(skb); | 1426 | unsigned char *b = skb_tail_pointer(skb); |
1420 | 1427 | ||
@@ -1426,7 +1433,7 @@ nla_put_failure: | |||
1426 | return -1; | 1433 | return -1; |
1427 | } | 1434 | } |
1428 | 1435 | ||
1429 | static __inline__ int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl) | 1436 | static int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl) |
1430 | { | 1437 | { |
1431 | unsigned char *b = skb_tail_pointer(skb); | 1438 | unsigned char *b = skb_tail_pointer(skb); |
1432 | struct tc_cbq_lssopt opt; | 1439 | struct tc_cbq_lssopt opt; |
@@ -1451,15 +1458,15 @@ nla_put_failure: | |||
1451 | return -1; | 1458 | return -1; |
1452 | } | 1459 | } |
1453 | 1460 | ||
1454 | static __inline__ int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl) | 1461 | static int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl) |
1455 | { | 1462 | { |
1456 | unsigned char *b = skb_tail_pointer(skb); | 1463 | unsigned char *b = skb_tail_pointer(skb); |
1457 | struct tc_cbq_wrropt opt; | 1464 | struct tc_cbq_wrropt opt; |
1458 | 1465 | ||
1459 | opt.flags = 0; | 1466 | opt.flags = 0; |
1460 | opt.allot = cl->allot; | 1467 | opt.allot = cl->allot; |
1461 | opt.priority = cl->priority+1; | 1468 | opt.priority = cl->priority + 1; |
1462 | opt.cpriority = cl->cpriority+1; | 1469 | opt.cpriority = cl->cpriority + 1; |
1463 | opt.weight = cl->weight; | 1470 | opt.weight = cl->weight; |
1464 | NLA_PUT(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt); | 1471 | NLA_PUT(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt); |
1465 | return skb->len; | 1472 | return skb->len; |
@@ -1469,13 +1476,13 @@ nla_put_failure: | |||
1469 | return -1; | 1476 | return -1; |
1470 | } | 1477 | } |
1471 | 1478 | ||
1472 | static __inline__ int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl) | 1479 | static int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl) |
1473 | { | 1480 | { |
1474 | unsigned char *b = skb_tail_pointer(skb); | 1481 | unsigned char *b = skb_tail_pointer(skb); |
1475 | struct tc_cbq_ovl opt; | 1482 | struct tc_cbq_ovl opt; |
1476 | 1483 | ||
1477 | opt.strategy = cl->ovl_strategy; | 1484 | opt.strategy = cl->ovl_strategy; |
1478 | opt.priority2 = cl->priority2+1; | 1485 | opt.priority2 = cl->priority2 + 1; |
1479 | opt.pad = 0; | 1486 | opt.pad = 0; |
1480 | opt.penalty = cl->penalty; | 1487 | opt.penalty = cl->penalty; |
1481 | NLA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt); | 1488 | NLA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt); |
@@ -1486,7 +1493,7 @@ nla_put_failure: | |||
1486 | return -1; | 1493 | return -1; |
1487 | } | 1494 | } |
1488 | 1495 | ||
1489 | static __inline__ int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl) | 1496 | static int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl) |
1490 | { | 1497 | { |
1491 | unsigned char *b = skb_tail_pointer(skb); | 1498 | unsigned char *b = skb_tail_pointer(skb); |
1492 | struct tc_cbq_fopt opt; | 1499 | struct tc_cbq_fopt opt; |
@@ -1505,7 +1512,7 @@ nla_put_failure: | |||
1505 | } | 1512 | } |
1506 | 1513 | ||
1507 | #ifdef CONFIG_NET_CLS_ACT | 1514 | #ifdef CONFIG_NET_CLS_ACT |
1508 | static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) | 1515 | static int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) |
1509 | { | 1516 | { |
1510 | unsigned char *b = skb_tail_pointer(skb); | 1517 | unsigned char *b = skb_tail_pointer(skb); |
1511 | struct tc_cbq_police opt; | 1518 | struct tc_cbq_police opt; |
@@ -1569,7 +1576,7 @@ static int | |||
1569 | cbq_dump_class(struct Qdisc *sch, unsigned long arg, | 1576 | cbq_dump_class(struct Qdisc *sch, unsigned long arg, |
1570 | struct sk_buff *skb, struct tcmsg *tcm) | 1577 | struct sk_buff *skb, struct tcmsg *tcm) |
1571 | { | 1578 | { |
1572 | struct cbq_class *cl = (struct cbq_class*)arg; | 1579 | struct cbq_class *cl = (struct cbq_class *)arg; |
1573 | struct nlattr *nest; | 1580 | struct nlattr *nest; |
1574 | 1581 | ||
1575 | if (cl->tparent) | 1582 | if (cl->tparent) |
@@ -1597,7 +1604,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg, | |||
1597 | struct gnet_dump *d) | 1604 | struct gnet_dump *d) |
1598 | { | 1605 | { |
1599 | struct cbq_sched_data *q = qdisc_priv(sch); | 1606 | struct cbq_sched_data *q = qdisc_priv(sch); |
1600 | struct cbq_class *cl = (struct cbq_class*)arg; | 1607 | struct cbq_class *cl = (struct cbq_class *)arg; |
1601 | 1608 | ||
1602 | cl->qstats.qlen = cl->q->q.qlen; | 1609 | cl->qstats.qlen = cl->q->q.qlen; |
1603 | cl->xstats.avgidle = cl->avgidle; | 1610 | cl->xstats.avgidle = cl->avgidle; |
@@ -1617,7 +1624,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg, | |||
1617 | static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | 1624 | static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, |
1618 | struct Qdisc **old) | 1625 | struct Qdisc **old) |
1619 | { | 1626 | { |
1620 | struct cbq_class *cl = (struct cbq_class*)arg; | 1627 | struct cbq_class *cl = (struct cbq_class *)arg; |
1621 | 1628 | ||
1622 | if (new == NULL) { | 1629 | if (new == NULL) { |
1623 | new = qdisc_create_dflt(sch->dev_queue, | 1630 | new = qdisc_create_dflt(sch->dev_queue, |
@@ -1640,10 +1647,9 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | |||
1640 | return 0; | 1647 | return 0; |
1641 | } | 1648 | } |
1642 | 1649 | ||
1643 | static struct Qdisc * | 1650 | static struct Qdisc *cbq_leaf(struct Qdisc *sch, unsigned long arg) |
1644 | cbq_leaf(struct Qdisc *sch, unsigned long arg) | ||
1645 | { | 1651 | { |
1646 | struct cbq_class *cl = (struct cbq_class*)arg; | 1652 | struct cbq_class *cl = (struct cbq_class *)arg; |
1647 | 1653 | ||
1648 | return cl->q; | 1654 | return cl->q; |
1649 | } | 1655 | } |
@@ -1682,13 +1688,12 @@ static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl) | |||
1682 | kfree(cl); | 1688 | kfree(cl); |
1683 | } | 1689 | } |
1684 | 1690 | ||
1685 | static void | 1691 | static void cbq_destroy(struct Qdisc *sch) |
1686 | cbq_destroy(struct Qdisc* sch) | ||
1687 | { | 1692 | { |
1688 | struct cbq_sched_data *q = qdisc_priv(sch); | 1693 | struct cbq_sched_data *q = qdisc_priv(sch); |
1689 | struct hlist_node *n, *next; | 1694 | struct hlist_node *n, *next; |
1690 | struct cbq_class *cl; | 1695 | struct cbq_class *cl; |
1691 | unsigned h; | 1696 | unsigned int h; |
1692 | 1697 | ||
1693 | #ifdef CONFIG_NET_CLS_ACT | 1698 | #ifdef CONFIG_NET_CLS_ACT |
1694 | q->rx_class = NULL; | 1699 | q->rx_class = NULL; |
@@ -1712,7 +1717,7 @@ cbq_destroy(struct Qdisc* sch) | |||
1712 | 1717 | ||
1713 | static void cbq_put(struct Qdisc *sch, unsigned long arg) | 1718 | static void cbq_put(struct Qdisc *sch, unsigned long arg) |
1714 | { | 1719 | { |
1715 | struct cbq_class *cl = (struct cbq_class*)arg; | 1720 | struct cbq_class *cl = (struct cbq_class *)arg; |
1716 | 1721 | ||
1717 | if (--cl->refcnt == 0) { | 1722 | if (--cl->refcnt == 0) { |
1718 | #ifdef CONFIG_NET_CLS_ACT | 1723 | #ifdef CONFIG_NET_CLS_ACT |
@@ -1735,7 +1740,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1735 | { | 1740 | { |
1736 | int err; | 1741 | int err; |
1737 | struct cbq_sched_data *q = qdisc_priv(sch); | 1742 | struct cbq_sched_data *q = qdisc_priv(sch); |
1738 | struct cbq_class *cl = (struct cbq_class*)*arg; | 1743 | struct cbq_class *cl = (struct cbq_class *)*arg; |
1739 | struct nlattr *opt = tca[TCA_OPTIONS]; | 1744 | struct nlattr *opt = tca[TCA_OPTIONS]; |
1740 | struct nlattr *tb[TCA_CBQ_MAX + 1]; | 1745 | struct nlattr *tb[TCA_CBQ_MAX + 1]; |
1741 | struct cbq_class *parent; | 1746 | struct cbq_class *parent; |
@@ -1827,13 +1832,14 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1827 | 1832 | ||
1828 | if (classid) { | 1833 | if (classid) { |
1829 | err = -EINVAL; | 1834 | err = -EINVAL; |
1830 | if (TC_H_MAJ(classid^sch->handle) || cbq_class_lookup(q, classid)) | 1835 | if (TC_H_MAJ(classid ^ sch->handle) || |
1836 | cbq_class_lookup(q, classid)) | ||
1831 | goto failure; | 1837 | goto failure; |
1832 | } else { | 1838 | } else { |
1833 | int i; | 1839 | int i; |
1834 | classid = TC_H_MAKE(sch->handle,0x8000); | 1840 | classid = TC_H_MAKE(sch->handle, 0x8000); |
1835 | 1841 | ||
1836 | for (i=0; i<0x8000; i++) { | 1842 | for (i = 0; i < 0x8000; i++) { |
1837 | if (++q->hgenerator >= 0x8000) | 1843 | if (++q->hgenerator >= 0x8000) |
1838 | q->hgenerator = 1; | 1844 | q->hgenerator = 1; |
1839 | if (cbq_class_lookup(q, classid|q->hgenerator) == NULL) | 1845 | if (cbq_class_lookup(q, classid|q->hgenerator) == NULL) |
@@ -1890,11 +1896,11 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1890 | cl->minidle = -0x7FFFFFFF; | 1896 | cl->minidle = -0x7FFFFFFF; |
1891 | cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT])); | 1897 | cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT])); |
1892 | cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT])); | 1898 | cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT])); |
1893 | if (cl->ewma_log==0) | 1899 | if (cl->ewma_log == 0) |
1894 | cl->ewma_log = q->link.ewma_log; | 1900 | cl->ewma_log = q->link.ewma_log; |
1895 | if (cl->maxidle==0) | 1901 | if (cl->maxidle == 0) |
1896 | cl->maxidle = q->link.maxidle; | 1902 | cl->maxidle = q->link.maxidle; |
1897 | if (cl->avpkt==0) | 1903 | if (cl->avpkt == 0) |
1898 | cl->avpkt = q->link.avpkt; | 1904 | cl->avpkt = q->link.avpkt; |
1899 | cl->overlimit = cbq_ovl_classic; | 1905 | cl->overlimit = cbq_ovl_classic; |
1900 | if (tb[TCA_CBQ_OVL_STRATEGY]) | 1906 | if (tb[TCA_CBQ_OVL_STRATEGY]) |
@@ -1920,7 +1926,7 @@ failure: | |||
1920 | static int cbq_delete(struct Qdisc *sch, unsigned long arg) | 1926 | static int cbq_delete(struct Qdisc *sch, unsigned long arg) |
1921 | { | 1927 | { |
1922 | struct cbq_sched_data *q = qdisc_priv(sch); | 1928 | struct cbq_sched_data *q = qdisc_priv(sch); |
1923 | struct cbq_class *cl = (struct cbq_class*)arg; | 1929 | struct cbq_class *cl = (struct cbq_class *)arg; |
1924 | unsigned int qlen; | 1930 | unsigned int qlen; |
1925 | 1931 | ||
1926 | if (cl->filters || cl->children || cl == &q->link) | 1932 | if (cl->filters || cl->children || cl == &q->link) |
@@ -1978,7 +1984,7 @@ static unsigned long cbq_bind_filter(struct Qdisc *sch, unsigned long parent, | |||
1978 | u32 classid) | 1984 | u32 classid) |
1979 | { | 1985 | { |
1980 | struct cbq_sched_data *q = qdisc_priv(sch); | 1986 | struct cbq_sched_data *q = qdisc_priv(sch); |
1981 | struct cbq_class *p = (struct cbq_class*)parent; | 1987 | struct cbq_class *p = (struct cbq_class *)parent; |
1982 | struct cbq_class *cl = cbq_class_lookup(q, classid); | 1988 | struct cbq_class *cl = cbq_class_lookup(q, classid); |
1983 | 1989 | ||
1984 | if (cl) { | 1990 | if (cl) { |
@@ -1992,7 +1998,7 @@ static unsigned long cbq_bind_filter(struct Qdisc *sch, unsigned long parent, | |||
1992 | 1998 | ||
1993 | static void cbq_unbind_filter(struct Qdisc *sch, unsigned long arg) | 1999 | static void cbq_unbind_filter(struct Qdisc *sch, unsigned long arg) |
1994 | { | 2000 | { |
1995 | struct cbq_class *cl = (struct cbq_class*)arg; | 2001 | struct cbq_class *cl = (struct cbq_class *)arg; |
1996 | 2002 | ||
1997 | cl->filters--; | 2003 | cl->filters--; |
1998 | } | 2004 | } |
@@ -2002,7 +2008,7 @@ static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
2002 | struct cbq_sched_data *q = qdisc_priv(sch); | 2008 | struct cbq_sched_data *q = qdisc_priv(sch); |
2003 | struct cbq_class *cl; | 2009 | struct cbq_class *cl; |
2004 | struct hlist_node *n; | 2010 | struct hlist_node *n; |
2005 | unsigned h; | 2011 | unsigned int h; |
2006 | 2012 | ||
2007 | if (arg->stop) | 2013 | if (arg->stop) |
2008 | return; | 2014 | return; |
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c new file mode 100644 index 000000000000..06afbaeb4c88 --- /dev/null +++ b/net/sched/sch_choke.c | |||
@@ -0,0 +1,688 @@ | |||
1 | /* | ||
2 | * net/sched/sch_choke.c CHOKE scheduler | ||
3 | * | ||
4 | * Copyright (c) 2011 Stephen Hemminger <shemminger@vyatta.com> | ||
5 | * Copyright (c) 2011 Eric Dumazet <eric.dumazet@gmail.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | #include <linux/reciprocal_div.h> | ||
18 | #include <linux/vmalloc.h> | ||
19 | #include <net/pkt_sched.h> | ||
20 | #include <net/inet_ecn.h> | ||
21 | #include <net/red.h> | ||
22 | #include <linux/ip.h> | ||
23 | #include <net/ip.h> | ||
24 | #include <linux/ipv6.h> | ||
25 | #include <net/ipv6.h> | ||
26 | |||
27 | /* | ||
28 | CHOKe stateless AQM for fair bandwidth allocation | ||
29 | ================================================= | ||
30 | |||
31 | CHOKe (CHOose and Keep for responsive flows, CHOose and Kill for | ||
32 | unresponsive flows) is a variant of RED that penalizes misbehaving flows but | ||
33 | maintains no flow state. The difference from RED is an additional step | ||
34 | during the enqueuing process. If average queue size is over the | ||
35 | low threshold (qmin), a packet is chosen at random from the queue. | ||
36 | If both the new and chosen packet are from the same flow, both | ||
37 | are dropped. Unlike RED, CHOKe is not really a "classful" qdisc because it | ||
38 | needs to access packets in queue randomly. It has a minimal class | ||
39 | interface to allow overriding the builtin flow classifier with | ||
40 | filters. | ||
41 | |||
42 | Source: | ||
43 | R. Pan, B. Prabhakar, and K. Psounis, "CHOKe, A Stateless | ||
44 | Active Queue Management Scheme for Approximating Fair Bandwidth Allocation", | ||
45 | IEEE INFOCOM, 2000. | ||
46 | |||
47 | A. Tang, J. Wang, S. Low, "Understanding CHOKe: Throughput and Spatial | ||
48 | Characteristics", IEEE/ACM Transactions on Networking, 2004 | ||
49 | |||
50 | */ | ||
51 | |||
52 | /* Upper bound on size of sk_buff table (packets) */ | ||
53 | #define CHOKE_MAX_QUEUE (128*1024 - 1) | ||
54 | |||
55 | struct choke_sched_data { | ||
56 | /* Parameters */ | ||
57 | u32 limit; | ||
58 | unsigned char flags; | ||
59 | |||
60 | struct red_parms parms; | ||
61 | |||
62 | /* Variables */ | ||
63 | struct tcf_proto *filter_list; | ||
64 | struct { | ||
65 | u32 prob_drop; /* Early probability drops */ | ||
66 | u32 prob_mark; /* Early probability marks */ | ||
67 | u32 forced_drop; /* Forced drops, qavg > max_thresh */ | ||
68 | u32 forced_mark; /* Forced marks, qavg > max_thresh */ | ||
69 | u32 pdrop; /* Drops due to queue limits */ | ||
70 | u32 other; /* Drops due to drop() calls */ | ||
71 | u32 matched; /* Drops to flow match */ | ||
72 | } stats; | ||
73 | |||
74 | unsigned int head; | ||
75 | unsigned int tail; | ||
76 | |||
77 | unsigned int tab_mask; /* size - 1 */ | ||
78 | |||
79 | struct sk_buff **tab; | ||
80 | }; | ||
81 | |||
82 | /* deliver a random number between 0 and N - 1 */ | ||
83 | static u32 random_N(unsigned int N) | ||
84 | { | ||
85 | return reciprocal_divide(random32(), N); | ||
86 | } | ||
87 | |||
88 | /* number of elements in queue including holes */ | ||
89 | static unsigned int choke_len(const struct choke_sched_data *q) | ||
90 | { | ||
91 | return (q->tail - q->head) & q->tab_mask; | ||
92 | } | ||
93 | |||
94 | /* Is ECN parameter configured */ | ||
95 | static int use_ecn(const struct choke_sched_data *q) | ||
96 | { | ||
97 | return q->flags & TC_RED_ECN; | ||
98 | } | ||
99 | |||
100 | /* Should packets over max just be dropped (versus marked) */ | ||
101 | static int use_harddrop(const struct choke_sched_data *q) | ||
102 | { | ||
103 | return q->flags & TC_RED_HARDDROP; | ||
104 | } | ||
105 | |||
106 | /* Move head pointer forward to skip over holes */ | ||
107 | static void choke_zap_head_holes(struct choke_sched_data *q) | ||
108 | { | ||
109 | do { | ||
110 | q->head = (q->head + 1) & q->tab_mask; | ||
111 | if (q->head == q->tail) | ||
112 | break; | ||
113 | } while (q->tab[q->head] == NULL); | ||
114 | } | ||
115 | |||
116 | /* Move tail pointer backwards to reuse holes */ | ||
117 | static void choke_zap_tail_holes(struct choke_sched_data *q) | ||
118 | { | ||
119 | do { | ||
120 | q->tail = (q->tail - 1) & q->tab_mask; | ||
121 | if (q->head == q->tail) | ||
122 | break; | ||
123 | } while (q->tab[q->tail] == NULL); | ||
124 | } | ||
125 | |||
126 | /* Drop packet from queue array by creating a "hole" */ | ||
127 | static void choke_drop_by_idx(struct Qdisc *sch, unsigned int idx) | ||
128 | { | ||
129 | struct choke_sched_data *q = qdisc_priv(sch); | ||
130 | struct sk_buff *skb = q->tab[idx]; | ||
131 | |||
132 | q->tab[idx] = NULL; | ||
133 | |||
134 | if (idx == q->head) | ||
135 | choke_zap_head_holes(q); | ||
136 | if (idx == q->tail) | ||
137 | choke_zap_tail_holes(q); | ||
138 | |||
139 | sch->qstats.backlog -= qdisc_pkt_len(skb); | ||
140 | qdisc_drop(skb, sch); | ||
141 | qdisc_tree_decrease_qlen(sch, 1); | ||
142 | --sch->q.qlen; | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Compare flow of two packets | ||
147 | * Returns true only if source and destination address and port match. | ||
148 | * false for special cases | ||
149 | */ | ||
150 | static bool choke_match_flow(struct sk_buff *skb1, | ||
151 | struct sk_buff *skb2) | ||
152 | { | ||
153 | int off1, off2, poff; | ||
154 | const u32 *ports1, *ports2; | ||
155 | u8 ip_proto; | ||
156 | __u32 hash1; | ||
157 | |||
158 | if (skb1->protocol != skb2->protocol) | ||
159 | return false; | ||
160 | |||
161 | /* Use hash value as quick check | ||
162 | * Assumes that __skb_get_rxhash makes IP header and ports linear | ||
163 | */ | ||
164 | hash1 = skb_get_rxhash(skb1); | ||
165 | if (!hash1 || hash1 != skb_get_rxhash(skb2)) | ||
166 | return false; | ||
167 | |||
168 | /* Probably match, but be sure to avoid hash collisions */ | ||
169 | off1 = skb_network_offset(skb1); | ||
170 | off2 = skb_network_offset(skb2); | ||
171 | |||
172 | switch (skb1->protocol) { | ||
173 | case __constant_htons(ETH_P_IP): { | ||
174 | const struct iphdr *ip1, *ip2; | ||
175 | |||
176 | ip1 = (const struct iphdr *) (skb1->data + off1); | ||
177 | ip2 = (const struct iphdr *) (skb2->data + off2); | ||
178 | |||
179 | ip_proto = ip1->protocol; | ||
180 | if (ip_proto != ip2->protocol || | ||
181 | ip1->saddr != ip2->saddr || ip1->daddr != ip2->daddr) | ||
182 | return false; | ||
183 | |||
184 | if ((ip1->frag_off | ip2->frag_off) & htons(IP_MF | IP_OFFSET)) | ||
185 | ip_proto = 0; | ||
186 | off1 += ip1->ihl * 4; | ||
187 | off2 += ip2->ihl * 4; | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | case __constant_htons(ETH_P_IPV6): { | ||
192 | const struct ipv6hdr *ip1, *ip2; | ||
193 | |||
194 | ip1 = (const struct ipv6hdr *) (skb1->data + off1); | ||
195 | ip2 = (const struct ipv6hdr *) (skb2->data + off2); | ||
196 | |||
197 | ip_proto = ip1->nexthdr; | ||
198 | if (ip_proto != ip2->nexthdr || | ||
199 | ipv6_addr_cmp(&ip1->saddr, &ip2->saddr) || | ||
200 | ipv6_addr_cmp(&ip1->daddr, &ip2->daddr)) | ||
201 | return false; | ||
202 | off1 += 40; | ||
203 | off2 += 40; | ||
204 | } | ||
205 | |||
206 | default: /* Maybe compare MAC header here? */ | ||
207 | return false; | ||
208 | } | ||
209 | |||
210 | poff = proto_ports_offset(ip_proto); | ||
211 | if (poff < 0) | ||
212 | return true; | ||
213 | |||
214 | off1 += poff; | ||
215 | off2 += poff; | ||
216 | |||
217 | ports1 = (__force u32 *)(skb1->data + off1); | ||
218 | ports2 = (__force u32 *)(skb2->data + off2); | ||
219 | return *ports1 == *ports2; | ||
220 | } | ||
221 | |||
222 | struct choke_skb_cb { | ||
223 | u16 classid; | ||
224 | }; | ||
225 | |||
226 | static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb) | ||
227 | { | ||
228 | BUILD_BUG_ON(sizeof(skb->cb) < | ||
229 | sizeof(struct qdisc_skb_cb) + sizeof(struct choke_skb_cb)); | ||
230 | return (struct choke_skb_cb *)qdisc_skb_cb(skb)->data; | ||
231 | } | ||
232 | |||
233 | static inline void choke_set_classid(struct sk_buff *skb, u16 classid) | ||
234 | { | ||
235 | choke_skb_cb(skb)->classid = classid; | ||
236 | } | ||
237 | |||
238 | static u16 choke_get_classid(const struct sk_buff *skb) | ||
239 | { | ||
240 | return choke_skb_cb(skb)->classid; | ||
241 | } | ||
242 | |||
243 | /* | ||
244 | * Classify flow using either: | ||
245 | * 1. pre-existing classification result in skb | ||
246 | * 2. fast internal classification | ||
247 | * 3. use TC filter based classification | ||
248 | */ | ||
249 | static bool choke_classify(struct sk_buff *skb, | ||
250 | struct Qdisc *sch, int *qerr) | ||
251 | |||
252 | { | ||
253 | struct choke_sched_data *q = qdisc_priv(sch); | ||
254 | struct tcf_result res; | ||
255 | int result; | ||
256 | |||
257 | result = tc_classify(skb, q->filter_list, &res); | ||
258 | if (result >= 0) { | ||
259 | #ifdef CONFIG_NET_CLS_ACT | ||
260 | switch (result) { | ||
261 | case TC_ACT_STOLEN: | ||
262 | case TC_ACT_QUEUED: | ||
263 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; | ||
264 | case TC_ACT_SHOT: | ||
265 | return false; | ||
266 | } | ||
267 | #endif | ||
268 | choke_set_classid(skb, TC_H_MIN(res.classid)); | ||
269 | return true; | ||
270 | } | ||
271 | |||
272 | return false; | ||
273 | } | ||
274 | |||
275 | /* | ||
276 | * Select a packet at random from queue | ||
277 | * HACK: since queue can have holes from previous deletion; retry several | ||
278 | * times to find a random skb but then just give up and return the head | ||
279 | * Will return NULL if queue is empty (q->head == q->tail) | ||
280 | */ | ||
281 | static struct sk_buff *choke_peek_random(const struct choke_sched_data *q, | ||
282 | unsigned int *pidx) | ||
283 | { | ||
284 | struct sk_buff *skb; | ||
285 | int retrys = 3; | ||
286 | |||
287 | do { | ||
288 | *pidx = (q->head + random_N(choke_len(q))) & q->tab_mask; | ||
289 | skb = q->tab[*pidx]; | ||
290 | if (skb) | ||
291 | return skb; | ||
292 | } while (--retrys > 0); | ||
293 | |||
294 | return q->tab[*pidx = q->head]; | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * Compare new packet with random packet in queue | ||
299 | * returns true if matched and sets *pidx | ||
300 | */ | ||
301 | static bool choke_match_random(const struct choke_sched_data *q, | ||
302 | struct sk_buff *nskb, | ||
303 | unsigned int *pidx) | ||
304 | { | ||
305 | struct sk_buff *oskb; | ||
306 | |||
307 | if (q->head == q->tail) | ||
308 | return false; | ||
309 | |||
310 | oskb = choke_peek_random(q, pidx); | ||
311 | if (q->filter_list) | ||
312 | return choke_get_classid(nskb) == choke_get_classid(oskb); | ||
313 | |||
314 | return choke_match_flow(oskb, nskb); | ||
315 | } | ||
316 | |||
317 | static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch) | ||
318 | { | ||
319 | struct choke_sched_data *q = qdisc_priv(sch); | ||
320 | struct red_parms *p = &q->parms; | ||
321 | int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | ||
322 | |||
323 | if (q->filter_list) { | ||
324 | /* If using external classifiers, get result and record it. */ | ||
325 | if (!choke_classify(skb, sch, &ret)) | ||
326 | goto other_drop; /* Packet was eaten by filter */ | ||
327 | } | ||
328 | |||
329 | /* Compute average queue usage (see RED) */ | ||
330 | p->qavg = red_calc_qavg(p, sch->q.qlen); | ||
331 | if (red_is_idling(p)) | ||
332 | red_end_of_idle_period(p); | ||
333 | |||
334 | /* Is queue small? */ | ||
335 | if (p->qavg <= p->qth_min) | ||
336 | p->qcount = -1; | ||
337 | else { | ||
338 | unsigned int idx; | ||
339 | |||
340 | /* Draw a packet at random from queue and compare flow */ | ||
341 | if (choke_match_random(q, skb, &idx)) { | ||
342 | q->stats.matched++; | ||
343 | choke_drop_by_idx(sch, idx); | ||
344 | goto congestion_drop; | ||
345 | } | ||
346 | |||
347 | /* Queue is large, always mark/drop */ | ||
348 | if (p->qavg > p->qth_max) { | ||
349 | p->qcount = -1; | ||
350 | |||
351 | sch->qstats.overlimits++; | ||
352 | if (use_harddrop(q) || !use_ecn(q) || | ||
353 | !INET_ECN_set_ce(skb)) { | ||
354 | q->stats.forced_drop++; | ||
355 | goto congestion_drop; | ||
356 | } | ||
357 | |||
358 | q->stats.forced_mark++; | ||
359 | } else if (++p->qcount) { | ||
360 | if (red_mark_probability(p, p->qavg)) { | ||
361 | p->qcount = 0; | ||
362 | p->qR = red_random(p); | ||
363 | |||
364 | sch->qstats.overlimits++; | ||
365 | if (!use_ecn(q) || !INET_ECN_set_ce(skb)) { | ||
366 | q->stats.prob_drop++; | ||
367 | goto congestion_drop; | ||
368 | } | ||
369 | |||
370 | q->stats.prob_mark++; | ||
371 | } | ||
372 | } else | ||
373 | p->qR = red_random(p); | ||
374 | } | ||
375 | |||
376 | /* Admit new packet */ | ||
377 | if (sch->q.qlen < q->limit) { | ||
378 | q->tab[q->tail] = skb; | ||
379 | q->tail = (q->tail + 1) & q->tab_mask; | ||
380 | ++sch->q.qlen; | ||
381 | sch->qstats.backlog += qdisc_pkt_len(skb); | ||
382 | return NET_XMIT_SUCCESS; | ||
383 | } | ||
384 | |||
385 | q->stats.pdrop++; | ||
386 | sch->qstats.drops++; | ||
387 | kfree_skb(skb); | ||
388 | return NET_XMIT_DROP; | ||
389 | |||
390 | congestion_drop: | ||
391 | qdisc_drop(skb, sch); | ||
392 | return NET_XMIT_CN; | ||
393 | |||
394 | other_drop: | ||
395 | if (ret & __NET_XMIT_BYPASS) | ||
396 | sch->qstats.drops++; | ||
397 | kfree_skb(skb); | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | static struct sk_buff *choke_dequeue(struct Qdisc *sch) | ||
402 | { | ||
403 | struct choke_sched_data *q = qdisc_priv(sch); | ||
404 | struct sk_buff *skb; | ||
405 | |||
406 | if (q->head == q->tail) { | ||
407 | if (!red_is_idling(&q->parms)) | ||
408 | red_start_of_idle_period(&q->parms); | ||
409 | return NULL; | ||
410 | } | ||
411 | |||
412 | skb = q->tab[q->head]; | ||
413 | q->tab[q->head] = NULL; | ||
414 | choke_zap_head_holes(q); | ||
415 | --sch->q.qlen; | ||
416 | sch->qstats.backlog -= qdisc_pkt_len(skb); | ||
417 | qdisc_bstats_update(sch, skb); | ||
418 | |||
419 | return skb; | ||
420 | } | ||
421 | |||
422 | static unsigned int choke_drop(struct Qdisc *sch) | ||
423 | { | ||
424 | struct choke_sched_data *q = qdisc_priv(sch); | ||
425 | unsigned int len; | ||
426 | |||
427 | len = qdisc_queue_drop(sch); | ||
428 | if (len > 0) | ||
429 | q->stats.other++; | ||
430 | else { | ||
431 | if (!red_is_idling(&q->parms)) | ||
432 | red_start_of_idle_period(&q->parms); | ||
433 | } | ||
434 | |||
435 | return len; | ||
436 | } | ||
437 | |||
438 | static void choke_reset(struct Qdisc *sch) | ||
439 | { | ||
440 | struct choke_sched_data *q = qdisc_priv(sch); | ||
441 | |||
442 | red_restart(&q->parms); | ||
443 | } | ||
444 | |||
445 | static const struct nla_policy choke_policy[TCA_CHOKE_MAX + 1] = { | ||
446 | [TCA_CHOKE_PARMS] = { .len = sizeof(struct tc_red_qopt) }, | ||
447 | [TCA_CHOKE_STAB] = { .len = RED_STAB_SIZE }, | ||
448 | }; | ||
449 | |||
450 | |||
451 | static void choke_free(void *addr) | ||
452 | { | ||
453 | if (addr) { | ||
454 | if (is_vmalloc_addr(addr)) | ||
455 | vfree(addr); | ||
456 | else | ||
457 | kfree(addr); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | static int choke_change(struct Qdisc *sch, struct nlattr *opt) | ||
462 | { | ||
463 | struct choke_sched_data *q = qdisc_priv(sch); | ||
464 | struct nlattr *tb[TCA_CHOKE_MAX + 1]; | ||
465 | const struct tc_red_qopt *ctl; | ||
466 | int err; | ||
467 | struct sk_buff **old = NULL; | ||
468 | unsigned int mask; | ||
469 | |||
470 | if (opt == NULL) | ||
471 | return -EINVAL; | ||
472 | |||
473 | err = nla_parse_nested(tb, TCA_CHOKE_MAX, opt, choke_policy); | ||
474 | if (err < 0) | ||
475 | return err; | ||
476 | |||
477 | if (tb[TCA_CHOKE_PARMS] == NULL || | ||
478 | tb[TCA_CHOKE_STAB] == NULL) | ||
479 | return -EINVAL; | ||
480 | |||
481 | ctl = nla_data(tb[TCA_CHOKE_PARMS]); | ||
482 | |||
483 | if (ctl->limit > CHOKE_MAX_QUEUE) | ||
484 | return -EINVAL; | ||
485 | |||
486 | mask = roundup_pow_of_two(ctl->limit + 1) - 1; | ||
487 | if (mask != q->tab_mask) { | ||
488 | struct sk_buff **ntab; | ||
489 | |||
490 | ntab = kcalloc(mask + 1, sizeof(struct sk_buff *), GFP_KERNEL); | ||
491 | if (!ntab) | ||
492 | ntab = vzalloc((mask + 1) * sizeof(struct sk_buff *)); | ||
493 | if (!ntab) | ||
494 | return -ENOMEM; | ||
495 | |||
496 | sch_tree_lock(sch); | ||
497 | old = q->tab; | ||
498 | if (old) { | ||
499 | unsigned int oqlen = sch->q.qlen, tail = 0; | ||
500 | |||
501 | while (q->head != q->tail) { | ||
502 | struct sk_buff *skb = q->tab[q->head]; | ||
503 | |||
504 | q->head = (q->head + 1) & q->tab_mask; | ||
505 | if (!skb) | ||
506 | continue; | ||
507 | if (tail < mask) { | ||
508 | ntab[tail++] = skb; | ||
509 | continue; | ||
510 | } | ||
511 | sch->qstats.backlog -= qdisc_pkt_len(skb); | ||
512 | --sch->q.qlen; | ||
513 | qdisc_drop(skb, sch); | ||
514 | } | ||
515 | qdisc_tree_decrease_qlen(sch, oqlen - sch->q.qlen); | ||
516 | q->head = 0; | ||
517 | q->tail = tail; | ||
518 | } | ||
519 | |||
520 | q->tab_mask = mask; | ||
521 | q->tab = ntab; | ||
522 | } else | ||
523 | sch_tree_lock(sch); | ||
524 | |||
525 | q->flags = ctl->flags; | ||
526 | q->limit = ctl->limit; | ||
527 | |||
528 | red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, | ||
529 | ctl->Plog, ctl->Scell_log, | ||
530 | nla_data(tb[TCA_CHOKE_STAB])); | ||
531 | |||
532 | if (q->head == q->tail) | ||
533 | red_end_of_idle_period(&q->parms); | ||
534 | |||
535 | sch_tree_unlock(sch); | ||
536 | choke_free(old); | ||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static int choke_init(struct Qdisc *sch, struct nlattr *opt) | ||
541 | { | ||
542 | return choke_change(sch, opt); | ||
543 | } | ||
544 | |||
545 | static int choke_dump(struct Qdisc *sch, struct sk_buff *skb) | ||
546 | { | ||
547 | struct choke_sched_data *q = qdisc_priv(sch); | ||
548 | struct nlattr *opts = NULL; | ||
549 | struct tc_red_qopt opt = { | ||
550 | .limit = q->limit, | ||
551 | .flags = q->flags, | ||
552 | .qth_min = q->parms.qth_min >> q->parms.Wlog, | ||
553 | .qth_max = q->parms.qth_max >> q->parms.Wlog, | ||
554 | .Wlog = q->parms.Wlog, | ||
555 | .Plog = q->parms.Plog, | ||
556 | .Scell_log = q->parms.Scell_log, | ||
557 | }; | ||
558 | |||
559 | opts = nla_nest_start(skb, TCA_OPTIONS); | ||
560 | if (opts == NULL) | ||
561 | goto nla_put_failure; | ||
562 | |||
563 | NLA_PUT(skb, TCA_CHOKE_PARMS, sizeof(opt), &opt); | ||
564 | return nla_nest_end(skb, opts); | ||
565 | |||
566 | nla_put_failure: | ||
567 | nla_nest_cancel(skb, opts); | ||
568 | return -EMSGSIZE; | ||
569 | } | ||
570 | |||
571 | static int choke_dump_stats(struct Qdisc *sch, struct gnet_dump *d) | ||
572 | { | ||
573 | struct choke_sched_data *q = qdisc_priv(sch); | ||
574 | struct tc_choke_xstats st = { | ||
575 | .early = q->stats.prob_drop + q->stats.forced_drop, | ||
576 | .marked = q->stats.prob_mark + q->stats.forced_mark, | ||
577 | .pdrop = q->stats.pdrop, | ||
578 | .other = q->stats.other, | ||
579 | .matched = q->stats.matched, | ||
580 | }; | ||
581 | |||
582 | return gnet_stats_copy_app(d, &st, sizeof(st)); | ||
583 | } | ||
584 | |||
585 | static void choke_destroy(struct Qdisc *sch) | ||
586 | { | ||
587 | struct choke_sched_data *q = qdisc_priv(sch); | ||
588 | |||
589 | tcf_destroy_chain(&q->filter_list); | ||
590 | choke_free(q->tab); | ||
591 | } | ||
592 | |||
593 | static struct Qdisc *choke_leaf(struct Qdisc *sch, unsigned long arg) | ||
594 | { | ||
595 | return NULL; | ||
596 | } | ||
597 | |||
598 | static unsigned long choke_get(struct Qdisc *sch, u32 classid) | ||
599 | { | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static void choke_put(struct Qdisc *q, unsigned long cl) | ||
604 | { | ||
605 | } | ||
606 | |||
607 | static unsigned long choke_bind(struct Qdisc *sch, unsigned long parent, | ||
608 | u32 classid) | ||
609 | { | ||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static struct tcf_proto **choke_find_tcf(struct Qdisc *sch, unsigned long cl) | ||
614 | { | ||
615 | struct choke_sched_data *q = qdisc_priv(sch); | ||
616 | |||
617 | if (cl) | ||
618 | return NULL; | ||
619 | return &q->filter_list; | ||
620 | } | ||
621 | |||
622 | static int choke_dump_class(struct Qdisc *sch, unsigned long cl, | ||
623 | struct sk_buff *skb, struct tcmsg *tcm) | ||
624 | { | ||
625 | tcm->tcm_handle |= TC_H_MIN(cl); | ||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | static void choke_walk(struct Qdisc *sch, struct qdisc_walker *arg) | ||
630 | { | ||
631 | if (!arg->stop) { | ||
632 | if (arg->fn(sch, 1, arg) < 0) { | ||
633 | arg->stop = 1; | ||
634 | return; | ||
635 | } | ||
636 | arg->count++; | ||
637 | } | ||
638 | } | ||
639 | |||
640 | static const struct Qdisc_class_ops choke_class_ops = { | ||
641 | .leaf = choke_leaf, | ||
642 | .get = choke_get, | ||
643 | .put = choke_put, | ||
644 | .tcf_chain = choke_find_tcf, | ||
645 | .bind_tcf = choke_bind, | ||
646 | .unbind_tcf = choke_put, | ||
647 | .dump = choke_dump_class, | ||
648 | .walk = choke_walk, | ||
649 | }; | ||
650 | |||
651 | static struct sk_buff *choke_peek_head(struct Qdisc *sch) | ||
652 | { | ||
653 | struct choke_sched_data *q = qdisc_priv(sch); | ||
654 | |||
655 | return (q->head != q->tail) ? q->tab[q->head] : NULL; | ||
656 | } | ||
657 | |||
658 | static struct Qdisc_ops choke_qdisc_ops __read_mostly = { | ||
659 | .id = "choke", | ||
660 | .priv_size = sizeof(struct choke_sched_data), | ||
661 | |||
662 | .enqueue = choke_enqueue, | ||
663 | .dequeue = choke_dequeue, | ||
664 | .peek = choke_peek_head, | ||
665 | .drop = choke_drop, | ||
666 | .init = choke_init, | ||
667 | .destroy = choke_destroy, | ||
668 | .reset = choke_reset, | ||
669 | .change = choke_change, | ||
670 | .dump = choke_dump, | ||
671 | .dump_stats = choke_dump_stats, | ||
672 | .owner = THIS_MODULE, | ||
673 | }; | ||
674 | |||
675 | static int __init choke_module_init(void) | ||
676 | { | ||
677 | return register_qdisc(&choke_qdisc_ops); | ||
678 | } | ||
679 | |||
680 | static void __exit choke_module_exit(void) | ||
681 | { | ||
682 | unregister_qdisc(&choke_qdisc_ops); | ||
683 | } | ||
684 | |||
685 | module_init(choke_module_init) | ||
686 | module_exit(choke_module_exit) | ||
687 | |||
688 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 0f7bf3fdfea5..2c790204d042 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c | |||
@@ -137,10 +137,10 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent, | |||
137 | mask = nla_get_u8(tb[TCA_DSMARK_MASK]); | 137 | mask = nla_get_u8(tb[TCA_DSMARK_MASK]); |
138 | 138 | ||
139 | if (tb[TCA_DSMARK_VALUE]) | 139 | if (tb[TCA_DSMARK_VALUE]) |
140 | p->value[*arg-1] = nla_get_u8(tb[TCA_DSMARK_VALUE]); | 140 | p->value[*arg - 1] = nla_get_u8(tb[TCA_DSMARK_VALUE]); |
141 | 141 | ||
142 | if (tb[TCA_DSMARK_MASK]) | 142 | if (tb[TCA_DSMARK_MASK]) |
143 | p->mask[*arg-1] = mask; | 143 | p->mask[*arg - 1] = mask; |
144 | 144 | ||
145 | err = 0; | 145 | err = 0; |
146 | 146 | ||
@@ -155,8 +155,8 @@ static int dsmark_delete(struct Qdisc *sch, unsigned long arg) | |||
155 | if (!dsmark_valid_index(p, arg)) | 155 | if (!dsmark_valid_index(p, arg)) |
156 | return -EINVAL; | 156 | return -EINVAL; |
157 | 157 | ||
158 | p->mask[arg-1] = 0xff; | 158 | p->mask[arg - 1] = 0xff; |
159 | p->value[arg-1] = 0; | 159 | p->value[arg - 1] = 0; |
160 | 160 | ||
161 | return 0; | 161 | return 0; |
162 | } | 162 | } |
@@ -175,7 +175,7 @@ static void dsmark_walk(struct Qdisc *sch, struct qdisc_walker *walker) | |||
175 | if (p->mask[i] == 0xff && !p->value[i]) | 175 | if (p->mask[i] == 0xff && !p->value[i]) |
176 | goto ignore; | 176 | goto ignore; |
177 | if (walker->count >= walker->skip) { | 177 | if (walker->count >= walker->skip) { |
178 | if (walker->fn(sch, i+1, walker) < 0) { | 178 | if (walker->fn(sch, i + 1, walker) < 0) { |
179 | walker->stop = 1; | 179 | walker->stop = 1; |
180 | break; | 180 | break; |
181 | } | 181 | } |
@@ -304,9 +304,8 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) | |||
304 | * and don't need yet another qdisc as a bypass. | 304 | * and don't need yet another qdisc as a bypass. |
305 | */ | 305 | */ |
306 | if (p->mask[index] != 0xff || p->value[index]) | 306 | if (p->mask[index] != 0xff || p->value[index]) |
307 | printk(KERN_WARNING | 307 | pr_warning("dsmark_dequeue: unsupported protocol %d\n", |
308 | "dsmark_dequeue: unsupported protocol %d\n", | 308 | ntohs(skb->protocol)); |
309 | ntohs(skb->protocol)); | ||
310 | break; | 309 | break; |
311 | } | 310 | } |
312 | 311 | ||
@@ -424,14 +423,14 @@ static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl, | |||
424 | if (!dsmark_valid_index(p, cl)) | 423 | if (!dsmark_valid_index(p, cl)) |
425 | return -EINVAL; | 424 | return -EINVAL; |
426 | 425 | ||
427 | tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1); | 426 | tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl - 1); |
428 | tcm->tcm_info = p->q->handle; | 427 | tcm->tcm_info = p->q->handle; |
429 | 428 | ||
430 | opts = nla_nest_start(skb, TCA_OPTIONS); | 429 | opts = nla_nest_start(skb, TCA_OPTIONS); |
431 | if (opts == NULL) | 430 | if (opts == NULL) |
432 | goto nla_put_failure; | 431 | goto nla_put_failure; |
433 | NLA_PUT_U8(skb, TCA_DSMARK_MASK, p->mask[cl-1]); | 432 | NLA_PUT_U8(skb, TCA_DSMARK_MASK, p->mask[cl - 1]); |
434 | NLA_PUT_U8(skb, TCA_DSMARK_VALUE, p->value[cl-1]); | 433 | NLA_PUT_U8(skb, TCA_DSMARK_VALUE, p->value[cl - 1]); |
435 | 434 | ||
436 | return nla_nest_end(skb, opts); | 435 | return nla_nest_end(skb, opts); |
437 | 436 | ||
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index d468b479aa93..66effe2da8e0 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c | |||
@@ -19,36 +19,25 @@ | |||
19 | 19 | ||
20 | /* 1 band FIFO pseudo-"scheduler" */ | 20 | /* 1 band FIFO pseudo-"scheduler" */ |
21 | 21 | ||
22 | struct fifo_sched_data | 22 | static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
23 | { | 23 | { |
24 | u32 limit; | 24 | if (likely(sch->qstats.backlog + qdisc_pkt_len(skb) <= sch->limit)) |
25 | }; | ||
26 | |||
27 | static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) | ||
28 | { | ||
29 | struct fifo_sched_data *q = qdisc_priv(sch); | ||
30 | |||
31 | if (likely(sch->qstats.backlog + qdisc_pkt_len(skb) <= q->limit)) | ||
32 | return qdisc_enqueue_tail(skb, sch); | 25 | return qdisc_enqueue_tail(skb, sch); |
33 | 26 | ||
34 | return qdisc_reshape_fail(skb, sch); | 27 | return qdisc_reshape_fail(skb, sch); |
35 | } | 28 | } |
36 | 29 | ||
37 | static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) | 30 | static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
38 | { | 31 | { |
39 | struct fifo_sched_data *q = qdisc_priv(sch); | 32 | if (likely(skb_queue_len(&sch->q) < sch->limit)) |
40 | |||
41 | if (likely(skb_queue_len(&sch->q) < q->limit)) | ||
42 | return qdisc_enqueue_tail(skb, sch); | 33 | return qdisc_enqueue_tail(skb, sch); |
43 | 34 | ||
44 | return qdisc_reshape_fail(skb, sch); | 35 | return qdisc_reshape_fail(skb, sch); |
45 | } | 36 | } |
46 | 37 | ||
47 | static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc* sch) | 38 | static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
48 | { | 39 | { |
49 | struct fifo_sched_data *q = qdisc_priv(sch); | 40 | if (likely(skb_queue_len(&sch->q) < sch->limit)) |
50 | |||
51 | if (likely(skb_queue_len(&sch->q) < q->limit)) | ||
52 | return qdisc_enqueue_tail(skb, sch); | 41 | return qdisc_enqueue_tail(skb, sch); |
53 | 42 | ||
54 | /* queue full, remove one skb to fulfill the limit */ | 43 | /* queue full, remove one skb to fulfill the limit */ |
@@ -61,31 +50,40 @@ static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
61 | 50 | ||
62 | static int fifo_init(struct Qdisc *sch, struct nlattr *opt) | 51 | static int fifo_init(struct Qdisc *sch, struct nlattr *opt) |
63 | { | 52 | { |
64 | struct fifo_sched_data *q = qdisc_priv(sch); | 53 | bool bypass; |
54 | bool is_bfifo = sch->ops == &bfifo_qdisc_ops; | ||
65 | 55 | ||
66 | if (opt == NULL) { | 56 | if (opt == NULL) { |
67 | u32 limit = qdisc_dev(sch)->tx_queue_len ? : 1; | 57 | u32 limit = qdisc_dev(sch)->tx_queue_len ? : 1; |
68 | 58 | ||
69 | if (sch->ops == &bfifo_qdisc_ops) | 59 | if (is_bfifo) |
70 | limit *= psched_mtu(qdisc_dev(sch)); | 60 | limit *= psched_mtu(qdisc_dev(sch)); |
71 | 61 | ||
72 | q->limit = limit; | 62 | sch->limit = limit; |
73 | } else { | 63 | } else { |
74 | struct tc_fifo_qopt *ctl = nla_data(opt); | 64 | struct tc_fifo_qopt *ctl = nla_data(opt); |
75 | 65 | ||
76 | if (nla_len(opt) < sizeof(*ctl)) | 66 | if (nla_len(opt) < sizeof(*ctl)) |
77 | return -EINVAL; | 67 | return -EINVAL; |
78 | 68 | ||
79 | q->limit = ctl->limit; | 69 | sch->limit = ctl->limit; |
80 | } | 70 | } |
81 | 71 | ||
72 | if (is_bfifo) | ||
73 | bypass = sch->limit >= psched_mtu(qdisc_dev(sch)); | ||
74 | else | ||
75 | bypass = sch->limit >= 1; | ||
76 | |||
77 | if (bypass) | ||
78 | sch->flags |= TCQ_F_CAN_BYPASS; | ||
79 | else | ||
80 | sch->flags &= ~TCQ_F_CAN_BYPASS; | ||
82 | return 0; | 81 | return 0; |
83 | } | 82 | } |
84 | 83 | ||
85 | static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb) | 84 | static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb) |
86 | { | 85 | { |
87 | struct fifo_sched_data *q = qdisc_priv(sch); | 86 | struct tc_fifo_qopt opt = { .limit = sch->limit }; |
88 | struct tc_fifo_qopt opt = { .limit = q->limit }; | ||
89 | 87 | ||
90 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | 88 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); |
91 | return skb->len; | 89 | return skb->len; |
@@ -96,7 +94,7 @@ nla_put_failure: | |||
96 | 94 | ||
97 | struct Qdisc_ops pfifo_qdisc_ops __read_mostly = { | 95 | struct Qdisc_ops pfifo_qdisc_ops __read_mostly = { |
98 | .id = "pfifo", | 96 | .id = "pfifo", |
99 | .priv_size = sizeof(struct fifo_sched_data), | 97 | .priv_size = 0, |
100 | .enqueue = pfifo_enqueue, | 98 | .enqueue = pfifo_enqueue, |
101 | .dequeue = qdisc_dequeue_head, | 99 | .dequeue = qdisc_dequeue_head, |
102 | .peek = qdisc_peek_head, | 100 | .peek = qdisc_peek_head, |
@@ -111,7 +109,7 @@ EXPORT_SYMBOL(pfifo_qdisc_ops); | |||
111 | 109 | ||
112 | struct Qdisc_ops bfifo_qdisc_ops __read_mostly = { | 110 | struct Qdisc_ops bfifo_qdisc_ops __read_mostly = { |
113 | .id = "bfifo", | 111 | .id = "bfifo", |
114 | .priv_size = sizeof(struct fifo_sched_data), | 112 | .priv_size = 0, |
115 | .enqueue = bfifo_enqueue, | 113 | .enqueue = bfifo_enqueue, |
116 | .dequeue = qdisc_dequeue_head, | 114 | .dequeue = qdisc_dequeue_head, |
117 | .peek = qdisc_peek_head, | 115 | .peek = qdisc_peek_head, |
@@ -126,7 +124,7 @@ EXPORT_SYMBOL(bfifo_qdisc_ops); | |||
126 | 124 | ||
127 | struct Qdisc_ops pfifo_head_drop_qdisc_ops __read_mostly = { | 125 | struct Qdisc_ops pfifo_head_drop_qdisc_ops __read_mostly = { |
128 | .id = "pfifo_head_drop", | 126 | .id = "pfifo_head_drop", |
129 | .priv_size = sizeof(struct fifo_sched_data), | 127 | .priv_size = 0, |
130 | .enqueue = pfifo_tail_enqueue, | 128 | .enqueue = pfifo_tail_enqueue, |
131 | .dequeue = qdisc_dequeue_head, | 129 | .dequeue = qdisc_dequeue_head, |
132 | .peek = qdisc_peek_head, | 130 | .peek = qdisc_peek_head, |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 34dc598440a2..c84b65920d1b 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -87,8 +87,8 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, | |||
87 | */ | 87 | */ |
88 | kfree_skb(skb); | 88 | kfree_skb(skb); |
89 | if (net_ratelimit()) | 89 | if (net_ratelimit()) |
90 | printk(KERN_WARNING "Dead loop on netdevice %s, " | 90 | pr_warning("Dead loop on netdevice %s, fix it urgently!\n", |
91 | "fix it urgently!\n", dev_queue->dev->name); | 91 | dev_queue->dev->name); |
92 | ret = qdisc_qlen(q); | 92 | ret = qdisc_qlen(q); |
93 | } else { | 93 | } else { |
94 | /* | 94 | /* |
@@ -137,8 +137,8 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, | |||
137 | } else { | 137 | } else { |
138 | /* Driver returned NETDEV_TX_BUSY - requeue skb */ | 138 | /* Driver returned NETDEV_TX_BUSY - requeue skb */ |
139 | if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit())) | 139 | if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit())) |
140 | printk(KERN_WARNING "BUG %s code %d qlen %d\n", | 140 | pr_warning("BUG %s code %d qlen %d\n", |
141 | dev->name, ret, q->q.qlen); | 141 | dev->name, ret, q->q.qlen); |
142 | 142 | ||
143 | ret = dev_requeue_skb(skb, q); | 143 | ret = dev_requeue_skb(skb, q); |
144 | } | 144 | } |
@@ -412,8 +412,9 @@ static struct Qdisc noqueue_qdisc = { | |||
412 | }; | 412 | }; |
413 | 413 | ||
414 | 414 | ||
415 | static const u8 prio2band[TC_PRIO_MAX+1] = | 415 | static const u8 prio2band[TC_PRIO_MAX + 1] = { |
416 | { 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 }; | 416 | 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 |
417 | }; | ||
417 | 418 | ||
418 | /* 3-band FIFO queue: old style, but should be a bit faster than | 419 | /* 3-band FIFO queue: old style, but should be a bit faster than |
419 | generic prio+fifo combination. | 420 | generic prio+fifo combination. |
@@ -445,7 +446,7 @@ static inline struct sk_buff_head *band2list(struct pfifo_fast_priv *priv, | |||
445 | return priv->q + band; | 446 | return priv->q + band; |
446 | } | 447 | } |
447 | 448 | ||
448 | static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) | 449 | static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc) |
449 | { | 450 | { |
450 | if (skb_queue_len(&qdisc->q) < qdisc_dev(qdisc)->tx_queue_len) { | 451 | if (skb_queue_len(&qdisc->q) < qdisc_dev(qdisc)->tx_queue_len) { |
451 | int band = prio2band[skb->priority & TC_PRIO_MAX]; | 452 | int band = prio2band[skb->priority & TC_PRIO_MAX]; |
@@ -460,7 +461,7 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) | |||
460 | return qdisc_drop(skb, qdisc); | 461 | return qdisc_drop(skb, qdisc); |
461 | } | 462 | } |
462 | 463 | ||
463 | static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc) | 464 | static struct sk_buff *pfifo_fast_dequeue(struct Qdisc *qdisc) |
464 | { | 465 | { |
465 | struct pfifo_fast_priv *priv = qdisc_priv(qdisc); | 466 | struct pfifo_fast_priv *priv = qdisc_priv(qdisc); |
466 | int band = bitmap2band[priv->bitmap]; | 467 | int band = bitmap2band[priv->bitmap]; |
@@ -479,7 +480,7 @@ static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc) | |||
479 | return NULL; | 480 | return NULL; |
480 | } | 481 | } |
481 | 482 | ||
482 | static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc) | 483 | static struct sk_buff *pfifo_fast_peek(struct Qdisc *qdisc) |
483 | { | 484 | { |
484 | struct pfifo_fast_priv *priv = qdisc_priv(qdisc); | 485 | struct pfifo_fast_priv *priv = qdisc_priv(qdisc); |
485 | int band = bitmap2band[priv->bitmap]; | 486 | int band = bitmap2band[priv->bitmap]; |
@@ -493,7 +494,7 @@ static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc) | |||
493 | return NULL; | 494 | return NULL; |
494 | } | 495 | } |
495 | 496 | ||
496 | static void pfifo_fast_reset(struct Qdisc* qdisc) | 497 | static void pfifo_fast_reset(struct Qdisc *qdisc) |
497 | { | 498 | { |
498 | int prio; | 499 | int prio; |
499 | struct pfifo_fast_priv *priv = qdisc_priv(qdisc); | 500 | struct pfifo_fast_priv *priv = qdisc_priv(qdisc); |
@@ -510,7 +511,7 @@ static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb) | |||
510 | { | 511 | { |
511 | struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS }; | 512 | struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS }; |
512 | 513 | ||
513 | memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1); | 514 | memcpy(&opt.priomap, prio2band, TC_PRIO_MAX + 1); |
514 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | 515 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); |
515 | return skb->len; | 516 | return skb->len; |
516 | 517 | ||
@@ -526,6 +527,8 @@ static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt) | |||
526 | for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) | 527 | for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) |
527 | skb_queue_head_init(band2list(priv, prio)); | 528 | skb_queue_head_init(band2list(priv, prio)); |
528 | 529 | ||
530 | /* Can by-pass the queue discipline */ | ||
531 | qdisc->flags |= TCQ_F_CAN_BYPASS; | ||
529 | return 0; | 532 | return 0; |
530 | } | 533 | } |
531 | 534 | ||
@@ -540,27 +543,32 @@ struct Qdisc_ops pfifo_fast_ops __read_mostly = { | |||
540 | .dump = pfifo_fast_dump, | 543 | .dump = pfifo_fast_dump, |
541 | .owner = THIS_MODULE, | 544 | .owner = THIS_MODULE, |
542 | }; | 545 | }; |
546 | EXPORT_SYMBOL(pfifo_fast_ops); | ||
543 | 547 | ||
544 | struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, | 548 | struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, |
545 | struct Qdisc_ops *ops) | 549 | struct Qdisc_ops *ops) |
546 | { | 550 | { |
547 | void *p; | 551 | void *p; |
548 | struct Qdisc *sch; | 552 | struct Qdisc *sch; |
549 | unsigned int size; | 553 | unsigned int size = QDISC_ALIGN(sizeof(*sch)) + ops->priv_size; |
550 | int err = -ENOBUFS; | 554 | int err = -ENOBUFS; |
551 | 555 | ||
552 | /* ensure that the Qdisc and the private data are 64-byte aligned */ | ||
553 | size = QDISC_ALIGN(sizeof(*sch)); | ||
554 | size += ops->priv_size + (QDISC_ALIGNTO - 1); | ||
555 | |||
556 | p = kzalloc_node(size, GFP_KERNEL, | 556 | p = kzalloc_node(size, GFP_KERNEL, |
557 | netdev_queue_numa_node_read(dev_queue)); | 557 | netdev_queue_numa_node_read(dev_queue)); |
558 | 558 | ||
559 | if (!p) | 559 | if (!p) |
560 | goto errout; | 560 | goto errout; |
561 | sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p); | 561 | sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p); |
562 | sch->padded = (char *) sch - (char *) p; | 562 | /* if we got non aligned memory, ask more and do alignment ourself */ |
563 | 563 | if (sch != p) { | |
564 | kfree(p); | ||
565 | p = kzalloc_node(size + QDISC_ALIGNTO - 1, GFP_KERNEL, | ||
566 | netdev_queue_numa_node_read(dev_queue)); | ||
567 | if (!p) | ||
568 | goto errout; | ||
569 | sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p); | ||
570 | sch->padded = (char *) sch - (char *) p; | ||
571 | } | ||
564 | INIT_LIST_HEAD(&sch->list); | 572 | INIT_LIST_HEAD(&sch->list); |
565 | skb_queue_head_init(&sch->q); | 573 | skb_queue_head_init(&sch->q); |
566 | spin_lock_init(&sch->busylock); | 574 | spin_lock_init(&sch->busylock); |
@@ -630,7 +638,7 @@ void qdisc_destroy(struct Qdisc *qdisc) | |||
630 | #ifdef CONFIG_NET_SCHED | 638 | #ifdef CONFIG_NET_SCHED |
631 | qdisc_list_del(qdisc); | 639 | qdisc_list_del(qdisc); |
632 | 640 | ||
633 | qdisc_put_stab(qdisc->stab); | 641 | qdisc_put_stab(rtnl_dereference(qdisc->stab)); |
634 | #endif | 642 | #endif |
635 | gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est); | 643 | gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est); |
636 | if (ops->reset) | 644 | if (ops->reset) |
@@ -674,25 +682,21 @@ struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, | |||
674 | 682 | ||
675 | return oqdisc; | 683 | return oqdisc; |
676 | } | 684 | } |
685 | EXPORT_SYMBOL(dev_graft_qdisc); | ||
677 | 686 | ||
678 | static void attach_one_default_qdisc(struct net_device *dev, | 687 | static void attach_one_default_qdisc(struct net_device *dev, |
679 | struct netdev_queue *dev_queue, | 688 | struct netdev_queue *dev_queue, |
680 | void *_unused) | 689 | void *_unused) |
681 | { | 690 | { |
682 | struct Qdisc *qdisc; | 691 | struct Qdisc *qdisc = &noqueue_qdisc; |
683 | 692 | ||
684 | if (dev->tx_queue_len) { | 693 | if (dev->tx_queue_len) { |
685 | qdisc = qdisc_create_dflt(dev_queue, | 694 | qdisc = qdisc_create_dflt(dev_queue, |
686 | &pfifo_fast_ops, TC_H_ROOT); | 695 | &pfifo_fast_ops, TC_H_ROOT); |
687 | if (!qdisc) { | 696 | if (!qdisc) { |
688 | printk(KERN_INFO "%s: activation failed\n", dev->name); | 697 | netdev_info(dev, "activation failed\n"); |
689 | return; | 698 | return; |
690 | } | 699 | } |
691 | |||
692 | /* Can by-pass the queue discipline for default qdisc */ | ||
693 | qdisc->flags |= TCQ_F_CAN_BYPASS; | ||
694 | } else { | ||
695 | qdisc = &noqueue_qdisc; | ||
696 | } | 700 | } |
697 | dev_queue->qdisc_sleeping = qdisc; | 701 | dev_queue->qdisc_sleeping = qdisc; |
698 | } | 702 | } |
@@ -761,6 +765,7 @@ void dev_activate(struct net_device *dev) | |||
761 | dev_watchdog_up(dev); | 765 | dev_watchdog_up(dev); |
762 | } | 766 | } |
763 | } | 767 | } |
768 | EXPORT_SYMBOL(dev_activate); | ||
764 | 769 | ||
765 | static void dev_deactivate_queue(struct net_device *dev, | 770 | static void dev_deactivate_queue(struct net_device *dev, |
766 | struct netdev_queue *dev_queue, | 771 | struct netdev_queue *dev_queue, |
@@ -839,7 +844,9 @@ void dev_deactivate(struct net_device *dev) | |||
839 | 844 | ||
840 | list_add(&dev->unreg_list, &single); | 845 | list_add(&dev->unreg_list, &single); |
841 | dev_deactivate_many(&single); | 846 | dev_deactivate_many(&single); |
847 | list_del(&single); | ||
842 | } | 848 | } |
849 | EXPORT_SYMBOL(dev_deactivate); | ||
843 | 850 | ||
844 | static void dev_init_scheduler_queue(struct net_device *dev, | 851 | static void dev_init_scheduler_queue(struct net_device *dev, |
845 | struct netdev_queue *dev_queue, | 852 | struct netdev_queue *dev_queue, |
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 51dcc2aa5c92..b9493a09a870 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c | |||
@@ -32,8 +32,7 @@ | |||
32 | struct gred_sched_data; | 32 | struct gred_sched_data; |
33 | struct gred_sched; | 33 | struct gred_sched; |
34 | 34 | ||
35 | struct gred_sched_data | 35 | struct gred_sched_data { |
36 | { | ||
37 | u32 limit; /* HARD maximal queue length */ | 36 | u32 limit; /* HARD maximal queue length */ |
38 | u32 DP; /* the drop pramaters */ | 37 | u32 DP; /* the drop pramaters */ |
39 | u32 bytesin; /* bytes seen on virtualQ so far*/ | 38 | u32 bytesin; /* bytes seen on virtualQ so far*/ |
@@ -50,8 +49,7 @@ enum { | |||
50 | GRED_RIO_MODE, | 49 | GRED_RIO_MODE, |
51 | }; | 50 | }; |
52 | 51 | ||
53 | struct gred_sched | 52 | struct gred_sched { |
54 | { | ||
55 | struct gred_sched_data *tab[MAX_DPs]; | 53 | struct gred_sched_data *tab[MAX_DPs]; |
56 | unsigned long flags; | 54 | unsigned long flags; |
57 | u32 red_flags; | 55 | u32 red_flags; |
@@ -150,17 +148,18 @@ static inline int gred_use_harddrop(struct gred_sched *t) | |||
150 | return t->red_flags & TC_RED_HARDDROP; | 148 | return t->red_flags & TC_RED_HARDDROP; |
151 | } | 149 | } |
152 | 150 | ||
153 | static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) | 151 | static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
154 | { | 152 | { |
155 | struct gred_sched_data *q=NULL; | 153 | struct gred_sched_data *q = NULL; |
156 | struct gred_sched *t= qdisc_priv(sch); | 154 | struct gred_sched *t = qdisc_priv(sch); |
157 | unsigned long qavg = 0; | 155 | unsigned long qavg = 0; |
158 | u16 dp = tc_index_to_dp(skb); | 156 | u16 dp = tc_index_to_dp(skb); |
159 | 157 | ||
160 | if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { | 158 | if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { |
161 | dp = t->def; | 159 | dp = t->def; |
162 | 160 | ||
163 | if ((q = t->tab[dp]) == NULL) { | 161 | q = t->tab[dp]; |
162 | if (!q) { | ||
164 | /* Pass through packets not assigned to a DP | 163 | /* Pass through packets not assigned to a DP |
165 | * if no default DP has been configured. This | 164 | * if no default DP has been configured. This |
166 | * allows for DP flows to be left untouched. | 165 | * allows for DP flows to be left untouched. |
@@ -183,7 +182,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
183 | for (i = 0; i < t->DPs; i++) { | 182 | for (i = 0; i < t->DPs; i++) { |
184 | if (t->tab[i] && t->tab[i]->prio < q->prio && | 183 | if (t->tab[i] && t->tab[i]->prio < q->prio && |
185 | !red_is_idling(&t->tab[i]->parms)) | 184 | !red_is_idling(&t->tab[i]->parms)) |
186 | qavg +=t->tab[i]->parms.qavg; | 185 | qavg += t->tab[i]->parms.qavg; |
187 | } | 186 | } |
188 | 187 | ||
189 | } | 188 | } |
@@ -203,28 +202,28 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
203 | gred_store_wred_set(t, q); | 202 | gred_store_wred_set(t, q); |
204 | 203 | ||
205 | switch (red_action(&q->parms, q->parms.qavg + qavg)) { | 204 | switch (red_action(&q->parms, q->parms.qavg + qavg)) { |
206 | case RED_DONT_MARK: | 205 | case RED_DONT_MARK: |
207 | break; | 206 | break; |
208 | 207 | ||
209 | case RED_PROB_MARK: | 208 | case RED_PROB_MARK: |
210 | sch->qstats.overlimits++; | 209 | sch->qstats.overlimits++; |
211 | if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { | 210 | if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { |
212 | q->stats.prob_drop++; | 211 | q->stats.prob_drop++; |
213 | goto congestion_drop; | 212 | goto congestion_drop; |
214 | } | 213 | } |
215 | 214 | ||
216 | q->stats.prob_mark++; | 215 | q->stats.prob_mark++; |
217 | break; | 216 | break; |
218 | 217 | ||
219 | case RED_HARD_MARK: | 218 | case RED_HARD_MARK: |
220 | sch->qstats.overlimits++; | 219 | sch->qstats.overlimits++; |
221 | if (gred_use_harddrop(t) || !gred_use_ecn(t) || | 220 | if (gred_use_harddrop(t) || !gred_use_ecn(t) || |
222 | !INET_ECN_set_ce(skb)) { | 221 | !INET_ECN_set_ce(skb)) { |
223 | q->stats.forced_drop++; | 222 | q->stats.forced_drop++; |
224 | goto congestion_drop; | 223 | goto congestion_drop; |
225 | } | 224 | } |
226 | q->stats.forced_mark++; | 225 | q->stats.forced_mark++; |
227 | break; | 226 | break; |
228 | } | 227 | } |
229 | 228 | ||
230 | if (q->backlog + qdisc_pkt_len(skb) <= q->limit) { | 229 | if (q->backlog + qdisc_pkt_len(skb) <= q->limit) { |
@@ -241,7 +240,7 @@ congestion_drop: | |||
241 | return NET_XMIT_CN; | 240 | return NET_XMIT_CN; |
242 | } | 241 | } |
243 | 242 | ||
244 | static struct sk_buff *gred_dequeue(struct Qdisc* sch) | 243 | static struct sk_buff *gred_dequeue(struct Qdisc *sch) |
245 | { | 244 | { |
246 | struct sk_buff *skb; | 245 | struct sk_buff *skb; |
247 | struct gred_sched *t = qdisc_priv(sch); | 246 | struct gred_sched *t = qdisc_priv(sch); |
@@ -254,9 +253,9 @@ static struct sk_buff *gred_dequeue(struct Qdisc* sch) | |||
254 | 253 | ||
255 | if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { | 254 | if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { |
256 | if (net_ratelimit()) | 255 | if (net_ratelimit()) |
257 | printk(KERN_WARNING "GRED: Unable to relocate " | 256 | pr_warning("GRED: Unable to relocate VQ 0x%x " |
258 | "VQ 0x%x after dequeue, screwing up " | 257 | "after dequeue, screwing up " |
259 | "backlog.\n", tc_index_to_dp(skb)); | 258 | "backlog.\n", tc_index_to_dp(skb)); |
260 | } else { | 259 | } else { |
261 | q->backlog -= qdisc_pkt_len(skb); | 260 | q->backlog -= qdisc_pkt_len(skb); |
262 | 261 | ||
@@ -273,7 +272,7 @@ static struct sk_buff *gred_dequeue(struct Qdisc* sch) | |||
273 | return NULL; | 272 | return NULL; |
274 | } | 273 | } |
275 | 274 | ||
276 | static unsigned int gred_drop(struct Qdisc* sch) | 275 | static unsigned int gred_drop(struct Qdisc *sch) |
277 | { | 276 | { |
278 | struct sk_buff *skb; | 277 | struct sk_buff *skb; |
279 | struct gred_sched *t = qdisc_priv(sch); | 278 | struct gred_sched *t = qdisc_priv(sch); |
@@ -286,9 +285,9 @@ static unsigned int gred_drop(struct Qdisc* sch) | |||
286 | 285 | ||
287 | if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { | 286 | if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { |
288 | if (net_ratelimit()) | 287 | if (net_ratelimit()) |
289 | printk(KERN_WARNING "GRED: Unable to relocate " | 288 | pr_warning("GRED: Unable to relocate VQ 0x%x " |
290 | "VQ 0x%x while dropping, screwing up " | 289 | "while dropping, screwing up " |
291 | "backlog.\n", tc_index_to_dp(skb)); | 290 | "backlog.\n", tc_index_to_dp(skb)); |
292 | } else { | 291 | } else { |
293 | q->backlog -= len; | 292 | q->backlog -= len; |
294 | q->stats.other++; | 293 | q->stats.other++; |
@@ -308,7 +307,7 @@ static unsigned int gred_drop(struct Qdisc* sch) | |||
308 | 307 | ||
309 | } | 308 | } |
310 | 309 | ||
311 | static void gred_reset(struct Qdisc* sch) | 310 | static void gred_reset(struct Qdisc *sch) |
312 | { | 311 | { |
313 | int i; | 312 | int i; |
314 | struct gred_sched *t = qdisc_priv(sch); | 313 | struct gred_sched *t = qdisc_priv(sch); |
@@ -369,8 +368,8 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps) | |||
369 | 368 | ||
370 | for (i = table->DPs; i < MAX_DPs; i++) { | 369 | for (i = table->DPs; i < MAX_DPs; i++) { |
371 | if (table->tab[i]) { | 370 | if (table->tab[i]) { |
372 | printk(KERN_WARNING "GRED: Warning: Destroying " | 371 | pr_warning("GRED: Warning: Destroying " |
373 | "shadowed VQ 0x%x\n", i); | 372 | "shadowed VQ 0x%x\n", i); |
374 | gred_destroy_vq(table->tab[i]); | 373 | gred_destroy_vq(table->tab[i]); |
375 | table->tab[i] = NULL; | 374 | table->tab[i] = NULL; |
376 | } | 375 | } |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 14a799de1c35..6488e6425652 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -81,8 +81,7 @@ | |||
81 | * that are expensive on 32-bit architectures. | 81 | * that are expensive on 32-bit architectures. |
82 | */ | 82 | */ |
83 | 83 | ||
84 | struct internal_sc | 84 | struct internal_sc { |
85 | { | ||
86 | u64 sm1; /* scaled slope of the 1st segment */ | 85 | u64 sm1; /* scaled slope of the 1st segment */ |
87 | u64 ism1; /* scaled inverse-slope of the 1st segment */ | 86 | u64 ism1; /* scaled inverse-slope of the 1st segment */ |
88 | u64 dx; /* the x-projection of the 1st segment */ | 87 | u64 dx; /* the x-projection of the 1st segment */ |
@@ -92,8 +91,7 @@ struct internal_sc | |||
92 | }; | 91 | }; |
93 | 92 | ||
94 | /* runtime service curve */ | 93 | /* runtime service curve */ |
95 | struct runtime_sc | 94 | struct runtime_sc { |
96 | { | ||
97 | u64 x; /* current starting position on x-axis */ | 95 | u64 x; /* current starting position on x-axis */ |
98 | u64 y; /* current starting position on y-axis */ | 96 | u64 y; /* current starting position on y-axis */ |
99 | u64 sm1; /* scaled slope of the 1st segment */ | 97 | u64 sm1; /* scaled slope of the 1st segment */ |
@@ -104,15 +102,13 @@ struct runtime_sc | |||
104 | u64 ism2; /* scaled inverse-slope of the 2nd segment */ | 102 | u64 ism2; /* scaled inverse-slope of the 2nd segment */ |
105 | }; | 103 | }; |
106 | 104 | ||
107 | enum hfsc_class_flags | 105 | enum hfsc_class_flags { |
108 | { | ||
109 | HFSC_RSC = 0x1, | 106 | HFSC_RSC = 0x1, |
110 | HFSC_FSC = 0x2, | 107 | HFSC_FSC = 0x2, |
111 | HFSC_USC = 0x4 | 108 | HFSC_USC = 0x4 |
112 | }; | 109 | }; |
113 | 110 | ||
114 | struct hfsc_class | 111 | struct hfsc_class { |
115 | { | ||
116 | struct Qdisc_class_common cl_common; | 112 | struct Qdisc_class_common cl_common; |
117 | unsigned int refcnt; /* usage count */ | 113 | unsigned int refcnt; /* usage count */ |
118 | 114 | ||
@@ -140,8 +136,8 @@ struct hfsc_class | |||
140 | u64 cl_cumul; /* cumulative work in bytes done by | 136 | u64 cl_cumul; /* cumulative work in bytes done by |
141 | real-time criteria */ | 137 | real-time criteria */ |
142 | 138 | ||
143 | u64 cl_d; /* deadline*/ | 139 | u64 cl_d; /* deadline*/ |
144 | u64 cl_e; /* eligible time */ | 140 | u64 cl_e; /* eligible time */ |
145 | u64 cl_vt; /* virtual time */ | 141 | u64 cl_vt; /* virtual time */ |
146 | u64 cl_f; /* time when this class will fit for | 142 | u64 cl_f; /* time when this class will fit for |
147 | link-sharing, max(myf, cfmin) */ | 143 | link-sharing, max(myf, cfmin) */ |
@@ -176,8 +172,7 @@ struct hfsc_class | |||
176 | unsigned long cl_nactive; /* number of active children */ | 172 | unsigned long cl_nactive; /* number of active children */ |
177 | }; | 173 | }; |
178 | 174 | ||
179 | struct hfsc_sched | 175 | struct hfsc_sched { |
180 | { | ||
181 | u16 defcls; /* default class id */ | 176 | u16 defcls; /* default class id */ |
182 | struct hfsc_class root; /* root class */ | 177 | struct hfsc_class root; /* root class */ |
183 | struct Qdisc_class_hash clhash; /* class hash */ | 178 | struct Qdisc_class_hash clhash; /* class hash */ |
@@ -693,7 +688,7 @@ init_vf(struct hfsc_class *cl, unsigned int len) | |||
693 | if (go_active) { | 688 | if (go_active) { |
694 | n = rb_last(&cl->cl_parent->vt_tree); | 689 | n = rb_last(&cl->cl_parent->vt_tree); |
695 | if (n != NULL) { | 690 | if (n != NULL) { |
696 | max_cl = rb_entry(n, struct hfsc_class,vt_node); | 691 | max_cl = rb_entry(n, struct hfsc_class, vt_node); |
697 | /* | 692 | /* |
698 | * set vt to the average of the min and max | 693 | * set vt to the average of the min and max |
699 | * classes. if the parent's period didn't | 694 | * classes. if the parent's period didn't |
@@ -1177,8 +1172,10 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
1177 | return NULL; | 1172 | return NULL; |
1178 | } | 1173 | } |
1179 | #endif | 1174 | #endif |
1180 | if ((cl = (struct hfsc_class *)res.class) == NULL) { | 1175 | cl = (struct hfsc_class *)res.class; |
1181 | if ((cl = hfsc_find_class(res.classid, sch)) == NULL) | 1176 | if (!cl) { |
1177 | cl = hfsc_find_class(res.classid, sch); | ||
1178 | if (!cl) | ||
1182 | break; /* filter selected invalid classid */ | 1179 | break; /* filter selected invalid classid */ |
1183 | if (cl->level >= head->level) | 1180 | if (cl->level >= head->level) |
1184 | break; /* filter may only point downwards */ | 1181 | break; /* filter may only point downwards */ |
@@ -1316,7 +1313,7 @@ hfsc_dump_sc(struct sk_buff *skb, int attr, struct internal_sc *sc) | |||
1316 | return -1; | 1313 | return -1; |
1317 | } | 1314 | } |
1318 | 1315 | ||
1319 | static inline int | 1316 | static int |
1320 | hfsc_dump_curves(struct sk_buff *skb, struct hfsc_class *cl) | 1317 | hfsc_dump_curves(struct sk_buff *skb, struct hfsc_class *cl) |
1321 | { | 1318 | { |
1322 | if ((cl->cl_flags & HFSC_RSC) && | 1319 | if ((cl->cl_flags & HFSC_RSC) && |
@@ -1420,7 +1417,8 @@ hfsc_schedule_watchdog(struct Qdisc *sch) | |||
1420 | struct hfsc_class *cl; | 1417 | struct hfsc_class *cl; |
1421 | u64 next_time = 0; | 1418 | u64 next_time = 0; |
1422 | 1419 | ||
1423 | if ((cl = eltree_get_minel(q)) != NULL) | 1420 | cl = eltree_get_minel(q); |
1421 | if (cl) | ||
1424 | next_time = cl->cl_e; | 1422 | next_time = cl->cl_e; |
1425 | if (q->root.cl_cfmin != 0) { | 1423 | if (q->root.cl_cfmin != 0) { |
1426 | if (next_time == 0 || next_time > q->root.cl_cfmin) | 1424 | if (next_time == 0 || next_time > q->root.cl_cfmin) |
@@ -1625,7 +1623,8 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1625 | * find the class with the minimum deadline among | 1623 | * find the class with the minimum deadline among |
1626 | * the eligible classes. | 1624 | * the eligible classes. |
1627 | */ | 1625 | */ |
1628 | if ((cl = eltree_get_mindl(q, cur_time)) != NULL) { | 1626 | cl = eltree_get_mindl(q, cur_time); |
1627 | if (cl) { | ||
1629 | realtime = 1; | 1628 | realtime = 1; |
1630 | } else { | 1629 | } else { |
1631 | /* | 1630 | /* |
@@ -1664,7 +1663,7 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1664 | set_passive(cl); | 1663 | set_passive(cl); |
1665 | } | 1664 | } |
1666 | 1665 | ||
1667 | sch->flags &= ~TCQ_F_THROTTLED; | 1666 | qdisc_unthrottled(sch); |
1668 | qdisc_bstats_update(sch, skb); | 1667 | qdisc_bstats_update(sch, skb); |
1669 | sch->q.qlen--; | 1668 | sch->q.qlen--; |
1670 | 1669 | ||
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index fc12fe6f5597..29b942ce9e82 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -99,9 +99,10 @@ struct htb_class { | |||
99 | struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */ | 99 | struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */ |
100 | struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */ | 100 | struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */ |
101 | /* When class changes from state 1->2 and disconnects from | 101 | /* When class changes from state 1->2 and disconnects from |
102 | parent's feed then we lost ptr value and start from the | 102 | * parent's feed then we lost ptr value and start from the |
103 | first child again. Here we store classid of the | 103 | * first child again. Here we store classid of the |
104 | last valid ptr (used when ptr is NULL). */ | 104 | * last valid ptr (used when ptr is NULL). |
105 | */ | ||
105 | u32 last_ptr_id[TC_HTB_NUMPRIO]; | 106 | u32 last_ptr_id[TC_HTB_NUMPRIO]; |
106 | } inner; | 107 | } inner; |
107 | } un; | 108 | } un; |
@@ -182,10 +183,10 @@ static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch) | |||
182 | * filters in qdisc and in inner nodes (if higher filter points to the inner | 183 | * filters in qdisc and in inner nodes (if higher filter points to the inner |
183 | * node). If we end up with classid MAJOR:0 we enqueue the skb into special | 184 | * node). If we end up with classid MAJOR:0 we enqueue the skb into special |
184 | * internal fifo (direct). These packets then go directly thru. If we still | 185 | * internal fifo (direct). These packets then go directly thru. If we still |
185 | * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull | 186 | * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful |
186 | * then finish and return direct queue. | 187 | * then finish and return direct queue. |
187 | */ | 188 | */ |
188 | #define HTB_DIRECT (struct htb_class*)-1 | 189 | #define HTB_DIRECT ((struct htb_class *)-1L) |
189 | 190 | ||
190 | static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, | 191 | static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, |
191 | int *qerr) | 192 | int *qerr) |
@@ -197,11 +198,13 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, | |||
197 | int result; | 198 | int result; |
198 | 199 | ||
199 | /* allow to select class by setting skb->priority to valid classid; | 200 | /* allow to select class by setting skb->priority to valid classid; |
200 | note that nfmark can be used too by attaching filter fw with no | 201 | * note that nfmark can be used too by attaching filter fw with no |
201 | rules in it */ | 202 | * rules in it |
203 | */ | ||
202 | if (skb->priority == sch->handle) | 204 | if (skb->priority == sch->handle) |
203 | return HTB_DIRECT; /* X:0 (direct flow) selected */ | 205 | return HTB_DIRECT; /* X:0 (direct flow) selected */ |
204 | if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0) | 206 | cl = htb_find(skb->priority, sch); |
207 | if (cl && cl->level == 0) | ||
205 | return cl; | 208 | return cl; |
206 | 209 | ||
207 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | 210 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; |
@@ -216,10 +219,12 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, | |||
216 | return NULL; | 219 | return NULL; |
217 | } | 220 | } |
218 | #endif | 221 | #endif |
219 | if ((cl = (void *)res.class) == NULL) { | 222 | cl = (void *)res.class; |
223 | if (!cl) { | ||
220 | if (res.classid == sch->handle) | 224 | if (res.classid == sch->handle) |
221 | return HTB_DIRECT; /* X:0 (direct flow) */ | 225 | return HTB_DIRECT; /* X:0 (direct flow) */ |
222 | if ((cl = htb_find(res.classid, sch)) == NULL) | 226 | cl = htb_find(res.classid, sch); |
227 | if (!cl) | ||
223 | break; /* filter selected invalid classid */ | 228 | break; /* filter selected invalid classid */ |
224 | } | 229 | } |
225 | if (!cl->level) | 230 | if (!cl->level) |
@@ -378,7 +383,8 @@ static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl) | |||
378 | 383 | ||
379 | if (p->un.inner.feed[prio].rb_node) | 384 | if (p->un.inner.feed[prio].rb_node) |
380 | /* parent already has its feed in use so that | 385 | /* parent already has its feed in use so that |
381 | reset bit in mask as parent is already ok */ | 386 | * reset bit in mask as parent is already ok |
387 | */ | ||
382 | mask &= ~(1 << prio); | 388 | mask &= ~(1 << prio); |
383 | 389 | ||
384 | htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio); | 390 | htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio); |
@@ -413,8 +419,9 @@ static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl) | |||
413 | 419 | ||
414 | if (p->un.inner.ptr[prio] == cl->node + prio) { | 420 | if (p->un.inner.ptr[prio] == cl->node + prio) { |
415 | /* we are removing child which is pointed to from | 421 | /* we are removing child which is pointed to from |
416 | parent feed - forget the pointer but remember | 422 | * parent feed - forget the pointer but remember |
417 | classid */ | 423 | * classid |
424 | */ | ||
418 | p->un.inner.last_ptr_id[prio] = cl->common.classid; | 425 | p->un.inner.last_ptr_id[prio] = cl->common.classid; |
419 | p->un.inner.ptr[prio] = NULL; | 426 | p->un.inner.ptr[prio] = NULL; |
420 | } | 427 | } |
@@ -663,8 +670,9 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level, | |||
663 | unsigned long start) | 670 | unsigned long start) |
664 | { | 671 | { |
665 | /* don't run for longer than 2 jiffies; 2 is used instead of | 672 | /* don't run for longer than 2 jiffies; 2 is used instead of |
666 | 1 to simplify things when jiffy is going to be incremented | 673 | * 1 to simplify things when jiffy is going to be incremented |
667 | too soon */ | 674 | * too soon |
675 | */ | ||
668 | unsigned long stop_at = start + 2; | 676 | unsigned long stop_at = start + 2; |
669 | while (time_before(jiffies, stop_at)) { | 677 | while (time_before(jiffies, stop_at)) { |
670 | struct htb_class *cl; | 678 | struct htb_class *cl; |
@@ -687,7 +695,7 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level, | |||
687 | 695 | ||
688 | /* too much load - let's continue after a break for scheduling */ | 696 | /* too much load - let's continue after a break for scheduling */ |
689 | if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) { | 697 | if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) { |
690 | printk(KERN_WARNING "htb: too many events!\n"); | 698 | pr_warning("htb: too many events!\n"); |
691 | q->warned |= HTB_WARN_TOOMANYEVENTS; | 699 | q->warned |= HTB_WARN_TOOMANYEVENTS; |
692 | } | 700 | } |
693 | 701 | ||
@@ -695,7 +703,8 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level, | |||
695 | } | 703 | } |
696 | 704 | ||
697 | /* Returns class->node+prio from id-tree where classe's id is >= id. NULL | 705 | /* Returns class->node+prio from id-tree where classe's id is >= id. NULL |
698 | is no such one exists. */ | 706 | * is no such one exists. |
707 | */ | ||
699 | static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n, | 708 | static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n, |
700 | u32 id) | 709 | u32 id) |
701 | { | 710 | { |
@@ -739,12 +748,14 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, | |||
739 | for (i = 0; i < 65535; i++) { | 748 | for (i = 0; i < 65535; i++) { |
740 | if (!*sp->pptr && *sp->pid) { | 749 | if (!*sp->pptr && *sp->pid) { |
741 | /* ptr was invalidated but id is valid - try to recover | 750 | /* ptr was invalidated but id is valid - try to recover |
742 | the original or next ptr */ | 751 | * the original or next ptr |
752 | */ | ||
743 | *sp->pptr = | 753 | *sp->pptr = |
744 | htb_id_find_next_upper(prio, sp->root, *sp->pid); | 754 | htb_id_find_next_upper(prio, sp->root, *sp->pid); |
745 | } | 755 | } |
746 | *sp->pid = 0; /* ptr is valid now so that remove this hint as it | 756 | *sp->pid = 0; /* ptr is valid now so that remove this hint as it |
747 | can become out of date quickly */ | 757 | * can become out of date quickly |
758 | */ | ||
748 | if (!*sp->pptr) { /* we are at right end; rewind & go up */ | 759 | if (!*sp->pptr) { /* we are at right end; rewind & go up */ |
749 | *sp->pptr = sp->root; | 760 | *sp->pptr = sp->root; |
750 | while ((*sp->pptr)->rb_left) | 761 | while ((*sp->pptr)->rb_left) |
@@ -772,7 +783,8 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, | |||
772 | } | 783 | } |
773 | 784 | ||
774 | /* dequeues packet at given priority and level; call only if | 785 | /* dequeues packet at given priority and level; call only if |
775 | you are sure that there is active class at prio/level */ | 786 | * you are sure that there is active class at prio/level |
787 | */ | ||
776 | static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, | 788 | static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, |
777 | int level) | 789 | int level) |
778 | { | 790 | { |
@@ -789,9 +801,10 @@ next: | |||
789 | return NULL; | 801 | return NULL; |
790 | 802 | ||
791 | /* class can be empty - it is unlikely but can be true if leaf | 803 | /* class can be empty - it is unlikely but can be true if leaf |
792 | qdisc drops packets in enqueue routine or if someone used | 804 | * qdisc drops packets in enqueue routine or if someone used |
793 | graft operation on the leaf since last dequeue; | 805 | * graft operation on the leaf since last dequeue; |
794 | simply deactivate and skip such class */ | 806 | * simply deactivate and skip such class |
807 | */ | ||
795 | if (unlikely(cl->un.leaf.q->q.qlen == 0)) { | 808 | if (unlikely(cl->un.leaf.q->q.qlen == 0)) { |
796 | struct htb_class *next; | 809 | struct htb_class *next; |
797 | htb_deactivate(q, cl); | 810 | htb_deactivate(q, cl); |
@@ -831,7 +844,8 @@ next: | |||
831 | ptr[0]) + prio); | 844 | ptr[0]) + prio); |
832 | } | 845 | } |
833 | /* this used to be after charge_class but this constelation | 846 | /* this used to be after charge_class but this constelation |
834 | gives us slightly better performance */ | 847 | * gives us slightly better performance |
848 | */ | ||
835 | if (!cl->un.leaf.q->q.qlen) | 849 | if (!cl->un.leaf.q->q.qlen) |
836 | htb_deactivate(q, cl); | 850 | htb_deactivate(q, cl); |
837 | htb_charge_class(q, cl, level, skb); | 851 | htb_charge_class(q, cl, level, skb); |
@@ -852,7 +866,7 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) | |||
852 | if (skb != NULL) { | 866 | if (skb != NULL) { |
853 | ok: | 867 | ok: |
854 | qdisc_bstats_update(sch, skb); | 868 | qdisc_bstats_update(sch, skb); |
855 | sch->flags &= ~TCQ_F_THROTTLED; | 869 | qdisc_unthrottled(sch); |
856 | sch->q.qlen--; | 870 | sch->q.qlen--; |
857 | return skb; | 871 | return skb; |
858 | } | 872 | } |
@@ -883,6 +897,7 @@ ok: | |||
883 | m = ~q->row_mask[level]; | 897 | m = ~q->row_mask[level]; |
884 | while (m != (int)(-1)) { | 898 | while (m != (int)(-1)) { |
885 | int prio = ffz(m); | 899 | int prio = ffz(m); |
900 | |||
886 | m |= 1 << prio; | 901 | m |= 1 << prio; |
887 | skb = htb_dequeue_tree(q, prio, level); | 902 | skb = htb_dequeue_tree(q, prio, level); |
888 | if (likely(skb != NULL)) | 903 | if (likely(skb != NULL)) |
@@ -987,13 +1002,12 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt) | |||
987 | return err; | 1002 | return err; |
988 | 1003 | ||
989 | if (tb[TCA_HTB_INIT] == NULL) { | 1004 | if (tb[TCA_HTB_INIT] == NULL) { |
990 | printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n"); | 1005 | pr_err("HTB: hey probably you have bad tc tool ?\n"); |
991 | return -EINVAL; | 1006 | return -EINVAL; |
992 | } | 1007 | } |
993 | gopt = nla_data(tb[TCA_HTB_INIT]); | 1008 | gopt = nla_data(tb[TCA_HTB_INIT]); |
994 | if (gopt->version != HTB_VER >> 16) { | 1009 | if (gopt->version != HTB_VER >> 16) { |
995 | printk(KERN_ERR | 1010 | pr_err("HTB: need tc/htb version %d (minor is %d), you have %d\n", |
996 | "HTB: need tc/htb version %d (minor is %d), you have %d\n", | ||
997 | HTB_VER >> 16, HTB_VER & 0xffff, gopt->version); | 1011 | HTB_VER >> 16, HTB_VER & 0xffff, gopt->version); |
998 | return -EINVAL; | 1012 | return -EINVAL; |
999 | } | 1013 | } |
@@ -1206,9 +1220,10 @@ static void htb_destroy(struct Qdisc *sch) | |||
1206 | cancel_work_sync(&q->work); | 1220 | cancel_work_sync(&q->work); |
1207 | qdisc_watchdog_cancel(&q->watchdog); | 1221 | qdisc_watchdog_cancel(&q->watchdog); |
1208 | /* This line used to be after htb_destroy_class call below | 1222 | /* This line used to be after htb_destroy_class call below |
1209 | and surprisingly it worked in 2.4. But it must precede it | 1223 | * and surprisingly it worked in 2.4. But it must precede it |
1210 | because filter need its target class alive to be able to call | 1224 | * because filter need its target class alive to be able to call |
1211 | unbind_filter on it (without Oops). */ | 1225 | * unbind_filter on it (without Oops). |
1226 | */ | ||
1212 | tcf_destroy_chain(&q->filter_list); | 1227 | tcf_destroy_chain(&q->filter_list); |
1213 | 1228 | ||
1214 | for (i = 0; i < q->clhash.hashsize; i++) { | 1229 | for (i = 0; i < q->clhash.hashsize; i++) { |
@@ -1342,11 +1357,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1342 | 1357 | ||
1343 | /* check maximal depth */ | 1358 | /* check maximal depth */ |
1344 | if (parent && parent->parent && parent->parent->level < 2) { | 1359 | if (parent && parent->parent && parent->parent->level < 2) { |
1345 | printk(KERN_ERR "htb: tree is too deep\n"); | 1360 | pr_err("htb: tree is too deep\n"); |
1346 | goto failure; | 1361 | goto failure; |
1347 | } | 1362 | } |
1348 | err = -ENOBUFS; | 1363 | err = -ENOBUFS; |
1349 | if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) | 1364 | cl = kzalloc(sizeof(*cl), GFP_KERNEL); |
1365 | if (!cl) | ||
1350 | goto failure; | 1366 | goto failure; |
1351 | 1367 | ||
1352 | err = gen_new_estimator(&cl->bstats, &cl->rate_est, | 1368 | err = gen_new_estimator(&cl->bstats, &cl->rate_est, |
@@ -1366,8 +1382,9 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1366 | RB_CLEAR_NODE(&cl->node[prio]); | 1382 | RB_CLEAR_NODE(&cl->node[prio]); |
1367 | 1383 | ||
1368 | /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL) | 1384 | /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL) |
1369 | so that can't be used inside of sch_tree_lock | 1385 | * so that can't be used inside of sch_tree_lock |
1370 | -- thanks to Karlis Peisenieks */ | 1386 | * -- thanks to Karlis Peisenieks |
1387 | */ | ||
1371 | new_q = qdisc_create_dflt(sch->dev_queue, | 1388 | new_q = qdisc_create_dflt(sch->dev_queue, |
1372 | &pfifo_qdisc_ops, classid); | 1389 | &pfifo_qdisc_ops, classid); |
1373 | sch_tree_lock(sch); | 1390 | sch_tree_lock(sch); |
@@ -1419,17 +1436,18 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1419 | } | 1436 | } |
1420 | 1437 | ||
1421 | /* it used to be a nasty bug here, we have to check that node | 1438 | /* it used to be a nasty bug here, we have to check that node |
1422 | is really leaf before changing cl->un.leaf ! */ | 1439 | * is really leaf before changing cl->un.leaf ! |
1440 | */ | ||
1423 | if (!cl->level) { | 1441 | if (!cl->level) { |
1424 | cl->quantum = rtab->rate.rate / q->rate2quantum; | 1442 | cl->quantum = rtab->rate.rate / q->rate2quantum; |
1425 | if (!hopt->quantum && cl->quantum < 1000) { | 1443 | if (!hopt->quantum && cl->quantum < 1000) { |
1426 | printk(KERN_WARNING | 1444 | pr_warning( |
1427 | "HTB: quantum of class %X is small. Consider r2q change.\n", | 1445 | "HTB: quantum of class %X is small. Consider r2q change.\n", |
1428 | cl->common.classid); | 1446 | cl->common.classid); |
1429 | cl->quantum = 1000; | 1447 | cl->quantum = 1000; |
1430 | } | 1448 | } |
1431 | if (!hopt->quantum && cl->quantum > 200000) { | 1449 | if (!hopt->quantum && cl->quantum > 200000) { |
1432 | printk(KERN_WARNING | 1450 | pr_warning( |
1433 | "HTB: quantum of class %X is big. Consider r2q change.\n", | 1451 | "HTB: quantum of class %X is big. Consider r2q change.\n", |
1434 | cl->common.classid); | 1452 | cl->common.classid); |
1435 | cl->quantum = 200000; | 1453 | cl->quantum = 200000; |
@@ -1478,13 +1496,13 @@ static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, | |||
1478 | struct htb_class *cl = htb_find(classid, sch); | 1496 | struct htb_class *cl = htb_find(classid, sch); |
1479 | 1497 | ||
1480 | /*if (cl && !cl->level) return 0; | 1498 | /*if (cl && !cl->level) return 0; |
1481 | The line above used to be there to prevent attaching filters to | 1499 | * The line above used to be there to prevent attaching filters to |
1482 | leaves. But at least tc_index filter uses this just to get class | 1500 | * leaves. But at least tc_index filter uses this just to get class |
1483 | for other reasons so that we have to allow for it. | 1501 | * for other reasons so that we have to allow for it. |
1484 | ---- | 1502 | * ---- |
1485 | 19.6.2002 As Werner explained it is ok - bind filter is just | 1503 | * 19.6.2002 As Werner explained it is ok - bind filter is just |
1486 | another way to "lock" the class - unlike "get" this lock can | 1504 | * another way to "lock" the class - unlike "get" this lock can |
1487 | be broken by class during destroy IIUC. | 1505 | * be broken by class during destroy IIUC. |
1488 | */ | 1506 | */ |
1489 | if (cl) | 1507 | if (cl) |
1490 | cl->filter_cnt++; | 1508 | cl->filter_cnt++; |
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c index ecc302f4d2a1..ec5cbc848963 100644 --- a/net/sched/sch_mq.c +++ b/net/sched/sch_mq.c | |||
@@ -61,7 +61,6 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt) | |||
61 | TC_H_MIN(ntx + 1))); | 61 | TC_H_MIN(ntx + 1))); |
62 | if (qdisc == NULL) | 62 | if (qdisc == NULL) |
63 | goto err; | 63 | goto err; |
64 | qdisc->flags |= TCQ_F_CAN_BYPASS; | ||
65 | priv->qdiscs[ntx] = qdisc; | 64 | priv->qdiscs[ntx] = qdisc; |
66 | } | 65 | } |
67 | 66 | ||
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c new file mode 100644 index 000000000000..ea17cbed29ef --- /dev/null +++ b/net/sched/sch_mqprio.c | |||
@@ -0,0 +1,418 @@ | |||
1 | /* | ||
2 | * net/sched/sch_mqprio.c | ||
3 | * | ||
4 | * Copyright (c) 2010 John Fastabend <john.r.fastabend@intel.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/types.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | #include <net/netlink.h> | ||
18 | #include <net/pkt_sched.h> | ||
19 | #include <net/sch_generic.h> | ||
20 | |||
21 | struct mqprio_sched { | ||
22 | struct Qdisc **qdiscs; | ||
23 | int hw_owned; | ||
24 | }; | ||
25 | |||
26 | static void mqprio_destroy(struct Qdisc *sch) | ||
27 | { | ||
28 | struct net_device *dev = qdisc_dev(sch); | ||
29 | struct mqprio_sched *priv = qdisc_priv(sch); | ||
30 | unsigned int ntx; | ||
31 | |||
32 | if (priv->qdiscs) { | ||
33 | for (ntx = 0; | ||
34 | ntx < dev->num_tx_queues && priv->qdiscs[ntx]; | ||
35 | ntx++) | ||
36 | qdisc_destroy(priv->qdiscs[ntx]); | ||
37 | kfree(priv->qdiscs); | ||
38 | } | ||
39 | |||
40 | if (priv->hw_owned && dev->netdev_ops->ndo_setup_tc) | ||
41 | dev->netdev_ops->ndo_setup_tc(dev, 0); | ||
42 | else | ||
43 | netdev_set_num_tc(dev, 0); | ||
44 | } | ||
45 | |||
46 | static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt) | ||
47 | { | ||
48 | int i, j; | ||
49 | |||
50 | /* Verify num_tc is not out of max range */ | ||
51 | if (qopt->num_tc > TC_MAX_QUEUE) | ||
52 | return -EINVAL; | ||
53 | |||
54 | /* Verify priority mapping uses valid tcs */ | ||
55 | for (i = 0; i < TC_BITMASK + 1; i++) { | ||
56 | if (qopt->prio_tc_map[i] >= qopt->num_tc) | ||
57 | return -EINVAL; | ||
58 | } | ||
59 | |||
60 | /* net_device does not support requested operation */ | ||
61 | if (qopt->hw && !dev->netdev_ops->ndo_setup_tc) | ||
62 | return -EINVAL; | ||
63 | |||
64 | /* if hw owned qcount and qoffset are taken from LLD so | ||
65 | * no reason to verify them here | ||
66 | */ | ||
67 | if (qopt->hw) | ||
68 | return 0; | ||
69 | |||
70 | for (i = 0; i < qopt->num_tc; i++) { | ||
71 | unsigned int last = qopt->offset[i] + qopt->count[i]; | ||
72 | |||
73 | /* Verify the queue count is in tx range being equal to the | ||
74 | * real_num_tx_queues indicates the last queue is in use. | ||
75 | */ | ||
76 | if (qopt->offset[i] >= dev->real_num_tx_queues || | ||
77 | !qopt->count[i] || | ||
78 | last > dev->real_num_tx_queues) | ||
79 | return -EINVAL; | ||
80 | |||
81 | /* Verify that the offset and counts do not overlap */ | ||
82 | for (j = i + 1; j < qopt->num_tc; j++) { | ||
83 | if (last > qopt->offset[j]) | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) | ||
92 | { | ||
93 | struct net_device *dev = qdisc_dev(sch); | ||
94 | struct mqprio_sched *priv = qdisc_priv(sch); | ||
95 | struct netdev_queue *dev_queue; | ||
96 | struct Qdisc *qdisc; | ||
97 | int i, err = -EOPNOTSUPP; | ||
98 | struct tc_mqprio_qopt *qopt = NULL; | ||
99 | |||
100 | BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE); | ||
101 | BUILD_BUG_ON(TC_BITMASK != TC_QOPT_BITMASK); | ||
102 | |||
103 | if (sch->parent != TC_H_ROOT) | ||
104 | return -EOPNOTSUPP; | ||
105 | |||
106 | if (!netif_is_multiqueue(dev)) | ||
107 | return -EOPNOTSUPP; | ||
108 | |||
109 | if (nla_len(opt) < sizeof(*qopt)) | ||
110 | return -EINVAL; | ||
111 | |||
112 | qopt = nla_data(opt); | ||
113 | if (mqprio_parse_opt(dev, qopt)) | ||
114 | return -EINVAL; | ||
115 | |||
116 | /* pre-allocate qdisc, attachment can't fail */ | ||
117 | priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]), | ||
118 | GFP_KERNEL); | ||
119 | if (priv->qdiscs == NULL) { | ||
120 | err = -ENOMEM; | ||
121 | goto err; | ||
122 | } | ||
123 | |||
124 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
125 | dev_queue = netdev_get_tx_queue(dev, i); | ||
126 | qdisc = qdisc_create_dflt(dev_queue, &pfifo_fast_ops, | ||
127 | TC_H_MAKE(TC_H_MAJ(sch->handle), | ||
128 | TC_H_MIN(i + 1))); | ||
129 | if (qdisc == NULL) { | ||
130 | err = -ENOMEM; | ||
131 | goto err; | ||
132 | } | ||
133 | priv->qdiscs[i] = qdisc; | ||
134 | } | ||
135 | |||
136 | /* If the mqprio options indicate that hardware should own | ||
137 | * the queue mapping then run ndo_setup_tc otherwise use the | ||
138 | * supplied and verified mapping | ||
139 | */ | ||
140 | if (qopt->hw) { | ||
141 | priv->hw_owned = 1; | ||
142 | err = dev->netdev_ops->ndo_setup_tc(dev, qopt->num_tc); | ||
143 | if (err) | ||
144 | goto err; | ||
145 | } else { | ||
146 | netdev_set_num_tc(dev, qopt->num_tc); | ||
147 | for (i = 0; i < qopt->num_tc; i++) | ||
148 | netdev_set_tc_queue(dev, i, | ||
149 | qopt->count[i], qopt->offset[i]); | ||
150 | } | ||
151 | |||
152 | /* Always use supplied priority mappings */ | ||
153 | for (i = 0; i < TC_BITMASK + 1; i++) | ||
154 | netdev_set_prio_tc_map(dev, i, qopt->prio_tc_map[i]); | ||
155 | |||
156 | sch->flags |= TCQ_F_MQROOT; | ||
157 | return 0; | ||
158 | |||
159 | err: | ||
160 | mqprio_destroy(sch); | ||
161 | return err; | ||
162 | } | ||
163 | |||
164 | static void mqprio_attach(struct Qdisc *sch) | ||
165 | { | ||
166 | struct net_device *dev = qdisc_dev(sch); | ||
167 | struct mqprio_sched *priv = qdisc_priv(sch); | ||
168 | struct Qdisc *qdisc; | ||
169 | unsigned int ntx; | ||
170 | |||
171 | /* Attach underlying qdisc */ | ||
172 | for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { | ||
173 | qdisc = priv->qdiscs[ntx]; | ||
174 | qdisc = dev_graft_qdisc(qdisc->dev_queue, qdisc); | ||
175 | if (qdisc) | ||
176 | qdisc_destroy(qdisc); | ||
177 | } | ||
178 | kfree(priv->qdiscs); | ||
179 | priv->qdiscs = NULL; | ||
180 | } | ||
181 | |||
182 | static struct netdev_queue *mqprio_queue_get(struct Qdisc *sch, | ||
183 | unsigned long cl) | ||
184 | { | ||
185 | struct net_device *dev = qdisc_dev(sch); | ||
186 | unsigned long ntx = cl - 1 - netdev_get_num_tc(dev); | ||
187 | |||
188 | if (ntx >= dev->num_tx_queues) | ||
189 | return NULL; | ||
190 | return netdev_get_tx_queue(dev, ntx); | ||
191 | } | ||
192 | |||
193 | static int mqprio_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, | ||
194 | struct Qdisc **old) | ||
195 | { | ||
196 | struct net_device *dev = qdisc_dev(sch); | ||
197 | struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl); | ||
198 | |||
199 | if (!dev_queue) | ||
200 | return -EINVAL; | ||
201 | |||
202 | if (dev->flags & IFF_UP) | ||
203 | dev_deactivate(dev); | ||
204 | |||
205 | *old = dev_graft_qdisc(dev_queue, new); | ||
206 | |||
207 | if (dev->flags & IFF_UP) | ||
208 | dev_activate(dev); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb) | ||
214 | { | ||
215 | struct net_device *dev = qdisc_dev(sch); | ||
216 | struct mqprio_sched *priv = qdisc_priv(sch); | ||
217 | unsigned char *b = skb_tail_pointer(skb); | ||
218 | struct tc_mqprio_qopt opt = { 0 }; | ||
219 | struct Qdisc *qdisc; | ||
220 | unsigned int i; | ||
221 | |||
222 | sch->q.qlen = 0; | ||
223 | memset(&sch->bstats, 0, sizeof(sch->bstats)); | ||
224 | memset(&sch->qstats, 0, sizeof(sch->qstats)); | ||
225 | |||
226 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
227 | qdisc = netdev_get_tx_queue(dev, i)->qdisc; | ||
228 | spin_lock_bh(qdisc_lock(qdisc)); | ||
229 | sch->q.qlen += qdisc->q.qlen; | ||
230 | sch->bstats.bytes += qdisc->bstats.bytes; | ||
231 | sch->bstats.packets += qdisc->bstats.packets; | ||
232 | sch->qstats.qlen += qdisc->qstats.qlen; | ||
233 | sch->qstats.backlog += qdisc->qstats.backlog; | ||
234 | sch->qstats.drops += qdisc->qstats.drops; | ||
235 | sch->qstats.requeues += qdisc->qstats.requeues; | ||
236 | sch->qstats.overlimits += qdisc->qstats.overlimits; | ||
237 | spin_unlock_bh(qdisc_lock(qdisc)); | ||
238 | } | ||
239 | |||
240 | opt.num_tc = netdev_get_num_tc(dev); | ||
241 | memcpy(opt.prio_tc_map, dev->prio_tc_map, sizeof(opt.prio_tc_map)); | ||
242 | opt.hw = priv->hw_owned; | ||
243 | |||
244 | for (i = 0; i < netdev_get_num_tc(dev); i++) { | ||
245 | opt.count[i] = dev->tc_to_txq[i].count; | ||
246 | opt.offset[i] = dev->tc_to_txq[i].offset; | ||
247 | } | ||
248 | |||
249 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | ||
250 | |||
251 | return skb->len; | ||
252 | nla_put_failure: | ||
253 | nlmsg_trim(skb, b); | ||
254 | return -1; | ||
255 | } | ||
256 | |||
257 | static struct Qdisc *mqprio_leaf(struct Qdisc *sch, unsigned long cl) | ||
258 | { | ||
259 | struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl); | ||
260 | |||
261 | if (!dev_queue) | ||
262 | return NULL; | ||
263 | |||
264 | return dev_queue->qdisc_sleeping; | ||
265 | } | ||
266 | |||
267 | static unsigned long mqprio_get(struct Qdisc *sch, u32 classid) | ||
268 | { | ||
269 | struct net_device *dev = qdisc_dev(sch); | ||
270 | unsigned int ntx = TC_H_MIN(classid); | ||
271 | |||
272 | if (ntx > dev->num_tx_queues + netdev_get_num_tc(dev)) | ||
273 | return 0; | ||
274 | return ntx; | ||
275 | } | ||
276 | |||
277 | static void mqprio_put(struct Qdisc *sch, unsigned long cl) | ||
278 | { | ||
279 | } | ||
280 | |||
281 | static int mqprio_dump_class(struct Qdisc *sch, unsigned long cl, | ||
282 | struct sk_buff *skb, struct tcmsg *tcm) | ||
283 | { | ||
284 | struct net_device *dev = qdisc_dev(sch); | ||
285 | |||
286 | if (cl <= netdev_get_num_tc(dev)) { | ||
287 | tcm->tcm_parent = TC_H_ROOT; | ||
288 | tcm->tcm_info = 0; | ||
289 | } else { | ||
290 | int i; | ||
291 | struct netdev_queue *dev_queue; | ||
292 | |||
293 | dev_queue = mqprio_queue_get(sch, cl); | ||
294 | tcm->tcm_parent = 0; | ||
295 | for (i = 0; i < netdev_get_num_tc(dev); i++) { | ||
296 | struct netdev_tc_txq tc = dev->tc_to_txq[i]; | ||
297 | int q_idx = cl - netdev_get_num_tc(dev); | ||
298 | |||
299 | if (q_idx > tc.offset && | ||
300 | q_idx <= tc.offset + tc.count) { | ||
301 | tcm->tcm_parent = | ||
302 | TC_H_MAKE(TC_H_MAJ(sch->handle), | ||
303 | TC_H_MIN(i + 1)); | ||
304 | break; | ||
305 | } | ||
306 | } | ||
307 | tcm->tcm_info = dev_queue->qdisc_sleeping->handle; | ||
308 | } | ||
309 | tcm->tcm_handle |= TC_H_MIN(cl); | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl, | ||
314 | struct gnet_dump *d) | ||
315 | __releases(d->lock) | ||
316 | __acquires(d->lock) | ||
317 | { | ||
318 | struct net_device *dev = qdisc_dev(sch); | ||
319 | |||
320 | if (cl <= netdev_get_num_tc(dev)) { | ||
321 | int i; | ||
322 | struct Qdisc *qdisc; | ||
323 | struct gnet_stats_queue qstats = {0}; | ||
324 | struct gnet_stats_basic_packed bstats = {0}; | ||
325 | struct netdev_tc_txq tc = dev->tc_to_txq[cl - 1]; | ||
326 | |||
327 | /* Drop lock here it will be reclaimed before touching | ||
328 | * statistics this is required because the d->lock we | ||
329 | * hold here is the look on dev_queue->qdisc_sleeping | ||
330 | * also acquired below. | ||
331 | */ | ||
332 | spin_unlock_bh(d->lock); | ||
333 | |||
334 | for (i = tc.offset; i < tc.offset + tc.count; i++) { | ||
335 | qdisc = netdev_get_tx_queue(dev, i)->qdisc; | ||
336 | spin_lock_bh(qdisc_lock(qdisc)); | ||
337 | bstats.bytes += qdisc->bstats.bytes; | ||
338 | bstats.packets += qdisc->bstats.packets; | ||
339 | qstats.qlen += qdisc->qstats.qlen; | ||
340 | qstats.backlog += qdisc->qstats.backlog; | ||
341 | qstats.drops += qdisc->qstats.drops; | ||
342 | qstats.requeues += qdisc->qstats.requeues; | ||
343 | qstats.overlimits += qdisc->qstats.overlimits; | ||
344 | spin_unlock_bh(qdisc_lock(qdisc)); | ||
345 | } | ||
346 | /* Reclaim root sleeping lock before completing stats */ | ||
347 | spin_lock_bh(d->lock); | ||
348 | if (gnet_stats_copy_basic(d, &bstats) < 0 || | ||
349 | gnet_stats_copy_queue(d, &qstats) < 0) | ||
350 | return -1; | ||
351 | } else { | ||
352 | struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl); | ||
353 | |||
354 | sch = dev_queue->qdisc_sleeping; | ||
355 | sch->qstats.qlen = sch->q.qlen; | ||
356 | if (gnet_stats_copy_basic(d, &sch->bstats) < 0 || | ||
357 | gnet_stats_copy_queue(d, &sch->qstats) < 0) | ||
358 | return -1; | ||
359 | } | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static void mqprio_walk(struct Qdisc *sch, struct qdisc_walker *arg) | ||
364 | { | ||
365 | struct net_device *dev = qdisc_dev(sch); | ||
366 | unsigned long ntx; | ||
367 | |||
368 | if (arg->stop) | ||
369 | return; | ||
370 | |||
371 | /* Walk hierarchy with a virtual class per tc */ | ||
372 | arg->count = arg->skip; | ||
373 | for (ntx = arg->skip; | ||
374 | ntx < dev->num_tx_queues + netdev_get_num_tc(dev); | ||
375 | ntx++) { | ||
376 | if (arg->fn(sch, ntx + 1, arg) < 0) { | ||
377 | arg->stop = 1; | ||
378 | break; | ||
379 | } | ||
380 | arg->count++; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | static const struct Qdisc_class_ops mqprio_class_ops = { | ||
385 | .graft = mqprio_graft, | ||
386 | .leaf = mqprio_leaf, | ||
387 | .get = mqprio_get, | ||
388 | .put = mqprio_put, | ||
389 | .walk = mqprio_walk, | ||
390 | .dump = mqprio_dump_class, | ||
391 | .dump_stats = mqprio_dump_class_stats, | ||
392 | }; | ||
393 | |||
394 | static struct Qdisc_ops mqprio_qdisc_ops __read_mostly = { | ||
395 | .cl_ops = &mqprio_class_ops, | ||
396 | .id = "mqprio", | ||
397 | .priv_size = sizeof(struct mqprio_sched), | ||
398 | .init = mqprio_init, | ||
399 | .destroy = mqprio_destroy, | ||
400 | .attach = mqprio_attach, | ||
401 | .dump = mqprio_dump, | ||
402 | .owner = THIS_MODULE, | ||
403 | }; | ||
404 | |||
405 | static int __init mqprio_module_init(void) | ||
406 | { | ||
407 | return register_qdisc(&mqprio_qdisc_ops); | ||
408 | } | ||
409 | |||
410 | static void __exit mqprio_module_exit(void) | ||
411 | { | ||
412 | unregister_qdisc(&mqprio_qdisc_ops); | ||
413 | } | ||
414 | |||
415 | module_init(mqprio_module_init); | ||
416 | module_exit(mqprio_module_exit); | ||
417 | |||
418 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 436a2e75b322..edc1950e0e77 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c | |||
@@ -156,7 +156,7 @@ static unsigned int multiq_drop(struct Qdisc *sch) | |||
156 | unsigned int len; | 156 | unsigned int len; |
157 | struct Qdisc *qdisc; | 157 | struct Qdisc *qdisc; |
158 | 158 | ||
159 | for (band = q->bands-1; band >= 0; band--) { | 159 | for (band = q->bands - 1; band >= 0; band--) { |
160 | qdisc = q->queues[band]; | 160 | qdisc = q->queues[band]; |
161 | if (qdisc->ops->drop) { | 161 | if (qdisc->ops->drop) { |
162 | len = qdisc->ops->drop(qdisc); | 162 | len = qdisc->ops->drop(qdisc); |
@@ -265,7 +265,7 @@ static int multiq_init(struct Qdisc *sch, struct nlattr *opt) | |||
265 | for (i = 0; i < q->max_bands; i++) | 265 | for (i = 0; i < q->max_bands; i++) |
266 | q->queues[i] = &noop_qdisc; | 266 | q->queues[i] = &noop_qdisc; |
267 | 267 | ||
268 | err = multiq_tune(sch,opt); | 268 | err = multiq_tune(sch, opt); |
269 | 269 | ||
270 | if (err) | 270 | if (err) |
271 | kfree(q->queues); | 271 | kfree(q->queues); |
@@ -346,7 +346,7 @@ static int multiq_dump_class(struct Qdisc *sch, unsigned long cl, | |||
346 | struct multiq_sched_data *q = qdisc_priv(sch); | 346 | struct multiq_sched_data *q = qdisc_priv(sch); |
347 | 347 | ||
348 | tcm->tcm_handle |= TC_H_MIN(cl); | 348 | tcm->tcm_handle |= TC_H_MIN(cl); |
349 | tcm->tcm_info = q->queues[cl-1]->handle; | 349 | tcm->tcm_info = q->queues[cl - 1]->handle; |
350 | return 0; | 350 | return 0; |
351 | } | 351 | } |
352 | 352 | ||
@@ -378,7 +378,7 @@ static void multiq_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
378 | arg->count++; | 378 | arg->count++; |
379 | continue; | 379 | continue; |
380 | } | 380 | } |
381 | if (arg->fn(sch, band+1, arg) < 0) { | 381 | if (arg->fn(sch, band + 1, arg) < 0) { |
382 | arg->stop = 1; | 382 | arg->stop = 1; |
383 | break; | 383 | break; |
384 | } | 384 | } |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 6a3006b38dc5..69c35f6cd13f 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -19,12 +19,13 @@ | |||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
21 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
22 | #include <linux/vmalloc.h> | ||
22 | #include <linux/rtnetlink.h> | 23 | #include <linux/rtnetlink.h> |
23 | 24 | ||
24 | #include <net/netlink.h> | 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.3" |
28 | 29 | ||
29 | /* Network Emulation Queuing algorithm. | 30 | /* Network Emulation Queuing algorithm. |
30 | ==================================== | 31 | ==================================== |
@@ -47,6 +48,20 @@ | |||
47 | layering other disciplines. It does not need to do bandwidth | 48 | layering other disciplines. It does not need to do bandwidth |
48 | control either since that can be handled by using token | 49 | control either since that can be handled by using token |
49 | bucket or other rate control. | 50 | bucket or other rate control. |
51 | |||
52 | Correlated Loss Generator models | ||
53 | |||
54 | Added generation of correlated loss according to the | ||
55 | "Gilbert-Elliot" model, a 4-state markov model. | ||
56 | |||
57 | References: | ||
58 | [1] NetemCLG Home http://netgroup.uniroma2.it/NetemCLG | ||
59 | [2] S. Salsano, F. Ludovici, A. Ordine, "Definition of a general | ||
60 | and intuitive loss model for packet networks and its implementation | ||
61 | in the Netem module in the Linux kernel", available in [1] | ||
62 | |||
63 | Authors: Stefano Salsano <stefano.salsano at uniroma2.it | ||
64 | Fabio Ludovici <fabio.ludovici at yahoo.it> | ||
50 | */ | 65 | */ |
51 | 66 | ||
52 | struct netem_sched_data { | 67 | struct netem_sched_data { |
@@ -73,6 +88,26 @@ struct netem_sched_data { | |||
73 | u32 size; | 88 | u32 size; |
74 | s16 table[0]; | 89 | s16 table[0]; |
75 | } *delay_dist; | 90 | } *delay_dist; |
91 | |||
92 | enum { | ||
93 | CLG_RANDOM, | ||
94 | CLG_4_STATES, | ||
95 | CLG_GILB_ELL, | ||
96 | } loss_model; | ||
97 | |||
98 | /* Correlated Loss Generation models */ | ||
99 | struct clgstate { | ||
100 | /* state of the Markov chain */ | ||
101 | u8 state; | ||
102 | |||
103 | /* 4-states and Gilbert-Elliot models */ | ||
104 | u32 a1; /* p13 for 4-states or p for GE */ | ||
105 | u32 a2; /* p31 for 4-states or r for GE */ | ||
106 | u32 a3; /* p32 for 4-states or h for GE */ | ||
107 | u32 a4; /* p14 for 4-states or 1-k for GE */ | ||
108 | u32 a5; /* p23 used only in 4-states */ | ||
109 | } clg; | ||
110 | |||
76 | }; | 111 | }; |
77 | 112 | ||
78 | /* Time stamp put into socket buffer control block */ | 113 | /* Time stamp put into socket buffer control block */ |
@@ -115,6 +150,122 @@ static u32 get_crandom(struct crndstate *state) | |||
115 | return answer; | 150 | return answer; |
116 | } | 151 | } |
117 | 152 | ||
153 | /* loss_4state - 4-state model loss generator | ||
154 | * Generates losses according to the 4-state Markov chain adopted in | ||
155 | * the GI (General and Intuitive) loss model. | ||
156 | */ | ||
157 | static bool loss_4state(struct netem_sched_data *q) | ||
158 | { | ||
159 | struct clgstate *clg = &q->clg; | ||
160 | u32 rnd = net_random(); | ||
161 | |||
162 | /* | ||
163 | * Makes a comparison between rnd and the transition | ||
164 | * probabilities outgoing from the current state, then decides the | ||
165 | * next state and if the next packet has to be transmitted or lost. | ||
166 | * The four states correspond to: | ||
167 | * 1 => successfully transmitted packets within a gap period | ||
168 | * 4 => isolated losses within a gap period | ||
169 | * 3 => lost packets within a burst period | ||
170 | * 2 => successfully transmitted packets within a burst period | ||
171 | */ | ||
172 | switch (clg->state) { | ||
173 | case 1: | ||
174 | if (rnd < clg->a4) { | ||
175 | clg->state = 4; | ||
176 | return true; | ||
177 | } else if (clg->a4 < rnd && rnd < clg->a1) { | ||
178 | clg->state = 3; | ||
179 | return true; | ||
180 | } else if (clg->a1 < rnd) | ||
181 | clg->state = 1; | ||
182 | |||
183 | break; | ||
184 | case 2: | ||
185 | if (rnd < clg->a5) { | ||
186 | clg->state = 3; | ||
187 | return true; | ||
188 | } else | ||
189 | clg->state = 2; | ||
190 | |||
191 | break; | ||
192 | case 3: | ||
193 | if (rnd < clg->a3) | ||
194 | clg->state = 2; | ||
195 | else if (clg->a3 < rnd && rnd < clg->a2 + clg->a3) { | ||
196 | clg->state = 1; | ||
197 | return true; | ||
198 | } else if (clg->a2 + clg->a3 < rnd) { | ||
199 | clg->state = 3; | ||
200 | return true; | ||
201 | } | ||
202 | break; | ||
203 | case 4: | ||
204 | clg->state = 1; | ||
205 | break; | ||
206 | } | ||
207 | |||
208 | return false; | ||
209 | } | ||
210 | |||
211 | /* loss_gilb_ell - Gilbert-Elliot model loss generator | ||
212 | * Generates losses according to the Gilbert-Elliot loss model or | ||
213 | * its special cases (Gilbert or Simple Gilbert) | ||
214 | * | ||
215 | * Makes a comparison between random number and the transition | ||
216 | * probabilities outgoing from the current state, then decides the | ||
217 | * next state. A second random number is extracted and the comparison | ||
218 | * with the loss probability of the current state decides if the next | ||
219 | * packet will be transmitted or lost. | ||
220 | */ | ||
221 | static bool loss_gilb_ell(struct netem_sched_data *q) | ||
222 | { | ||
223 | struct clgstate *clg = &q->clg; | ||
224 | |||
225 | switch (clg->state) { | ||
226 | case 1: | ||
227 | if (net_random() < clg->a1) | ||
228 | clg->state = 2; | ||
229 | if (net_random() < clg->a4) | ||
230 | return true; | ||
231 | case 2: | ||
232 | if (net_random() < clg->a2) | ||
233 | clg->state = 1; | ||
234 | if (clg->a3 > net_random()) | ||
235 | return true; | ||
236 | } | ||
237 | |||
238 | return false; | ||
239 | } | ||
240 | |||
241 | static bool loss_event(struct netem_sched_data *q) | ||
242 | { | ||
243 | switch (q->loss_model) { | ||
244 | case CLG_RANDOM: | ||
245 | /* Random packet drop 0 => none, ~0 => all */ | ||
246 | return q->loss && q->loss >= get_crandom(&q->loss_cor); | ||
247 | |||
248 | case CLG_4_STATES: | ||
249 | /* 4state loss model algorithm (used also for GI model) | ||
250 | * Extracts a value from the markov 4 state loss generator, | ||
251 | * if it is 1 drops a packet and if needed writes the event in | ||
252 | * the kernel logs | ||
253 | */ | ||
254 | return loss_4state(q); | ||
255 | |||
256 | case CLG_GILB_ELL: | ||
257 | /* Gilbert-Elliot loss model algorithm | ||
258 | * Extracts a value from the Gilbert-Elliot loss generator, | ||
259 | * if it is 1 drops a packet and if needed writes the event in | ||
260 | * the kernel logs | ||
261 | */ | ||
262 | return loss_gilb_ell(q); | ||
263 | } | ||
264 | |||
265 | return false; /* not reached */ | ||
266 | } | ||
267 | |||
268 | |||
118 | /* tabledist - return a pseudo-randomly distributed value with mean mu and | 269 | /* tabledist - return a pseudo-randomly distributed value with mean mu and |
119 | * std deviation sigma. Uses table lookup to approximate the desired | 270 | * std deviation sigma. Uses table lookup to approximate the desired |
120 | * distribution, and a uniformly-distributed pseudo-random source. | 271 | * distribution, and a uniformly-distributed pseudo-random source. |
@@ -161,14 +312,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
161 | int ret; | 312 | int ret; |
162 | int count = 1; | 313 | int count = 1; |
163 | 314 | ||
164 | pr_debug("netem_enqueue skb=%p\n", skb); | ||
165 | |||
166 | /* Random duplication */ | 315 | /* Random duplication */ |
167 | if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) | 316 | if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) |
168 | ++count; | 317 | ++count; |
169 | 318 | ||
170 | /* Random packet drop 0 => none, ~0 => all */ | 319 | /* Drop packet? */ |
171 | if (q->loss && q->loss >= get_crandom(&q->loss_cor)) | 320 | if (loss_event(q)) |
172 | --count; | 321 | --count; |
173 | 322 | ||
174 | if (count == 0) { | 323 | if (count == 0) { |
@@ -211,8 +360,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
211 | } | 360 | } |
212 | 361 | ||
213 | cb = netem_skb_cb(skb); | 362 | cb = netem_skb_cb(skb); |
214 | if (q->gap == 0 || /* not doing reordering */ | 363 | if (q->gap == 0 || /* not doing reordering */ |
215 | q->counter < q->gap || /* inside last reordering gap */ | 364 | q->counter < q->gap || /* inside last reordering gap */ |
216 | q->reorder < get_crandom(&q->reorder_cor)) { | 365 | q->reorder < get_crandom(&q->reorder_cor)) { |
217 | psched_time_t now; | 366 | psched_time_t now; |
218 | psched_tdiff_t delay; | 367 | psched_tdiff_t delay; |
@@ -238,17 +387,18 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
238 | ret = NET_XMIT_SUCCESS; | 387 | ret = NET_XMIT_SUCCESS; |
239 | } | 388 | } |
240 | 389 | ||
241 | if (likely(ret == NET_XMIT_SUCCESS)) { | 390 | if (ret != NET_XMIT_SUCCESS) { |
242 | sch->q.qlen++; | 391 | if (net_xmit_drop_count(ret)) { |
243 | } else if (net_xmit_drop_count(ret)) { | 392 | sch->qstats.drops++; |
244 | sch->qstats.drops++; | 393 | return ret; |
394 | } | ||
245 | } | 395 | } |
246 | 396 | ||
247 | pr_debug("netem: enqueue ret %d\n", ret); | 397 | sch->q.qlen++; |
248 | return ret; | 398 | return NET_XMIT_SUCCESS; |
249 | } | 399 | } |
250 | 400 | ||
251 | static unsigned int netem_drop(struct Qdisc* sch) | 401 | static unsigned int netem_drop(struct Qdisc *sch) |
252 | { | 402 | { |
253 | struct netem_sched_data *q = qdisc_priv(sch); | 403 | struct netem_sched_data *q = qdisc_priv(sch); |
254 | unsigned int len = 0; | 404 | unsigned int len = 0; |
@@ -265,7 +415,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) | |||
265 | struct netem_sched_data *q = qdisc_priv(sch); | 415 | struct netem_sched_data *q = qdisc_priv(sch); |
266 | struct sk_buff *skb; | 416 | struct sk_buff *skb; |
267 | 417 | ||
268 | if (sch->flags & TCQ_F_THROTTLED) | 418 | if (qdisc_is_throttled(sch)) |
269 | return NULL; | 419 | return NULL; |
270 | 420 | ||
271 | skb = q->qdisc->ops->peek(q->qdisc); | 421 | skb = q->qdisc->ops->peek(q->qdisc); |
@@ -287,9 +437,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) | |||
287 | if (G_TC_FROM(skb->tc_verd) & AT_INGRESS) | 437 | if (G_TC_FROM(skb->tc_verd) & AT_INGRESS) |
288 | skb->tstamp.tv64 = 0; | 438 | skb->tstamp.tv64 = 0; |
289 | #endif | 439 | #endif |
290 | pr_debug("netem_dequeue: return skb=%p\n", skb); | 440 | |
291 | qdisc_bstats_update(sch, skb); | ||
292 | sch->q.qlen--; | 441 | sch->q.qlen--; |
442 | qdisc_unthrottled(sch); | ||
443 | qdisc_bstats_update(sch, skb); | ||
293 | return skb; | 444 | return skb; |
294 | } | 445 | } |
295 | 446 | ||
@@ -308,6 +459,16 @@ static void netem_reset(struct Qdisc *sch) | |||
308 | qdisc_watchdog_cancel(&q->watchdog); | 459 | qdisc_watchdog_cancel(&q->watchdog); |
309 | } | 460 | } |
310 | 461 | ||
462 | static void dist_free(struct disttable *d) | ||
463 | { | ||
464 | if (d) { | ||
465 | if (is_vmalloc_addr(d)) | ||
466 | vfree(d); | ||
467 | else | ||
468 | kfree(d); | ||
469 | } | ||
470 | } | ||
471 | |||
311 | /* | 472 | /* |
312 | * Distribution data is a variable size payload containing | 473 | * Distribution data is a variable size payload containing |
313 | * signed 16 bit values. | 474 | * signed 16 bit values. |
@@ -315,16 +476,20 @@ static void netem_reset(struct Qdisc *sch) | |||
315 | static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) | 476 | static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) |
316 | { | 477 | { |
317 | struct netem_sched_data *q = qdisc_priv(sch); | 478 | struct netem_sched_data *q = qdisc_priv(sch); |
318 | unsigned long n = nla_len(attr)/sizeof(__s16); | 479 | size_t n = nla_len(attr)/sizeof(__s16); |
319 | const __s16 *data = nla_data(attr); | 480 | const __s16 *data = nla_data(attr); |
320 | spinlock_t *root_lock; | 481 | spinlock_t *root_lock; |
321 | struct disttable *d; | 482 | struct disttable *d; |
322 | int i; | 483 | int i; |
484 | size_t s; | ||
323 | 485 | ||
324 | if (n > 65536) | 486 | if (n > NETEM_DIST_MAX) |
325 | return -EINVAL; | 487 | return -EINVAL; |
326 | 488 | ||
327 | d = kmalloc(sizeof(*d) + n*sizeof(d->table[0]), GFP_KERNEL); | 489 | s = sizeof(struct disttable) + n * sizeof(s16); |
490 | d = kmalloc(s, GFP_KERNEL); | ||
491 | if (!d) | ||
492 | d = vmalloc(s); | ||
328 | if (!d) | 493 | if (!d) |
329 | return -ENOMEM; | 494 | return -ENOMEM; |
330 | 495 | ||
@@ -335,7 +500,7 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) | |||
335 | root_lock = qdisc_root_sleeping_lock(sch); | 500 | root_lock = qdisc_root_sleeping_lock(sch); |
336 | 501 | ||
337 | spin_lock_bh(root_lock); | 502 | spin_lock_bh(root_lock); |
338 | kfree(q->delay_dist); | 503 | dist_free(q->delay_dist); |
339 | q->delay_dist = d; | 504 | q->delay_dist = d; |
340 | spin_unlock_bh(root_lock); | 505 | spin_unlock_bh(root_lock); |
341 | return 0; | 506 | return 0; |
@@ -369,10 +534,66 @@ static void get_corrupt(struct Qdisc *sch, const struct nlattr *attr) | |||
369 | init_crandom(&q->corrupt_cor, r->correlation); | 534 | init_crandom(&q->corrupt_cor, r->correlation); |
370 | } | 535 | } |
371 | 536 | ||
537 | static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr) | ||
538 | { | ||
539 | struct netem_sched_data *q = qdisc_priv(sch); | ||
540 | const struct nlattr *la; | ||
541 | int rem; | ||
542 | |||
543 | nla_for_each_nested(la, attr, rem) { | ||
544 | u16 type = nla_type(la); | ||
545 | |||
546 | switch(type) { | ||
547 | case NETEM_LOSS_GI: { | ||
548 | const struct tc_netem_gimodel *gi = nla_data(la); | ||
549 | |||
550 | if (nla_len(la) != sizeof(struct tc_netem_gimodel)) { | ||
551 | pr_info("netem: incorrect gi model size\n"); | ||
552 | return -EINVAL; | ||
553 | } | ||
554 | |||
555 | q->loss_model = CLG_4_STATES; | ||
556 | |||
557 | q->clg.state = 1; | ||
558 | q->clg.a1 = gi->p13; | ||
559 | q->clg.a2 = gi->p31; | ||
560 | q->clg.a3 = gi->p32; | ||
561 | q->clg.a4 = gi->p14; | ||
562 | q->clg.a5 = gi->p23; | ||
563 | break; | ||
564 | } | ||
565 | |||
566 | case NETEM_LOSS_GE: { | ||
567 | const struct tc_netem_gemodel *ge = nla_data(la); | ||
568 | |||
569 | if (nla_len(la) != sizeof(struct tc_netem_gemodel)) { | ||
570 | pr_info("netem: incorrect gi model size\n"); | ||
571 | return -EINVAL; | ||
572 | } | ||
573 | |||
574 | q->loss_model = CLG_GILB_ELL; | ||
575 | q->clg.state = 1; | ||
576 | q->clg.a1 = ge->p; | ||
577 | q->clg.a2 = ge->r; | ||
578 | q->clg.a3 = ge->h; | ||
579 | q->clg.a4 = ge->k1; | ||
580 | break; | ||
581 | } | ||
582 | |||
583 | default: | ||
584 | pr_info("netem: unknown loss type %u\n", type); | ||
585 | return -EINVAL; | ||
586 | } | ||
587 | } | ||
588 | |||
589 | return 0; | ||
590 | } | ||
591 | |||
372 | static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = { | 592 | static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = { |
373 | [TCA_NETEM_CORR] = { .len = sizeof(struct tc_netem_corr) }, | 593 | [TCA_NETEM_CORR] = { .len = sizeof(struct tc_netem_corr) }, |
374 | [TCA_NETEM_REORDER] = { .len = sizeof(struct tc_netem_reorder) }, | 594 | [TCA_NETEM_REORDER] = { .len = sizeof(struct tc_netem_reorder) }, |
375 | [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) }, | 595 | [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) }, |
596 | [TCA_NETEM_LOSS] = { .type = NLA_NESTED }, | ||
376 | }; | 597 | }; |
377 | 598 | ||
378 | static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, | 599 | static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, |
@@ -380,11 +601,15 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, | |||
380 | { | 601 | { |
381 | int nested_len = nla_len(nla) - NLA_ALIGN(len); | 602 | int nested_len = nla_len(nla) - NLA_ALIGN(len); |
382 | 603 | ||
383 | if (nested_len < 0) | 604 | if (nested_len < 0) { |
605 | pr_info("netem: invalid attributes len %d\n", nested_len); | ||
384 | return -EINVAL; | 606 | return -EINVAL; |
607 | } | ||
608 | |||
385 | if (nested_len >= nla_attr_size(0)) | 609 | if (nested_len >= nla_attr_size(0)) |
386 | return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len), | 610 | return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len), |
387 | nested_len, policy); | 611 | nested_len, policy); |
612 | |||
388 | memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); | 613 | memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); |
389 | return 0; | 614 | return 0; |
390 | } | 615 | } |
@@ -407,7 +632,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
407 | 632 | ||
408 | ret = fifo_set_limit(q->qdisc, qopt->limit); | 633 | ret = fifo_set_limit(q->qdisc, qopt->limit); |
409 | if (ret) { | 634 | if (ret) { |
410 | pr_debug("netem: can't set fifo limit\n"); | 635 | pr_info("netem: can't set fifo limit\n"); |
411 | return ret; | 636 | return ret; |
412 | } | 637 | } |
413 | 638 | ||
@@ -440,7 +665,11 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
440 | if (tb[TCA_NETEM_CORRUPT]) | 665 | if (tb[TCA_NETEM_CORRUPT]) |
441 | get_corrupt(sch, tb[TCA_NETEM_CORRUPT]); | 666 | get_corrupt(sch, tb[TCA_NETEM_CORRUPT]); |
442 | 667 | ||
443 | return 0; | 668 | q->loss_model = CLG_RANDOM; |
669 | if (tb[TCA_NETEM_LOSS]) | ||
670 | ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]); | ||
671 | |||
672 | return ret; | ||
444 | } | 673 | } |
445 | 674 | ||
446 | /* | 675 | /* |
@@ -535,16 +764,17 @@ static int netem_init(struct Qdisc *sch, struct nlattr *opt) | |||
535 | 764 | ||
536 | qdisc_watchdog_init(&q->watchdog, sch); | 765 | qdisc_watchdog_init(&q->watchdog, sch); |
537 | 766 | ||
767 | q->loss_model = CLG_RANDOM; | ||
538 | q->qdisc = qdisc_create_dflt(sch->dev_queue, &tfifo_qdisc_ops, | 768 | q->qdisc = qdisc_create_dflt(sch->dev_queue, &tfifo_qdisc_ops, |
539 | TC_H_MAKE(sch->handle, 1)); | 769 | TC_H_MAKE(sch->handle, 1)); |
540 | if (!q->qdisc) { | 770 | if (!q->qdisc) { |
541 | pr_debug("netem: qdisc create failed\n"); | 771 | pr_notice("netem: qdisc create tfifo qdisc failed\n"); |
542 | return -ENOMEM; | 772 | return -ENOMEM; |
543 | } | 773 | } |
544 | 774 | ||
545 | ret = netem_change(sch, opt); | 775 | ret = netem_change(sch, opt); |
546 | if (ret) { | 776 | if (ret) { |
547 | pr_debug("netem: change failed\n"); | 777 | pr_info("netem: change failed\n"); |
548 | qdisc_destroy(q->qdisc); | 778 | qdisc_destroy(q->qdisc); |
549 | } | 779 | } |
550 | return ret; | 780 | return ret; |
@@ -556,14 +786,61 @@ static void netem_destroy(struct Qdisc *sch) | |||
556 | 786 | ||
557 | qdisc_watchdog_cancel(&q->watchdog); | 787 | qdisc_watchdog_cancel(&q->watchdog); |
558 | qdisc_destroy(q->qdisc); | 788 | qdisc_destroy(q->qdisc); |
559 | kfree(q->delay_dist); | 789 | dist_free(q->delay_dist); |
790 | } | ||
791 | |||
792 | static int dump_loss_model(const struct netem_sched_data *q, | ||
793 | struct sk_buff *skb) | ||
794 | { | ||
795 | struct nlattr *nest; | ||
796 | |||
797 | nest = nla_nest_start(skb, TCA_NETEM_LOSS); | ||
798 | if (nest == NULL) | ||
799 | goto nla_put_failure; | ||
800 | |||
801 | switch (q->loss_model) { | ||
802 | case CLG_RANDOM: | ||
803 | /* legacy loss model */ | ||
804 | nla_nest_cancel(skb, nest); | ||
805 | return 0; /* no data */ | ||
806 | |||
807 | case CLG_4_STATES: { | ||
808 | struct tc_netem_gimodel gi = { | ||
809 | .p13 = q->clg.a1, | ||
810 | .p31 = q->clg.a2, | ||
811 | .p32 = q->clg.a3, | ||
812 | .p14 = q->clg.a4, | ||
813 | .p23 = q->clg.a5, | ||
814 | }; | ||
815 | |||
816 | NLA_PUT(skb, NETEM_LOSS_GI, sizeof(gi), &gi); | ||
817 | break; | ||
818 | } | ||
819 | case CLG_GILB_ELL: { | ||
820 | struct tc_netem_gemodel ge = { | ||
821 | .p = q->clg.a1, | ||
822 | .r = q->clg.a2, | ||
823 | .h = q->clg.a3, | ||
824 | .k1 = q->clg.a4, | ||
825 | }; | ||
826 | |||
827 | NLA_PUT(skb, NETEM_LOSS_GE, sizeof(ge), &ge); | ||
828 | break; | ||
829 | } | ||
830 | } | ||
831 | |||
832 | nla_nest_end(skb, nest); | ||
833 | return 0; | ||
834 | |||
835 | nla_put_failure: | ||
836 | nla_nest_cancel(skb, nest); | ||
837 | return -1; | ||
560 | } | 838 | } |
561 | 839 | ||
562 | static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) | 840 | static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) |
563 | { | 841 | { |
564 | const struct netem_sched_data *q = qdisc_priv(sch); | 842 | const struct netem_sched_data *q = qdisc_priv(sch); |
565 | unsigned char *b = skb_tail_pointer(skb); | 843 | struct nlattr *nla = (struct nlattr *) skb_tail_pointer(skb); |
566 | struct nlattr *nla = (struct nlattr *) b; | ||
567 | struct tc_netem_qopt qopt; | 844 | struct tc_netem_qopt qopt; |
568 | struct tc_netem_corr cor; | 845 | struct tc_netem_corr cor; |
569 | struct tc_netem_reorder reorder; | 846 | struct tc_netem_reorder reorder; |
@@ -590,17 +867,87 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
590 | corrupt.correlation = q->corrupt_cor.rho; | 867 | corrupt.correlation = q->corrupt_cor.rho; |
591 | NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt); | 868 | NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt); |
592 | 869 | ||
593 | nla->nla_len = skb_tail_pointer(skb) - b; | 870 | if (dump_loss_model(q, skb) != 0) |
871 | goto nla_put_failure; | ||
594 | 872 | ||
595 | return skb->len; | 873 | return nla_nest_end(skb, nla); |
596 | 874 | ||
597 | nla_put_failure: | 875 | nla_put_failure: |
598 | nlmsg_trim(skb, b); | 876 | nlmsg_trim(skb, nla); |
599 | return -1; | 877 | return -1; |
600 | } | 878 | } |
601 | 879 | ||
880 | static int netem_dump_class(struct Qdisc *sch, unsigned long cl, | ||
881 | struct sk_buff *skb, struct tcmsg *tcm) | ||
882 | { | ||
883 | struct netem_sched_data *q = qdisc_priv(sch); | ||
884 | |||
885 | if (cl != 1) /* only one class */ | ||
886 | return -ENOENT; | ||
887 | |||
888 | tcm->tcm_handle |= TC_H_MIN(1); | ||
889 | tcm->tcm_info = q->qdisc->handle; | ||
890 | |||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | ||
895 | struct Qdisc **old) | ||
896 | { | ||
897 | struct netem_sched_data *q = qdisc_priv(sch); | ||
898 | |||
899 | if (new == NULL) | ||
900 | new = &noop_qdisc; | ||
901 | |||
902 | sch_tree_lock(sch); | ||
903 | *old = q->qdisc; | ||
904 | q->qdisc = new; | ||
905 | qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); | ||
906 | qdisc_reset(*old); | ||
907 | sch_tree_unlock(sch); | ||
908 | |||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg) | ||
913 | { | ||
914 | struct netem_sched_data *q = qdisc_priv(sch); | ||
915 | return q->qdisc; | ||
916 | } | ||
917 | |||
918 | static unsigned long netem_get(struct Qdisc *sch, u32 classid) | ||
919 | { | ||
920 | return 1; | ||
921 | } | ||
922 | |||
923 | static void netem_put(struct Qdisc *sch, unsigned long arg) | ||
924 | { | ||
925 | } | ||
926 | |||
927 | static void netem_walk(struct Qdisc *sch, struct qdisc_walker *walker) | ||
928 | { | ||
929 | if (!walker->stop) { | ||
930 | if (walker->count >= walker->skip) | ||
931 | if (walker->fn(sch, 1, walker) < 0) { | ||
932 | walker->stop = 1; | ||
933 | return; | ||
934 | } | ||
935 | walker->count++; | ||
936 | } | ||
937 | } | ||
938 | |||
939 | static const struct Qdisc_class_ops netem_class_ops = { | ||
940 | .graft = netem_graft, | ||
941 | .leaf = netem_leaf, | ||
942 | .get = netem_get, | ||
943 | .put = netem_put, | ||
944 | .walk = netem_walk, | ||
945 | .dump = netem_dump_class, | ||
946 | }; | ||
947 | |||
602 | static struct Qdisc_ops netem_qdisc_ops __read_mostly = { | 948 | static struct Qdisc_ops netem_qdisc_ops __read_mostly = { |
603 | .id = "netem", | 949 | .id = "netem", |
950 | .cl_ops = &netem_class_ops, | ||
604 | .priv_size = sizeof(struct netem_sched_data), | 951 | .priv_size = sizeof(struct netem_sched_data), |
605 | .enqueue = netem_enqueue, | 952 | .enqueue = netem_enqueue, |
606 | .dequeue = netem_dequeue, | 953 | .dequeue = netem_dequeue, |
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index fbd710d619bf..2a318f2dc3e5 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c | |||
@@ -22,8 +22,7 @@ | |||
22 | #include <net/pkt_sched.h> | 22 | #include <net/pkt_sched.h> |
23 | 23 | ||
24 | 24 | ||
25 | struct prio_sched_data | 25 | struct prio_sched_data { |
26 | { | ||
27 | int bands; | 26 | int bands; |
28 | struct tcf_proto *filter_list; | 27 | struct tcf_proto *filter_list; |
29 | u8 prio2band[TC_PRIO_MAX+1]; | 28 | u8 prio2band[TC_PRIO_MAX+1]; |
@@ -54,7 +53,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
54 | if (!q->filter_list || err < 0) { | 53 | if (!q->filter_list || err < 0) { |
55 | if (TC_H_MAJ(band)) | 54 | if (TC_H_MAJ(band)) |
56 | band = 0; | 55 | band = 0; |
57 | return q->queues[q->prio2band[band&TC_PRIO_MAX]]; | 56 | return q->queues[q->prio2band[band & TC_PRIO_MAX]]; |
58 | } | 57 | } |
59 | band = res.classid; | 58 | band = res.classid; |
60 | } | 59 | } |
@@ -106,7 +105,7 @@ static struct sk_buff *prio_peek(struct Qdisc *sch) | |||
106 | return NULL; | 105 | return NULL; |
107 | } | 106 | } |
108 | 107 | ||
109 | static struct sk_buff *prio_dequeue(struct Qdisc* sch) | 108 | static struct sk_buff *prio_dequeue(struct Qdisc *sch) |
110 | { | 109 | { |
111 | struct prio_sched_data *q = qdisc_priv(sch); | 110 | struct prio_sched_data *q = qdisc_priv(sch); |
112 | int prio; | 111 | int prio; |
@@ -124,7 +123,7 @@ static struct sk_buff *prio_dequeue(struct Qdisc* sch) | |||
124 | 123 | ||
125 | } | 124 | } |
126 | 125 | ||
127 | static unsigned int prio_drop(struct Qdisc* sch) | 126 | static unsigned int prio_drop(struct Qdisc *sch) |
128 | { | 127 | { |
129 | struct prio_sched_data *q = qdisc_priv(sch); | 128 | struct prio_sched_data *q = qdisc_priv(sch); |
130 | int prio; | 129 | int prio; |
@@ -143,24 +142,24 @@ static unsigned int prio_drop(struct Qdisc* sch) | |||
143 | 142 | ||
144 | 143 | ||
145 | static void | 144 | static void |
146 | prio_reset(struct Qdisc* sch) | 145 | prio_reset(struct Qdisc *sch) |
147 | { | 146 | { |
148 | int prio; | 147 | int prio; |
149 | struct prio_sched_data *q = qdisc_priv(sch); | 148 | struct prio_sched_data *q = qdisc_priv(sch); |
150 | 149 | ||
151 | for (prio=0; prio<q->bands; prio++) | 150 | for (prio = 0; prio < q->bands; prio++) |
152 | qdisc_reset(q->queues[prio]); | 151 | qdisc_reset(q->queues[prio]); |
153 | sch->q.qlen = 0; | 152 | sch->q.qlen = 0; |
154 | } | 153 | } |
155 | 154 | ||
156 | static void | 155 | static void |
157 | prio_destroy(struct Qdisc* sch) | 156 | prio_destroy(struct Qdisc *sch) |
158 | { | 157 | { |
159 | int prio; | 158 | int prio; |
160 | struct prio_sched_data *q = qdisc_priv(sch); | 159 | struct prio_sched_data *q = qdisc_priv(sch); |
161 | 160 | ||
162 | tcf_destroy_chain(&q->filter_list); | 161 | tcf_destroy_chain(&q->filter_list); |
163 | for (prio=0; prio<q->bands; prio++) | 162 | for (prio = 0; prio < q->bands; prio++) |
164 | qdisc_destroy(q->queues[prio]); | 163 | qdisc_destroy(q->queues[prio]); |
165 | } | 164 | } |
166 | 165 | ||
@@ -177,7 +176,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt) | |||
177 | if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2) | 176 | if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2) |
178 | return -EINVAL; | 177 | return -EINVAL; |
179 | 178 | ||
180 | for (i=0; i<=TC_PRIO_MAX; i++) { | 179 | for (i = 0; i <= TC_PRIO_MAX; i++) { |
181 | if (qopt->priomap[i] >= qopt->bands) | 180 | if (qopt->priomap[i] >= qopt->bands) |
182 | return -EINVAL; | 181 | return -EINVAL; |
183 | } | 182 | } |
@@ -186,7 +185,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt) | |||
186 | q->bands = qopt->bands; | 185 | q->bands = qopt->bands; |
187 | memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); | 186 | memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); |
188 | 187 | ||
189 | for (i=q->bands; i<TCQ_PRIO_BANDS; i++) { | 188 | for (i = q->bands; i < TCQ_PRIO_BANDS; i++) { |
190 | struct Qdisc *child = q->queues[i]; | 189 | struct Qdisc *child = q->queues[i]; |
191 | q->queues[i] = &noop_qdisc; | 190 | q->queues[i] = &noop_qdisc; |
192 | if (child != &noop_qdisc) { | 191 | if (child != &noop_qdisc) { |
@@ -196,9 +195,10 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt) | |||
196 | } | 195 | } |
197 | sch_tree_unlock(sch); | 196 | sch_tree_unlock(sch); |
198 | 197 | ||
199 | for (i=0; i<q->bands; i++) { | 198 | for (i = 0; i < q->bands; i++) { |
200 | if (q->queues[i] == &noop_qdisc) { | 199 | if (q->queues[i] == &noop_qdisc) { |
201 | struct Qdisc *child, *old; | 200 | struct Qdisc *child, *old; |
201 | |||
202 | child = qdisc_create_dflt(sch->dev_queue, | 202 | child = qdisc_create_dflt(sch->dev_queue, |
203 | &pfifo_qdisc_ops, | 203 | &pfifo_qdisc_ops, |
204 | TC_H_MAKE(sch->handle, i + 1)); | 204 | TC_H_MAKE(sch->handle, i + 1)); |
@@ -224,7 +224,7 @@ static int prio_init(struct Qdisc *sch, struct nlattr *opt) | |||
224 | struct prio_sched_data *q = qdisc_priv(sch); | 224 | struct prio_sched_data *q = qdisc_priv(sch); |
225 | int i; | 225 | int i; |
226 | 226 | ||
227 | for (i=0; i<TCQ_PRIO_BANDS; i++) | 227 | for (i = 0; i < TCQ_PRIO_BANDS; i++) |
228 | q->queues[i] = &noop_qdisc; | 228 | q->queues[i] = &noop_qdisc; |
229 | 229 | ||
230 | if (opt == NULL) { | 230 | if (opt == NULL) { |
@@ -232,7 +232,7 @@ static int prio_init(struct Qdisc *sch, struct nlattr *opt) | |||
232 | } else { | 232 | } else { |
233 | int err; | 233 | int err; |
234 | 234 | ||
235 | if ((err= prio_tune(sch, opt)) != 0) | 235 | if ((err = prio_tune(sch, opt)) != 0) |
236 | return err; | 236 | return err; |
237 | } | 237 | } |
238 | return 0; | 238 | return 0; |
@@ -245,7 +245,7 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
245 | struct tc_prio_qopt opt; | 245 | struct tc_prio_qopt opt; |
246 | 246 | ||
247 | opt.bands = q->bands; | 247 | opt.bands = q->bands; |
248 | memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX+1); | 248 | memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX + 1); |
249 | 249 | ||
250 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | 250 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); |
251 | 251 | ||
@@ -342,7 +342,7 @@ static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
342 | arg->count++; | 342 | arg->count++; |
343 | continue; | 343 | continue; |
344 | } | 344 | } |
345 | if (arg->fn(sch, prio+1, arg) < 0) { | 345 | if (arg->fn(sch, prio + 1, arg) < 0) { |
346 | arg->stop = 1; | 346 | arg->stop = 1; |
347 | break; | 347 | break; |
348 | } | 348 | } |
@@ -350,7 +350,7 @@ static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
350 | } | 350 | } |
351 | } | 351 | } |
352 | 352 | ||
353 | static struct tcf_proto ** prio_find_tcf(struct Qdisc *sch, unsigned long cl) | 353 | static struct tcf_proto **prio_find_tcf(struct Qdisc *sch, unsigned long cl) |
354 | { | 354 | { |
355 | struct prio_sched_data *q = qdisc_priv(sch); | 355 | struct prio_sched_data *q = qdisc_priv(sch); |
356 | 356 | ||
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 9f98dbd32d4c..6649463da1b6 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c | |||
@@ -36,8 +36,7 @@ | |||
36 | if RED works correctly. | 36 | if RED works correctly. |
37 | */ | 37 | */ |
38 | 38 | ||
39 | struct red_sched_data | 39 | struct red_sched_data { |
40 | { | ||
41 | u32 limit; /* HARD maximal queue length */ | 40 | u32 limit; /* HARD maximal queue length */ |
42 | unsigned char flags; | 41 | unsigned char flags; |
43 | struct red_parms parms; | 42 | struct red_parms parms; |
@@ -55,7 +54,7 @@ static inline int red_use_harddrop(struct red_sched_data *q) | |||
55 | return q->flags & TC_RED_HARDDROP; | 54 | return q->flags & TC_RED_HARDDROP; |
56 | } | 55 | } |
57 | 56 | ||
58 | static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) | 57 | static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
59 | { | 58 | { |
60 | struct red_sched_data *q = qdisc_priv(sch); | 59 | struct red_sched_data *q = qdisc_priv(sch); |
61 | struct Qdisc *child = q->qdisc; | 60 | struct Qdisc *child = q->qdisc; |
@@ -67,29 +66,29 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
67 | red_end_of_idle_period(&q->parms); | 66 | red_end_of_idle_period(&q->parms); |
68 | 67 | ||
69 | switch (red_action(&q->parms, q->parms.qavg)) { | 68 | switch (red_action(&q->parms, q->parms.qavg)) { |
70 | case RED_DONT_MARK: | 69 | case RED_DONT_MARK: |
71 | break; | 70 | break; |
72 | 71 | ||
73 | case RED_PROB_MARK: | 72 | case RED_PROB_MARK: |
74 | sch->qstats.overlimits++; | 73 | sch->qstats.overlimits++; |
75 | if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) { | 74 | if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) { |
76 | q->stats.prob_drop++; | 75 | q->stats.prob_drop++; |
77 | goto congestion_drop; | 76 | goto congestion_drop; |
78 | } | 77 | } |
79 | 78 | ||
80 | q->stats.prob_mark++; | 79 | q->stats.prob_mark++; |
81 | break; | 80 | break; |
82 | 81 | ||
83 | case RED_HARD_MARK: | 82 | case RED_HARD_MARK: |
84 | sch->qstats.overlimits++; | 83 | sch->qstats.overlimits++; |
85 | if (red_use_harddrop(q) || !red_use_ecn(q) || | 84 | if (red_use_harddrop(q) || !red_use_ecn(q) || |
86 | !INET_ECN_set_ce(skb)) { | 85 | !INET_ECN_set_ce(skb)) { |
87 | q->stats.forced_drop++; | 86 | q->stats.forced_drop++; |
88 | goto congestion_drop; | 87 | goto congestion_drop; |
89 | } | 88 | } |
90 | 89 | ||
91 | q->stats.forced_mark++; | 90 | q->stats.forced_mark++; |
92 | break; | 91 | break; |
93 | } | 92 | } |
94 | 93 | ||
95 | ret = qdisc_enqueue(skb, child); | 94 | ret = qdisc_enqueue(skb, child); |
@@ -106,7 +105,7 @@ congestion_drop: | |||
106 | return NET_XMIT_CN; | 105 | return NET_XMIT_CN; |
107 | } | 106 | } |
108 | 107 | ||
109 | static struct sk_buff * red_dequeue(struct Qdisc* sch) | 108 | static struct sk_buff *red_dequeue(struct Qdisc *sch) |
110 | { | 109 | { |
111 | struct sk_buff *skb; | 110 | struct sk_buff *skb; |
112 | struct red_sched_data *q = qdisc_priv(sch); | 111 | struct red_sched_data *q = qdisc_priv(sch); |
@@ -123,7 +122,7 @@ static struct sk_buff * red_dequeue(struct Qdisc* sch) | |||
123 | return skb; | 122 | return skb; |
124 | } | 123 | } |
125 | 124 | ||
126 | static struct sk_buff * red_peek(struct Qdisc* sch) | 125 | static struct sk_buff *red_peek(struct Qdisc *sch) |
127 | { | 126 | { |
128 | struct red_sched_data *q = qdisc_priv(sch); | 127 | struct red_sched_data *q = qdisc_priv(sch); |
129 | struct Qdisc *child = q->qdisc; | 128 | struct Qdisc *child = q->qdisc; |
@@ -131,7 +130,7 @@ static struct sk_buff * red_peek(struct Qdisc* sch) | |||
131 | return child->ops->peek(child); | 130 | return child->ops->peek(child); |
132 | } | 131 | } |
133 | 132 | ||
134 | static unsigned int red_drop(struct Qdisc* sch) | 133 | static unsigned int red_drop(struct Qdisc *sch) |
135 | { | 134 | { |
136 | struct red_sched_data *q = qdisc_priv(sch); | 135 | struct red_sched_data *q = qdisc_priv(sch); |
137 | struct Qdisc *child = q->qdisc; | 136 | struct Qdisc *child = q->qdisc; |
@@ -150,7 +149,7 @@ static unsigned int red_drop(struct Qdisc* sch) | |||
150 | return 0; | 149 | return 0; |
151 | } | 150 | } |
152 | 151 | ||
153 | static void red_reset(struct Qdisc* sch) | 152 | static void red_reset(struct Qdisc *sch) |
154 | { | 153 | { |
155 | struct red_sched_data *q = qdisc_priv(sch); | 154 | struct red_sched_data *q = qdisc_priv(sch); |
156 | 155 | ||
@@ -217,7 +216,7 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) | |||
217 | return 0; | 216 | return 0; |
218 | } | 217 | } |
219 | 218 | ||
220 | static int red_init(struct Qdisc* sch, struct nlattr *opt) | 219 | static int red_init(struct Qdisc *sch, struct nlattr *opt) |
221 | { | 220 | { |
222 | struct red_sched_data *q = qdisc_priv(sch); | 221 | struct red_sched_data *q = qdisc_priv(sch); |
223 | 222 | ||
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c new file mode 100644 index 000000000000..0a833d0c1f61 --- /dev/null +++ b/net/sched/sch_sfb.c | |||
@@ -0,0 +1,709 @@ | |||
1 | /* | ||
2 | * net/sched/sch_sfb.c Stochastic Fair Blue | ||
3 | * | ||
4 | * Copyright (c) 2008-2011 Juliusz Chroboczek <jch@pps.jussieu.fr> | ||
5 | * Copyright (c) 2011 Eric Dumazet <eric.dumazet@gmail.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * W. Feng, D. Kandlur, D. Saha, K. Shin. Blue: | ||
12 | * A New Class of Active Queue Management Algorithms. | ||
13 | * U. Michigan CSE-TR-387-99, April 1999. | ||
14 | * | ||
15 | * http://www.thefengs.com/wuchang/blue/CSE-TR-387-99.pdf | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/skbuff.h> | ||
24 | #include <linux/random.h> | ||
25 | #include <linux/jhash.h> | ||
26 | #include <net/ip.h> | ||
27 | #include <net/pkt_sched.h> | ||
28 | #include <net/inet_ecn.h> | ||
29 | |||
30 | /* | ||
31 | * SFB uses two B[l][n] : L x N arrays of bins (L levels, N bins per level) | ||
32 | * This implementation uses L = 8 and N = 16 | ||
33 | * This permits us to split one 32bit hash (provided per packet by rxhash or | ||
34 | * external classifier) into 8 subhashes of 4 bits. | ||
35 | */ | ||
36 | #define SFB_BUCKET_SHIFT 4 | ||
37 | #define SFB_NUMBUCKETS (1 << SFB_BUCKET_SHIFT) /* N bins per Level */ | ||
38 | #define SFB_BUCKET_MASK (SFB_NUMBUCKETS - 1) | ||
39 | #define SFB_LEVELS (32 / SFB_BUCKET_SHIFT) /* L */ | ||
40 | |||
41 | /* SFB algo uses a virtual queue, named "bin" */ | ||
42 | struct sfb_bucket { | ||
43 | u16 qlen; /* length of virtual queue */ | ||
44 | u16 p_mark; /* marking probability */ | ||
45 | }; | ||
46 | |||
47 | /* We use a double buffering right before hash change | ||
48 | * (Section 4.4 of SFB reference : moving hash functions) | ||
49 | */ | ||
50 | struct sfb_bins { | ||
51 | u32 perturbation; /* jhash perturbation */ | ||
52 | struct sfb_bucket bins[SFB_LEVELS][SFB_NUMBUCKETS]; | ||
53 | }; | ||
54 | |||
55 | struct sfb_sched_data { | ||
56 | struct Qdisc *qdisc; | ||
57 | struct tcf_proto *filter_list; | ||
58 | unsigned long rehash_interval; | ||
59 | unsigned long warmup_time; /* double buffering warmup time in jiffies */ | ||
60 | u32 max; | ||
61 | u32 bin_size; /* maximum queue length per bin */ | ||
62 | u32 increment; /* d1 */ | ||
63 | u32 decrement; /* d2 */ | ||
64 | u32 limit; /* HARD maximal queue length */ | ||
65 | u32 penalty_rate; | ||
66 | u32 penalty_burst; | ||
67 | u32 tokens_avail; | ||
68 | unsigned long rehash_time; | ||
69 | unsigned long token_time; | ||
70 | |||
71 | u8 slot; /* current active bins (0 or 1) */ | ||
72 | bool double_buffering; | ||
73 | struct sfb_bins bins[2]; | ||
74 | |||
75 | struct { | ||
76 | u32 earlydrop; | ||
77 | u32 penaltydrop; | ||
78 | u32 bucketdrop; | ||
79 | u32 queuedrop; | ||
80 | u32 childdrop; /* drops in child qdisc */ | ||
81 | u32 marked; /* ECN mark */ | ||
82 | } stats; | ||
83 | }; | ||
84 | |||
85 | /* | ||
86 | * Each queued skb might be hashed on one or two bins | ||
87 | * We store in skb_cb the two hash values. | ||
88 | * (A zero value means double buffering was not used) | ||
89 | */ | ||
90 | struct sfb_skb_cb { | ||
91 | u32 hashes[2]; | ||
92 | }; | ||
93 | |||
94 | static inline struct sfb_skb_cb *sfb_skb_cb(const struct sk_buff *skb) | ||
95 | { | ||
96 | BUILD_BUG_ON(sizeof(skb->cb) < | ||
97 | sizeof(struct qdisc_skb_cb) + sizeof(struct sfb_skb_cb)); | ||
98 | return (struct sfb_skb_cb *)qdisc_skb_cb(skb)->data; | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * If using 'internal' SFB flow classifier, hash comes from skb rxhash | ||
103 | * If using external classifier, hash comes from the classid. | ||
104 | */ | ||
105 | static u32 sfb_hash(const struct sk_buff *skb, u32 slot) | ||
106 | { | ||
107 | return sfb_skb_cb(skb)->hashes[slot]; | ||
108 | } | ||
109 | |||
110 | /* Probabilities are coded as Q0.16 fixed-point values, | ||
111 | * with 0xFFFF representing 65535/65536 (almost 1.0) | ||
112 | * Addition and subtraction are saturating in [0, 65535] | ||
113 | */ | ||
114 | static u32 prob_plus(u32 p1, u32 p2) | ||
115 | { | ||
116 | u32 res = p1 + p2; | ||
117 | |||
118 | return min_t(u32, res, SFB_MAX_PROB); | ||
119 | } | ||
120 | |||
121 | static u32 prob_minus(u32 p1, u32 p2) | ||
122 | { | ||
123 | return p1 > p2 ? p1 - p2 : 0; | ||
124 | } | ||
125 | |||
126 | static void increment_one_qlen(u32 sfbhash, u32 slot, struct sfb_sched_data *q) | ||
127 | { | ||
128 | int i; | ||
129 | struct sfb_bucket *b = &q->bins[slot].bins[0][0]; | ||
130 | |||
131 | for (i = 0; i < SFB_LEVELS; i++) { | ||
132 | u32 hash = sfbhash & SFB_BUCKET_MASK; | ||
133 | |||
134 | sfbhash >>= SFB_BUCKET_SHIFT; | ||
135 | if (b[hash].qlen < 0xFFFF) | ||
136 | b[hash].qlen++; | ||
137 | b += SFB_NUMBUCKETS; /* next level */ | ||
138 | } | ||
139 | } | ||
140 | |||
141 | static void increment_qlen(const struct sk_buff *skb, struct sfb_sched_data *q) | ||
142 | { | ||
143 | u32 sfbhash; | ||
144 | |||
145 | sfbhash = sfb_hash(skb, 0); | ||
146 | if (sfbhash) | ||
147 | increment_one_qlen(sfbhash, 0, q); | ||
148 | |||
149 | sfbhash = sfb_hash(skb, 1); | ||
150 | if (sfbhash) | ||
151 | increment_one_qlen(sfbhash, 1, q); | ||
152 | } | ||
153 | |||
154 | static void decrement_one_qlen(u32 sfbhash, u32 slot, | ||
155 | struct sfb_sched_data *q) | ||
156 | { | ||
157 | int i; | ||
158 | struct sfb_bucket *b = &q->bins[slot].bins[0][0]; | ||
159 | |||
160 | for (i = 0; i < SFB_LEVELS; i++) { | ||
161 | u32 hash = sfbhash & SFB_BUCKET_MASK; | ||
162 | |||
163 | sfbhash >>= SFB_BUCKET_SHIFT; | ||
164 | if (b[hash].qlen > 0) | ||
165 | b[hash].qlen--; | ||
166 | b += SFB_NUMBUCKETS; /* next level */ | ||
167 | } | ||
168 | } | ||
169 | |||
170 | static void decrement_qlen(const struct sk_buff *skb, struct sfb_sched_data *q) | ||
171 | { | ||
172 | u32 sfbhash; | ||
173 | |||
174 | sfbhash = sfb_hash(skb, 0); | ||
175 | if (sfbhash) | ||
176 | decrement_one_qlen(sfbhash, 0, q); | ||
177 | |||
178 | sfbhash = sfb_hash(skb, 1); | ||
179 | if (sfbhash) | ||
180 | decrement_one_qlen(sfbhash, 1, q); | ||
181 | } | ||
182 | |||
183 | static void decrement_prob(struct sfb_bucket *b, struct sfb_sched_data *q) | ||
184 | { | ||
185 | b->p_mark = prob_minus(b->p_mark, q->decrement); | ||
186 | } | ||
187 | |||
188 | static void increment_prob(struct sfb_bucket *b, struct sfb_sched_data *q) | ||
189 | { | ||
190 | b->p_mark = prob_plus(b->p_mark, q->increment); | ||
191 | } | ||
192 | |||
193 | static void sfb_zero_all_buckets(struct sfb_sched_data *q) | ||
194 | { | ||
195 | memset(&q->bins, 0, sizeof(q->bins)); | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * compute max qlen, max p_mark, and avg p_mark | ||
200 | */ | ||
201 | static u32 sfb_compute_qlen(u32 *prob_r, u32 *avgpm_r, const struct sfb_sched_data *q) | ||
202 | { | ||
203 | int i; | ||
204 | u32 qlen = 0, prob = 0, totalpm = 0; | ||
205 | const struct sfb_bucket *b = &q->bins[q->slot].bins[0][0]; | ||
206 | |||
207 | for (i = 0; i < SFB_LEVELS * SFB_NUMBUCKETS; i++) { | ||
208 | if (qlen < b->qlen) | ||
209 | qlen = b->qlen; | ||
210 | totalpm += b->p_mark; | ||
211 | if (prob < b->p_mark) | ||
212 | prob = b->p_mark; | ||
213 | b++; | ||
214 | } | ||
215 | *prob_r = prob; | ||
216 | *avgpm_r = totalpm / (SFB_LEVELS * SFB_NUMBUCKETS); | ||
217 | return qlen; | ||
218 | } | ||
219 | |||
220 | |||
221 | static void sfb_init_perturbation(u32 slot, struct sfb_sched_data *q) | ||
222 | { | ||
223 | q->bins[slot].perturbation = net_random(); | ||
224 | } | ||
225 | |||
226 | static void sfb_swap_slot(struct sfb_sched_data *q) | ||
227 | { | ||
228 | sfb_init_perturbation(q->slot, q); | ||
229 | q->slot ^= 1; | ||
230 | q->double_buffering = false; | ||
231 | } | ||
232 | |||
233 | /* Non elastic flows are allowed to use part of the bandwidth, expressed | ||
234 | * in "penalty_rate" packets per second, with "penalty_burst" burst | ||
235 | */ | ||
236 | static bool sfb_rate_limit(struct sk_buff *skb, struct sfb_sched_data *q) | ||
237 | { | ||
238 | if (q->penalty_rate == 0 || q->penalty_burst == 0) | ||
239 | return true; | ||
240 | |||
241 | if (q->tokens_avail < 1) { | ||
242 | unsigned long age = min(10UL * HZ, jiffies - q->token_time); | ||
243 | |||
244 | q->tokens_avail = (age * q->penalty_rate) / HZ; | ||
245 | if (q->tokens_avail > q->penalty_burst) | ||
246 | q->tokens_avail = q->penalty_burst; | ||
247 | q->token_time = jiffies; | ||
248 | if (q->tokens_avail < 1) | ||
249 | return true; | ||
250 | } | ||
251 | |||
252 | q->tokens_avail--; | ||
253 | return false; | ||
254 | } | ||
255 | |||
256 | static bool sfb_classify(struct sk_buff *skb, struct sfb_sched_data *q, | ||
257 | int *qerr, u32 *salt) | ||
258 | { | ||
259 | struct tcf_result res; | ||
260 | int result; | ||
261 | |||
262 | result = tc_classify(skb, q->filter_list, &res); | ||
263 | if (result >= 0) { | ||
264 | #ifdef CONFIG_NET_CLS_ACT | ||
265 | switch (result) { | ||
266 | case TC_ACT_STOLEN: | ||
267 | case TC_ACT_QUEUED: | ||
268 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; | ||
269 | case TC_ACT_SHOT: | ||
270 | return false; | ||
271 | } | ||
272 | #endif | ||
273 | *salt = TC_H_MIN(res.classid); | ||
274 | return true; | ||
275 | } | ||
276 | return false; | ||
277 | } | ||
278 | |||
279 | static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | ||
280 | { | ||
281 | |||
282 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
283 | struct Qdisc *child = q->qdisc; | ||
284 | int i; | ||
285 | u32 p_min = ~0; | ||
286 | u32 minqlen = ~0; | ||
287 | u32 r, slot, salt, sfbhash; | ||
288 | int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | ||
289 | |||
290 | if (q->rehash_interval > 0) { | ||
291 | unsigned long limit = q->rehash_time + q->rehash_interval; | ||
292 | |||
293 | if (unlikely(time_after(jiffies, limit))) { | ||
294 | sfb_swap_slot(q); | ||
295 | q->rehash_time = jiffies; | ||
296 | } else if (unlikely(!q->double_buffering && q->warmup_time > 0 && | ||
297 | time_after(jiffies, limit - q->warmup_time))) { | ||
298 | q->double_buffering = true; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | if (q->filter_list) { | ||
303 | /* If using external classifiers, get result and record it. */ | ||
304 | if (!sfb_classify(skb, q, &ret, &salt)) | ||
305 | goto other_drop; | ||
306 | } else { | ||
307 | salt = skb_get_rxhash(skb); | ||
308 | } | ||
309 | |||
310 | slot = q->slot; | ||
311 | |||
312 | sfbhash = jhash_1word(salt, q->bins[slot].perturbation); | ||
313 | if (!sfbhash) | ||
314 | sfbhash = 1; | ||
315 | sfb_skb_cb(skb)->hashes[slot] = sfbhash; | ||
316 | |||
317 | for (i = 0; i < SFB_LEVELS; i++) { | ||
318 | u32 hash = sfbhash & SFB_BUCKET_MASK; | ||
319 | struct sfb_bucket *b = &q->bins[slot].bins[i][hash]; | ||
320 | |||
321 | sfbhash >>= SFB_BUCKET_SHIFT; | ||
322 | if (b->qlen == 0) | ||
323 | decrement_prob(b, q); | ||
324 | else if (b->qlen >= q->bin_size) | ||
325 | increment_prob(b, q); | ||
326 | if (minqlen > b->qlen) | ||
327 | minqlen = b->qlen; | ||
328 | if (p_min > b->p_mark) | ||
329 | p_min = b->p_mark; | ||
330 | } | ||
331 | |||
332 | slot ^= 1; | ||
333 | sfb_skb_cb(skb)->hashes[slot] = 0; | ||
334 | |||
335 | if (unlikely(minqlen >= q->max || sch->q.qlen >= q->limit)) { | ||
336 | sch->qstats.overlimits++; | ||
337 | if (minqlen >= q->max) | ||
338 | q->stats.bucketdrop++; | ||
339 | else | ||
340 | q->stats.queuedrop++; | ||
341 | goto drop; | ||
342 | } | ||
343 | |||
344 | if (unlikely(p_min >= SFB_MAX_PROB)) { | ||
345 | /* Inelastic flow */ | ||
346 | if (q->double_buffering) { | ||
347 | sfbhash = jhash_1word(salt, q->bins[slot].perturbation); | ||
348 | if (!sfbhash) | ||
349 | sfbhash = 1; | ||
350 | sfb_skb_cb(skb)->hashes[slot] = sfbhash; | ||
351 | |||
352 | for (i = 0; i < SFB_LEVELS; i++) { | ||
353 | u32 hash = sfbhash & SFB_BUCKET_MASK; | ||
354 | struct sfb_bucket *b = &q->bins[slot].bins[i][hash]; | ||
355 | |||
356 | sfbhash >>= SFB_BUCKET_SHIFT; | ||
357 | if (b->qlen == 0) | ||
358 | decrement_prob(b, q); | ||
359 | else if (b->qlen >= q->bin_size) | ||
360 | increment_prob(b, q); | ||
361 | } | ||
362 | } | ||
363 | if (sfb_rate_limit(skb, q)) { | ||
364 | sch->qstats.overlimits++; | ||
365 | q->stats.penaltydrop++; | ||
366 | goto drop; | ||
367 | } | ||
368 | goto enqueue; | ||
369 | } | ||
370 | |||
371 | r = net_random() & SFB_MAX_PROB; | ||
372 | |||
373 | if (unlikely(r < p_min)) { | ||
374 | if (unlikely(p_min > SFB_MAX_PROB / 2)) { | ||
375 | /* If we're marking that many packets, then either | ||
376 | * this flow is unresponsive, or we're badly congested. | ||
377 | * In either case, we want to start dropping packets. | ||
378 | */ | ||
379 | if (r < (p_min - SFB_MAX_PROB / 2) * 2) { | ||
380 | q->stats.earlydrop++; | ||
381 | goto drop; | ||
382 | } | ||
383 | } | ||
384 | if (INET_ECN_set_ce(skb)) { | ||
385 | q->stats.marked++; | ||
386 | } else { | ||
387 | q->stats.earlydrop++; | ||
388 | goto drop; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | enqueue: | ||
393 | ret = qdisc_enqueue(skb, child); | ||
394 | if (likely(ret == NET_XMIT_SUCCESS)) { | ||
395 | sch->q.qlen++; | ||
396 | increment_qlen(skb, q); | ||
397 | } else if (net_xmit_drop_count(ret)) { | ||
398 | q->stats.childdrop++; | ||
399 | sch->qstats.drops++; | ||
400 | } | ||
401 | return ret; | ||
402 | |||
403 | drop: | ||
404 | qdisc_drop(skb, sch); | ||
405 | return NET_XMIT_CN; | ||
406 | other_drop: | ||
407 | if (ret & __NET_XMIT_BYPASS) | ||
408 | sch->qstats.drops++; | ||
409 | kfree_skb(skb); | ||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | static struct sk_buff *sfb_dequeue(struct Qdisc *sch) | ||
414 | { | ||
415 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
416 | struct Qdisc *child = q->qdisc; | ||
417 | struct sk_buff *skb; | ||
418 | |||
419 | skb = child->dequeue(q->qdisc); | ||
420 | |||
421 | if (skb) { | ||
422 | qdisc_bstats_update(sch, skb); | ||
423 | sch->q.qlen--; | ||
424 | decrement_qlen(skb, q); | ||
425 | } | ||
426 | |||
427 | return skb; | ||
428 | } | ||
429 | |||
430 | static struct sk_buff *sfb_peek(struct Qdisc *sch) | ||
431 | { | ||
432 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
433 | struct Qdisc *child = q->qdisc; | ||
434 | |||
435 | return child->ops->peek(child); | ||
436 | } | ||
437 | |||
438 | /* No sfb_drop -- impossible since the child doesn't return the dropped skb. */ | ||
439 | |||
440 | static void sfb_reset(struct Qdisc *sch) | ||
441 | { | ||
442 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
443 | |||
444 | qdisc_reset(q->qdisc); | ||
445 | sch->q.qlen = 0; | ||
446 | q->slot = 0; | ||
447 | q->double_buffering = false; | ||
448 | sfb_zero_all_buckets(q); | ||
449 | sfb_init_perturbation(0, q); | ||
450 | } | ||
451 | |||
452 | static void sfb_destroy(struct Qdisc *sch) | ||
453 | { | ||
454 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
455 | |||
456 | tcf_destroy_chain(&q->filter_list); | ||
457 | qdisc_destroy(q->qdisc); | ||
458 | } | ||
459 | |||
460 | static const struct nla_policy sfb_policy[TCA_SFB_MAX + 1] = { | ||
461 | [TCA_SFB_PARMS] = { .len = sizeof(struct tc_sfb_qopt) }, | ||
462 | }; | ||
463 | |||
464 | static const struct tc_sfb_qopt sfb_default_ops = { | ||
465 | .rehash_interval = 600 * MSEC_PER_SEC, | ||
466 | .warmup_time = 60 * MSEC_PER_SEC, | ||
467 | .limit = 0, | ||
468 | .max = 25, | ||
469 | .bin_size = 20, | ||
470 | .increment = (SFB_MAX_PROB + 500) / 1000, /* 0.1 % */ | ||
471 | .decrement = (SFB_MAX_PROB + 3000) / 6000, | ||
472 | .penalty_rate = 10, | ||
473 | .penalty_burst = 20, | ||
474 | }; | ||
475 | |||
476 | static int sfb_change(struct Qdisc *sch, struct nlattr *opt) | ||
477 | { | ||
478 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
479 | struct Qdisc *child; | ||
480 | struct nlattr *tb[TCA_SFB_MAX + 1]; | ||
481 | const struct tc_sfb_qopt *ctl = &sfb_default_ops; | ||
482 | u32 limit; | ||
483 | int err; | ||
484 | |||
485 | if (opt) { | ||
486 | err = nla_parse_nested(tb, TCA_SFB_MAX, opt, sfb_policy); | ||
487 | if (err < 0) | ||
488 | return -EINVAL; | ||
489 | |||
490 | if (tb[TCA_SFB_PARMS] == NULL) | ||
491 | return -EINVAL; | ||
492 | |||
493 | ctl = nla_data(tb[TCA_SFB_PARMS]); | ||
494 | } | ||
495 | |||
496 | limit = ctl->limit; | ||
497 | if (limit == 0) | ||
498 | limit = max_t(u32, qdisc_dev(sch)->tx_queue_len, 1); | ||
499 | |||
500 | child = fifo_create_dflt(sch, &pfifo_qdisc_ops, limit); | ||
501 | if (IS_ERR(child)) | ||
502 | return PTR_ERR(child); | ||
503 | |||
504 | sch_tree_lock(sch); | ||
505 | |||
506 | qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); | ||
507 | qdisc_destroy(q->qdisc); | ||
508 | q->qdisc = child; | ||
509 | |||
510 | q->rehash_interval = msecs_to_jiffies(ctl->rehash_interval); | ||
511 | q->warmup_time = msecs_to_jiffies(ctl->warmup_time); | ||
512 | q->rehash_time = jiffies; | ||
513 | q->limit = limit; | ||
514 | q->increment = ctl->increment; | ||
515 | q->decrement = ctl->decrement; | ||
516 | q->max = ctl->max; | ||
517 | q->bin_size = ctl->bin_size; | ||
518 | q->penalty_rate = ctl->penalty_rate; | ||
519 | q->penalty_burst = ctl->penalty_burst; | ||
520 | q->tokens_avail = ctl->penalty_burst; | ||
521 | q->token_time = jiffies; | ||
522 | |||
523 | q->slot = 0; | ||
524 | q->double_buffering = false; | ||
525 | sfb_zero_all_buckets(q); | ||
526 | sfb_init_perturbation(0, q); | ||
527 | sfb_init_perturbation(1, q); | ||
528 | |||
529 | sch_tree_unlock(sch); | ||
530 | |||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static int sfb_init(struct Qdisc *sch, struct nlattr *opt) | ||
535 | { | ||
536 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
537 | |||
538 | q->qdisc = &noop_qdisc; | ||
539 | return sfb_change(sch, opt); | ||
540 | } | ||
541 | |||
542 | static int sfb_dump(struct Qdisc *sch, struct sk_buff *skb) | ||
543 | { | ||
544 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
545 | struct nlattr *opts; | ||
546 | struct tc_sfb_qopt opt = { | ||
547 | .rehash_interval = jiffies_to_msecs(q->rehash_interval), | ||
548 | .warmup_time = jiffies_to_msecs(q->warmup_time), | ||
549 | .limit = q->limit, | ||
550 | .max = q->max, | ||
551 | .bin_size = q->bin_size, | ||
552 | .increment = q->increment, | ||
553 | .decrement = q->decrement, | ||
554 | .penalty_rate = q->penalty_rate, | ||
555 | .penalty_burst = q->penalty_burst, | ||
556 | }; | ||
557 | |||
558 | sch->qstats.backlog = q->qdisc->qstats.backlog; | ||
559 | opts = nla_nest_start(skb, TCA_OPTIONS); | ||
560 | NLA_PUT(skb, TCA_SFB_PARMS, sizeof(opt), &opt); | ||
561 | return nla_nest_end(skb, opts); | ||
562 | |||
563 | nla_put_failure: | ||
564 | nla_nest_cancel(skb, opts); | ||
565 | return -EMSGSIZE; | ||
566 | } | ||
567 | |||
568 | static int sfb_dump_stats(struct Qdisc *sch, struct gnet_dump *d) | ||
569 | { | ||
570 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
571 | struct tc_sfb_xstats st = { | ||
572 | .earlydrop = q->stats.earlydrop, | ||
573 | .penaltydrop = q->stats.penaltydrop, | ||
574 | .bucketdrop = q->stats.bucketdrop, | ||
575 | .queuedrop = q->stats.queuedrop, | ||
576 | .childdrop = q->stats.childdrop, | ||
577 | .marked = q->stats.marked, | ||
578 | }; | ||
579 | |||
580 | st.maxqlen = sfb_compute_qlen(&st.maxprob, &st.avgprob, q); | ||
581 | |||
582 | return gnet_stats_copy_app(d, &st, sizeof(st)); | ||
583 | } | ||
584 | |||
585 | static int sfb_dump_class(struct Qdisc *sch, unsigned long cl, | ||
586 | struct sk_buff *skb, struct tcmsg *tcm) | ||
587 | { | ||
588 | return -ENOSYS; | ||
589 | } | ||
590 | |||
591 | static int sfb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | ||
592 | struct Qdisc **old) | ||
593 | { | ||
594 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
595 | |||
596 | if (new == NULL) | ||
597 | new = &noop_qdisc; | ||
598 | |||
599 | sch_tree_lock(sch); | ||
600 | *old = q->qdisc; | ||
601 | q->qdisc = new; | ||
602 | qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); | ||
603 | qdisc_reset(*old); | ||
604 | sch_tree_unlock(sch); | ||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | static struct Qdisc *sfb_leaf(struct Qdisc *sch, unsigned long arg) | ||
609 | { | ||
610 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
611 | |||
612 | return q->qdisc; | ||
613 | } | ||
614 | |||
615 | static unsigned long sfb_get(struct Qdisc *sch, u32 classid) | ||
616 | { | ||
617 | return 1; | ||
618 | } | ||
619 | |||
620 | static void sfb_put(struct Qdisc *sch, unsigned long arg) | ||
621 | { | ||
622 | } | ||
623 | |||
624 | static int sfb_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | ||
625 | struct nlattr **tca, unsigned long *arg) | ||
626 | { | ||
627 | return -ENOSYS; | ||
628 | } | ||
629 | |||
630 | static int sfb_delete(struct Qdisc *sch, unsigned long cl) | ||
631 | { | ||
632 | return -ENOSYS; | ||
633 | } | ||
634 | |||
635 | static void sfb_walk(struct Qdisc *sch, struct qdisc_walker *walker) | ||
636 | { | ||
637 | if (!walker->stop) { | ||
638 | if (walker->count >= walker->skip) | ||
639 | if (walker->fn(sch, 1, walker) < 0) { | ||
640 | walker->stop = 1; | ||
641 | return; | ||
642 | } | ||
643 | walker->count++; | ||
644 | } | ||
645 | } | ||
646 | |||
647 | static struct tcf_proto **sfb_find_tcf(struct Qdisc *sch, unsigned long cl) | ||
648 | { | ||
649 | struct sfb_sched_data *q = qdisc_priv(sch); | ||
650 | |||
651 | if (cl) | ||
652 | return NULL; | ||
653 | return &q->filter_list; | ||
654 | } | ||
655 | |||
656 | static unsigned long sfb_bind(struct Qdisc *sch, unsigned long parent, | ||
657 | u32 classid) | ||
658 | { | ||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | |||
663 | static const struct Qdisc_class_ops sfb_class_ops = { | ||
664 | .graft = sfb_graft, | ||
665 | .leaf = sfb_leaf, | ||
666 | .get = sfb_get, | ||
667 | .put = sfb_put, | ||
668 | .change = sfb_change_class, | ||
669 | .delete = sfb_delete, | ||
670 | .walk = sfb_walk, | ||
671 | .tcf_chain = sfb_find_tcf, | ||
672 | .bind_tcf = sfb_bind, | ||
673 | .unbind_tcf = sfb_put, | ||
674 | .dump = sfb_dump_class, | ||
675 | }; | ||
676 | |||
677 | static struct Qdisc_ops sfb_qdisc_ops __read_mostly = { | ||
678 | .id = "sfb", | ||
679 | .priv_size = sizeof(struct sfb_sched_data), | ||
680 | .cl_ops = &sfb_class_ops, | ||
681 | .enqueue = sfb_enqueue, | ||
682 | .dequeue = sfb_dequeue, | ||
683 | .peek = sfb_peek, | ||
684 | .init = sfb_init, | ||
685 | .reset = sfb_reset, | ||
686 | .destroy = sfb_destroy, | ||
687 | .change = sfb_change, | ||
688 | .dump = sfb_dump, | ||
689 | .dump_stats = sfb_dump_stats, | ||
690 | .owner = THIS_MODULE, | ||
691 | }; | ||
692 | |||
693 | static int __init sfb_module_init(void) | ||
694 | { | ||
695 | return register_qdisc(&sfb_qdisc_ops); | ||
696 | } | ||
697 | |||
698 | static void __exit sfb_module_exit(void) | ||
699 | { | ||
700 | unregister_qdisc(&sfb_qdisc_ops); | ||
701 | } | ||
702 | |||
703 | module_init(sfb_module_init) | ||
704 | module_exit(sfb_module_exit) | ||
705 | |||
706 | MODULE_DESCRIPTION("Stochastic Fair Blue queue discipline"); | ||
707 | MODULE_AUTHOR("Juliusz Chroboczek"); | ||
708 | MODULE_AUTHOR("Eric Dumazet"); | ||
709 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index edea8cefec6c..c2e628dfaacc 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
22 | #include <linux/jhash.h> | 22 | #include <linux/jhash.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/vmalloc.h> | ||
24 | #include <net/ip.h> | 25 | #include <net/ip.h> |
25 | #include <net/netlink.h> | 26 | #include <net/netlink.h> |
26 | #include <net/pkt_sched.h> | 27 | #include <net/pkt_sched.h> |
@@ -76,7 +77,8 @@ | |||
76 | #define SFQ_DEPTH 128 /* max number of packets per flow */ | 77 | #define SFQ_DEPTH 128 /* max number of packets per flow */ |
77 | #define SFQ_SLOTS 128 /* max number of flows */ | 78 | #define SFQ_SLOTS 128 /* max number of flows */ |
78 | #define SFQ_EMPTY_SLOT 255 | 79 | #define SFQ_EMPTY_SLOT 255 |
79 | #define SFQ_HASH_DIVISOR 1024 | 80 | #define SFQ_DEFAULT_HASH_DIVISOR 1024 |
81 | |||
80 | /* We use 16 bits to store allot, and want to handle packets up to 64K | 82 | /* We use 16 bits to store allot, and want to handle packets up to 64K |
81 | * Scale allot by 8 (1<<3) so that no overflow occurs. | 83 | * Scale allot by 8 (1<<3) so that no overflow occurs. |
82 | */ | 84 | */ |
@@ -92,8 +94,7 @@ typedef unsigned char sfq_index; | |||
92 | * while following values [SFQ_SLOTS ... SFQ_SLOTS + SFQ_DEPTH - 1] | 94 | * while following values [SFQ_SLOTS ... SFQ_SLOTS + SFQ_DEPTH - 1] |
93 | * are 'pointers' to dep[] array | 95 | * are 'pointers' to dep[] array |
94 | */ | 96 | */ |
95 | struct sfq_head | 97 | struct sfq_head { |
96 | { | ||
97 | sfq_index next; | 98 | sfq_index next; |
98 | sfq_index prev; | 99 | sfq_index prev; |
99 | }; | 100 | }; |
@@ -108,13 +109,12 @@ struct sfq_slot { | |||
108 | short allot; /* credit for this slot */ | 109 | short allot; /* credit for this slot */ |
109 | }; | 110 | }; |
110 | 111 | ||
111 | struct sfq_sched_data | 112 | struct sfq_sched_data { |
112 | { | ||
113 | /* Parameters */ | 113 | /* Parameters */ |
114 | int perturb_period; | 114 | int perturb_period; |
115 | unsigned quantum; /* Allotment per round: MUST BE >= MTU */ | 115 | unsigned int quantum; /* Allotment per round: MUST BE >= MTU */ |
116 | int limit; | 116 | int limit; |
117 | 117 | unsigned int divisor; /* number of slots in hash table */ | |
118 | /* Variables */ | 118 | /* Variables */ |
119 | struct tcf_proto *filter_list; | 119 | struct tcf_proto *filter_list; |
120 | struct timer_list perturb_timer; | 120 | struct timer_list perturb_timer; |
@@ -122,7 +122,7 @@ struct sfq_sched_data | |||
122 | sfq_index cur_depth; /* depth of longest slot */ | 122 | sfq_index cur_depth; /* depth of longest slot */ |
123 | unsigned short scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */ | 123 | unsigned short scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */ |
124 | struct sfq_slot *tail; /* current slot in round */ | 124 | struct sfq_slot *tail; /* current slot in round */ |
125 | sfq_index ht[SFQ_HASH_DIVISOR]; /* Hash table */ | 125 | sfq_index *ht; /* Hash table (divisor slots) */ |
126 | struct sfq_slot slots[SFQ_SLOTS]; | 126 | struct sfq_slot slots[SFQ_SLOTS]; |
127 | struct sfq_head dep[SFQ_DEPTH]; /* Linked list of slots, indexed by depth */ | 127 | struct sfq_head dep[SFQ_DEPTH]; /* Linked list of slots, indexed by depth */ |
128 | }; | 128 | }; |
@@ -137,12 +137,12 @@ static inline struct sfq_head *sfq_dep_head(struct sfq_sched_data *q, sfq_index | |||
137 | return &q->dep[val - SFQ_SLOTS]; | 137 | return &q->dep[val - SFQ_SLOTS]; |
138 | } | 138 | } |
139 | 139 | ||
140 | static __inline__ unsigned sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1) | 140 | static unsigned int sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1) |
141 | { | 141 | { |
142 | return jhash_2words(h, h1, q->perturbation) & (SFQ_HASH_DIVISOR - 1); | 142 | return jhash_2words(h, h1, q->perturbation) & (q->divisor - 1); |
143 | } | 143 | } |
144 | 144 | ||
145 | static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | 145 | static unsigned int sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) |
146 | { | 146 | { |
147 | u32 h, h2; | 147 | u32 h, h2; |
148 | 148 | ||
@@ -157,13 +157,13 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
157 | iph = ip_hdr(skb); | 157 | iph = ip_hdr(skb); |
158 | h = (__force u32)iph->daddr; | 158 | h = (__force u32)iph->daddr; |
159 | h2 = (__force u32)iph->saddr ^ iph->protocol; | 159 | h2 = (__force u32)iph->saddr ^ iph->protocol; |
160 | if (iph->frag_off & htons(IP_MF|IP_OFFSET)) | 160 | if (iph->frag_off & htons(IP_MF | IP_OFFSET)) |
161 | break; | 161 | break; |
162 | poff = proto_ports_offset(iph->protocol); | 162 | poff = proto_ports_offset(iph->protocol); |
163 | if (poff >= 0 && | 163 | if (poff >= 0 && |
164 | pskb_network_may_pull(skb, iph->ihl * 4 + 4 + poff)) { | 164 | pskb_network_may_pull(skb, iph->ihl * 4 + 4 + poff)) { |
165 | iph = ip_hdr(skb); | 165 | iph = ip_hdr(skb); |
166 | h2 ^= *(u32*)((void *)iph + iph->ihl * 4 + poff); | 166 | h2 ^= *(u32 *)((void *)iph + iph->ihl * 4 + poff); |
167 | } | 167 | } |
168 | break; | 168 | break; |
169 | } | 169 | } |
@@ -181,7 +181,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
181 | if (poff >= 0 && | 181 | if (poff >= 0 && |
182 | pskb_network_may_pull(skb, sizeof(*iph) + 4 + poff)) { | 182 | pskb_network_may_pull(skb, sizeof(*iph) + 4 + poff)) { |
183 | iph = ipv6_hdr(skb); | 183 | iph = ipv6_hdr(skb); |
184 | h2 ^= *(u32*)((void *)iph + sizeof(*iph) + poff); | 184 | h2 ^= *(u32 *)((void *)iph + sizeof(*iph) + poff); |
185 | } | 185 | } |
186 | break; | 186 | break; |
187 | } | 187 | } |
@@ -203,7 +203,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch, | |||
203 | 203 | ||
204 | if (TC_H_MAJ(skb->priority) == sch->handle && | 204 | if (TC_H_MAJ(skb->priority) == sch->handle && |
205 | TC_H_MIN(skb->priority) > 0 && | 205 | TC_H_MIN(skb->priority) > 0 && |
206 | TC_H_MIN(skb->priority) <= SFQ_HASH_DIVISOR) | 206 | TC_H_MIN(skb->priority) <= q->divisor) |
207 | return TC_H_MIN(skb->priority); | 207 | return TC_H_MIN(skb->priority); |
208 | 208 | ||
209 | if (!q->filter_list) | 209 | if (!q->filter_list) |
@@ -221,7 +221,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch, | |||
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
223 | #endif | 223 | #endif |
224 | if (TC_H_MIN(res.classid) <= SFQ_HASH_DIVISOR) | 224 | if (TC_H_MIN(res.classid) <= q->divisor) |
225 | return TC_H_MIN(res.classid); | 225 | return TC_H_MIN(res.classid); |
226 | } | 226 | } |
227 | return 0; | 227 | return 0; |
@@ -491,13 +491,18 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) | |||
491 | if (opt->nla_len < nla_attr_size(sizeof(*ctl))) | 491 | if (opt->nla_len < nla_attr_size(sizeof(*ctl))) |
492 | return -EINVAL; | 492 | return -EINVAL; |
493 | 493 | ||
494 | if (ctl->divisor && | ||
495 | (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536)) | ||
496 | return -EINVAL; | ||
497 | |||
494 | sch_tree_lock(sch); | 498 | sch_tree_lock(sch); |
495 | q->quantum = ctl->quantum ? : psched_mtu(qdisc_dev(sch)); | 499 | q->quantum = ctl->quantum ? : psched_mtu(qdisc_dev(sch)); |
496 | q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum); | 500 | q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum); |
497 | q->perturb_period = ctl->perturb_period * HZ; | 501 | q->perturb_period = ctl->perturb_period * HZ; |
498 | if (ctl->limit) | 502 | if (ctl->limit) |
499 | q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1); | 503 | q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1); |
500 | 504 | if (ctl->divisor) | |
505 | q->divisor = ctl->divisor; | ||
501 | qlen = sch->q.qlen; | 506 | qlen = sch->q.qlen; |
502 | while (sch->q.qlen > q->limit) | 507 | while (sch->q.qlen > q->limit) |
503 | sfq_drop(sch); | 508 | sfq_drop(sch); |
@@ -515,15 +520,13 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) | |||
515 | static int sfq_init(struct Qdisc *sch, struct nlattr *opt) | 520 | static int sfq_init(struct Qdisc *sch, struct nlattr *opt) |
516 | { | 521 | { |
517 | struct sfq_sched_data *q = qdisc_priv(sch); | 522 | struct sfq_sched_data *q = qdisc_priv(sch); |
523 | size_t sz; | ||
518 | int i; | 524 | int i; |
519 | 525 | ||
520 | q->perturb_timer.function = sfq_perturbation; | 526 | q->perturb_timer.function = sfq_perturbation; |
521 | q->perturb_timer.data = (unsigned long)sch; | 527 | q->perturb_timer.data = (unsigned long)sch; |
522 | init_timer_deferrable(&q->perturb_timer); | 528 | init_timer_deferrable(&q->perturb_timer); |
523 | 529 | ||
524 | for (i = 0; i < SFQ_HASH_DIVISOR; i++) | ||
525 | q->ht[i] = SFQ_EMPTY_SLOT; | ||
526 | |||
527 | for (i = 0; i < SFQ_DEPTH; i++) { | 530 | for (i = 0; i < SFQ_DEPTH; i++) { |
528 | q->dep[i].next = i + SFQ_SLOTS; | 531 | q->dep[i].next = i + SFQ_SLOTS; |
529 | q->dep[i].prev = i + SFQ_SLOTS; | 532 | q->dep[i].prev = i + SFQ_SLOTS; |
@@ -532,6 +535,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt) | |||
532 | q->limit = SFQ_DEPTH - 1; | 535 | q->limit = SFQ_DEPTH - 1; |
533 | q->cur_depth = 0; | 536 | q->cur_depth = 0; |
534 | q->tail = NULL; | 537 | q->tail = NULL; |
538 | q->divisor = SFQ_DEFAULT_HASH_DIVISOR; | ||
535 | if (opt == NULL) { | 539 | if (opt == NULL) { |
536 | q->quantum = psched_mtu(qdisc_dev(sch)); | 540 | q->quantum = psched_mtu(qdisc_dev(sch)); |
537 | q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum); | 541 | q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum); |
@@ -543,10 +547,23 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt) | |||
543 | return err; | 547 | return err; |
544 | } | 548 | } |
545 | 549 | ||
550 | sz = sizeof(q->ht[0]) * q->divisor; | ||
551 | q->ht = kmalloc(sz, GFP_KERNEL); | ||
552 | if (!q->ht && sz > PAGE_SIZE) | ||
553 | q->ht = vmalloc(sz); | ||
554 | if (!q->ht) | ||
555 | return -ENOMEM; | ||
556 | for (i = 0; i < q->divisor; i++) | ||
557 | q->ht[i] = SFQ_EMPTY_SLOT; | ||
558 | |||
546 | for (i = 0; i < SFQ_SLOTS; i++) { | 559 | for (i = 0; i < SFQ_SLOTS; i++) { |
547 | slot_queue_init(&q->slots[i]); | 560 | slot_queue_init(&q->slots[i]); |
548 | sfq_link(q, i); | 561 | sfq_link(q, i); |
549 | } | 562 | } |
563 | if (q->limit >= 1) | ||
564 | sch->flags |= TCQ_F_CAN_BYPASS; | ||
565 | else | ||
566 | sch->flags &= ~TCQ_F_CAN_BYPASS; | ||
550 | return 0; | 567 | return 0; |
551 | } | 568 | } |
552 | 569 | ||
@@ -557,6 +574,10 @@ static void sfq_destroy(struct Qdisc *sch) | |||
557 | tcf_destroy_chain(&q->filter_list); | 574 | tcf_destroy_chain(&q->filter_list); |
558 | q->perturb_period = 0; | 575 | q->perturb_period = 0; |
559 | del_timer_sync(&q->perturb_timer); | 576 | del_timer_sync(&q->perturb_timer); |
577 | if (is_vmalloc_addr(q->ht)) | ||
578 | vfree(q->ht); | ||
579 | else | ||
580 | kfree(q->ht); | ||
560 | } | 581 | } |
561 | 582 | ||
562 | static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) | 583 | static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) |
@@ -569,7 +590,7 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
569 | opt.perturb_period = q->perturb_period / HZ; | 590 | opt.perturb_period = q->perturb_period / HZ; |
570 | 591 | ||
571 | opt.limit = q->limit; | 592 | opt.limit = q->limit; |
572 | opt.divisor = SFQ_HASH_DIVISOR; | 593 | opt.divisor = q->divisor; |
573 | opt.flows = q->limit; | 594 | opt.flows = q->limit; |
574 | 595 | ||
575 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | 596 | NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); |
@@ -594,6 +615,8 @@ static unsigned long sfq_get(struct Qdisc *sch, u32 classid) | |||
594 | static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent, | 615 | static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent, |
595 | u32 classid) | 616 | u32 classid) |
596 | { | 617 | { |
618 | /* we cannot bypass queue discipline anymore */ | ||
619 | sch->flags &= ~TCQ_F_CAN_BYPASS; | ||
597 | return 0; | 620 | return 0; |
598 | } | 621 | } |
599 | 622 | ||
@@ -647,7 +670,7 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
647 | if (arg->stop) | 670 | if (arg->stop) |
648 | return; | 671 | return; |
649 | 672 | ||
650 | for (i = 0; i < SFQ_HASH_DIVISOR; i++) { | 673 | for (i = 0; i < q->divisor; i++) { |
651 | if (q->ht[i] == SFQ_EMPTY_SLOT || | 674 | if (q->ht[i] == SFQ_EMPTY_SLOT || |
652 | arg->count < arg->skip) { | 675 | arg->count < arg->skip) { |
653 | arg->count++; | 676 | arg->count++; |
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index e93165820c3f..1dcfb5223a86 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -97,8 +97,7 @@ | |||
97 | changed the limit is not effective anymore. | 97 | changed the limit is not effective anymore. |
98 | */ | 98 | */ |
99 | 99 | ||
100 | struct tbf_sched_data | 100 | struct tbf_sched_data { |
101 | { | ||
102 | /* Parameters */ | 101 | /* Parameters */ |
103 | u32 limit; /* Maximal length of backlog: bytes */ | 102 | u32 limit; /* Maximal length of backlog: bytes */ |
104 | u32 buffer; /* Token bucket depth/rate: MUST BE >= MTU/B */ | 103 | u32 buffer; /* Token bucket depth/rate: MUST BE >= MTU/B */ |
@@ -115,10 +114,10 @@ struct tbf_sched_data | |||
115 | struct qdisc_watchdog watchdog; /* Watchdog timer */ | 114 | struct qdisc_watchdog watchdog; /* Watchdog timer */ |
116 | }; | 115 | }; |
117 | 116 | ||
118 | #define L2T(q,L) qdisc_l2t((q)->R_tab,L) | 117 | #define L2T(q, L) qdisc_l2t((q)->R_tab, L) |
119 | #define L2T_P(q,L) qdisc_l2t((q)->P_tab,L) | 118 | #define L2T_P(q, L) qdisc_l2t((q)->P_tab, L) |
120 | 119 | ||
121 | static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) | 120 | static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
122 | { | 121 | { |
123 | struct tbf_sched_data *q = qdisc_priv(sch); | 122 | struct tbf_sched_data *q = qdisc_priv(sch); |
124 | int ret; | 123 | int ret; |
@@ -137,7 +136,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
137 | return NET_XMIT_SUCCESS; | 136 | return NET_XMIT_SUCCESS; |
138 | } | 137 | } |
139 | 138 | ||
140 | static unsigned int tbf_drop(struct Qdisc* sch) | 139 | static unsigned int tbf_drop(struct Qdisc *sch) |
141 | { | 140 | { |
142 | struct tbf_sched_data *q = qdisc_priv(sch); | 141 | struct tbf_sched_data *q = qdisc_priv(sch); |
143 | unsigned int len = 0; | 142 | unsigned int len = 0; |
@@ -149,7 +148,7 @@ static unsigned int tbf_drop(struct Qdisc* sch) | |||
149 | return len; | 148 | return len; |
150 | } | 149 | } |
151 | 150 | ||
152 | static struct sk_buff *tbf_dequeue(struct Qdisc* sch) | 151 | static struct sk_buff *tbf_dequeue(struct Qdisc *sch) |
153 | { | 152 | { |
154 | struct tbf_sched_data *q = qdisc_priv(sch); | 153 | struct tbf_sched_data *q = qdisc_priv(sch); |
155 | struct sk_buff *skb; | 154 | struct sk_buff *skb; |
@@ -185,7 +184,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) | |||
185 | q->tokens = toks; | 184 | q->tokens = toks; |
186 | q->ptokens = ptoks; | 185 | q->ptokens = ptoks; |
187 | sch->q.qlen--; | 186 | sch->q.qlen--; |
188 | sch->flags &= ~TCQ_F_THROTTLED; | 187 | qdisc_unthrottled(sch); |
189 | qdisc_bstats_update(sch, skb); | 188 | qdisc_bstats_update(sch, skb); |
190 | return skb; | 189 | return skb; |
191 | } | 190 | } |
@@ -209,7 +208,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) | |||
209 | return NULL; | 208 | return NULL; |
210 | } | 209 | } |
211 | 210 | ||
212 | static void tbf_reset(struct Qdisc* sch) | 211 | static void tbf_reset(struct Qdisc *sch) |
213 | { | 212 | { |
214 | struct tbf_sched_data *q = qdisc_priv(sch); | 213 | struct tbf_sched_data *q = qdisc_priv(sch); |
215 | 214 | ||
@@ -227,7 +226,7 @@ static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = { | |||
227 | [TCA_TBF_PTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, | 226 | [TCA_TBF_PTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, |
228 | }; | 227 | }; |
229 | 228 | ||
230 | static int tbf_change(struct Qdisc* sch, struct nlattr *opt) | 229 | static int tbf_change(struct Qdisc *sch, struct nlattr *opt) |
231 | { | 230 | { |
232 | int err; | 231 | int err; |
233 | struct tbf_sched_data *q = qdisc_priv(sch); | 232 | struct tbf_sched_data *q = qdisc_priv(sch); |
@@ -236,7 +235,7 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt) | |||
236 | struct qdisc_rate_table *rtab = NULL; | 235 | struct qdisc_rate_table *rtab = NULL; |
237 | struct qdisc_rate_table *ptab = NULL; | 236 | struct qdisc_rate_table *ptab = NULL; |
238 | struct Qdisc *child = NULL; | 237 | struct Qdisc *child = NULL; |
239 | int max_size,n; | 238 | int max_size, n; |
240 | 239 | ||
241 | err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy); | 240 | err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy); |
242 | if (err < 0) | 241 | if (err < 0) |
@@ -259,15 +258,18 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt) | |||
259 | } | 258 | } |
260 | 259 | ||
261 | for (n = 0; n < 256; n++) | 260 | for (n = 0; n < 256; n++) |
262 | if (rtab->data[n] > qopt->buffer) break; | 261 | if (rtab->data[n] > qopt->buffer) |
263 | max_size = (n << qopt->rate.cell_log)-1; | 262 | break; |
263 | max_size = (n << qopt->rate.cell_log) - 1; | ||
264 | if (ptab) { | 264 | if (ptab) { |
265 | int size; | 265 | int size; |
266 | 266 | ||
267 | for (n = 0; n < 256; n++) | 267 | for (n = 0; n < 256; n++) |
268 | if (ptab->data[n] > qopt->mtu) break; | 268 | if (ptab->data[n] > qopt->mtu) |
269 | size = (n << qopt->peakrate.cell_log)-1; | 269 | break; |
270 | if (size < max_size) max_size = size; | 270 | size = (n << qopt->peakrate.cell_log) - 1; |
271 | if (size < max_size) | ||
272 | max_size = size; | ||
271 | } | 273 | } |
272 | if (max_size < 0) | 274 | if (max_size < 0) |
273 | goto done; | 275 | goto done; |
@@ -310,7 +312,7 @@ done: | |||
310 | return err; | 312 | return err; |
311 | } | 313 | } |
312 | 314 | ||
313 | static int tbf_init(struct Qdisc* sch, struct nlattr *opt) | 315 | static int tbf_init(struct Qdisc *sch, struct nlattr *opt) |
314 | { | 316 | { |
315 | struct tbf_sched_data *q = qdisc_priv(sch); | 317 | struct tbf_sched_data *q = qdisc_priv(sch); |
316 | 318 | ||
@@ -422,8 +424,7 @@ static void tbf_walk(struct Qdisc *sch, struct qdisc_walker *walker) | |||
422 | } | 424 | } |
423 | } | 425 | } |
424 | 426 | ||
425 | static const struct Qdisc_class_ops tbf_class_ops = | 427 | static const struct Qdisc_class_ops tbf_class_ops = { |
426 | { | ||
427 | .graft = tbf_graft, | 428 | .graft = tbf_graft, |
428 | .leaf = tbf_leaf, | 429 | .leaf = tbf_leaf, |
429 | .get = tbf_get, | 430 | .get = tbf_get, |
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index d84e7329660f..45cd30098e34 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c | |||
@@ -53,8 +53,7 @@ | |||
53 | which will not break load balancing, though native slave | 53 | which will not break load balancing, though native slave |
54 | traffic will have the highest priority. */ | 54 | traffic will have the highest priority. */ |
55 | 55 | ||
56 | struct teql_master | 56 | struct teql_master { |
57 | { | ||
58 | struct Qdisc_ops qops; | 57 | struct Qdisc_ops qops; |
59 | struct net_device *dev; | 58 | struct net_device *dev; |
60 | struct Qdisc *slaves; | 59 | struct Qdisc *slaves; |
@@ -65,22 +64,21 @@ struct teql_master | |||
65 | unsigned long tx_dropped; | 64 | unsigned long tx_dropped; |
66 | }; | 65 | }; |
67 | 66 | ||
68 | struct teql_sched_data | 67 | struct teql_sched_data { |
69 | { | ||
70 | struct Qdisc *next; | 68 | struct Qdisc *next; |
71 | struct teql_master *m; | 69 | struct teql_master *m; |
72 | struct neighbour *ncache; | 70 | struct neighbour *ncache; |
73 | struct sk_buff_head q; | 71 | struct sk_buff_head q; |
74 | }; | 72 | }; |
75 | 73 | ||
76 | #define NEXT_SLAVE(q) (((struct teql_sched_data*)qdisc_priv(q))->next) | 74 | #define NEXT_SLAVE(q) (((struct teql_sched_data *)qdisc_priv(q))->next) |
77 | 75 | ||
78 | #define FMASK (IFF_BROADCAST|IFF_POINTOPOINT) | 76 | #define FMASK (IFF_BROADCAST | IFF_POINTOPOINT) |
79 | 77 | ||
80 | /* "teql*" qdisc routines */ | 78 | /* "teql*" qdisc routines */ |
81 | 79 | ||
82 | static int | 80 | static int |
83 | teql_enqueue(struct sk_buff *skb, struct Qdisc* sch) | 81 | teql_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
84 | { | 82 | { |
85 | struct net_device *dev = qdisc_dev(sch); | 83 | struct net_device *dev = qdisc_dev(sch); |
86 | struct teql_sched_data *q = qdisc_priv(sch); | 84 | struct teql_sched_data *q = qdisc_priv(sch); |
@@ -96,7 +94,7 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
96 | } | 94 | } |
97 | 95 | ||
98 | static struct sk_buff * | 96 | static struct sk_buff * |
99 | teql_dequeue(struct Qdisc* sch) | 97 | teql_dequeue(struct Qdisc *sch) |
100 | { | 98 | { |
101 | struct teql_sched_data *dat = qdisc_priv(sch); | 99 | struct teql_sched_data *dat = qdisc_priv(sch); |
102 | struct netdev_queue *dat_queue; | 100 | struct netdev_queue *dat_queue; |
@@ -118,13 +116,13 @@ teql_dequeue(struct Qdisc* sch) | |||
118 | } | 116 | } |
119 | 117 | ||
120 | static struct sk_buff * | 118 | static struct sk_buff * |
121 | teql_peek(struct Qdisc* sch) | 119 | teql_peek(struct Qdisc *sch) |
122 | { | 120 | { |
123 | /* teql is meant to be used as root qdisc */ | 121 | /* teql is meant to be used as root qdisc */ |
124 | return NULL; | 122 | return NULL; |
125 | } | 123 | } |
126 | 124 | ||
127 | static __inline__ void | 125 | static inline void |
128 | teql_neigh_release(struct neighbour *n) | 126 | teql_neigh_release(struct neighbour *n) |
129 | { | 127 | { |
130 | if (n) | 128 | if (n) |
@@ -132,7 +130,7 @@ teql_neigh_release(struct neighbour *n) | |||
132 | } | 130 | } |
133 | 131 | ||
134 | static void | 132 | static void |
135 | teql_reset(struct Qdisc* sch) | 133 | teql_reset(struct Qdisc *sch) |
136 | { | 134 | { |
137 | struct teql_sched_data *dat = qdisc_priv(sch); | 135 | struct teql_sched_data *dat = qdisc_priv(sch); |
138 | 136 | ||
@@ -142,13 +140,14 @@ teql_reset(struct Qdisc* sch) | |||
142 | } | 140 | } |
143 | 141 | ||
144 | static void | 142 | static void |
145 | teql_destroy(struct Qdisc* sch) | 143 | teql_destroy(struct Qdisc *sch) |
146 | { | 144 | { |
147 | struct Qdisc *q, *prev; | 145 | struct Qdisc *q, *prev; |
148 | struct teql_sched_data *dat = qdisc_priv(sch); | 146 | struct teql_sched_data *dat = qdisc_priv(sch); |
149 | struct teql_master *master = dat->m; | 147 | struct teql_master *master = dat->m; |
150 | 148 | ||
151 | if ((prev = master->slaves) != NULL) { | 149 | prev = master->slaves; |
150 | if (prev) { | ||
152 | do { | 151 | do { |
153 | q = NEXT_SLAVE(prev); | 152 | q = NEXT_SLAVE(prev); |
154 | if (q == sch) { | 153 | if (q == sch) { |
@@ -180,7 +179,7 @@ teql_destroy(struct Qdisc* sch) | |||
180 | static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt) | 179 | static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt) |
181 | { | 180 | { |
182 | struct net_device *dev = qdisc_dev(sch); | 181 | struct net_device *dev = qdisc_dev(sch); |
183 | struct teql_master *m = (struct teql_master*)sch->ops; | 182 | struct teql_master *m = (struct teql_master *)sch->ops; |
184 | struct teql_sched_data *q = qdisc_priv(sch); | 183 | struct teql_sched_data *q = qdisc_priv(sch); |
185 | 184 | ||
186 | if (dev->hard_header_len > m->dev->hard_header_len) | 185 | if (dev->hard_header_len > m->dev->hard_header_len) |
@@ -291,7 +290,8 @@ restart: | |||
291 | nores = 0; | 290 | nores = 0; |
292 | busy = 0; | 291 | busy = 0; |
293 | 292 | ||
294 | if ((q = start) == NULL) | 293 | q = start; |
294 | if (!q) | ||
295 | goto drop; | 295 | goto drop; |
296 | 296 | ||
297 | do { | 297 | do { |
@@ -356,10 +356,10 @@ drop: | |||
356 | 356 | ||
357 | static int teql_master_open(struct net_device *dev) | 357 | static int teql_master_open(struct net_device *dev) |
358 | { | 358 | { |
359 | struct Qdisc * q; | 359 | struct Qdisc *q; |
360 | struct teql_master *m = netdev_priv(dev); | 360 | struct teql_master *m = netdev_priv(dev); |
361 | int mtu = 0xFFFE; | 361 | int mtu = 0xFFFE; |
362 | unsigned flags = IFF_NOARP|IFF_MULTICAST; | 362 | unsigned int flags = IFF_NOARP | IFF_MULTICAST; |
363 | 363 | ||
364 | if (m->slaves == NULL) | 364 | if (m->slaves == NULL) |
365 | return -EUNATCH; | 365 | return -EUNATCH; |
@@ -427,7 +427,7 @@ static int teql_master_mtu(struct net_device *dev, int new_mtu) | |||
427 | do { | 427 | do { |
428 | if (new_mtu > qdisc_dev(q)->mtu) | 428 | if (new_mtu > qdisc_dev(q)->mtu) |
429 | return -EINVAL; | 429 | return -EINVAL; |
430 | } while ((q=NEXT_SLAVE(q)) != m->slaves); | 430 | } while ((q = NEXT_SLAVE(q)) != m->slaves); |
431 | } | 431 | } |
432 | 432 | ||
433 | dev->mtu = new_mtu; | 433 | dev->mtu = new_mtu; |