sch_prio.c (14f0290ba44de6ed435fea24bba26e7868421c66) | sch_prio.c (cc7ec456f82da7f89a5b376e613b3ac4311b3e9a) |
---|---|
1/* 2 * net/sched/sch_prio.c Simple 3-band priority "scheduler". 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 * --- 8 unchanged lines hidden (view full) --- 17#include <linux/kernel.h> 18#include <linux/string.h> 19#include <linux/errno.h> 20#include <linux/skbuff.h> 21#include <net/netlink.h> 22#include <net/pkt_sched.h> 23 24 | 1/* 2 * net/sched/sch_prio.c Simple 3-band priority "scheduler". 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 * --- 8 unchanged lines hidden (view full) --- 17#include <linux/kernel.h> 18#include <linux/string.h> 19#include <linux/errno.h> 20#include <linux/skbuff.h> 21#include <net/netlink.h> 22#include <net/pkt_sched.h> 23 24 |
25struct prio_sched_data 26{ | 25struct prio_sched_data { |
27 int bands; 28 struct tcf_proto *filter_list; 29 u8 prio2band[TC_PRIO_MAX+1]; 30 struct Qdisc *queues[TCQ_PRIO_BANDS]; 31}; 32 33 34static struct Qdisc * --- 14 unchanged lines hidden (view full) --- 49 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; 50 case TC_ACT_SHOT: 51 return NULL; 52 } 53#endif 54 if (!q->filter_list || err < 0) { 55 if (TC_H_MAJ(band)) 56 band = 0; | 26 int bands; 27 struct tcf_proto *filter_list; 28 u8 prio2band[TC_PRIO_MAX+1]; 29 struct Qdisc *queues[TCQ_PRIO_BANDS]; 30}; 31 32 33static struct Qdisc * --- 14 unchanged lines hidden (view full) --- 48 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; 49 case TC_ACT_SHOT: 50 return NULL; 51 } 52#endif 53 if (!q->filter_list || err < 0) { 54 if (TC_H_MAJ(band)) 55 band = 0; |
57 return q->queues[q->prio2band[band&TC_PRIO_MAX]]; | 56 return q->queues[q->prio2band[band & TC_PRIO_MAX]]; |
58 } 59 band = res.classid; 60 } 61 band = TC_H_MIN(band) - 1; 62 if (band >= q->bands) 63 return q->queues[q->prio2band[0]]; 64 65 return q->queues[band]; --- 36 unchanged lines hidden (view full) --- 102 struct Qdisc *qdisc = q->queues[prio]; 103 struct sk_buff *skb = qdisc->ops->peek(qdisc); 104 if (skb) 105 return skb; 106 } 107 return NULL; 108} 109 | 57 } 58 band = res.classid; 59 } 60 band = TC_H_MIN(band) - 1; 61 if (band >= q->bands) 62 return q->queues[q->prio2band[0]]; 63 64 return q->queues[band]; --- 36 unchanged lines hidden (view full) --- 101 struct Qdisc *qdisc = q->queues[prio]; 102 struct sk_buff *skb = qdisc->ops->peek(qdisc); 103 if (skb) 104 return skb; 105 } 106 return NULL; 107} 108 |
110static struct sk_buff *prio_dequeue(struct Qdisc* sch) | 109static struct sk_buff *prio_dequeue(struct Qdisc *sch) |
111{ 112 struct prio_sched_data *q = qdisc_priv(sch); 113 int prio; 114 115 for (prio = 0; prio < q->bands; prio++) { 116 struct Qdisc *qdisc = q->queues[prio]; 117 struct sk_buff *skb = qdisc->dequeue(qdisc); 118 if (skb) { 119 sch->q.qlen--; 120 return skb; 121 } 122 } 123 return NULL; 124 125} 126 | 110{ 111 struct prio_sched_data *q = qdisc_priv(sch); 112 int prio; 113 114 for (prio = 0; prio < q->bands; prio++) { 115 struct Qdisc *qdisc = q->queues[prio]; 116 struct sk_buff *skb = qdisc->dequeue(qdisc); 117 if (skb) { 118 sch->q.qlen--; 119 return skb; 120 } 121 } 122 return NULL; 123 124} 125 |
127static unsigned int prio_drop(struct Qdisc* sch) | 126static unsigned int prio_drop(struct Qdisc *sch) |
128{ 129 struct prio_sched_data *q = qdisc_priv(sch); 130 int prio; 131 unsigned int len; 132 struct Qdisc *qdisc; 133 134 for (prio = q->bands-1; prio >= 0; prio--) { 135 qdisc = q->queues[prio]; 136 if (qdisc->ops->drop && (len = qdisc->ops->drop(qdisc)) != 0) { 137 sch->q.qlen--; 138 return len; 139 } 140 } 141 return 0; 142} 143 144 145static void | 127{ 128 struct prio_sched_data *q = qdisc_priv(sch); 129 int prio; 130 unsigned int len; 131 struct Qdisc *qdisc; 132 133 for (prio = q->bands-1; prio >= 0; prio--) { 134 qdisc = q->queues[prio]; 135 if (qdisc->ops->drop && (len = qdisc->ops->drop(qdisc)) != 0) { 136 sch->q.qlen--; 137 return len; 138 } 139 } 140 return 0; 141} 142 143 144static void |
146prio_reset(struct Qdisc* sch) | 145prio_reset(struct Qdisc *sch) |
147{ 148 int prio; 149 struct prio_sched_data *q = qdisc_priv(sch); 150 | 146{ 147 int prio; 148 struct prio_sched_data *q = qdisc_priv(sch); 149 |
151 for (prio=0; prio<q->bands; prio++) | 150 for (prio = 0; prio < q->bands; prio++) |
152 qdisc_reset(q->queues[prio]); 153 sch->q.qlen = 0; 154} 155 156static void | 151 qdisc_reset(q->queues[prio]); 152 sch->q.qlen = 0; 153} 154 155static void |
157prio_destroy(struct Qdisc* sch) | 156prio_destroy(struct Qdisc *sch) |
158{ 159 int prio; 160 struct prio_sched_data *q = qdisc_priv(sch); 161 162 tcf_destroy_chain(&q->filter_list); | 157{ 158 int prio; 159 struct prio_sched_data *q = qdisc_priv(sch); 160 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]); 165} 166 167static int prio_tune(struct Qdisc *sch, struct nlattr *opt) 168{ 169 struct prio_sched_data *q = qdisc_priv(sch); 170 struct tc_prio_qopt *qopt; 171 int i; 172 173 if (nla_len(opt) < sizeof(*qopt)) 174 return -EINVAL; 175 qopt = nla_data(opt); 176 177 if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2) 178 return -EINVAL; 179 | 163 qdisc_destroy(q->queues[prio]); 164} 165 166static int prio_tune(struct Qdisc *sch, struct nlattr *opt) 167{ 168 struct prio_sched_data *q = qdisc_priv(sch); 169 struct tc_prio_qopt *qopt; 170 int i; 171 172 if (nla_len(opt) < sizeof(*qopt)) 173 return -EINVAL; 174 qopt = nla_data(opt); 175 176 if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2) 177 return -EINVAL; 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) 182 return -EINVAL; 183 } 184 185 sch_tree_lock(sch); 186 q->bands = qopt->bands; 187 memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); 188 | 180 if (qopt->priomap[i] >= qopt->bands) 181 return -EINVAL; 182 } 183 184 sch_tree_lock(sch); 185 q->bands = qopt->bands; 186 memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); 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]; 191 q->queues[i] = &noop_qdisc; 192 if (child != &noop_qdisc) { 193 qdisc_tree_decrease_qlen(child, child->q.qlen); 194 qdisc_destroy(child); 195 } 196 } 197 sch_tree_unlock(sch); 198 | 189 struct Qdisc *child = q->queues[i]; 190 q->queues[i] = &noop_qdisc; 191 if (child != &noop_qdisc) { 192 qdisc_tree_decrease_qlen(child, child->q.qlen); 193 qdisc_destroy(child); 194 } 195 } 196 sch_tree_unlock(sch); 197 |
199 for (i=0; i<q->bands; i++) { | 198 for (i = 0; i < q->bands; i++) { |
200 if (q->queues[i] == &noop_qdisc) { 201 struct Qdisc *child, *old; | 199 if (q->queues[i] == &noop_qdisc) { 200 struct Qdisc *child, *old; |
201 |
|
202 child = qdisc_create_dflt(sch->dev_queue, 203 &pfifo_qdisc_ops, 204 TC_H_MAKE(sch->handle, i + 1)); 205 if (child) { 206 sch_tree_lock(sch); 207 old = q->queues[i]; 208 q->queues[i] = child; 209 --- 9 unchanged lines hidden (view full) --- 219 return 0; 220} 221 222static int prio_init(struct Qdisc *sch, struct nlattr *opt) 223{ 224 struct prio_sched_data *q = qdisc_priv(sch); 225 int i; 226 | 202 child = qdisc_create_dflt(sch->dev_queue, 203 &pfifo_qdisc_ops, 204 TC_H_MAKE(sch->handle, i + 1)); 205 if (child) { 206 sch_tree_lock(sch); 207 old = q->queues[i]; 208 q->queues[i] = child; 209 --- 9 unchanged lines hidden (view full) --- 219 return 0; 220} 221 222static int prio_init(struct Qdisc *sch, struct nlattr *opt) 223{ 224 struct prio_sched_data *q = qdisc_priv(sch); 225 int i; 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; 229 230 if (opt == NULL) { 231 return -EINVAL; 232 } else { 233 int err; 234 | 228 q->queues[i] = &noop_qdisc; 229 230 if (opt == NULL) { 231 return -EINVAL; 232 } else { 233 int err; 234 |
235 if ((err= prio_tune(sch, opt)) != 0) | 235 if ((err = prio_tune(sch, opt)) != 0) |
236 return err; 237 } 238 return 0; 239} 240 241static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) 242{ 243 struct prio_sched_data *q = qdisc_priv(sch); 244 unsigned char *b = skb_tail_pointer(skb); 245 struct tc_prio_qopt opt; 246 247 opt.bands = q->bands; | 236 return err; 237 } 238 return 0; 239} 240 241static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) 242{ 243 struct prio_sched_data *q = qdisc_priv(sch); 244 unsigned char *b = skb_tail_pointer(skb); 245 struct tc_prio_qopt opt; 246 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 250 NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); 251 252 return skb->len; 253 254nla_put_failure: 255 nlmsg_trim(skb, b); 256 return -1; --- 80 unchanged lines hidden (view full) --- 337 if (arg->stop) 338 return; 339 340 for (prio = 0; prio < q->bands; prio++) { 341 if (arg->count < arg->skip) { 342 arg->count++; 343 continue; 344 } | 249 250 NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); 251 252 return skb->len; 253 254nla_put_failure: 255 nlmsg_trim(skb, b); 256 return -1; --- 80 unchanged lines hidden (view full) --- 337 if (arg->stop) 338 return; 339 340 for (prio = 0; prio < q->bands; prio++) { 341 if (arg->count < arg->skip) { 342 arg->count++; 343 continue; 344 } |
345 if (arg->fn(sch, prio+1, arg) < 0) { | 345 if (arg->fn(sch, prio + 1, arg) < 0) { |
346 arg->stop = 1; 347 break; 348 } 349 arg->count++; 350 } 351} 352 | 346 arg->stop = 1; 347 break; 348 } 349 arg->count++; 350 } 351} 352 |
353static struct tcf_proto ** prio_find_tcf(struct Qdisc *sch, unsigned long cl) | 353static struct tcf_proto **prio_find_tcf(struct Qdisc *sch, unsigned long cl) |
354{ 355 struct prio_sched_data *q = qdisc_priv(sch); 356 357 if (cl) 358 return NULL; 359 return &q->filter_list; 360} 361 --- 44 unchanged lines hidden --- | 354{ 355 struct prio_sched_data *q = qdisc_priv(sch); 356 357 if (cl) 358 return NULL; 359 return &q->filter_list; 360} 361 --- 44 unchanged lines hidden --- |