1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * m_sample.c ingress/egress packet sampling module
5 * Authors: Yotam Gigi <yotamg@mellanox.com>
11 #include "tc_common.h"
12 #include <linux/tc_act/tc_sample.h>
14 static void explain(void)
17 "Usage: sample SAMPLE_CONF\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");
28 static void usage(void)
34 static int parse_sample(const struct action_util
*a
, int *argc_p
, char ***argv_p
,
35 int tca_id
, struct nlmsghdr
*n
)
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
;
49 fprintf(stderr
, "sample bad argument count %d\n", argc
);
54 if (matches(*argv
, "sample") == 0) {
57 fprintf(stderr
, "sample bad argument %s\n", *argv
);
62 if (matches(*argv
, "rate") == 0) {
64 if (get_u32(&rate
, *argv
, 10) != 0) {
65 fprintf(stderr
, "Illegal rate %s\n", *argv
);
70 } else if (matches(*argv
, "group") == 0) {
72 if (get_u32(&group
, *argv
, 10) != 0) {
73 fprintf(stderr
, "Illegal group num %s\n",
79 } else if (matches(*argv
, "trunc") == 0) {
81 if (get_u32(&trunc
, *argv
, 10) != 0) {
82 fprintf(stderr
, "Illegal truncation size %s\n",
88 } else if (matches(*argv
, "help") == 0) {
97 parse_action_control_dflt(&argc
, &argv
, &p
.action
, false, TC_ACT_PIPE
);
100 if (matches(*argv
, "index") == 0) {
102 if (get_u32(&p
.index
, *argv
, 10)) {
103 fprintf(stderr
, "sample: Illegal \"index\"\n");
110 if (!p
.index
&& !group_set
) {
111 fprintf(stderr
, "param \"group\" not set\n");
115 if (!p
.index
&& !rate_set
) {
116 fprintf(stderr
, "param \"rate\" not set\n");
120 tail
= addattr_nest(n
, MAX_MSG
, tca_id
);
121 addattr_l(n
, MAX_MSG
, TCA_SAMPLE_PARMS
, &p
, sizeof(p
));
123 addattr32(n
, MAX_MSG
, TCA_SAMPLE_RATE
, rate
);
125 addattr32(n
, MAX_MSG
, TCA_SAMPLE_PSAMPLE_GROUP
, group
);
127 addattr32(n
, MAX_MSG
, TCA_SAMPLE_TRUNC_SIZE
, trunc
);
129 addattr_nest_end(n
, tail
);
136 static int print_sample(const struct action_util
*au
, FILE *f
, struct rtattr
*arg
)
138 struct rtattr
*tb
[TCA_SAMPLE_MAX
+ 1];
141 print_string(PRINT_ANY
, "kind", "%s ", "sample");
145 parse_rtattr_nested(tb
, TCA_SAMPLE_MAX
, arg
);
147 if (!tb
[TCA_SAMPLE_PARMS
] || !tb
[TCA_SAMPLE_RATE
] ||
148 !tb
[TCA_SAMPLE_PSAMPLE_GROUP
]) {
149 fprintf(stderr
, "Missing sample parameters\n");
152 p
= RTA_DATA(tb
[TCA_SAMPLE_PARMS
]);
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
]));
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
]));
163 print_action_control(f
, " ", p
->action
, "");
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
);
171 if (tb
[TCA_SAMPLE_TM
]) {
172 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_SAMPLE_TM
]);
181 struct action_util sample_action_util
= {
183 .parse_aopt
= parse_sample
,
184 .print_aopt
= print_sample
,