From: Jamal Hadi Salim Date: Tue, 8 Aug 2006 18:55:15 +0000 (-0700) Subject: This patch adds ability to monitor tc events similar to ipmonitor. X-Git-Tag: v2.6.19-061214~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bec34845bba39dfc1efb409ebc2b158a9f0fbc4;p=thirdparty%2Fiproute2.git This patch adds ability to monitor tc events similar to ipmonitor. User runs "tc monitor" (without quotes) and watches events of addition, deletion and updates from qdiscs, classes, filters and actions as they happen. Signed-off-by: Stephen Hemminger --- diff --git a/tc/Makefile b/tc/Makefile index 9d618ffce..7640c58ee 100644 --- a/tc/Makefile +++ b/tc/Makefile @@ -1,6 +1,6 @@ TCOBJ= tc.o tc_qdisc.o tc_class.o tc_filter.o tc_util.o \ - m_police.o m_estimator.o m_action.o m_ematch.o \ - emp_ematch.yacc.o emp_ematch.lex.o + tc_monitor.o m_police.o m_estimator.o m_action.o \ + m_ematch.o emp_ematch.yacc.o emp_ematch.lex.o include ../Config diff --git a/tc/m_action.c b/tc/m_action.c index b4eff91c7..c67bc8836 100644 --- a/tc/m_action.c +++ b/tc/m_action.c @@ -313,7 +313,7 @@ tc_print_action(FILE * f, const struct rtattr *arg) return 0; } -static int do_print_action(const struct sockaddr_nl *who, +int print_action(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { @@ -333,7 +333,7 @@ static int do_print_action(const struct sockaddr_nl *who, if (NULL == tb[TCA_ACT_TAB]) { if (n->nlmsg_type != RTM_GETACTION) - fprintf(stderr, "do_print_action: NULL kind\n"); + fprintf(stderr, "print_action: NULL kind\n"); return -1; } @@ -454,7 +454,7 @@ int tc_action_gd(int cmd, unsigned flags, int *argc_p, char ***argv_p) return 1; } - if (ans && do_print_action(NULL, &req.n, (void*)stdout) < 0) { + if (ans && print_action(NULL, &req.n, (void*)stdout) < 0) { fprintf(stderr, "Dump terminated\n"); return 1; } @@ -556,7 +556,7 @@ int tc_act_list_or_flush(int argc, char **argv, int event) perror("Cannot send dump request"); return 1; } - ret = rtnl_dump_filter(&rth, do_print_action, stdout, NULL, NULL); + ret = rtnl_dump_filter(&rth, print_action, stdout, NULL, NULL); } if (event == RTM_DELACTION) { diff --git a/tc/tc.c b/tc/tc.c index fa36ee076..789f6f628 100644 --- a/tc/tc.c +++ b/tc/tc.c @@ -181,7 +181,7 @@ static void usage(void) { fprintf(stderr, "Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n" " tc [-force] -batch file\n" - "where OBJECT := { qdisc | class | filter | action }\n" + "where OBJECT := { qdisc | class | filter | action | monitor }\n" " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -b[atch] [file] }\n"); } @@ -199,6 +199,9 @@ static int do_cmd(int argc, char **argv) if (matches(*argv, "actions") == 0) return do_action(argc-1, argv+1); + if (matches(*argv, "monitor") == 0) + return do_tcmonitor(argc-1, argv+1); + if (matches(*argv, "help") == 0) { usage(); return 0; diff --git a/tc/tc_class.c b/tc/tc_class.c index 93d5def5f..8d93b5a8f 100644 --- a/tc/tc_class.c +++ b/tc/tc_class.c @@ -147,7 +147,7 @@ int tc_class_modify(int cmd, unsigned flags, int argc, char **argv) int filter_ifindex; __u32 filter_qdisc; -static int print_class(const struct sockaddr_nl *who, +int print_class(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; diff --git a/tc/tc_common.h b/tc/tc_common.h index 7e135824a..5bfc43e46 100644 --- a/tc/tc_common.h +++ b/tc/tc_common.h @@ -6,6 +6,11 @@ extern int do_qdisc(int argc, char **argv); extern int do_class(int argc, char **argv); extern int do_filter(int argc, char **argv); extern int do_action(int argc, char **argv); +extern int do_tcmonitor(int argc, char **argv); +extern int print_action(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); +extern int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); +extern int print_qdisc(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); + extern int print_class(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); struct tc_estimator; extern int parse_estimator(int *p_argc, char ***p_argv, struct tc_estimator *est); diff --git a/tc/tc_filter.c b/tc/tc_filter.c index 58af07722..f3319d552 100644 --- a/tc/tc_filter.c +++ b/tc/tc_filter.c @@ -176,7 +176,7 @@ static int filter_ifindex; static __u32 filter_prio; static __u32 filter_protocol; -static int print_filter(const struct sockaddr_nl *who, +int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { diff --git a/tc/tc_monitor.c b/tc/tc_monitor.c new file mode 100644 index 000000000..1af6cf0af --- /dev/null +++ b/tc/tc_monitor.c @@ -0,0 +1,110 @@ +/* + * tc_monitor.c "tc monitor". + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Jamal Hadi Salim + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rt_names.h" +#include "utils.h" +#include "tc_util.h" +#include "tc_common.h" + + +static void usage(void) __attribute__((noreturn)); + +static void usage(void) +{ + fprintf(stderr, "Usage: tc monitor\n"); + exit(-1); +} + + +int accept_tcmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) +{ + FILE *fp = (FILE*)arg; + + if (n->nlmsg_type == RTM_NEWTFILTER || n->nlmsg_type == RTM_DELTFILTER) { + print_filter(who, n, arg); + return 0; + } + if (n->nlmsg_type == RTM_NEWTCLASS || n->nlmsg_type == RTM_DELTCLASS) { + print_class(who, n, arg); + return 0; + } + if (n->nlmsg_type == RTM_NEWQDISC || n->nlmsg_type == RTM_DELQDISC) { + print_qdisc(who, n, arg); + return 0; + } + if (n->nlmsg_type == RTM_GETACTION || n->nlmsg_type == RTM_NEWACTION || + n->nlmsg_type == RTM_DELACTION) { + print_action(who, n, arg); + return 0; + } + if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP && + n->nlmsg_type != NLMSG_DONE) { + fprintf(fp, "Unknown message: length %08d type %08x flags %08x\n", + n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); + } + return 0; +} + +int do_tcmonitor(int argc, char **argv) +{ + struct rtnl_handle rth; + char *file = NULL; + unsigned groups = RTMGRP_TC; + + while (argc > 0) { + if (matches(*argv, "file") == 0) { + NEXT_ARG(); + file = *argv; + } else { + if (matches(*argv, "help") == 0) { + usage(); + } else { + fprintf(stderr, "Argument \"%s\" is unknown, try \"tc monitor help\".\n", *argv); + exit(-1); + } + } + argc--; argv++; + } + + if (file) { + FILE *fp; + fp = fopen(file, "r"); + if (fp == NULL) { + perror("Cannot fopen"); + exit(-1); + } + return rtnl_from_file(fp, accept_tcmsg, (void*)stdout); + } + + if (rtnl_open(&rth, groups) < 0) + exit(1); + + ll_init_map(&rth); + + if (rtnl_listen(&rth, accept_tcmsg, (void*)stdout) < 0) { + rtnl_close(&rth); + exit(2); + } + + rtnl_close(&rth); + exit(0); +} diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c index fb107f462..50b264976 100644 --- a/tc/tc_qdisc.c +++ b/tc/tc_qdisc.c @@ -162,7 +162,7 @@ int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) static int filter_ifindex; -static int print_qdisc(const struct sockaddr_nl *who, +int print_qdisc(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) {