sch_tbf.c (14f0290ba44de6ed435fea24bba26e7868421c66) | sch_tbf.c (cc7ec456f82da7f89a5b376e613b3ac4311b3e9a) |
---|---|
1/* 2 * net/sched/sch_tbf.c Token Bucket Filter 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 * --- 83 unchanged lines hidden (view full) --- 92 P_crit = 150Kbytes/sec. So, if you need greater peak 93 rates, use alpha with HZ=1000 :-) 94 95 With classful TBF, limit is just kept for backwards compatibility. 96 It is passed to the default bfifo qdisc - if the inner qdisc is 97 changed the limit is not effective anymore. 98*/ 99 | 1/* 2 * net/sched/sch_tbf.c Token Bucket Filter 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 * --- 83 unchanged lines hidden (view full) --- 92 P_crit = 150Kbytes/sec. So, if you need greater peak 93 rates, use alpha with HZ=1000 :-) 94 95 With classful TBF, limit is just kept for backwards compatibility. 96 It is passed to the default bfifo qdisc - if the inner qdisc is 97 changed the limit is not effective anymore. 98*/ 99 |
100struct tbf_sched_data 101{ | 100struct tbf_sched_data { |
102/* Parameters */ 103 u32 limit; /* Maximal length of backlog: bytes */ 104 u32 buffer; /* Token bucket depth/rate: MUST BE >= MTU/B */ 105 u32 mtu; 106 u32 max_size; 107 struct qdisc_rate_table *R_tab; 108 struct qdisc_rate_table *P_tab; 109 110/* Variables */ 111 long tokens; /* Current number of B tokens */ 112 long ptokens; /* Current number of P tokens */ 113 psched_time_t t_c; /* Time check-point */ 114 struct Qdisc *qdisc; /* Inner qdisc, default - bfifo queue */ 115 struct qdisc_watchdog watchdog; /* Watchdog timer */ 116}; 117 | 101/* Parameters */ 102 u32 limit; /* Maximal length of backlog: bytes */ 103 u32 buffer; /* Token bucket depth/rate: MUST BE >= MTU/B */ 104 u32 mtu; 105 u32 max_size; 106 struct qdisc_rate_table *R_tab; 107 struct qdisc_rate_table *P_tab; 108 109/* Variables */ 110 long tokens; /* Current number of B tokens */ 111 long ptokens; /* Current number of P tokens */ 112 psched_time_t t_c; /* Time check-point */ 113 struct Qdisc *qdisc; /* Inner qdisc, default - bfifo queue */ 114 struct qdisc_watchdog watchdog; /* Watchdog timer */ 115}; 116 |
118#define L2T(q,L) qdisc_l2t((q)->R_tab,L) 119#define L2T_P(q,L) qdisc_l2t((q)->P_tab,L) | 117#define L2T(q, L) qdisc_l2t((q)->R_tab, L) 118#define L2T_P(q, L) qdisc_l2t((q)->P_tab, L) |
120 | 119 |
121static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) | 120static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
122{ 123 struct tbf_sched_data *q = qdisc_priv(sch); 124 int ret; 125 126 if (qdisc_pkt_len(skb) > q->max_size) 127 return qdisc_reshape_fail(skb, sch); 128 129 ret = qdisc_enqueue(skb, q->qdisc); 130 if (ret != NET_XMIT_SUCCESS) { 131 if (net_xmit_drop_count(ret)) 132 sch->qstats.drops++; 133 return ret; 134 } 135 136 sch->q.qlen++; 137 qdisc_bstats_update(sch, skb); 138 return NET_XMIT_SUCCESS; 139} 140 | 121{ 122 struct tbf_sched_data *q = qdisc_priv(sch); 123 int ret; 124 125 if (qdisc_pkt_len(skb) > q->max_size) 126 return qdisc_reshape_fail(skb, sch); 127 128 ret = qdisc_enqueue(skb, q->qdisc); 129 if (ret != NET_XMIT_SUCCESS) { 130 if (net_xmit_drop_count(ret)) 131 sch->qstats.drops++; 132 return ret; 133 } 134 135 sch->q.qlen++; 136 qdisc_bstats_update(sch, skb); 137 return NET_XMIT_SUCCESS; 138} 139 |
141static unsigned int tbf_drop(struct Qdisc* sch) | 140static unsigned int tbf_drop(struct Qdisc *sch) |
142{ 143 struct tbf_sched_data *q = qdisc_priv(sch); 144 unsigned int len = 0; 145 146 if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) { 147 sch->q.qlen--; 148 sch->qstats.drops++; 149 } 150 return len; 151} 152 | 141{ 142 struct tbf_sched_data *q = qdisc_priv(sch); 143 unsigned int len = 0; 144 145 if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) { 146 sch->q.qlen--; 147 sch->qstats.drops++; 148 } 149 return len; 150} 151 |
153static struct sk_buff *tbf_dequeue(struct Qdisc* sch) | 152static struct sk_buff *tbf_dequeue(struct Qdisc *sch) |
154{ 155 struct tbf_sched_data *q = qdisc_priv(sch); 156 struct sk_buff *skb; 157 158 skb = q->qdisc->ops->peek(q->qdisc); 159 160 if (skb) { 161 psched_time_t now; --- 42 unchanged lines hidden (view full) --- 204 (cf. CSZ, HPFQ, HFSC) 205 */ 206 207 sch->qstats.overlimits++; 208 } 209 return NULL; 210} 211 | 153{ 154 struct tbf_sched_data *q = qdisc_priv(sch); 155 struct sk_buff *skb; 156 157 skb = q->qdisc->ops->peek(q->qdisc); 158 159 if (skb) { 160 psched_time_t now; --- 42 unchanged lines hidden (view full) --- 203 (cf. CSZ, HPFQ, HFSC) 204 */ 205 206 sch->qstats.overlimits++; 207 } 208 return NULL; 209} 210 |
212static void tbf_reset(struct Qdisc* sch) | 211static void tbf_reset(struct Qdisc *sch) |
213{ 214 struct tbf_sched_data *q = qdisc_priv(sch); 215 216 qdisc_reset(q->qdisc); 217 sch->q.qlen = 0; 218 q->t_c = psched_get_time(); 219 q->tokens = q->buffer; 220 q->ptokens = q->mtu; 221 qdisc_watchdog_cancel(&q->watchdog); 222} 223 224static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = { 225 [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) }, 226 [TCA_TBF_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, 227 [TCA_TBF_PTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, 228}; 229 | 212{ 213 struct tbf_sched_data *q = qdisc_priv(sch); 214 215 qdisc_reset(q->qdisc); 216 sch->q.qlen = 0; 217 q->t_c = psched_get_time(); 218 q->tokens = q->buffer; 219 q->ptokens = q->mtu; 220 qdisc_watchdog_cancel(&q->watchdog); 221} 222 223static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = { 224 [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) }, 225 [TCA_TBF_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, 226 [TCA_TBF_PTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, 227}; 228 |
230static int tbf_change(struct Qdisc* sch, struct nlattr *opt) | 229static int tbf_change(struct Qdisc *sch, struct nlattr *opt) |
231{ 232 int err; 233 struct tbf_sched_data *q = qdisc_priv(sch); 234 struct nlattr *tb[TCA_TBF_PTAB + 1]; 235 struct tc_tbf_qopt *qopt; 236 struct qdisc_rate_table *rtab = NULL; 237 struct qdisc_rate_table *ptab = NULL; 238 struct Qdisc *child = NULL; | 230{ 231 int err; 232 struct tbf_sched_data *q = qdisc_priv(sch); 233 struct nlattr *tb[TCA_TBF_PTAB + 1]; 234 struct tc_tbf_qopt *qopt; 235 struct qdisc_rate_table *rtab = NULL; 236 struct qdisc_rate_table *ptab = NULL; 237 struct Qdisc *child = NULL; |
239 int max_size,n; | 238 int max_size, n; |
240 241 err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy); 242 if (err < 0) 243 return err; 244 245 err = -EINVAL; 246 if (tb[TCA_TBF_PARMS] == NULL) 247 goto done; --- 6 unchanged lines hidden (view full) --- 254 if (qopt->peakrate.rate) { 255 if (qopt->peakrate.rate > qopt->rate.rate) 256 ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]); 257 if (ptab == NULL) 258 goto done; 259 } 260 261 for (n = 0; n < 256; n++) | 239 240 err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy); 241 if (err < 0) 242 return err; 243 244 err = -EINVAL; 245 if (tb[TCA_TBF_PARMS] == NULL) 246 goto done; --- 6 unchanged lines hidden (view full) --- 253 if (qopt->peakrate.rate) { 254 if (qopt->peakrate.rate > qopt->rate.rate) 255 ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]); 256 if (ptab == NULL) 257 goto done; 258 } 259 260 for (n = 0; n < 256; n++) |
262 if (rtab->data[n] > qopt->buffer) break; 263 max_size = (n << qopt->rate.cell_log)-1; | 261 if (rtab->data[n] > qopt->buffer) 262 break; 263 max_size = (n << qopt->rate.cell_log) - 1; |
264 if (ptab) { 265 int size; 266 267 for (n = 0; n < 256; n++) | 264 if (ptab) { 265 int size; 266 267 for (n = 0; n < 256; n++) |
268 if (ptab->data[n] > qopt->mtu) break; 269 size = (n << qopt->peakrate.cell_log)-1; 270 if (size < max_size) max_size = size; | 268 if (ptab->data[n] > qopt->mtu) 269 break; 270 size = (n << qopt->peakrate.cell_log) - 1; 271 if (size < max_size) 272 max_size = size; |
271 } 272 if (max_size < 0) 273 goto done; 274 275 if (q->qdisc != &noop_qdisc) { 276 err = fifo_set_limit(q->qdisc, qopt->limit); 277 if (err) 278 goto done; --- 26 unchanged lines hidden (view full) --- 305done: 306 if (rtab) 307 qdisc_put_rtab(rtab); 308 if (ptab) 309 qdisc_put_rtab(ptab); 310 return err; 311} 312 | 273 } 274 if (max_size < 0) 275 goto done; 276 277 if (q->qdisc != &noop_qdisc) { 278 err = fifo_set_limit(q->qdisc, qopt->limit); 279 if (err) 280 goto done; --- 26 unchanged lines hidden (view full) --- 307done: 308 if (rtab) 309 qdisc_put_rtab(rtab); 310 if (ptab) 311 qdisc_put_rtab(ptab); 312 return err; 313} 314 |
313static int tbf_init(struct Qdisc* sch, struct nlattr *opt) | 315static int tbf_init(struct Qdisc *sch, struct nlattr *opt) |
314{ 315 struct tbf_sched_data *q = qdisc_priv(sch); 316 317 if (opt == NULL) 318 return -EINVAL; 319 320 q->t_c = psched_get_time(); 321 qdisc_watchdog_init(&q->watchdog, sch); --- 95 unchanged lines hidden (view full) --- 417 if (walker->fn(sch, 1, walker) < 0) { 418 walker->stop = 1; 419 return; 420 } 421 walker->count++; 422 } 423} 424 | 316{ 317 struct tbf_sched_data *q = qdisc_priv(sch); 318 319 if (opt == NULL) 320 return -EINVAL; 321 322 q->t_c = psched_get_time(); 323 qdisc_watchdog_init(&q->watchdog, sch); --- 95 unchanged lines hidden (view full) --- 419 if (walker->fn(sch, 1, walker) < 0) { 420 walker->stop = 1; 421 return; 422 } 423 walker->count++; 424 } 425} 426 |
425static const struct Qdisc_class_ops tbf_class_ops = 426{ | 427static const struct Qdisc_class_ops tbf_class_ops = { |
427 .graft = tbf_graft, 428 .leaf = tbf_leaf, 429 .get = tbf_get, 430 .put = tbf_put, 431 .walk = tbf_walk, 432 .dump = tbf_dump_class, 433}; 434 --- 29 unchanged lines hidden --- | 428 .graft = tbf_graft, 429 .leaf = tbf_leaf, 430 .get = tbf_get, 431 .put = tbf_put, 432 .walk = tbf_walk, 433 .dump = tbf_dump_class, 434}; 435 --- 29 unchanged lines hidden --- |