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