iproute2/tc/m_sample.c
<<
>>
Prefs
   1/*
   2 * m_sample.c           ingress/egress packet sampling module
   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:     Yotam Gigi <yotamg@mellanox.com>
  10 *
  11 */
  12
  13#include <stdio.h>
  14#include "utils.h"
  15#include "tc_util.h"
  16#include "tc_common.h"
  17#include <linux/tc_act/tc_sample.h>
  18
  19static void explain(void)
  20{
  21        fprintf(stderr,
  22                "Usage: sample SAMPLE_CONF\n"
  23                "where:\n"
  24                "\tSAMPLE_CONF := SAMPLE_PARAMS | SAMPLE_INDEX\n"
  25                "\tSAMPLE_PARAMS := rate RATE group GROUP [trunc SIZE] [SAMPLE_INDEX]\n"
  26                "\tSAMPLE_INDEX := index INDEX\n"
  27                "\tRATE := The ratio of packets observed at the data source to the samples generated.\n"
  28                "\tGROUP := the psample sampling group\n"
  29                "\tSIZE := the truncation size\n"
  30                "\tINDEX := integer index of the sample action\n");
  31}
  32
  33static void usage(void)
  34{
  35        explain();
  36        exit(-1);
  37}
  38
  39static int parse_sample(struct action_util *a, int *argc_p, char ***argv_p,
  40                        int tca_id, struct nlmsghdr *n)
  41{
  42        struct tc_sample p = { 0 };
  43        bool trunc_set = false;
  44        bool group_set = false;
  45        bool rate_set = false;
  46        char **argv = *argv_p;
  47        struct rtattr *tail;
  48        int argc = *argc_p;
  49        __u32 trunc;
  50        __u32 group;
  51        __u32 rate;
  52
  53        if (argc <= 1) {
  54                fprintf(stderr, "sample bad argument count %d\n", argc);
  55                usage();
  56                return -1;
  57        }
  58
  59        if (matches(*argv, "sample") == 0) {
  60                NEXT_ARG();
  61        } else {
  62                fprintf(stderr, "sample bad argument %s\n", *argv);
  63                return -1;
  64        }
  65
  66        while (argc > 0) {
  67                if (matches(*argv, "rate") == 0) {
  68                        NEXT_ARG();
  69                        if (get_u32(&rate, *argv, 10) != 0) {
  70                                fprintf(stderr, "Illegal rate %s\n", *argv);
  71                                usage();
  72                                return -1;
  73                        }
  74                        rate_set = true;
  75                } else if (matches(*argv, "group") == 0) {
  76                        NEXT_ARG();
  77                        if (get_u32(&group, *argv, 10) != 0) {
  78                                fprintf(stderr, "Illegal group num %s\n",
  79                                        *argv);
  80                                usage();
  81                                return -1;
  82                        }
  83                        group_set = true;
  84                } else if (matches(*argv, "trunc") == 0) {
  85                        NEXT_ARG();
  86                        if (get_u32(&trunc, *argv, 10) != 0) {
  87                                fprintf(stderr, "Illegal truncation size %s\n",
  88                                        *argv);
  89                                usage();
  90                                return -1;
  91                        }
  92                        trunc_set = true;
  93                } else if (matches(*argv, "help") == 0) {
  94                        usage();
  95                } else {
  96                        break;
  97                }
  98
  99                NEXT_ARG_FWD();
 100        }
 101
 102        parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE);
 103
 104        if (argc) {
 105                if (matches(*argv, "index") == 0) {
 106                        NEXT_ARG();
 107                        if (get_u32(&p.index, *argv, 10)) {
 108                                fprintf(stderr, "sample: Illegal \"index\"\n");
 109                                return -1;
 110                        }
 111                        NEXT_ARG_FWD();
 112                }
 113        }
 114
 115        if (!p.index && !group_set) {
 116                fprintf(stderr, "param \"group\" not set\n");
 117                usage();
 118        }
 119
 120        if (!p.index && !rate_set) {
 121                fprintf(stderr, "param \"rate\" not set\n");
 122                usage();
 123        }
 124
 125        tail = addattr_nest(n, MAX_MSG, tca_id);
 126        addattr_l(n, MAX_MSG, TCA_SAMPLE_PARMS, &p, sizeof(p));
 127        if (rate_set)
 128                addattr32(n, MAX_MSG, TCA_SAMPLE_RATE, rate);
 129        if (group_set)
 130                addattr32(n, MAX_MSG, TCA_SAMPLE_PSAMPLE_GROUP, group);
 131        if (trunc_set)
 132                addattr32(n, MAX_MSG, TCA_SAMPLE_TRUNC_SIZE, trunc);
 133
 134        addattr_nest_end(n, tail);
 135
 136        *argc_p = argc;
 137        *argv_p = argv;
 138        return 0;
 139}
 140
 141static int print_sample(struct action_util *au, FILE *f, struct rtattr *arg)
 142{
 143        struct rtattr *tb[TCA_SAMPLE_MAX + 1];
 144        struct tc_sample *p;
 145
 146        print_string(PRINT_ANY, "kind", "%s ", "sample");
 147        if (arg == NULL)
 148                return 0;
 149
 150        parse_rtattr_nested(tb, TCA_SAMPLE_MAX, arg);
 151
 152        if (!tb[TCA_SAMPLE_PARMS] || !tb[TCA_SAMPLE_RATE] ||
 153            !tb[TCA_SAMPLE_PSAMPLE_GROUP]) {
 154                fprintf(stderr, "Missing sample parameters\n");
 155                return -1;
 156        }
 157        p = RTA_DATA(tb[TCA_SAMPLE_PARMS]);
 158
 159        print_uint(PRINT_ANY, "rate", "rate 1/%u ",
 160                   rta_getattr_u32(tb[TCA_SAMPLE_RATE]));
 161        print_uint(PRINT_ANY, "group", "group %u",
 162                   rta_getattr_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]));
 163
 164        if (tb[TCA_SAMPLE_TRUNC_SIZE])
 165                print_uint(PRINT_ANY, "trunc_size", " trunc_size %u",
 166                           rta_getattr_u32(tb[TCA_SAMPLE_TRUNC_SIZE]));
 167
 168        print_action_control(f, " ", p->action, "");
 169
 170        print_nl();
 171        print_uint(PRINT_ANY, "index", "\t index %u", p->index);
 172        print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
 173        print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
 174
 175        if (show_stats) {
 176                if (tb[TCA_SAMPLE_TM]) {
 177                        struct tcf_t *tm = RTA_DATA(tb[TCA_SAMPLE_TM]);
 178
 179                        print_tm(f, tm);
 180                }
 181        }
 182        print_nl();
 183        return 0;
 184}
 185
 186struct action_util sample_action_util = {
 187        .id = "sample",
 188        .parse_aopt = parse_sample,
 189        .print_aopt = print_sample,
 190};
 191