Commit 5bec3484 authored by Jamal Hadi Salim's avatar Jamal Hadi Salim Committed by Stephen Hemminger

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: default avatarStephen Hemminger <shemminger@osdl.org>
parent e81c1a22
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
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......@@ -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)
{
......
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <time.h>
#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);
}
......@@ -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)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment