1 /* SPDX-License-Identifier: GPL-2.0 */
3 * f_tcindex.c Traffic control index filter
5 * Written 1998,1999 by Werner Almesberger
13 #include <netinet/in.h>
18 static void explain(void)
21 " Usage: ... tcindex [ hash SIZE ] [ mask MASK ] [ shift SHIFT ]\n"
22 " [ pass_on | fall_through ]\n"
23 " [ classid CLASSID ] [ action ACTION_SPEC ]\n");
26 static int tcindex_parse_opt(struct filter_util
*qu
, char *handle
, int argc
,
27 char **argv
, struct nlmsghdr
*n
)
29 struct tcmsg
*t
= NLMSG_DATA(n
);
34 t
->tcm_handle
= strtoul(handle
, &end
, 0);
36 fprintf(stderr
, "Illegal filter ID\n");
41 tail
= addattr_nest(n
, 4096, TCA_OPTIONS
);
43 if (!strcmp(*argv
, "hash")) {
47 hash
= strtoul(*argv
, &end
, 0);
48 if (*end
|| !hash
|| hash
> 0x10000) {
52 addattr_l(n
, 4096, TCA_TCINDEX_HASH
, &hash
,
54 } else if (!strcmp(*argv
,"mask")) {
58 mask
= strtoul(*argv
, &end
, 0);
63 addattr_l(n
, 4096, TCA_TCINDEX_MASK
, &mask
,
65 } else if (!strcmp(*argv
,"shift")) {
69 shift
= strtoul(*argv
, &end
, 0);
74 addattr_l(n
, 4096, TCA_TCINDEX_SHIFT
, &shift
,
76 } else if (!strcmp(*argv
,"fall_through")) {
79 addattr_l(n
, 4096, TCA_TCINDEX_FALL_THROUGH
, &value
,
81 } else if (!strcmp(*argv
,"pass_on")) {
84 addattr_l(n
, 4096, TCA_TCINDEX_FALL_THROUGH
, &value
,
86 } else if (!strcmp(*argv
,"classid")) {
90 if (get_tc_classid(&handle
, *argv
)) {
91 fprintf(stderr
, "Illegal \"classid\"\n");
94 addattr_l(n
, 4096, TCA_TCINDEX_CLASSID
, &handle
, 4);
95 } else if (!strcmp(*argv
,"police")) {
97 if (parse_police(&argc
, &argv
, TCA_TCINDEX_POLICE
, n
)) {
98 fprintf(stderr
, "Illegal \"police\"\n");
102 } else if (!strcmp(*argv
,"action")) {
104 if (parse_action(&argc
, &argv
, TCA_TCINDEX_ACT
, n
)) {
105 fprintf(stderr
, "Illegal \"action\"\n");
116 addattr_nest_end(n
, tail
);
121 static int tcindex_print_opt(struct filter_util
*qu
, FILE *f
,
122 struct rtattr
*opt
, __u32 handle
)
124 struct rtattr
*tb
[TCA_TCINDEX_MAX
+1];
129 parse_rtattr_nested(tb
, TCA_TCINDEX_MAX
, opt
);
131 if (handle
!= ~0) fprintf(f
, "handle 0x%04x ", handle
);
132 if (tb
[TCA_TCINDEX_HASH
]) {
135 if (RTA_PAYLOAD(tb
[TCA_TCINDEX_HASH
]) < sizeof(hash
))
137 hash
= rta_getattr_u16(tb
[TCA_TCINDEX_HASH
]);
138 fprintf(f
, "hash %d ", hash
);
140 if (tb
[TCA_TCINDEX_MASK
]) {
143 if (RTA_PAYLOAD(tb
[TCA_TCINDEX_MASK
]) < sizeof(mask
))
145 mask
= rta_getattr_u16(tb
[TCA_TCINDEX_MASK
]);
146 fprintf(f
, "mask 0x%04x ", mask
);
148 if (tb
[TCA_TCINDEX_SHIFT
]) {
151 if (RTA_PAYLOAD(tb
[TCA_TCINDEX_SHIFT
]) < sizeof(shift
))
153 shift
= rta_getattr_u32(tb
[TCA_TCINDEX_SHIFT
]);
154 fprintf(f
, "shift %d ", shift
);
156 if (tb
[TCA_TCINDEX_FALL_THROUGH
]) {
159 if (RTA_PAYLOAD(tb
[TCA_TCINDEX_FALL_THROUGH
]) <
160 sizeof(fall_through
))
162 fall_through
= rta_getattr_u32(tb
[TCA_TCINDEX_FALL_THROUGH
]);
163 fprintf(f
, fall_through
? "fall_through " : "pass_on ");
165 if (tb
[TCA_TCINDEX_CLASSID
]) {
167 fprintf(f
, "classid %s ", sprint_tc_classid(*(__u32
*)
168 RTA_DATA(tb
[TCA_TCINDEX_CLASSID
]), b1
));
170 if (tb
[TCA_TCINDEX_POLICE
]) {
172 tc_print_police(f
, tb
[TCA_TCINDEX_POLICE
]);
174 if (tb
[TCA_TCINDEX_ACT
]) {
176 tc_print_action(f
, tb
[TCA_TCINDEX_ACT
], 0);
181 struct filter_util tcindex_filter_util
= {
183 .parse_fopt
= tcindex_parse_opt
,
184 .print_fopt
= tcindex_print_opt
,