iproute2/tc/q_pie.c
<<
>>
Prefs
   1/* Copyright (C) 2013 Cisco Systems, Inc, 2013.
   2 *
   3 * This program is free software; you can redistribute it and/or
   4 * modify it under the terms of the GNU General Public License
   5 * as published by the Free Software Foundation; either version 2
   6 * of the License.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 *
  13 * Author: Vijay Subramanian <vijaynsu@cisco.com>
  14 * Author: Mythili Prabhu <mysuryan@cisco.com>
  15 *
  16 */
  17
  18#include <stdio.h>
  19#include <stdlib.h>
  20#include <unistd.h>
  21#include <fcntl.h>
  22#include <sys/socket.h>
  23#include <netinet/in.h>
  24#include <arpa/inet.h>
  25#include <string.h>
  26#include <math.h>
  27
  28#include "utils.h"
  29#include "tc_util.h"
  30
  31static void explain(void)
  32{
  33        fprintf(stderr,
  34                "Usage: ... pie [ limit PACKETS ] [ target TIME ]\n"
  35                "               [ tupdate TIME ] [ alpha ALPHA ] [ beta BETA ]\n"
  36                "               [ bytemode | nobytemode ] [ ecn | noecn ]\n"
  37                "               [ dq_rate_estimator | no_dq_rate_estimator ]\n");
  38}
  39
  40#define ALPHA_MAX 32
  41#define BETA_MAX 32
  42
  43static int pie_parse_opt(struct qdisc_util *qu, int argc, char **argv,
  44                         struct nlmsghdr *n, const char *dev)
  45{
  46        unsigned int limit   = 0;
  47        unsigned int target  = 0;
  48        unsigned int tupdate = 0;
  49        unsigned int alpha   = 0;
  50        unsigned int beta    = 0;
  51        int ecn = -1;
  52        int bytemode = -1;
  53        int dq_rate_estimator = -1;
  54        struct rtattr *tail;
  55
  56        while (argc > 0) {
  57                if (strcmp(*argv, "limit") == 0) {
  58                        NEXT_ARG();
  59                        if (get_unsigned(&limit, *argv, 0)) {
  60                                fprintf(stderr, "Illegal \"limit\"\n");
  61                                return -1;
  62                        }
  63                } else if (strcmp(*argv, "target") == 0) {
  64                        NEXT_ARG();
  65                        if (get_time(&target, *argv)) {
  66                                fprintf(stderr, "Illegal \"target\"\n");
  67                                return -1;
  68                        }
  69                } else if (strcmp(*argv, "tupdate") == 0) {
  70                        NEXT_ARG();
  71                        if (get_time(&tupdate, *argv)) {
  72                                fprintf(stderr, "Illegal \"tupdate\"\n");
  73                                return -1;
  74                        }
  75                } else if (strcmp(*argv, "alpha") == 0) {
  76                        NEXT_ARG();
  77                        if (get_unsigned(&alpha, *argv, 0) ||
  78                            (alpha > ALPHA_MAX)) {
  79                                fprintf(stderr, "Illegal \"alpha\"\n");
  80                                return -1;
  81                        }
  82                } else if (strcmp(*argv, "beta") == 0) {
  83                        NEXT_ARG();
  84                        if (get_unsigned(&beta, *argv, 0) ||
  85                            (beta > BETA_MAX)) {
  86                                fprintf(stderr, "Illegal \"beta\"\n");
  87                                return -1;
  88                        }
  89                } else if (strcmp(*argv, "ecn") == 0) {
  90                        ecn = 1;
  91                } else if (strcmp(*argv, "noecn") == 0) {
  92                        ecn = 0;
  93                } else if (strcmp(*argv, "bytemode") == 0) {
  94                        bytemode = 1;
  95                } else if (strcmp(*argv, "nobytemode") == 0) {
  96                        bytemode = 0;
  97                } else if (strcmp(*argv, "dq_rate_estimator") == 0) {
  98                        dq_rate_estimator = 1;
  99                } else if (strcmp(*argv, "no_dq_rate_estimator") == 0) {
 100                        dq_rate_estimator = 0;
 101                } else if (strcmp(*argv, "help") == 0) {
 102                        explain();
 103                        return -1;
 104                } else {
 105                        fprintf(stderr, "What is \"%s\"?\n", *argv);
 106                        explain();
 107                        return -1;
 108                }
 109                argc--;
 110                argv++;
 111        }
 112
 113        tail = addattr_nest(n, 1024, TCA_OPTIONS);
 114        if (limit)
 115                addattr_l(n, 1024, TCA_PIE_LIMIT, &limit, sizeof(limit));
 116        if (tupdate)
 117                addattr_l(n, 1024, TCA_PIE_TUPDATE, &tupdate, sizeof(tupdate));
 118        if (target)
 119                addattr_l(n, 1024, TCA_PIE_TARGET, &target, sizeof(target));
 120        if (alpha)
 121                addattr_l(n, 1024, TCA_PIE_ALPHA, &alpha, sizeof(alpha));
 122        if (beta)
 123                addattr_l(n, 1024, TCA_PIE_BETA, &beta, sizeof(beta));
 124        if (ecn != -1)
 125                addattr_l(n, 1024, TCA_PIE_ECN, &ecn, sizeof(ecn));
 126        if (bytemode != -1)
 127                addattr_l(n, 1024, TCA_PIE_BYTEMODE, &bytemode,
 128                          sizeof(bytemode));
 129        if (dq_rate_estimator != -1)
 130                addattr_l(n, 1024, TCA_PIE_DQ_RATE_ESTIMATOR,
 131                          &dq_rate_estimator, sizeof(dq_rate_estimator));
 132
 133        addattr_nest_end(n, tail);
 134        return 0;
 135}
 136
 137static int pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 138{
 139        struct rtattr *tb[TCA_PIE_MAX + 1];
 140        unsigned int limit;
 141        unsigned int tupdate;
 142        unsigned int target;
 143        unsigned int alpha;
 144        unsigned int beta;
 145        unsigned int ecn;
 146        unsigned int bytemode;
 147        unsigned int dq_rate_estimator;
 148
 149        SPRINT_BUF(b1);
 150
 151        if (opt == NULL)
 152                return 0;
 153
 154        parse_rtattr_nested(tb, TCA_PIE_MAX, opt);
 155
 156        if (tb[TCA_PIE_LIMIT] &&
 157            RTA_PAYLOAD(tb[TCA_PIE_LIMIT]) >= sizeof(__u32)) {
 158                limit = rta_getattr_u32(tb[TCA_PIE_LIMIT]);
 159                print_uint(PRINT_ANY, "limit", "limit %up ", limit);
 160        }
 161        if (tb[TCA_PIE_TARGET] &&
 162            RTA_PAYLOAD(tb[TCA_PIE_TARGET]) >= sizeof(__u32)) {
 163                target = rta_getattr_u32(tb[TCA_PIE_TARGET]);
 164                print_uint(PRINT_JSON, "target", NULL, target);
 165                print_string(PRINT_FP, NULL, "target %s ",
 166                             sprint_time(target, b1));
 167        }
 168        if (tb[TCA_PIE_TUPDATE] &&
 169            RTA_PAYLOAD(tb[TCA_PIE_TUPDATE]) >= sizeof(__u32)) {
 170                tupdate = rta_getattr_u32(tb[TCA_PIE_TUPDATE]);
 171                print_uint(PRINT_JSON, "tupdate", NULL, tupdate);
 172                print_string(PRINT_FP, NULL, "tupdate %s ",
 173                             sprint_time(tupdate, b1));
 174        }
 175        if (tb[TCA_PIE_ALPHA] &&
 176            RTA_PAYLOAD(tb[TCA_PIE_ALPHA]) >= sizeof(__u32)) {
 177                alpha = rta_getattr_u32(tb[TCA_PIE_ALPHA]);
 178                print_uint(PRINT_ANY, "alpha", "alpha %u ", alpha);
 179        }
 180        if (tb[TCA_PIE_BETA] &&
 181            RTA_PAYLOAD(tb[TCA_PIE_BETA]) >= sizeof(__u32)) {
 182                beta = rta_getattr_u32(tb[TCA_PIE_BETA]);
 183                print_uint(PRINT_ANY, "beta", "beta %u ", beta);
 184        }
 185
 186        if (tb[TCA_PIE_ECN] && RTA_PAYLOAD(tb[TCA_PIE_ECN]) >= sizeof(__u32)) {
 187                ecn = rta_getattr_u32(tb[TCA_PIE_ECN]);
 188                if (ecn)
 189                        print_bool(PRINT_ANY, "ecn", "ecn ", true);
 190        }
 191
 192        if (tb[TCA_PIE_BYTEMODE] &&
 193            RTA_PAYLOAD(tb[TCA_PIE_BYTEMODE]) >= sizeof(__u32)) {
 194                bytemode = rta_getattr_u32(tb[TCA_PIE_BYTEMODE]);
 195                if (bytemode)
 196                        print_bool(PRINT_ANY, "bytemode", "bytemode ", true);
 197        }
 198
 199        if (tb[TCA_PIE_DQ_RATE_ESTIMATOR] &&
 200            RTA_PAYLOAD(tb[TCA_PIE_DQ_RATE_ESTIMATOR]) >= sizeof(__u32)) {
 201                dq_rate_estimator =
 202                                rta_getattr_u32(tb[TCA_PIE_DQ_RATE_ESTIMATOR]);
 203                if (dq_rate_estimator)
 204                        print_bool(PRINT_ANY, "dq_rate_estimator",
 205                                   "dq_rate_estimator ", true);
 206        }
 207
 208        return 0;
 209}
 210
 211static int pie_print_xstats(struct qdisc_util *qu, FILE *f,
 212                            struct rtattr *xstats)
 213{
 214        struct tc_pie_xstats *st;
 215
 216        SPRINT_BUF(b1);
 217
 218        if (xstats == NULL)
 219                return 0;
 220
 221        if (RTA_PAYLOAD(xstats) < sizeof(*st))
 222                return -1;
 223
 224        st = RTA_DATA(xstats);
 225
 226        /* prob is returned as a fracion of maximum integer value */
 227        print_float(PRINT_ANY, "prob", "  prob %lg",
 228                    (double)st->prob / (double)UINT64_MAX);
 229        print_uint(PRINT_JSON, "delay", NULL, st->delay);
 230        print_string(PRINT_FP, NULL, " delay %s", sprint_time(st->delay, b1));
 231
 232        if (st->dq_rate_estimating)
 233                print_uint(PRINT_ANY, "avg_dq_rate", " avg_dq_rate %u",
 234                           st->avg_dq_rate);
 235
 236        print_nl();
 237        print_uint(PRINT_ANY, "pkts_in", "  pkts_in %u", st->packets_in);
 238        print_uint(PRINT_ANY, "overlimit", " overlimit %u", st->overlimit);
 239        print_uint(PRINT_ANY, "dropped", " dropped %u", st->dropped);
 240        print_uint(PRINT_ANY, "maxq", " maxq %u", st->maxq);
 241        print_uint(PRINT_ANY, "ecn_mark", " ecn_mark %u", st->ecn_mark);
 242
 243        return 0;
 244
 245}
 246
 247struct qdisc_util pie_qdisc_util = {
 248        .id = "pie",
 249        .parse_qopt     = pie_parse_opt,
 250        .print_qopt     = pie_print_opt,
 251        .print_xstats   = pie_print_xstats,
 252};
 253