iproute2/tc/f_matchall.c
<<
>>
Prefs
   1/*
   2 * f_matchall.c         Match-all Classifier
   3 *
   4 *              This program is free software; you can distribute 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:     Jiri Pirko <jiri@mellanox.com>, Yotam Gigi <yotamg@mellanox.com>
  10 *
  11 */
  12
  13#include <stdio.h>
  14#include <stdlib.h>
  15#include <unistd.h>
  16#include <fcntl.h>
  17#include <sys/socket.h>
  18#include <netinet/in.h>
  19#include <arpa/inet.h>
  20#include <string.h>
  21#include <linux/if.h>
  22
  23#include "utils.h"
  24#include "tc_util.h"
  25
  26static void explain(void)
  27{
  28        fprintf(stderr,
  29                "Usage: ... matchall [skip_sw | skip_hw]\n"
  30                "                 [ action ACTION_SPEC ] [ classid CLASSID ]\n"
  31                "\n"
  32                "Where: SELECTOR := SAMPLE SAMPLE ...\n"
  33                "       FILTERID := X:Y:Z\n"
  34                "       ACTION_SPEC := ... look at individual actions\n"
  35                "\n"
  36                "NOTE: CLASSID is parsed as hexadecimal input.\n");
  37}
  38
  39static int matchall_parse_opt(struct filter_util *qu, char *handle,
  40                           int argc, char **argv, struct nlmsghdr *n)
  41{
  42        struct tcmsg *t = NLMSG_DATA(n);
  43        struct rtattr *tail;
  44        __u32 flags = 0;
  45        long h = 0;
  46
  47        if (handle) {
  48                h = strtol(handle, NULL, 0);
  49                if (h == LONG_MIN || h == LONG_MAX) {
  50                        fprintf(stderr, "Illegal handle \"%s\", must be numeric.\n",
  51                            handle);
  52                        return -1;
  53                }
  54        }
  55        t->tcm_handle = h;
  56
  57        if (argc == 0)
  58                return 0;
  59
  60        tail = (struct rtattr *)(((void *)n)+NLMSG_ALIGN(n->nlmsg_len));
  61        addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
  62
  63        while (argc > 0) {
  64                if (matches(*argv, "classid") == 0 ||
  65                           strcmp(*argv, "flowid") == 0) {
  66                        unsigned int handle;
  67
  68                        NEXT_ARG();
  69                        if (get_tc_classid(&handle, *argv)) {
  70                                fprintf(stderr, "Illegal \"classid\"\n");
  71                                return -1;
  72                        }
  73                        addattr_l(n, MAX_MSG, TCA_MATCHALL_CLASSID, &handle, 4);
  74                } else if (matches(*argv, "action") == 0) {
  75                        NEXT_ARG();
  76                        if (parse_action(&argc, &argv, TCA_MATCHALL_ACT, n)) {
  77                                fprintf(stderr, "Illegal \"action\"\n");
  78                                return -1;
  79                        }
  80                        continue;
  81
  82                } else if (strcmp(*argv, "skip_hw") == 0) {
  83                        NEXT_ARG();
  84                        flags |= TCA_CLS_FLAGS_SKIP_HW;
  85                        continue;
  86                } else if (strcmp(*argv, "skip_sw") == 0) {
  87                        NEXT_ARG();
  88                        flags |= TCA_CLS_FLAGS_SKIP_SW;
  89                        continue;
  90                } else if (strcmp(*argv, "help") == 0) {
  91                        explain();
  92                        return -1;
  93                } else {
  94                        fprintf(stderr, "What is \"%s\"?\n", *argv);
  95                        explain();
  96                        return -1;
  97                }
  98                argc--; argv++;
  99        }
 100
 101        if (flags) {
 102                if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW |
 103                               TCA_CLS_FLAGS_SKIP_SW))) {
 104                        fprintf(stderr,
 105                                "skip_hw and skip_sw are mutually exclusive\n");
 106                        return -1;
 107                }
 108                addattr_l(n, MAX_MSG, TCA_MATCHALL_FLAGS, &flags, 4);
 109        }
 110
 111        tail->rta_len = (((void *)n)+n->nlmsg_len) - (void *)tail;
 112        return 0;
 113}
 114
 115static int matchall_print_opt(struct filter_util *qu, FILE *f,
 116                           struct rtattr *opt, __u32 handle)
 117{
 118        struct rtattr *tb[TCA_MATCHALL_MAX+1];
 119        struct tc_matchall_pcnt *pf = NULL;
 120
 121        if (opt == NULL)
 122                return 0;
 123
 124        parse_rtattr_nested(tb, TCA_MATCHALL_MAX, opt);
 125
 126        if (handle)
 127                print_uint(PRINT_ANY, "handle", "handle 0x%x ", handle);
 128
 129        if (tb[TCA_MATCHALL_CLASSID]) {
 130                SPRINT_BUF(b1);
 131                print_string(PRINT_ANY, "flowid", "flowid %s ",
 132                        sprint_tc_classid(rta_getattr_u32(tb[TCA_MATCHALL_CLASSID]), b1));
 133        }
 134
 135        if (tb[TCA_MATCHALL_FLAGS]) {
 136                __u32 flags = rta_getattr_u32(tb[TCA_MATCHALL_FLAGS]);
 137
 138                if (flags & TCA_CLS_FLAGS_SKIP_HW)
 139                        print_bool(PRINT_ANY, "skip_hw", "\n  skip_hw", true);
 140                if (flags & TCA_CLS_FLAGS_SKIP_SW)
 141                        print_bool(PRINT_ANY, "skip_sw", "\n  skip_sw", true);
 142
 143                if (flags & TCA_CLS_FLAGS_IN_HW)
 144                        print_bool(PRINT_ANY, "in_hw", "\n  in_hw", true);
 145                else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
 146                        print_bool(PRINT_ANY, "not_in_hw", "\n  not_in_hw", true);
 147        }
 148
 149        if (tb[TCA_MATCHALL_PCNT]) {
 150                if (RTA_PAYLOAD(tb[TCA_MATCHALL_PCNT])  < sizeof(*pf)) {
 151                        print_string(PRINT_FP, NULL, "Broken perf counters\n", NULL);
 152                        return -1;
 153                }
 154                pf = RTA_DATA(tb[TCA_MATCHALL_PCNT]);
 155        }
 156
 157        if (show_stats && NULL != pf)
 158                print_u64(PRINT_ANY, "rule_hit", " (rule hit %llu)",
 159                        (unsigned long long) pf->rhit);
 160
 161
 162        if (tb[TCA_MATCHALL_ACT])
 163                tc_print_action(f, tb[TCA_MATCHALL_ACT], 0);
 164
 165        return 0;
 166}
 167
 168struct filter_util matchall_filter_util = {
 169        .id = "matchall",
 170        .parse_fopt = matchall_parse_opt,
 171        .print_fopt = matchall_print_opt,
 172};
 173