diff options
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r-- | net/sched/sch_generic.c | 84 |
1 files changed, 34 insertions, 50 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 87e48a4e1051..7683b34dc6a9 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -243,31 +243,27 @@ static void dev_watchdog_down(struct net_device *dev) | |||
243 | cheaper. | 243 | cheaper. |
244 | */ | 244 | */ |
245 | 245 | ||
246 | static int | 246 | static int noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc) |
247 | noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc) | ||
248 | { | 247 | { |
249 | kfree_skb(skb); | 248 | kfree_skb(skb); |
250 | return NET_XMIT_CN; | 249 | return NET_XMIT_CN; |
251 | } | 250 | } |
252 | 251 | ||
253 | static struct sk_buff * | 252 | static struct sk_buff *noop_dequeue(struct Qdisc * qdisc) |
254 | noop_dequeue(struct Qdisc * qdisc) | ||
255 | { | 253 | { |
256 | return NULL; | 254 | return NULL; |
257 | } | 255 | } |
258 | 256 | ||
259 | static int | 257 | static int noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc) |
260 | noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc) | ||
261 | { | 258 | { |
262 | if (net_ratelimit()) | 259 | if (net_ratelimit()) |
263 | printk(KERN_DEBUG "%s deferred output. It is buggy.\n", skb->dev->name); | 260 | printk(KERN_DEBUG "%s deferred output. It is buggy.\n", |
261 | skb->dev->name); | ||
264 | kfree_skb(skb); | 262 | kfree_skb(skb); |
265 | return NET_XMIT_CN; | 263 | return NET_XMIT_CN; |
266 | } | 264 | } |
267 | 265 | ||
268 | struct Qdisc_ops noop_qdisc_ops = { | 266 | struct Qdisc_ops noop_qdisc_ops = { |
269 | .next = NULL, | ||
270 | .cl_ops = NULL, | ||
271 | .id = "noop", | 267 | .id = "noop", |
272 | .priv_size = 0, | 268 | .priv_size = 0, |
273 | .enqueue = noop_enqueue, | 269 | .enqueue = noop_enqueue, |
@@ -285,8 +281,6 @@ struct Qdisc noop_qdisc = { | |||
285 | }; | 281 | }; |
286 | 282 | ||
287 | static struct Qdisc_ops noqueue_qdisc_ops = { | 283 | static struct Qdisc_ops noqueue_qdisc_ops = { |
288 | .next = NULL, | ||
289 | .cl_ops = NULL, | ||
290 | .id = "noqueue", | 284 | .id = "noqueue", |
291 | .priv_size = 0, | 285 | .priv_size = 0, |
292 | .enqueue = noop_enqueue, | 286 | .enqueue = noop_enqueue, |
@@ -311,97 +305,87 @@ static const u8 prio2band[TC_PRIO_MAX+1] = | |||
311 | generic prio+fifo combination. | 305 | generic prio+fifo combination. |
312 | */ | 306 | */ |
313 | 307 | ||
314 | static int | 308 | #define PFIFO_FAST_BANDS 3 |
315 | pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) | 309 | |
310 | static inline struct sk_buff_head *prio2list(struct sk_buff *skb, | ||
311 | struct Qdisc *qdisc) | ||
316 | { | 312 | { |
317 | struct sk_buff_head *list = qdisc_priv(qdisc); | 313 | struct sk_buff_head *list = qdisc_priv(qdisc); |
314 | return list + prio2band[skb->priority & TC_PRIO_MAX]; | ||
315 | } | ||
318 | 316 | ||
319 | list += prio2band[skb->priority&TC_PRIO_MAX]; | 317 | static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) |
318 | { | ||
319 | struct sk_buff_head *list = prio2list(skb, qdisc); | ||
320 | 320 | ||
321 | if (list->qlen < qdisc->dev->tx_queue_len) { | 321 | if (skb_queue_len(list) < qdisc->dev->tx_queue_len) { |
322 | __skb_queue_tail(list, skb); | ||
323 | qdisc->q.qlen++; | 322 | qdisc->q.qlen++; |
324 | qdisc->bstats.bytes += skb->len; | 323 | return __qdisc_enqueue_tail(skb, qdisc, list); |
325 | qdisc->bstats.packets++; | ||
326 | return 0; | ||
327 | } | 324 | } |
328 | qdisc->qstats.drops++; | 325 | |
329 | kfree_skb(skb); | 326 | return qdisc_drop(skb, qdisc); |
330 | return NET_XMIT_DROP; | ||
331 | } | 327 | } |
332 | 328 | ||
333 | static struct sk_buff * | 329 | static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc) |
334 | pfifo_fast_dequeue(struct Qdisc* qdisc) | ||
335 | { | 330 | { |
336 | int prio; | 331 | int prio; |
337 | struct sk_buff_head *list = qdisc_priv(qdisc); | 332 | struct sk_buff_head *list = qdisc_priv(qdisc); |
338 | struct sk_buff *skb; | ||
339 | 333 | ||
340 | for (prio = 0; prio < 3; prio++, list++) { | 334 | for (prio = 0; prio < PFIFO_FAST_BANDS; prio++, list++) { |
341 | skb = __skb_dequeue(list); | 335 | struct sk_buff *skb = __qdisc_dequeue_head(qdisc, list); |
342 | if (skb) { | 336 | if (skb) { |
343 | qdisc->q.qlen--; | 337 | qdisc->q.qlen--; |
344 | return skb; | 338 | return skb; |
345 | } | 339 | } |
346 | } | 340 | } |
341 | |||
347 | return NULL; | 342 | return NULL; |
348 | } | 343 | } |
349 | 344 | ||
350 | static int | 345 | static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc) |
351 | pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc) | ||
352 | { | 346 | { |
353 | struct sk_buff_head *list = qdisc_priv(qdisc); | ||
354 | |||
355 | list += prio2band[skb->priority&TC_PRIO_MAX]; | ||
356 | |||
357 | __skb_queue_head(list, skb); | ||
358 | qdisc->q.qlen++; | 347 | qdisc->q.qlen++; |
359 | qdisc->qstats.requeues++; | 348 | return __qdisc_requeue(skb, qdisc, prio2list(skb, qdisc)); |
360 | return 0; | ||
361 | } | 349 | } |
362 | 350 | ||
363 | static void | 351 | static void pfifo_fast_reset(struct Qdisc* qdisc) |
364 | pfifo_fast_reset(struct Qdisc* qdisc) | ||
365 | { | 352 | { |
366 | int prio; | 353 | int prio; |
367 | struct sk_buff_head *list = qdisc_priv(qdisc); | 354 | struct sk_buff_head *list = qdisc_priv(qdisc); |
368 | 355 | ||
369 | for (prio=0; prio < 3; prio++) | 356 | for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) |
370 | skb_queue_purge(list+prio); | 357 | __qdisc_reset_queue(qdisc, list + prio); |
358 | |||
359 | qdisc->qstats.backlog = 0; | ||
371 | qdisc->q.qlen = 0; | 360 | qdisc->q.qlen = 0; |
372 | } | 361 | } |
373 | 362 | ||
374 | static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb) | 363 | static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb) |
375 | { | 364 | { |
376 | unsigned char *b = skb->tail; | 365 | struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS }; |
377 | struct tc_prio_qopt opt; | ||
378 | 366 | ||
379 | opt.bands = 3; | ||
380 | memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1); | 367 | memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1); |
381 | RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | 368 | RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); |
382 | return skb->len; | 369 | return skb->len; |
383 | 370 | ||
384 | rtattr_failure: | 371 | rtattr_failure: |
385 | skb_trim(skb, b - skb->data); | ||
386 | return -1; | 372 | return -1; |
387 | } | 373 | } |
388 | 374 | ||
389 | static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt) | 375 | static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt) |
390 | { | 376 | { |
391 | int i; | 377 | int prio; |
392 | struct sk_buff_head *list = qdisc_priv(qdisc); | 378 | struct sk_buff_head *list = qdisc_priv(qdisc); |
393 | 379 | ||
394 | for (i=0; i<3; i++) | 380 | for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) |
395 | skb_queue_head_init(list+i); | 381 | skb_queue_head_init(list + prio); |
396 | 382 | ||
397 | return 0; | 383 | return 0; |
398 | } | 384 | } |
399 | 385 | ||
400 | static struct Qdisc_ops pfifo_fast_ops = { | 386 | static struct Qdisc_ops pfifo_fast_ops = { |
401 | .next = NULL, | ||
402 | .cl_ops = NULL, | ||
403 | .id = "pfifo_fast", | 387 | .id = "pfifo_fast", |
404 | .priv_size = 3 * sizeof(struct sk_buff_head), | 388 | .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head), |
405 | .enqueue = pfifo_fast_enqueue, | 389 | .enqueue = pfifo_fast_enqueue, |
406 | .dequeue = pfifo_fast_dequeue, | 390 | .dequeue = pfifo_fast_dequeue, |
407 | .requeue = pfifo_fast_requeue, | 391 | .requeue = pfifo_fast_requeue, |