From: Jiri Pirko
Signed-off-by: Jiri Pirko
---
v3->v4:
- reworked to chain object
v1->v2:
- moved the template handling
from "tc filter template" to "tc chaintemplate"
---
include/uapi/linux/rtnetlink.h | 7 +++
man/man8/tc.8 | 26
tc/tc.c| 5 +-
tc/tc_common.h | 1 +
tc/tc_filter.c | 131 +
tc/tc_monitor.c| 5 +-
6 files changed, 135 insertions(+), 40 deletions(-)
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index c3a7d8ecc7b9..8c1d600bfa33 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -150,6 +150,13 @@ enum {
RTM_NEWCACHEREPORT = 96,
#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
+ RTM_NEWCHAIN = 100,
+#define RTM_NEWCHAIN RTM_NEWCHAIN
+ RTM_DELCHAIN,
+#define RTM_DELCHAIN RTM_DELCHAIN
+ RTM_GETCHAIN,
+#define RTM_GETCHAIN RTM_GETCHAIN
+
__RTM_MAX,
#define RTM_MAX(((__RTM_MAX + 3) & ~3) - 1)
};
diff --git a/man/man8/tc.8 b/man/man8/tc.8
index 716dfec5f3a8..fd33f9b2f180 100644
--- a/man/man8/tc.8
+++ b/man/man8/tc.8
@@ -58,6 +58,22 @@ tc \- show / manipulate traffic control settings
.B flowid
\fIflow-id\fR
+.B tc
+.RI "[ " OPTIONS " ]"
+.B chain [ add | delete | get ] dev
+\fIDEV\fR
+.B [ parent
+\fIqdisc-id\fR
+.B | root ]\fR filtertype
+[ filtertype specific parameters ]
+
+.B tc
+.RI "[ " OPTIONS " ]"
+.B chain [ add | delete | get ] block
+\fIBLOCK_INDEX\fR filtertype
+[ filtertype specific parameters ]
+
+
.B tc
.RI "[ " OPTIONS " ]"
.RI "[ " FORMAT " ]"
@@ -80,6 +96,16 @@ tc \- show / manipulate traffic control settings
.RI "[ " OPTIONS " ]"
.B filter show block
\fIBLOCK_INDEX\fR
+.P
+.B tc
+.RI "[ " OPTIONS " ]"
+.B chain show dev
+\fIDEV\fR
+.P
+.B tc
+.RI "[ " OPTIONS " ]"
+.B chain show block
+\fIBLOCK_INDEX\fR
.P
.B tc
diff --git a/tc/tc.c b/tc/tc.c
index 0d223281ba25..2af67963c1e1 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -197,7 +197,8 @@ static void usage(void)
fprintf(stderr,
"Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n"
" tc [-force] -batch filename\n"
- "where OBJECT := { qdisc | class | filter | action | monitor |
exec }\n"
+ "where OBJECT := { qdisc | class | filter | chain |\n"
+ " action | monitor | exec }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |
-r[aw] |\n"
"-o[neline] | -j[son] | -p[retty] |
-c[olor]\n"
"-b[atch] [filename] | -n[etns] name |\n"
@@ -212,6 +213,8 @@ static int do_cmd(int argc, char **argv, void *buf, size_t
buflen)
return do_class(argc-1, argv+1);
if (matches(*argv, "filter") == 0)
return do_filter(argc-1, argv+1, buf, buflen);
+ if (matches(*argv, "chain") == 0)
+ return do_chain(argc-1, argv+1, buf, buflen);
if (matches(*argv, "actions") == 0)
return do_action(argc-1, argv+1, buf, buflen);
if (matches(*argv, "monitor") == 0)
diff --git a/tc/tc_common.h b/tc/tc_common.h
index 49c24616c2c3..272d1727027d 100644
--- a/tc/tc_common.h
+++ b/tc/tc_common.h
@@ -8,6 +8,7 @@ extern struct rtnl_handle rth;
extern int do_qdisc(int argc, char **argv);
extern int do_class(int argc, char **argv);
extern int do_filter(int argc, char **argv, void *buf, size_t buflen);
+extern int do_chain(int argc, char **argv, void *buf, size_t buflen);
extern int do_action(int argc, char **argv, void *buf, size_t buflen);
extern int do_tcmonitor(int argc, char **argv);
extern int do_exec(int argc, char **argv);
diff --git a/tc/tc_filter.c b/tc/tc_filter.c
index c5bb0bffe19b..15044b4bc6ed 100644
--- a/tc/tc_filter.c
+++ b/tc/tc_filter.c
@@ -45,6 +45,13 @@ static void usage(void)
"OPTIONS := ... try tc filter add
help\n");
}
+static void chain_usage(void)
+{
+ fprintf(stderr,
+ "Usage: tc chain [ add | del | get | show ] [ dev STRING ]\n"
+ " tc chain [ add | del | get | show ] [ block BLOCK_INDEX
] ]\n");
+}
+
struct tc_filter_req {
struct nlmsghdr n;
struct tcmsgt;
@@ -85,7 +92,8 @@ static int tc_filter_modify(int cmd, unsigned int flags, int
argc, char **argv,
req->n.nlmsg_type = cmd;
req->t.tcm_family = AF_UNSPEC;
- if (cmd == RTM_NEWTFILTER && flags & NLM_F_CREATE)
+ if ((cmd == RTM_NEWTFILTER || cmd == RTM_NEWCHAIN) &&
+ flags & NLM_F_CREATE)
protocol = htons(ETH_P_ALL);
while (argc > 0) {
@@ -261,7 +269,10 @@ int print_filter(const struct sockaddr_nl *who, struct
nlmsghdr *n, void *arg)
if (n->nlmsg_type != RTM_NEWTFILTER &&
n->nlmsg_type != RTM_GETTFILTER &&
- n->nlmsg_type !=