]>
git.proxmox.com Git - mirror_iproute2.git/blob - tc/tc.c
2 * tc.c "tc" utility frontend.
4 * This program is free software; you can redistribute 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: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
13 * Petri Mattila <petri@prihateam.fi> 990308: wrong memset's resulted in faults
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
30 #include "tc_common.h"
31 #include "namespace.h"
50 static char *conf_file
;
52 struct rtnl_handle rth
;
54 static void *BODY
; /* cached handle dlopen(NULL) */
55 static struct qdisc_util
*qdisc_list
;
56 static struct filter_util
*filter_list
;
58 static int print_noqopt(struct qdisc_util
*qu
, FILE *f
,
61 if (opt
&& RTA_PAYLOAD(opt
))
62 fprintf(f
, "[Unknown qdisc, optlen=%u] ",
63 (unsigned int) RTA_PAYLOAD(opt
));
67 static int parse_noqopt(struct qdisc_util
*qu
, int argc
, char **argv
,
68 struct nlmsghdr
*n
, const char *dev
)
72 "Unknown qdisc \"%s\", hence option \"%s\" is unparsable\n",
79 static int print_nofopt(struct filter_util
*qu
, FILE *f
, struct rtattr
*opt
, __u32 fhandle
)
81 if (opt
&& RTA_PAYLOAD(opt
))
82 fprintf(f
, "fh %08x [Unknown filter, optlen=%u] ",
83 fhandle
, (unsigned int) RTA_PAYLOAD(opt
));
85 fprintf(f
, "fh %08x ", fhandle
);
89 static int parse_nofopt(struct filter_util
*qu
, char *fhandle
,
90 int argc
, char **argv
, struct nlmsghdr
*n
)
96 "Unknown filter \"%s\", hence option \"%s\" is unparsable\n",
101 struct tcmsg
*t
= NLMSG_DATA(n
);
103 if (get_u32(&handle
, fhandle
, 16)) {
104 fprintf(stderr
, "Unparsable filter ID \"%s\"\n", fhandle
);
107 t
->tcm_handle
= handle
;
112 struct qdisc_util
*get_qdisc_kind(const char *str
)
116 struct qdisc_util
*q
;
118 for (q
= qdisc_list
; q
; q
= q
->next
)
119 if (strcmp(q
->id
, str
) == 0)
122 snprintf(buf
, sizeof(buf
), "%s/q_%s.so", get_tc_lib(), str
);
123 dlh
= dlopen(buf
, RTLD_LAZY
);
125 /* look in current binary, only open once */
128 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
134 snprintf(buf
, sizeof(buf
), "%s_qdisc_util", str
);
140 q
->next
= qdisc_list
;
145 q
= calloc(1, sizeof(*q
));
148 q
->parse_qopt
= parse_noqopt
;
149 q
->print_qopt
= print_noqopt
;
156 struct filter_util
*get_filter_kind(const char *str
)
160 struct filter_util
*q
;
162 for (q
= filter_list
; q
; q
= q
->next
)
163 if (strcmp(q
->id
, str
) == 0)
166 snprintf(buf
, sizeof(buf
), "%s/f_%s.so", get_tc_lib(), str
);
167 dlh
= dlopen(buf
, RTLD_LAZY
);
171 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
177 snprintf(buf
, sizeof(buf
), "%s_filter_util", str
);
183 q
->next
= filter_list
;
187 q
= calloc(1, sizeof(*q
));
189 strncpy(q
->id
, str
, 15);
190 q
->parse_fopt
= parse_nofopt
;
191 q
->print_fopt
= print_nofopt
;
197 static void usage(void)
200 "Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n"
201 " tc [-force] -batch filename\n"
202 "where OBJECT := { qdisc | class | filter | chain |\n"
203 " action | monitor | exec }\n"
204 " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[aw] |\n"
205 " -o[neline] | -j[son] | -p[retty] | -c[olor]\n"
206 " -b[atch] [filename] | -n[etns] name | -N[umeric] |\n"
207 " -nm | -nam[es] | { -cf | -conf } path\n"
211 static int do_cmd(int argc
, char **argv
)
213 if (matches(*argv
, "qdisc") == 0)
214 return do_qdisc(argc
-1, argv
+1);
215 if (matches(*argv
, "class") == 0)
216 return do_class(argc
-1, argv
+1);
217 if (matches(*argv
, "filter") == 0)
218 return do_filter(argc
-1, argv
+1);
219 if (matches(*argv
, "chain") == 0)
220 return do_chain(argc
-1, argv
+1);
221 if (matches(*argv
, "actions") == 0)
222 return do_action(argc
-1, argv
+1);
223 if (matches(*argv
, "monitor") == 0)
224 return do_tcmonitor(argc
-1, argv
+1);
225 if (matches(*argv
, "exec") == 0)
226 return do_exec(argc
-1, argv
+1);
227 if (matches(*argv
, "help") == 0) {
232 fprintf(stderr
, "Object \"%s\" is unknown, try \"tc help\".\n",
237 static int tc_batch_cmd(int argc
, char *argv
[], void *data
)
239 return do_cmd(argc
, argv
);
242 static int batch(const char *name
)
249 if (rtnl_open(&rth
, 0) < 0) {
250 fprintf(stderr
, "Cannot open rtnetlink\n");
254 ret
= do_batch(name
, force
, tc_batch_cmd
, NULL
);
261 int main(int argc
, char **argv
)
263 const char *libbpf_version
;
264 char *batch_file
= NULL
;
268 if (argv
[1][0] != '-')
270 if (matches(argv
[1], "-stats") == 0 ||
271 matches(argv
[1], "-statistics") == 0) {
273 } else if (matches(argv
[1], "-details") == 0) {
275 } else if (matches(argv
[1], "-raw") == 0) {
277 } else if (matches(argv
[1], "-pretty") == 0) {
279 } else if (matches(argv
[1], "-graph") == 0) {
281 } else if (matches(argv
[1], "-Version") == 0) {
282 printf("tc utility, iproute2-%s", version
);
283 libbpf_version
= get_libbpf_version();
285 printf(", libbpf %s", libbpf_version
);
288 } else if (matches(argv
[1], "-iec") == 0) {
290 } else if (matches(argv
[1], "-help") == 0) {
293 } else if (matches(argv
[1], "-force") == 0) {
295 } else if (matches(argv
[1], "-batch") == 0) {
299 batch_file
= argv
[1];
300 } else if (matches(argv
[1], "-netns") == 0) {
302 if (netns_switch(argv
[1]))
304 } else if (matches(argv
[1], "-Numeric") == 0) {
306 } else if (matches(argv
[1], "-names") == 0 ||
307 matches(argv
[1], "-nm") == 0) {
309 } else if (matches(argv
[1], "-cf") == 0 ||
310 matches(argv
[1], "-conf") == 0) {
313 } else if (matches_color(argv
[1], &color
)) {
314 } else if (matches(argv
[1], "-timestamp") == 0) {
316 } else if (matches(argv
[1], "-tshort") == 0) {
319 } else if (matches(argv
[1], "-json") == 0) {
321 } else if (matches(argv
[1], "-oneline") == 0) {
323 }else if (matches(argv
[1], "-brief") == 0) {
327 "Option \"%s\" is unknown, try \"tc -help\".\n",
334 _SL_
= oneline
? "\\" : "\n";
336 check_enable_color(color
, json
);
339 return batch(batch_file
);
347 if (rtnl_open(&rth
, 0) < 0) {
348 fprintf(stderr
, "Cannot open rtnetlink\n");
352 if (use_names
&& cls_names_init(conf_file
)) {
357 ret
= do_cmd(argc
-1, argv
+1);