]> git.ipfire.org Git - thirdparty/iproute2.git/blob - tc/m_sample.c
tc: make action_util arg const
[thirdparty/iproute2.git] / tc / m_sample.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * m_sample.c ingress/egress packet sampling module
4 *
5 * Authors: Yotam Gigi <yotamg@mellanox.com>
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
14 static void explain(void)
15 {
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");
26 }
27
28 static void usage(void)
29 {
30 explain();
31 exit(-1);
32 }
33
34 static int parse_sample(const struct action_util *a, int *argc_p, char ***argv_p,
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();
64 if (get_u32(&rate, *argv, 10) != 0) {
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();
72 if (get_u32(&group, *argv, 10) != 0) {
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();
81 if (get_u32(&trunc, *argv, 10) != 0) {
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
97 parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE);
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
120 tail = addattr_nest(n, MAX_MSG, tca_id);
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
129 addattr_nest_end(n, tail);
130
131 *argc_p = argc;
132 *argv_p = argv;
133 return 0;
134 }
135
136 static int print_sample(const struct action_util *au, FILE *f, struct rtattr *arg)
137 {
138 struct rtattr *tb[TCA_SAMPLE_MAX + 1];
139 struct tc_sample *p;
140
141 print_string(PRINT_ANY, "kind", "%s ", "sample");
142 if (arg == NULL)
143 return 0;
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]) {
149 fprintf(stderr, "Missing sample parameters\n");
150 return -1;
151 }
152 p = RTA_DATA(tb[TCA_SAMPLE_PARMS]);
153
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]));
158
159 if (tb[TCA_SAMPLE_TRUNC_SIZE])
160 print_uint(PRINT_ANY, "trunc_size", " trunc_size %u",
161 rta_getattr_u32(tb[TCA_SAMPLE_TRUNC_SIZE]));
162
163 print_action_control(f, " ", p->action, "");
164
165 print_nl();
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);
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 }
177 print_nl();
178 return 0;
179 }
180
181 struct action_util sample_action_util = {
182 .id = "sample",
183 .parse_aopt = parse_sample,
184 .print_aopt = print_sample,
185 };