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 ---