iproute2/tc/q_sfb.c
<<
>>
Prefs
   1/*
   2 * q_sfb.c      Stochastic Fair Blue.
   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 *
   9 * Authors:     Juliusz Chroboczek <jch@pps.jussieu.fr>
  10 *
  11 */
  12
  13
  14
  15#include <stdio.h>
  16#include <stdlib.h>
  17#include <unistd.h>
  18#include <fcntl.h>
  19#include <sys/socket.h>
  20#include <netinet/in.h>
  21#include <arpa/inet.h>
  22#include <string.h>
  23
  24#include "utils.h"
  25#include "tc_util.h"
  26
  27static void explain(void)
  28{
  29        fprintf(stderr,
  30                "Usage: ... sfb [ rehash SECS ] [ db SECS ]\n"
  31                "           [ limit PACKETS ] [ max PACKETS ] [ target PACKETS ]\n"
  32                "           [ increment FLOAT ] [ decrement FLOAT ]\n"
  33                "           [ penalty_rate PPS ] [ penalty_burst PACKETS ]\n");
  34}
  35
  36static int get_prob(__u32 *val, const char *arg)
  37{
  38        double d;
  39        char *ptr;
  40
  41        if (!arg || !*arg)
  42                return -1;
  43        d = strtod(arg, &ptr);
  44        if (!ptr || ptr == arg || d < 0.0 || d > 1.0)
  45                return -1;
  46        *val = (__u32)(d * SFB_MAX_PROB + 0.5);
  47        return 0;
  48}
  49
  50static int sfb_parse_opt(struct qdisc_util *qu, int argc, char **argv,
  51                         struct nlmsghdr *n, const char *dev)
  52{
  53        struct tc_sfb_qopt opt = {
  54                .rehash_interval = 600*1000,
  55                .warmup_time = 60*1000,
  56                .penalty_rate = 10,
  57                .penalty_burst = 20,
  58                .increment = (SFB_MAX_PROB + 1000) / 2000,
  59                .decrement = (SFB_MAX_PROB + 10000) / 20000,
  60        };
  61        struct rtattr *tail;
  62
  63        while (argc > 0) {
  64            if (strcmp(*argv, "rehash") == 0) {
  65                        NEXT_ARG();
  66                        if (get_u32(&opt.rehash_interval, *argv, 0)) {
  67                                fprintf(stderr, "Illegal \"rehash\"\n");
  68                                return -1;
  69                        }
  70                } else if (strcmp(*argv, "db") == 0) {
  71                        NEXT_ARG();
  72                        if (get_u32(&opt.warmup_time, *argv, 0)) {
  73                                fprintf(stderr, "Illegal \"db\"\n");
  74                                return -1;
  75                        }
  76                } else if (strcmp(*argv, "limit") == 0) {
  77                        NEXT_ARG();
  78                        if (get_u32(&opt.limit, *argv, 0)) {
  79                                fprintf(stderr, "Illegal \"limit\"\n");
  80                                return -1;
  81                        }
  82                } else if (strcmp(*argv, "max") == 0) {
  83                        NEXT_ARG();
  84                        if (get_u32(&opt.max, *argv, 0)) {
  85                                fprintf(stderr, "Illegal \"max\"\n");
  86                                return -1;
  87                        }
  88                } else if (strcmp(*argv, "target") == 0) {
  89                        NEXT_ARG();
  90                        if (get_u32(&opt.bin_size, *argv, 0)) {
  91                                fprintf(stderr, "Illegal \"target\"\n");
  92                                return -1;
  93                        }
  94                } else if (strcmp(*argv, "increment") == 0) {
  95                        NEXT_ARG();
  96                        if (get_prob(&opt.increment, *argv)) {
  97                                fprintf(stderr, "Illegal \"increment\"\n");
  98                                return -1;
  99                        }
 100                } else if (strcmp(*argv, "decrement") == 0) {
 101                        NEXT_ARG();
 102                        if (get_prob(&opt.decrement, *argv)) {
 103                                fprintf(stderr, "Illegal \"decrement\"\n");
 104                                return -1;
 105                        }
 106                } else if (strcmp(*argv, "penalty_rate") == 0) {
 107                        NEXT_ARG();
 108                        if (get_u32(&opt.penalty_rate, *argv, 0)) {
 109                                fprintf(stderr, "Illegal \"penalty_rate\"\n");
 110                                return -1;
 111                        }
 112                } else if (strcmp(*argv, "penalty_burst") == 0) {
 113                        NEXT_ARG();
 114                        if (get_u32(&opt.penalty_burst, *argv, 0)) {
 115                                fprintf(stderr, "Illegal \"penalty_burst\"\n");
 116                                return -1;
 117                        }
 118                } else {
 119                        fprintf(stderr, "What is \"%s\"?\n", *argv);
 120                        explain();
 121                        return -1;
 122                }
 123                argc--; argv++;
 124        }
 125
 126        if (opt.max == 0) {
 127                if (opt.bin_size >= 1)
 128                        opt.max = (opt.bin_size * 5 + 1) / 4;
 129                else
 130                        opt.max = 25;
 131        }
 132        if (opt.bin_size == 0)
 133                opt.bin_size = (opt.max * 4 + 3) / 5;
 134
 135        tail = addattr_nest(n, 1024, TCA_OPTIONS);
 136        addattr_l(n, 1024, TCA_SFB_PARMS, &opt, sizeof(opt));
 137        addattr_nest_end(n, tail);
 138        return 0;
 139}
 140
 141static int sfb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 142{
 143        struct rtattr *tb[__TCA_SFB_MAX];
 144        struct tc_sfb_qopt *qopt;
 145
 146        SPRINT_BUF(b1);
 147
 148        if (opt == NULL)
 149                return 0;
 150
 151        parse_rtattr_nested(tb, TCA_SFB_MAX, opt);
 152        if (tb[TCA_SFB_PARMS] == NULL)
 153                return -1;
 154        qopt = RTA_DATA(tb[TCA_SFB_PARMS]);
 155        if (RTA_PAYLOAD(tb[TCA_SFB_PARMS]) < sizeof(*qopt))
 156                return -1;
 157
 158        print_uint(PRINT_JSON, "rehash", NULL, qopt->rehash_interval * 1000);
 159        print_string(PRINT_FP, NULL, "rehash %s ",
 160                     sprint_time(qopt->rehash_interval * 1000, b1));
 161
 162        print_uint(PRINT_JSON, "db", NULL, qopt->warmup_time * 1000);
 163        print_string(PRINT_FP, NULL, "db %s ",
 164                     sprint_time(qopt->warmup_time * 1000, b1));
 165
 166        print_uint(PRINT_ANY, "limit", "limit %up ", qopt->limit);
 167        print_uint(PRINT_ANY, "max", "max %up ", qopt->max);
 168        print_uint(PRINT_ANY, "target", "target %up ", qopt->bin_size);
 169
 170        print_float(PRINT_ANY, "increment", "increment %lg ",
 171                    (double)qopt->increment / SFB_MAX_PROB);
 172        print_float(PRINT_ANY, "decrement", "decrement %lg ",
 173                    (double)qopt->decrement / SFB_MAX_PROB);
 174
 175        print_uint(PRINT_ANY, "penalty_rate", "penalty_rate %upps ",
 176                   qopt->penalty_rate);
 177        print_uint(PRINT_ANY, "penalty_burst", "penalty_burst %up ",
 178                   qopt->penalty_burst);
 179
 180        return 0;
 181}
 182
 183static int sfb_print_xstats(struct qdisc_util *qu, FILE *f,
 184                            struct rtattr *xstats)
 185{
 186        struct tc_sfb_xstats *st;
 187
 188        if (xstats == NULL)
 189                return 0;
 190
 191        if (RTA_PAYLOAD(xstats) < sizeof(*st))
 192                return -1;
 193
 194        st = RTA_DATA(xstats);
 195
 196        print_uint(PRINT_ANY, "earlydrop", "  earlydrop %u", st->earlydrop);
 197        print_uint(PRINT_ANY, "penaltydrop", " penaltydrop %u",
 198                   st->penaltydrop);
 199        print_uint(PRINT_ANY, "bucketdrop", " bucketdrop %u", st->bucketdrop);
 200        print_uint(PRINT_ANY, "queuedrop", " queuedrop %u", st->queuedrop);
 201        print_uint(PRINT_ANY, "childdrop", " childdrop %u", st->childdrop);
 202        print_uint(PRINT_ANY, "marked", " marked %u", st->marked);
 203        print_nl();
 204        print_uint(PRINT_ANY, "maxqlen", "  maxqlen %u", st->maxqlen);
 205
 206        print_float(PRINT_ANY, "maxprob", " maxprob %lg",
 207                    (double)st->maxprob / SFB_MAX_PROB);
 208        print_float(PRINT_ANY, "avgprob", " avgprob %lg",
 209                    (double)st->avgprob / SFB_MAX_PROB);
 210
 211        return 0;
 212}
 213
 214struct qdisc_util sfb_qdisc_util = {
 215        .id             = "sfb",
 216        .parse_qopt     = sfb_parse_opt,
 217        .print_qopt     = sfb_print_opt,
 218        .print_xstats   = sfb_print_xstats,
 219};
 220