2 * m_sample.c ingress/egress packet sampling module
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.
9 * Authors: Yotam Gigi <yotamg@mellanox.com>
16 #include "tc_common.h"
17 #include <linux/tc_act/tc_sample.h>
19 static void explain(void)
22 "Usage: sample SAMPLE_CONF\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");
33 static void usage(void)
39 static int parse_sample(struct action_util
*a
, int *argc_p
, char ***argv_p
,
40 int tca_id
, struct nlmsghdr
*n
)
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
;
54 fprintf(stderr
, "sample bad argument count %d\n", argc
);
59 if (matches(*argv
, "sample") == 0) {
62 fprintf(stderr
, "sample bad argument %s\n", *argv
);
67 if (matches(*argv
, "rate") == 0) {
69 if (get_u32(&rate
, *argv
, 10) != 0) {
70 fprintf(stderr
, "Illegal rate %s\n", *argv
);
75 } else if (matches(*argv
, "group") == 0) {
77 if (get_u32(&group
, *argv
, 10) != 0) {
78 fprintf(stderr
, "Illegal group num %s\n",
84 } else if (matches(*argv
, "trunc") == 0) {
86 if (get_u32(&trunc
, *argv
, 10) != 0) {
87 fprintf(stderr
, "Illegal truncation size %s\n",
93 } else if (matches(*argv
, "help") == 0) {
102 parse_action_control_dflt(&argc
, &argv
, &p
.action
, false, TC_ACT_PIPE
);
105 if (matches(*argv
, "index") == 0) {
107 if (get_u32(&p
.index
, *argv
, 10)) {
108 fprintf(stderr
, "sample: Illegal \"index\"\n");
115 if (!p
.index
&& !group_set
) {
116 fprintf(stderr
, "param \"group\" not set\n");
120 if (!p
.index
&& !rate_set
) {
121 fprintf(stderr
, "param \"rate\" not set\n");
125 tail
= addattr_nest(n
, MAX_MSG
, tca_id
);
126 addattr_l(n
, MAX_MSG
, TCA_SAMPLE_PARMS
, &p
, sizeof(p
));
128 addattr32(n
, MAX_MSG
, TCA_SAMPLE_RATE
, rate
);
130 addattr32(n
, MAX_MSG
, TCA_SAMPLE_PSAMPLE_GROUP
, group
);
132 addattr32(n
, MAX_MSG
, TCA_SAMPLE_TRUNC_SIZE
, trunc
);
134 addattr_nest_end(n
, tail
);
141 static int print_sample(struct action_util
*au
, FILE *f
, struct rtattr
*arg
)
143 struct rtattr
*tb
[TCA_SAMPLE_MAX
+ 1];
146 print_string(PRINT_ANY
, "kind", "%s ", "sample");
150 parse_rtattr_nested(tb
, TCA_SAMPLE_MAX
, arg
);
152 if (!tb
[TCA_SAMPLE_PARMS
] || !tb
[TCA_SAMPLE_RATE
] ||
153 !tb
[TCA_SAMPLE_PSAMPLE_GROUP
]) {
154 fprintf(stderr
, "Missing sample parameters\n");
157 p
= RTA_DATA(tb
[TCA_SAMPLE_PARMS
]);
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
]));
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
]));
168 print_action_control(f
, " ", p
->action
, "");
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
);
176 if (tb
[TCA_SAMPLE_TM
]) {
177 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_SAMPLE_TM
]);
186 struct action_util sample_action_util
= {
188 .parse_aopt
= parse_sample
,
189 .print_aopt
= print_sample
,