aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_gred.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2005-11-05 15:14:15 -0500
committerThomas Graf <tgr@axs.localdomain>2005-11-05 16:02:27 -0500
commitf62d6b936df500247474c13360eb23e1b602bad0 (patch)
tree2517635e3005c5bcdc50d6a0f719d7a5df1815ea /net/sched/sch_gred.c
parenta8aaa9958eea2420e13d5a00c3fae934e0a3889e (diff)
[PKT_SCHED]: GRED: Use central VQ change procedure
Introduces a function gred_change_vq() acting as a central point to change VQ parameters. Fixes priority inheritance in rio mode when the default DP equals 0. Adds proper locking during changes. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Diffstat (limited to 'net/sched/sch_gred.c')
-rw-r--r--net/sched/sch_gred.c173
1 files changed, 84 insertions, 89 deletions
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index b04b07fcc2cf..ca6cb271493b 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -58,6 +58,8 @@
58#define D2PRINTK(format,args...) 58#define D2PRINTK(format,args...)
59#endif 59#endif
60 60
61#define GRED_DEF_PRIO (MAX_DPs / 2)
62
61struct gred_sched_data; 63struct gred_sched_data;
62struct gred_sched; 64struct gred_sched;
63 65
@@ -432,77 +434,102 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps)
432 return 0; 434 return 0;
433} 435}
434 436
435static int gred_change(struct Qdisc *sch, struct rtattr *opt) 437static inline int gred_change_vq(struct Qdisc *sch, int dp,
438 struct tc_gred_qopt *ctl, int prio, u8 *stab)
436{ 439{
437 struct gred_sched *table = qdisc_priv(sch); 440 struct gred_sched *table = qdisc_priv(sch);
438 struct gred_sched_data *q; 441 struct gred_sched_data *q;
442
443 if (table->tab[dp] == NULL) {
444 table->tab[dp] = kmalloc(sizeof(*q), GFP_KERNEL);
445 if (table->tab[dp] == NULL)
446 return -ENOMEM;
447 memset(table->tab[dp], 0, sizeof(*q));
448 }
449
450 q = table->tab[dp];
451 q->DP = dp;
452 q->prio = prio;
453
454 q->Wlog = ctl->Wlog;
455 q->Plog = ctl->Plog;
456 q->limit = ctl->limit;
457 q->Scell_log = ctl->Scell_log;
458 q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
459 q->Scell_max = (255<<q->Scell_log);
460 q->qth_min = ctl->qth_min<<ctl->Wlog;
461 q->qth_max = ctl->qth_max<<ctl->Wlog;
462 q->qave=0;
463 q->backlog=0;
464 q->qcount = -1;
465 q->other=0;
466 q->forced=0;
467 q->pdrop=0;
468 q->early=0;
469
470 PSCHED_SET_PASTPERFECT(q->qidlestart);
471 memcpy(q->Stab, stab, 256);
472
473 return 0;
474}
475
476static int gred_change(struct Qdisc *sch, struct rtattr *opt)
477{
478 struct gred_sched *table = qdisc_priv(sch);
439 struct tc_gred_qopt *ctl; 479 struct tc_gred_qopt *ctl;
440 struct rtattr *tb[TCA_GRED_STAB]; 480 struct rtattr *tb[TCA_GRED_MAX];
481 int err = -EINVAL, prio = GRED_DEF_PRIO;
482 u8 *stab;
441 483
442 if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt)) 484 if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_MAX, opt))
443 return -EINVAL; 485 return -EINVAL;
444 486
445 if (tb[TCA_GRED_PARMS-1] == NULL && tb[TCA_GRED_STAB-1] == NULL) 487 if (tb[TCA_GRED_PARMS-1] == NULL && tb[TCA_GRED_STAB-1] == NULL)
446 return gred_change_table_def(sch, tb[TCA_GRED_DPS-1]); 488 return gred_change_table_def(sch, opt);
447 489
448 if (!table->DPs || tb[TCA_GRED_PARMS-1] == 0 || tb[TCA_GRED_STAB-1] == 0 || 490 if (tb[TCA_GRED_PARMS-1] == NULL ||
449 RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) || 491 RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) ||
450 RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256) 492 tb[TCA_GRED_STAB-1] == NULL ||
451 return -EINVAL; 493 RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256)
494 return -EINVAL;
452 495
453 ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]); 496 ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]);
497 stab = RTA_DATA(tb[TCA_GRED_STAB-1]);
454 498
455 if (ctl->DP >= table->DPs) 499 if (ctl->DP >= table->DPs)
456 return -EINVAL; 500 goto errout;
457
458 if (table->tab[ctl->DP] == NULL) {
459 table->tab[ctl->DP]=kmalloc(sizeof(struct gred_sched_data),
460 GFP_KERNEL);
461 if (NULL == table->tab[ctl->DP])
462 return -ENOMEM;
463 memset(table->tab[ctl->DP], 0, (sizeof(struct gred_sched_data)));
464 }
465 q= table->tab[ctl->DP];
466 501
467 if (gred_rio_mode(table)) { 502 if (gred_rio_mode(table)) {
468 if (ctl->prio <=0) { 503 if (ctl->prio == 0) {
469 if (table->def && table->tab[table->def]) { 504 int def_prio = GRED_DEF_PRIO;
470 DPRINTK("\nGRED: DP %u does not have a prio" 505
471 "setting default to %d\n",ctl->DP, 506 if (table->tab[table->def])
472 table->tab[table->def]->prio); 507 def_prio = table->tab[table->def]->prio;
473 q->prio=table->tab[table->def]->prio; 508
474 } else { 509 printk(KERN_DEBUG "GRED: DP %u does not have a prio "
475 DPRINTK("\nGRED: DP %u does not have a prio" 510 "setting default to %d\n", ctl->DP, def_prio);
476 " setting default to 8\n",ctl->DP); 511
477 q->prio=8; 512 prio = def_prio;
478 } 513 } else
479 } else { 514 prio = ctl->prio;
480 q->prio=ctl->prio;
481 }
482 } else {
483 q->prio=8;
484 } 515 }
485 516
517 sch_tree_lock(sch);
486 518
487 q->DP=ctl->DP; 519 err = gred_change_vq(sch, ctl->DP, ctl, prio, stab);
488 q->Wlog = ctl->Wlog; 520 if (err < 0)
489 q->Plog = ctl->Plog; 521 goto errout_locked;
490 q->limit = ctl->limit;
491 q->Scell_log = ctl->Scell_log;
492 q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
493 q->Scell_max = (255<<q->Scell_log);
494 q->qth_min = ctl->qth_min<<ctl->Wlog;
495 q->qth_max = ctl->qth_max<<ctl->Wlog;
496 q->qave=0;
497 q->backlog=0;
498 q->qcount = -1;
499 q->other=0;
500 q->forced=0;
501 q->pdrop=0;
502 q->early=0;
503 522
504 PSCHED_SET_PASTPERFECT(q->qidlestart); 523 if (table->tab[table->def] == NULL) {
505 memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256); 524 if (gred_rio_mode(table))
525 prio = table->tab[ctl->DP]->prio;
526
527 err = gred_change_vq(sch, table->def, ctl, prio, stab);
528 if (err < 0)
529 goto errout_locked;
530 }
531
532 table->initd = 1;
506 533
507 if (gred_rio_mode(table)) { 534 if (gred_rio_mode(table)) {
508 gred_disable_wred_mode(table); 535 gred_disable_wred_mode(table);
@@ -510,44 +537,12 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt)
510 gred_enable_wred_mode(table); 537 gred_enable_wred_mode(table);
511 } 538 }
512 539
513 if (!table->initd) { 540 err = 0;
514 table->initd=1;
515 /*
516 the first entry also goes into the default until
517 over-written
518 */
519
520 if (table->tab[table->def] == NULL) {
521 table->tab[table->def]=
522 kmalloc(sizeof(struct gred_sched_data), GFP_KERNEL);
523 if (NULL == table->tab[table->def])
524 return -ENOMEM;
525
526 memset(table->tab[table->def], 0,
527 (sizeof(struct gred_sched_data)));
528 }
529 q= table->tab[table->def];
530 q->DP=table->def;
531 q->Wlog = ctl->Wlog;
532 q->Plog = ctl->Plog;
533 q->limit = ctl->limit;
534 q->Scell_log = ctl->Scell_log;
535 q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
536 q->Scell_max = (255<<q->Scell_log);
537 q->qth_min = ctl->qth_min<<ctl->Wlog;
538 q->qth_max = ctl->qth_max<<ctl->Wlog;
539
540 if (gred_rio_mode(table))
541 q->prio=table->tab[ctl->DP]->prio;
542 else
543 q->prio=8;
544
545 q->qcount = -1;
546 PSCHED_SET_PASTPERFECT(q->qidlestart);
547 memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256);
548 }
549 return 0;
550 541
542errout_locked:
543 sch_tree_unlock(sch);
544errout:
545 return err;
551} 546}
552 547
553static int gred_init(struct Qdisc *sch, struct rtattr *opt) 548static int gred_init(struct Qdisc *sch, struct rtattr *opt)