diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-07-13 09:57:38 -0400 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-07-13 09:57:38 -0400 |
commit | f7f24758ac98a506770bc5910d33567610fa3403 (patch) | |
tree | ff7fad3d01bf9dc2e2e54b908f9fca4891e1ee72 /net/sched | |
parent | b38a3ab3d1bb0dc3288f73903d4dc4672b5cd2d0 (diff) | |
parent | c32511e2718618f0b53479eb36e07439aa363a74 (diff) |
Merge with /home/shaggy/git/linus-clean/
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/Kconfig | 50 | ||||
-rw-r--r-- | net/sched/Makefile | 3 | ||||
-rw-r--r-- | net/sched/act_api.c | 10 | ||||
-rw-r--r-- | net/sched/cls_api.c | 2 | ||||
-rw-r--r-- | net/sched/cls_rsvp.h | 1 | ||||
-rw-r--r-- | net/sched/em_meta.c | 6 | ||||
-rw-r--r-- | net/sched/em_text.c | 157 | ||||
-rw-r--r-- | net/sched/sch_api.c | 65 | ||||
-rw-r--r-- | net/sched/sch_blackhole.c | 54 | ||||
-rw-r--r-- | net/sched/sch_cbq.c | 3 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 35 | ||||
-rw-r--r-- | net/sched/sch_red.c | 2 |
12 files changed, 331 insertions, 57 deletions
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index b22c9beb604d..59d3e71f8b85 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -1,6 +1,43 @@ | |||
1 | # | 1 | # |
2 | # Traffic control configuration. | 2 | # Traffic control configuration. |
3 | # | 3 | # |
4 | |||
5 | menuconfig NET_SCHED | ||
6 | bool "QoS and/or fair queueing" | ||
7 | ---help--- | ||
8 | When the kernel has several packets to send out over a network | ||
9 | device, it has to decide which ones to send first, which ones to | ||
10 | delay, and which ones to drop. This is the job of the packet | ||
11 | scheduler, and several different algorithms for how to do this | ||
12 | "fairly" have been proposed. | ||
13 | |||
14 | If you say N here, you will get the standard packet scheduler, which | ||
15 | is a FIFO (first come, first served). If you say Y here, you will be | ||
16 | able to choose from among several alternative algorithms which can | ||
17 | then be attached to different network devices. This is useful for | ||
18 | example if some of your network devices are real time devices that | ||
19 | need a certain minimum data flow rate, or if you need to limit the | ||
20 | maximum data flow rate for traffic which matches specified criteria. | ||
21 | This code is considered to be experimental. | ||
22 | |||
23 | To administer these schedulers, you'll need the user-level utilities | ||
24 | from the package iproute2+tc at <ftp://ftp.tux.org/pub/net/ip-routing/>. | ||
25 | That package also contains some documentation; for more, check out | ||
26 | <http://snafu.freedom.org/linux2.2/iproute-notes.html>. | ||
27 | |||
28 | This Quality of Service (QoS) support will enable you to use | ||
29 | Differentiated Services (diffserv) and Resource Reservation Protocol | ||
30 | (RSVP) on your Linux router if you also say Y to "QoS support", | ||
31 | "Packet classifier API" and to some classifiers below. Documentation | ||
32 | and software is at <http://diffserv.sourceforge.net/>. | ||
33 | |||
34 | If you say Y here and to "/proc file system" below, you will be able | ||
35 | to read status information about packet schedulers from the file | ||
36 | /proc/net/psched. | ||
37 | |||
38 | The available schedulers are listed in the following questions; you | ||
39 | can say Y to as many as you like. If unsure, say N now. | ||
40 | |||
4 | choice | 41 | choice |
5 | prompt "Packet scheduler clock source" | 42 | prompt "Packet scheduler clock source" |
6 | depends on NET_SCHED | 43 | depends on NET_SCHED |
@@ -449,6 +486,19 @@ config NET_EMATCH_META | |||
449 | To compile this code as a module, choose M here: the | 486 | To compile this code as a module, choose M here: the |
450 | module will be called em_meta. | 487 | module will be called em_meta. |
451 | 488 | ||
489 | config NET_EMATCH_TEXT | ||
490 | tristate "Textsearch" | ||
491 | depends on NET_EMATCH | ||
492 | select TEXTSEARCH | ||
493 | select TEXTSEARCH_KMP | ||
494 | select TEXTSEARCH_FSM | ||
495 | ---help--- | ||
496 | Say Y here if you want to be ablt to classify packets based on | ||
497 | textsearch comparisons. | ||
498 | |||
499 | To compile this code as a module, choose M here: the | ||
500 | module will be called em_text. | ||
501 | |||
452 | config NET_CLS_ACT | 502 | config NET_CLS_ACT |
453 | bool "Packet ACTION" | 503 | bool "Packet ACTION" |
454 | depends on EXPERIMENTAL && NET_CLS && NET_QOS | 504 | depends on EXPERIMENTAL && NET_CLS && NET_QOS |
diff --git a/net/sched/Makefile b/net/sched/Makefile index eb3fe583eba8..e48d0d456b3e 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | obj-y := sch_generic.o | 5 | obj-y := sch_generic.o |
6 | 6 | ||
7 | obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o | 7 | obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o sch_blackhole.o |
8 | obj-$(CONFIG_NET_CLS) += cls_api.o | 8 | obj-$(CONFIG_NET_CLS) += cls_api.o |
9 | obj-$(CONFIG_NET_CLS_ACT) += act_api.o | 9 | obj-$(CONFIG_NET_CLS_ACT) += act_api.o |
10 | obj-$(CONFIG_NET_ACT_POLICE) += police.o | 10 | obj-$(CONFIG_NET_ACT_POLICE) += police.o |
@@ -40,3 +40,4 @@ obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o | |||
40 | obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o | 40 | obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o |
41 | obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o | 41 | obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o |
42 | obj-$(CONFIG_NET_EMATCH_META) += em_meta.o | 42 | obj-$(CONFIG_NET_EMATCH_META) += em_meta.o |
43 | obj-$(CONFIG_NET_EMATCH_TEXT) += em_text.o | ||
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 9594206e6035..249c61936ea0 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -439,6 +439,8 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq, | |||
439 | 439 | ||
440 | t = NLMSG_DATA(nlh); | 440 | t = NLMSG_DATA(nlh); |
441 | t->tca_family = AF_UNSPEC; | 441 | t->tca_family = AF_UNSPEC; |
442 | t->tca__pad1 = 0; | ||
443 | t->tca__pad2 = 0; | ||
442 | 444 | ||
443 | x = (struct rtattr*) skb->tail; | 445 | x = (struct rtattr*) skb->tail; |
444 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); | 446 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); |
@@ -580,6 +582,8 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid) | |||
580 | nlh = NLMSG_PUT(skb, pid, n->nlmsg_seq, RTM_DELACTION, sizeof(*t)); | 582 | nlh = NLMSG_PUT(skb, pid, n->nlmsg_seq, RTM_DELACTION, sizeof(*t)); |
581 | t = NLMSG_DATA(nlh); | 583 | t = NLMSG_DATA(nlh); |
582 | t->tca_family = AF_UNSPEC; | 584 | t->tca_family = AF_UNSPEC; |
585 | t->tca__pad1 = 0; | ||
586 | t->tca__pad2 = 0; | ||
583 | 587 | ||
584 | x = (struct rtattr *) skb->tail; | 588 | x = (struct rtattr *) skb->tail; |
585 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); | 589 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); |
@@ -687,7 +691,9 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, | |||
687 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags); | 691 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags); |
688 | t = NLMSG_DATA(nlh); | 692 | t = NLMSG_DATA(nlh); |
689 | t->tca_family = AF_UNSPEC; | 693 | t->tca_family = AF_UNSPEC; |
690 | 694 | t->tca__pad1 = 0; | |
695 | t->tca__pad2 = 0; | ||
696 | |||
691 | x = (struct rtattr*) skb->tail; | 697 | x = (struct rtattr*) skb->tail; |
692 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); | 698 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); |
693 | 699 | ||
@@ -842,6 +848,8 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
842 | cb->nlh->nlmsg_type, sizeof(*t)); | 848 | cb->nlh->nlmsg_type, sizeof(*t)); |
843 | t = NLMSG_DATA(nlh); | 849 | t = NLMSG_DATA(nlh); |
844 | t->tca_family = AF_UNSPEC; | 850 | t->tca_family = AF_UNSPEC; |
851 | t->tca__pad1 = 0; | ||
852 | t->tca__pad2 = 0; | ||
845 | 853 | ||
846 | x = (struct rtattr *) skb->tail; | 854 | x = (struct rtattr *) skb->tail; |
847 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); | 855 | RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 1616bf5c9627..3b5714ef4d1a 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -331,6 +331,8 @@ tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh, | |||
331 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); | 331 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
332 | tcm = NLMSG_DATA(nlh); | 332 | tcm = NLMSG_DATA(nlh); |
333 | tcm->tcm_family = AF_UNSPEC; | 333 | tcm->tcm_family = AF_UNSPEC; |
334 | tcm->tcm__pad1 = 0; | ||
335 | tcm->tcm__pad1 = 0; | ||
334 | tcm->tcm_ifindex = tp->q->dev->ifindex; | 336 | tcm->tcm_ifindex = tp->q->dev->ifindex; |
335 | tcm->tcm_parent = tp->classid; | 337 | tcm->tcm_parent = tp->classid; |
336 | tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol); | 338 | tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol); |
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 232fb9196810..006168d69376 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h | |||
@@ -618,6 +618,7 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh, | |||
618 | pinfo.protocol = s->protocol; | 618 | pinfo.protocol = s->protocol; |
619 | pinfo.tunnelid = s->tunnelid; | 619 | pinfo.tunnelid = s->tunnelid; |
620 | pinfo.tunnelhdr = f->tunnelhdr; | 620 | pinfo.tunnelhdr = f->tunnelhdr; |
621 | pinfo.pad = 0; | ||
621 | RTA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo); | 622 | RTA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo); |
622 | if (f->res.classid) | 623 | if (f->res.classid) |
623 | RTA_PUT(skb, TCA_RSVP_CLASSID, 4, &f->res.classid); | 624 | RTA_PUT(skb, TCA_RSVP_CLASSID, 4, &f->res.classid); |
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 48bb23c2a35a..53d98f8d3d80 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c | |||
@@ -205,11 +205,6 @@ META_COLLECTOR(int_protocol) | |||
205 | dst->value = skb->protocol; | 205 | dst->value = skb->protocol; |
206 | } | 206 | } |
207 | 207 | ||
208 | META_COLLECTOR(int_security) | ||
209 | { | ||
210 | dst->value = skb->security; | ||
211 | } | ||
212 | |||
213 | META_COLLECTOR(int_pkttype) | 208 | META_COLLECTOR(int_pkttype) |
214 | { | 209 | { |
215 | dst->value = skb->pkt_type; | 210 | dst->value = skb->pkt_type; |
@@ -524,7 +519,6 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { | |||
524 | [META_ID(REALDEV)] = META_FUNC(int_realdev), | 519 | [META_ID(REALDEV)] = META_FUNC(int_realdev), |
525 | [META_ID(PRIORITY)] = META_FUNC(int_priority), | 520 | [META_ID(PRIORITY)] = META_FUNC(int_priority), |
526 | [META_ID(PROTOCOL)] = META_FUNC(int_protocol), | 521 | [META_ID(PROTOCOL)] = META_FUNC(int_protocol), |
527 | [META_ID(SECURITY)] = META_FUNC(int_security), | ||
528 | [META_ID(PKTTYPE)] = META_FUNC(int_pkttype), | 522 | [META_ID(PKTTYPE)] = META_FUNC(int_pkttype), |
529 | [META_ID(PKTLEN)] = META_FUNC(int_pktlen), | 523 | [META_ID(PKTLEN)] = META_FUNC(int_pktlen), |
530 | [META_ID(DATALEN)] = META_FUNC(int_datalen), | 524 | [META_ID(DATALEN)] = META_FUNC(int_datalen), |
diff --git a/net/sched/em_text.c b/net/sched/em_text.c new file mode 100644 index 000000000000..873840d8d072 --- /dev/null +++ b/net/sched/em_text.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * net/sched/em_text.c Textsearch ematch | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Authors: Thomas Graf <tgraf@suug.ch> | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/skbuff.h> | ||
19 | #include <linux/textsearch.h> | ||
20 | #include <linux/tc_ematch/tc_em_text.h> | ||
21 | #include <net/pkt_cls.h> | ||
22 | |||
23 | struct text_match | ||
24 | { | ||
25 | u16 from_offset; | ||
26 | u16 to_offset; | ||
27 | u8 from_layer; | ||
28 | u8 to_layer; | ||
29 | struct ts_config *config; | ||
30 | }; | ||
31 | |||
32 | #define EM_TEXT_PRIV(m) ((struct text_match *) (m)->data) | ||
33 | |||
34 | static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m, | ||
35 | struct tcf_pkt_info *info) | ||
36 | { | ||
37 | struct text_match *tm = EM_TEXT_PRIV(m); | ||
38 | int from, to; | ||
39 | struct ts_state state; | ||
40 | |||
41 | from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data; | ||
42 | from += tm->from_offset; | ||
43 | |||
44 | to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data; | ||
45 | to += tm->to_offset; | ||
46 | |||
47 | return skb_find_text(skb, from, to, tm->config, &state) != UINT_MAX; | ||
48 | } | ||
49 | |||
50 | static int em_text_change(struct tcf_proto *tp, void *data, int len, | ||
51 | struct tcf_ematch *m) | ||
52 | { | ||
53 | struct text_match *tm; | ||
54 | struct tcf_em_text *conf = data; | ||
55 | struct ts_config *ts_conf; | ||
56 | int flags = 0; | ||
57 | |||
58 | printk("Configuring text: %s from %d:%d to %d:%d len %d\n", conf->algo, conf->from_offset, | ||
59 | conf->from_layer, conf->to_offset, conf->to_layer, conf->pattern_len); | ||
60 | |||
61 | if (len < sizeof(*conf) || len < (sizeof(*conf) + conf->pattern_len)) | ||
62 | return -EINVAL; | ||
63 | |||
64 | if (conf->from_layer > conf->to_layer) | ||
65 | return -EINVAL; | ||
66 | |||
67 | if (conf->from_layer == conf->to_layer && | ||
68 | conf->from_offset > conf->to_offset) | ||
69 | return -EINVAL; | ||
70 | |||
71 | retry: | ||
72 | ts_conf = textsearch_prepare(conf->algo, (u8 *) conf + sizeof(*conf), | ||
73 | conf->pattern_len, GFP_KERNEL, flags); | ||
74 | |||
75 | if (flags & TS_AUTOLOAD) | ||
76 | rtnl_lock(); | ||
77 | |||
78 | if (IS_ERR(ts_conf)) { | ||
79 | if (PTR_ERR(ts_conf) == -ENOENT && !(flags & TS_AUTOLOAD)) { | ||
80 | rtnl_unlock(); | ||
81 | flags |= TS_AUTOLOAD; | ||
82 | goto retry; | ||
83 | } else | ||
84 | return PTR_ERR(ts_conf); | ||
85 | } else if (flags & TS_AUTOLOAD) { | ||
86 | textsearch_destroy(ts_conf); | ||
87 | return -EAGAIN; | ||
88 | } | ||
89 | |||
90 | tm = kmalloc(sizeof(*tm), GFP_KERNEL); | ||
91 | if (tm == NULL) { | ||
92 | textsearch_destroy(ts_conf); | ||
93 | return -ENOBUFS; | ||
94 | } | ||
95 | |||
96 | tm->from_offset = conf->from_offset; | ||
97 | tm->to_offset = conf->to_offset; | ||
98 | tm->from_layer = conf->from_layer; | ||
99 | tm->to_layer = conf->to_layer; | ||
100 | tm->config = ts_conf; | ||
101 | |||
102 | m->datalen = sizeof(*tm); | ||
103 | m->data = (unsigned long) tm; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static void em_text_destroy(struct tcf_proto *tp, struct tcf_ematch *m) | ||
109 | { | ||
110 | textsearch_destroy(EM_TEXT_PRIV(m)->config); | ||
111 | } | ||
112 | |||
113 | static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m) | ||
114 | { | ||
115 | struct text_match *tm = EM_TEXT_PRIV(m); | ||
116 | struct tcf_em_text conf; | ||
117 | |||
118 | strncpy(conf.algo, tm->config->ops->name, sizeof(conf.algo) - 1); | ||
119 | conf.from_offset = tm->from_offset; | ||
120 | conf.to_offset = tm->to_offset; | ||
121 | conf.from_layer = tm->from_layer; | ||
122 | conf.to_layer = tm->to_layer; | ||
123 | conf.pattern_len = textsearch_get_pattern_len(tm->config); | ||
124 | conf.pad = 0; | ||
125 | |||
126 | RTA_PUT_NOHDR(skb, sizeof(conf), &conf); | ||
127 | RTA_APPEND(skb, conf.pattern_len, textsearch_get_pattern(tm->config)); | ||
128 | return 0; | ||
129 | |||
130 | rtattr_failure: | ||
131 | return -1; | ||
132 | } | ||
133 | |||
134 | static struct tcf_ematch_ops em_text_ops = { | ||
135 | .kind = TCF_EM_TEXT, | ||
136 | .change = em_text_change, | ||
137 | .match = em_text_match, | ||
138 | .destroy = em_text_destroy, | ||
139 | .dump = em_text_dump, | ||
140 | .owner = THIS_MODULE, | ||
141 | .link = LIST_HEAD_INIT(em_text_ops.link) | ||
142 | }; | ||
143 | |||
144 | static int __init init_em_text(void) | ||
145 | { | ||
146 | return tcf_em_register(&em_text_ops); | ||
147 | } | ||
148 | |||
149 | static void __exit exit_em_text(void) | ||
150 | { | ||
151 | tcf_em_unregister(&em_text_ops); | ||
152 | } | ||
153 | |||
154 | MODULE_LICENSE("GPL"); | ||
155 | |||
156 | module_init(init_em_text); | ||
157 | module_exit(exit_em_text); | ||
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 97c1c75d5c78..b9a069af4a02 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -399,10 +399,8 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) | |||
399 | { | 399 | { |
400 | int err; | 400 | int err; |
401 | struct rtattr *kind = tca[TCA_KIND-1]; | 401 | struct rtattr *kind = tca[TCA_KIND-1]; |
402 | void *p = NULL; | ||
403 | struct Qdisc *sch; | 402 | struct Qdisc *sch; |
404 | struct Qdisc_ops *ops; | 403 | struct Qdisc_ops *ops; |
405 | int size; | ||
406 | 404 | ||
407 | ops = qdisc_lookup_ops(kind); | 405 | ops = qdisc_lookup_ops(kind); |
408 | #ifdef CONFIG_KMOD | 406 | #ifdef CONFIG_KMOD |
@@ -437,64 +435,55 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) | |||
437 | if (ops == NULL) | 435 | if (ops == NULL) |
438 | goto err_out; | 436 | goto err_out; |
439 | 437 | ||
440 | /* ensure that the Qdisc and the private data are 32-byte aligned */ | 438 | sch = qdisc_alloc(dev, ops); |
441 | size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST); | 439 | if (IS_ERR(sch)) { |
442 | size += ops->priv_size + QDISC_ALIGN_CONST; | 440 | err = PTR_ERR(sch); |
443 | |||
444 | p = kmalloc(size, GFP_KERNEL); | ||
445 | err = -ENOBUFS; | ||
446 | if (!p) | ||
447 | goto err_out2; | 441 | goto err_out2; |
448 | memset(p, 0, size); | 442 | } |
449 | sch = (struct Qdisc *)(((unsigned long)p + QDISC_ALIGN_CONST) | ||
450 | & ~QDISC_ALIGN_CONST); | ||
451 | sch->padded = (char *)sch - (char *)p; | ||
452 | |||
453 | INIT_LIST_HEAD(&sch->list); | ||
454 | skb_queue_head_init(&sch->q); | ||
455 | 443 | ||
456 | if (handle == TC_H_INGRESS) | 444 | if (handle == TC_H_INGRESS) { |
457 | sch->flags |= TCQ_F_INGRESS; | 445 | sch->flags |= TCQ_F_INGRESS; |
458 | 446 | handle = TC_H_MAKE(TC_H_INGRESS, 0); | |
459 | sch->ops = ops; | 447 | } else if (handle == 0) { |
460 | sch->enqueue = ops->enqueue; | ||
461 | sch->dequeue = ops->dequeue; | ||
462 | sch->dev = dev; | ||
463 | dev_hold(dev); | ||
464 | atomic_set(&sch->refcnt, 1); | ||
465 | sch->stats_lock = &dev->queue_lock; | ||
466 | if (handle == 0) { | ||
467 | handle = qdisc_alloc_handle(dev); | 448 | handle = qdisc_alloc_handle(dev); |
468 | err = -ENOMEM; | 449 | err = -ENOMEM; |
469 | if (handle == 0) | 450 | if (handle == 0) |
470 | goto err_out3; | 451 | goto err_out3; |
471 | } | 452 | } |
472 | 453 | ||
473 | if (handle == TC_H_INGRESS) | 454 | sch->handle = handle; |
474 | sch->handle =TC_H_MAKE(TC_H_INGRESS, 0); | ||
475 | else | ||
476 | sch->handle = handle; | ||
477 | 455 | ||
478 | if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { | 456 | if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { |
457 | #ifdef CONFIG_NET_ESTIMATOR | ||
458 | if (tca[TCA_RATE-1]) { | ||
459 | err = gen_new_estimator(&sch->bstats, &sch->rate_est, | ||
460 | sch->stats_lock, | ||
461 | tca[TCA_RATE-1]); | ||
462 | if (err) { | ||
463 | /* | ||
464 | * Any broken qdiscs that would require | ||
465 | * a ops->reset() here? The qdisc was never | ||
466 | * in action so it shouldn't be necessary. | ||
467 | */ | ||
468 | if (ops->destroy) | ||
469 | ops->destroy(sch); | ||
470 | goto err_out3; | ||
471 | } | ||
472 | } | ||
473 | #endif | ||
479 | qdisc_lock_tree(dev); | 474 | qdisc_lock_tree(dev); |
480 | list_add_tail(&sch->list, &dev->qdisc_list); | 475 | list_add_tail(&sch->list, &dev->qdisc_list); |
481 | qdisc_unlock_tree(dev); | 476 | qdisc_unlock_tree(dev); |
482 | 477 | ||
483 | #ifdef CONFIG_NET_ESTIMATOR | ||
484 | if (tca[TCA_RATE-1]) | ||
485 | gen_new_estimator(&sch->bstats, &sch->rate_est, | ||
486 | sch->stats_lock, tca[TCA_RATE-1]); | ||
487 | #endif | ||
488 | return sch; | 478 | return sch; |
489 | } | 479 | } |
490 | err_out3: | 480 | err_out3: |
491 | dev_put(dev); | 481 | dev_put(dev); |
482 | kfree((char *) sch - sch->padded); | ||
492 | err_out2: | 483 | err_out2: |
493 | module_put(ops->owner); | 484 | module_put(ops->owner); |
494 | err_out: | 485 | err_out: |
495 | *errp = err; | 486 | *errp = err; |
496 | if (p) | ||
497 | kfree(p); | ||
498 | return NULL; | 487 | return NULL; |
499 | } | 488 | } |
500 | 489 | ||
@@ -770,6 +759,8 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
770 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); | 759 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
771 | tcm = NLMSG_DATA(nlh); | 760 | tcm = NLMSG_DATA(nlh); |
772 | tcm->tcm_family = AF_UNSPEC; | 761 | tcm->tcm_family = AF_UNSPEC; |
762 | tcm->tcm__pad1 = 0; | ||
763 | tcm->tcm__pad2 = 0; | ||
773 | tcm->tcm_ifindex = q->dev->ifindex; | 764 | tcm->tcm_ifindex = q->dev->ifindex; |
774 | tcm->tcm_parent = clid; | 765 | tcm->tcm_parent = clid; |
775 | tcm->tcm_handle = q->handle; | 766 | tcm->tcm_handle = q->handle; |
diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c new file mode 100644 index 000000000000..81f0b8346d17 --- /dev/null +++ b/net/sched/sch_blackhole.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * net/sched/sch_blackhole.c Black hole queue | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Authors: Thomas Graf <tgraf@suug.ch> | ||
10 | * | ||
11 | * Note: Quantum tunneling is not supported. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/skbuff.h> | ||
20 | #include <net/pkt_sched.h> | ||
21 | |||
22 | static int blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch) | ||
23 | { | ||
24 | qdisc_drop(skb, sch); | ||
25 | return NET_XMIT_SUCCESS; | ||
26 | } | ||
27 | |||
28 | static struct sk_buff *blackhole_dequeue(struct Qdisc *sch) | ||
29 | { | ||
30 | return NULL; | ||
31 | } | ||
32 | |||
33 | static struct Qdisc_ops blackhole_qdisc_ops = { | ||
34 | .id = "blackhole", | ||
35 | .priv_size = 0, | ||
36 | .enqueue = blackhole_enqueue, | ||
37 | .dequeue = blackhole_dequeue, | ||
38 | .owner = THIS_MODULE, | ||
39 | }; | ||
40 | |||
41 | static int __init blackhole_module_init(void) | ||
42 | { | ||
43 | return register_qdisc(&blackhole_qdisc_ops); | ||
44 | } | ||
45 | |||
46 | static void __exit blackhole_module_exit(void) | ||
47 | { | ||
48 | unregister_qdisc(&blackhole_qdisc_ops); | ||
49 | } | ||
50 | |||
51 | module_init(blackhole_module_init) | ||
52 | module_exit(blackhole_module_exit) | ||
53 | |||
54 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index d43e3b8cbf6a..09453f997d8c 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -1528,6 +1528,7 @@ static __inline__ int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl) | |||
1528 | 1528 | ||
1529 | opt.strategy = cl->ovl_strategy; | 1529 | opt.strategy = cl->ovl_strategy; |
1530 | opt.priority2 = cl->priority2+1; | 1530 | opt.priority2 = cl->priority2+1; |
1531 | opt.pad = 0; | ||
1531 | opt.penalty = (cl->penalty*1000)/HZ; | 1532 | opt.penalty = (cl->penalty*1000)/HZ; |
1532 | RTA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt); | 1533 | RTA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt); |
1533 | return skb->len; | 1534 | return skb->len; |
@@ -1563,6 +1564,8 @@ static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) | |||
1563 | 1564 | ||
1564 | if (cl->police) { | 1565 | if (cl->police) { |
1565 | opt.police = cl->police; | 1566 | opt.police = cl->police; |
1567 | opt.__res1 = 0; | ||
1568 | opt.__res2 = 0; | ||
1566 | RTA_PUT(skb, TCA_CBQ_POLICE, sizeof(opt), &opt); | 1569 | RTA_PUT(skb, TCA_CBQ_POLICE, sizeof(opt), &opt); |
1567 | } | 1570 | } |
1568 | return skb->len; | 1571 | return skb->len; |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 7683b34dc6a9..73e218e646ac 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -395,24 +395,23 @@ static struct Qdisc_ops pfifo_fast_ops = { | |||
395 | .owner = THIS_MODULE, | 395 | .owner = THIS_MODULE, |
396 | }; | 396 | }; |
397 | 397 | ||
398 | struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) | 398 | struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops) |
399 | { | 399 | { |
400 | void *p; | 400 | void *p; |
401 | struct Qdisc *sch; | 401 | struct Qdisc *sch; |
402 | int size; | 402 | unsigned int size; |
403 | int err = -ENOBUFS; | ||
403 | 404 | ||
404 | /* ensure that the Qdisc and the private data are 32-byte aligned */ | 405 | /* ensure that the Qdisc and the private data are 32-byte aligned */ |
405 | size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST); | 406 | size = QDISC_ALIGN(sizeof(*sch)); |
406 | size += ops->priv_size + QDISC_ALIGN_CONST; | 407 | size += ops->priv_size + (QDISC_ALIGNTO - 1); |
407 | 408 | ||
408 | p = kmalloc(size, GFP_KERNEL); | 409 | p = kmalloc(size, GFP_KERNEL); |
409 | if (!p) | 410 | if (!p) |
410 | return NULL; | 411 | goto errout; |
411 | memset(p, 0, size); | 412 | memset(p, 0, size); |
412 | 413 | sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p); | |
413 | sch = (struct Qdisc *)(((unsigned long)p + QDISC_ALIGN_CONST) | 414 | sch->padded = (char *) sch - (char *) p; |
414 | & ~QDISC_ALIGN_CONST); | ||
415 | sch->padded = (char *)sch - (char *)p; | ||
416 | 415 | ||
417 | INIT_LIST_HEAD(&sch->list); | 416 | INIT_LIST_HEAD(&sch->list); |
418 | skb_queue_head_init(&sch->q); | 417 | skb_queue_head_init(&sch->q); |
@@ -423,11 +422,24 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) | |||
423 | dev_hold(dev); | 422 | dev_hold(dev); |
424 | sch->stats_lock = &dev->queue_lock; | 423 | sch->stats_lock = &dev->queue_lock; |
425 | atomic_set(&sch->refcnt, 1); | 424 | atomic_set(&sch->refcnt, 1); |
425 | |||
426 | return sch; | ||
427 | errout: | ||
428 | return ERR_PTR(-err); | ||
429 | } | ||
430 | |||
431 | struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) | ||
432 | { | ||
433 | struct Qdisc *sch; | ||
434 | |||
435 | sch = qdisc_alloc(dev, ops); | ||
436 | if (IS_ERR(sch)) | ||
437 | goto errout; | ||
438 | |||
426 | if (!ops->init || ops->init(sch, NULL) == 0) | 439 | if (!ops->init || ops->init(sch, NULL) == 0) |
427 | return sch; | 440 | return sch; |
428 | 441 | ||
429 | dev_put(dev); | 442 | errout: |
430 | kfree(p); | ||
431 | return NULL; | 443 | return NULL; |
432 | } | 444 | } |
433 | 445 | ||
@@ -591,6 +603,7 @@ EXPORT_SYMBOL(__netdev_watchdog_up); | |||
591 | EXPORT_SYMBOL(noop_qdisc); | 603 | EXPORT_SYMBOL(noop_qdisc); |
592 | EXPORT_SYMBOL(noop_qdisc_ops); | 604 | EXPORT_SYMBOL(noop_qdisc_ops); |
593 | EXPORT_SYMBOL(qdisc_create_dflt); | 605 | EXPORT_SYMBOL(qdisc_create_dflt); |
606 | EXPORT_SYMBOL(qdisc_alloc); | ||
594 | EXPORT_SYMBOL(qdisc_destroy); | 607 | EXPORT_SYMBOL(qdisc_destroy); |
595 | EXPORT_SYMBOL(qdisc_reset); | 608 | EXPORT_SYMBOL(qdisc_reset); |
596 | EXPORT_SYMBOL(qdisc_restart); | 609 | EXPORT_SYMBOL(qdisc_restart); |
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 664d0e47374f..7845d045eec4 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c | |||
@@ -385,7 +385,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt) | |||
385 | memcpy(q->Stab, RTA_DATA(tb[TCA_RED_STAB-1]), 256); | 385 | memcpy(q->Stab, RTA_DATA(tb[TCA_RED_STAB-1]), 256); |
386 | 386 | ||
387 | q->qcount = -1; | 387 | q->qcount = -1; |
388 | if (skb_queue_len(&sch->q) == 0) | 388 | if (skb_queue_empty(&sch->q)) |
389 | PSCHED_SET_PASTPERFECT(q->qidlestart); | 389 | PSCHED_SET_PASTPERFECT(q->qidlestart); |
390 | sch_tree_unlock(sch); | 390 | sch_tree_unlock(sch); |
391 | return 0; | 391 | return 0; |