diff options
author | Thomas Graf <tgraf@suug.ch> | 2005-11-05 15:14:15 -0500 |
---|---|---|
committer | Thomas Graf <tgr@axs.localdomain> | 2005-11-05 16:02:27 -0500 |
commit | f62d6b936df500247474c13360eb23e1b602bad0 (patch) | |
tree | 2517635e3005c5bcdc50d6a0f719d7a5df1815ea | |
parent | a8aaa9958eea2420e13d5a00c3fae934e0a3889e (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>
-rw-r--r-- | net/sched/sch_gred.c | 173 |
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 | |||
61 | struct gred_sched_data; | 63 | struct gred_sched_data; |
62 | struct gred_sched; | 64 | struct 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 | ||
435 | static int gred_change(struct Qdisc *sch, struct rtattr *opt) | 437 | static 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 | |||
476 | static 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 | ||
542 | errout_locked: | ||
543 | sch_tree_unlock(sch); | ||
544 | errout: | ||
545 | return err; | ||
551 | } | 546 | } |
552 | 547 | ||
553 | static int gred_init(struct Qdisc *sch, struct rtattr *opt) | 548 | static int gred_init(struct Qdisc *sch, struct rtattr *opt) |