iproute2/tc/q_hhf.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/* q_hhf.c              Heavy-Hitter Filter (HHF)
   3 *
   4 * Copyright (C) 2013 Terry Lam <vtlam@google.com>
   5 */
   6#include <stdio.h>
   7#include <stdlib.h>
   8#include <unistd.h>
   9#include <fcntl.h>
  10#include <sys/socket.h>
  11#include <netinet/in.h>
  12#include <arpa/inet.h>
  13#include <string.h>
  14
  15#include "utils.h"
  16#include "tc_util.h"
  17
  18static void explain(void)
  19{
  20        fprintf(stderr,
  21                "Usage: ... hhf [ limit PACKETS ] [ quantum BYTES]\n"
  22                "               [ hh_limit NUMBER ]\n"
  23                "               [ reset_timeout TIME ]\n"
  24                "               [ admit_bytes BYTES ]\n"
  25                "               [ evict_timeout TIME ]\n"
  26                "               [ non_hh_weight NUMBER ]\n");
  27}
  28
  29static int hhf_parse_opt(struct qdisc_util *qu, int argc, char **argv,
  30                         struct nlmsghdr *n, const char *dev)
  31{
  32        unsigned int limit = 0;
  33        unsigned int quantum = 0;
  34        unsigned int hh_limit = 0;
  35        unsigned int reset_timeout = 0;
  36        unsigned int admit_bytes = 0;
  37        unsigned int evict_timeout = 0;
  38        unsigned int non_hh_weight = 0;
  39        struct rtattr *tail;
  40
  41        while (argc > 0) {
  42                if (strcmp(*argv, "limit") == 0) {
  43                        NEXT_ARG();
  44                        if (get_unsigned(&limit, *argv, 0)) {
  45                                fprintf(stderr, "Illegal \"limit\"\n");
  46                                return -1;
  47                        }
  48                } else if (strcmp(*argv, "quantum") == 0) {
  49                        NEXT_ARG();
  50                        if (get_unsigned(&quantum, *argv, 0)) {
  51                                fprintf(stderr, "Illegal \"quantum\"\n");
  52                                return -1;
  53                        }
  54                } else if (strcmp(*argv, "hh_limit") == 0) {
  55                        NEXT_ARG();
  56                        if (get_unsigned(&hh_limit, *argv, 0)) {
  57                                fprintf(stderr, "Illegal \"hh_limit\"\n");
  58                                return -1;
  59                        }
  60                } else if (strcmp(*argv, "reset_timeout") == 0) {
  61                        NEXT_ARG();
  62                        if (get_time(&reset_timeout, *argv)) {
  63                                fprintf(stderr, "Illegal \"reset_timeout\"\n");
  64                                return -1;
  65                        }
  66                } else if (strcmp(*argv, "admit_bytes") == 0) {
  67                        NEXT_ARG();
  68                        if (get_unsigned(&admit_bytes, *argv, 0)) {
  69                                fprintf(stderr, "Illegal \"admit_bytes\"\n");
  70                                return -1;
  71                        }
  72                } else if (strcmp(*argv, "evict_timeout") == 0) {
  73                        NEXT_ARG();
  74                        if (get_time(&evict_timeout, *argv)) {
  75                                fprintf(stderr, "Illegal \"evict_timeout\"\n");
  76                                return -1;
  77                        }
  78                } else if (strcmp(*argv, "non_hh_weight") == 0) {
  79                        NEXT_ARG();
  80                        if (get_unsigned(&non_hh_weight, *argv, 0)) {
  81                                fprintf(stderr, "Illegal \"non_hh_weight\"\n");
  82                                return -1;
  83                        }
  84                } else if (strcmp(*argv, "help") == 0) {
  85                        explain();
  86                        return -1;
  87                } else {
  88                        fprintf(stderr, "What is \"%s\"?\n", *argv);
  89                        explain();
  90                        return -1;
  91                }
  92                argc--; argv++;
  93        }
  94
  95        tail = addattr_nest(n, 1024, TCA_OPTIONS);
  96        if (limit)
  97                addattr_l(n, 1024, TCA_HHF_BACKLOG_LIMIT, &limit,
  98                          sizeof(limit));
  99        if (quantum)
 100                addattr_l(n, 1024, TCA_HHF_QUANTUM, &quantum, sizeof(quantum));
 101        if (hh_limit)
 102                addattr_l(n, 1024, TCA_HHF_HH_FLOWS_LIMIT, &hh_limit,
 103                          sizeof(hh_limit));
 104        if (reset_timeout)
 105                addattr_l(n, 1024, TCA_HHF_RESET_TIMEOUT, &reset_timeout,
 106                          sizeof(reset_timeout));
 107        if (admit_bytes)
 108                addattr_l(n, 1024, TCA_HHF_ADMIT_BYTES, &admit_bytes,
 109                          sizeof(admit_bytes));
 110        if (evict_timeout)
 111                addattr_l(n, 1024, TCA_HHF_EVICT_TIMEOUT, &evict_timeout,
 112                          sizeof(evict_timeout));
 113        if (non_hh_weight)
 114                addattr_l(n, 1024, TCA_HHF_NON_HH_WEIGHT, &non_hh_weight,
 115                          sizeof(non_hh_weight));
 116        addattr_nest_end(n, tail);
 117        return 0;
 118}
 119
 120static int hhf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 121{
 122        struct rtattr *tb[TCA_HHF_MAX + 1];
 123        unsigned int limit;
 124        unsigned int quantum;
 125        unsigned int hh_limit;
 126        unsigned int reset_timeout;
 127        unsigned int admit_bytes;
 128        unsigned int evict_timeout;
 129        unsigned int non_hh_weight;
 130
 131        SPRINT_BUF(b1);
 132
 133        if (opt == NULL)
 134                return 0;
 135
 136        parse_rtattr_nested(tb, TCA_HHF_MAX, opt);
 137
 138        if (tb[TCA_HHF_BACKLOG_LIMIT] &&
 139            RTA_PAYLOAD(tb[TCA_HHF_BACKLOG_LIMIT]) >= sizeof(__u32)) {
 140                limit = rta_getattr_u32(tb[TCA_HHF_BACKLOG_LIMIT]);
 141                print_uint(PRINT_ANY, "limit", "limit %up ", limit);
 142        }
 143        if (tb[TCA_HHF_QUANTUM] &&
 144            RTA_PAYLOAD(tb[TCA_HHF_QUANTUM]) >= sizeof(__u32)) {
 145                quantum = rta_getattr_u32(tb[TCA_HHF_QUANTUM]);
 146                print_size(PRINT_ANY, "quantum", "quantum %s ", quantum);
 147        }
 148        if (tb[TCA_HHF_HH_FLOWS_LIMIT] &&
 149            RTA_PAYLOAD(tb[TCA_HHF_HH_FLOWS_LIMIT]) >= sizeof(__u32)) {
 150                hh_limit = rta_getattr_u32(tb[TCA_HHF_HH_FLOWS_LIMIT]);
 151                print_uint(PRINT_ANY, "hh_limit", "hh_limit %u ", hh_limit);
 152        }
 153        if (tb[TCA_HHF_RESET_TIMEOUT] &&
 154            RTA_PAYLOAD(tb[TCA_HHF_RESET_TIMEOUT]) >= sizeof(__u32)) {
 155                reset_timeout = rta_getattr_u32(tb[TCA_HHF_RESET_TIMEOUT]);
 156                print_uint(PRINT_JSON, "reset_timeout", NULL, reset_timeout);
 157                print_string(PRINT_FP, NULL, "reset_timeout %s ",
 158                             sprint_time(reset_timeout, b1));
 159        }
 160        if (tb[TCA_HHF_ADMIT_BYTES] &&
 161            RTA_PAYLOAD(tb[TCA_HHF_ADMIT_BYTES]) >= sizeof(__u32)) {
 162                admit_bytes = rta_getattr_u32(tb[TCA_HHF_ADMIT_BYTES]);
 163                print_size(PRINT_ANY, "admit_bytes", "admit_bytes %s ",
 164                           admit_bytes);
 165        }
 166        if (tb[TCA_HHF_EVICT_TIMEOUT] &&
 167            RTA_PAYLOAD(tb[TCA_HHF_EVICT_TIMEOUT]) >= sizeof(__u32)) {
 168                evict_timeout = rta_getattr_u32(tb[TCA_HHF_EVICT_TIMEOUT]);
 169                print_uint(PRINT_JSON, "evict_timeout", NULL, evict_timeout);
 170                print_string(PRINT_FP, NULL, "evict_timeout %s ",
 171                             sprint_time(evict_timeout, b1));
 172        }
 173        if (tb[TCA_HHF_NON_HH_WEIGHT] &&
 174            RTA_PAYLOAD(tb[TCA_HHF_NON_HH_WEIGHT]) >= sizeof(__u32)) {
 175                non_hh_weight = rta_getattr_u32(tb[TCA_HHF_NON_HH_WEIGHT]);
 176                print_uint(PRINT_ANY, "non_hh_weight", "non_hh_weight %u ",
 177                           non_hh_weight);
 178        }
 179        return 0;
 180}
 181
 182static int hhf_print_xstats(struct qdisc_util *qu, FILE *f,
 183                            struct rtattr *xstats)
 184{
 185        struct tc_hhf_xstats *st;
 186
 187        if (xstats == NULL)
 188                return 0;
 189
 190        if (RTA_PAYLOAD(xstats) < sizeof(*st))
 191                return -1;
 192
 193        st = RTA_DATA(xstats);
 194
 195        print_uint(PRINT_ANY, "drop_overlimit", "  drop_overlimit %u",
 196                   st->drop_overlimit);
 197        print_uint(PRINT_ANY, "hh_overlimit", " hh_overlimit %u",
 198                   st->hh_overlimit);
 199        print_uint(PRINT_ANY, "tot_hh", " tot_hh %u", st->hh_tot_count);
 200        print_uint(PRINT_ANY, "cur_hh", " cur_hh %u", st->hh_cur_count);
 201
 202        return 0;
 203}
 204
 205struct qdisc_util hhf_qdisc_util = {
 206        .id             = "hhf",
 207        .parse_qopt     = hhf_parse_opt,
 208        .print_qopt     = hhf_print_opt,
 209        .print_xstats   = hhf_print_xstats,
 210};
 211