tc_filter: add support for chain index
Allow user to put filter to a specific chain identified by index. Signed-off-by: Jiri Pirko <jiri@mellanox.com>
This commit is contained in:
parent
cda81a4ea5
commit
732f03461b
|
|
@ -31,7 +31,7 @@ static void usage(void)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: tc filter [ add | del | change | replace | show ] dev STRING\n"
|
"Usage: tc filter [ add | del | change | replace | show ] dev STRING\n"
|
||||||
"Usage: tc filter get dev STRING parent CLASSID protocol PROTO handle FILTERID pref PRIO FILTER_TYPE\n"
|
"Usage: tc filter get dev STRING parent CLASSID protocol PROTO handle FILTERID pref PRIO FILTER_TYPE\n"
|
||||||
" [ pref PRIO ] protocol PROTO\n"
|
" [ pref PRIO ] protocol PROTO [ chain CHAIN_INDEX ]\n"
|
||||||
" [ estimator INTERVAL TIME_CONSTANT ]\n"
|
" [ estimator INTERVAL TIME_CONSTANT ]\n"
|
||||||
" [ root | ingress | egress | parent CLASSID ]\n"
|
" [ root | ingress | egress | parent CLASSID ]\n"
|
||||||
" [ handle FILTERID ] [ [ FILTER_TYPE ] [ help | OPTIONS ] ]\n"
|
" [ handle FILTERID ] [ [ FILTER_TYPE ] [ help | OPTIONS ] ]\n"
|
||||||
|
|
@ -59,6 +59,8 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
__u32 prio = 0;
|
__u32 prio = 0;
|
||||||
__u32 protocol = 0;
|
__u32 protocol = 0;
|
||||||
int protocol_set = 0;
|
int protocol_set = 0;
|
||||||
|
__u32 chain_index;
|
||||||
|
int chain_index_set = 0;
|
||||||
char *fhandle = NULL;
|
char *fhandle = NULL;
|
||||||
char d[16] = {};
|
char d[16] = {};
|
||||||
char k[16] = {};
|
char k[16] = {};
|
||||||
|
|
@ -127,6 +129,13 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
invarg("invalid protocol", *argv);
|
invarg("invalid protocol", *argv);
|
||||||
protocol = id;
|
protocol = id;
|
||||||
protocol_set = 1;
|
protocol_set = 1;
|
||||||
|
} else if (matches(*argv, "chain") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (chain_index_set)
|
||||||
|
duparg("chain", *argv);
|
||||||
|
if (get_u32(&chain_index, *argv, 0))
|
||||||
|
invarg("invalid chain index value", *argv);
|
||||||
|
chain_index_set = 1;
|
||||||
} else if (matches(*argv, "estimator") == 0) {
|
} else if (matches(*argv, "estimator") == 0) {
|
||||||
if (parse_estimator(&argc, &argv, &est) < 0)
|
if (parse_estimator(&argc, &argv, &est) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -146,6 +155,9 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
|
|
||||||
req.t.tcm_info = TC_H_MAKE(prio<<16, protocol);
|
req.t.tcm_info = TC_H_MAKE(prio<<16, protocol);
|
||||||
|
|
||||||
|
if (chain_index_set)
|
||||||
|
addattr32(&req.n, sizeof(req), TCA_CHAIN, chain_index);
|
||||||
|
|
||||||
if (k[0])
|
if (k[0])
|
||||||
addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1);
|
addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1);
|
||||||
|
|
||||||
|
|
@ -167,6 +179,7 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (est.ewma_log)
|
if (est.ewma_log)
|
||||||
addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est));
|
addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est));
|
||||||
|
|
||||||
|
|
@ -193,6 +206,8 @@ static __u32 filter_parent;
|
||||||
static int filter_ifindex;
|
static int filter_ifindex;
|
||||||
static __u32 filter_prio;
|
static __u32 filter_prio;
|
||||||
static __u32 filter_protocol;
|
static __u32 filter_protocol;
|
||||||
|
static __u32 filter_chain_index;
|
||||||
|
static int filter_chain_index_set;
|
||||||
__u16 f_proto;
|
__u16 f_proto;
|
||||||
|
|
||||||
int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
||||||
|
|
@ -270,6 +285,15 @@ int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(fp, "%s ", rta_getattr_str(tb[TCA_KIND]));
|
fprintf(fp, "%s ", rta_getattr_str(tb[TCA_KIND]));
|
||||||
|
|
||||||
|
if (tb[TCA_CHAIN]) {
|
||||||
|
__u32 chain_index = rta_getattr_u32(tb[TCA_CHAIN]);
|
||||||
|
|
||||||
|
if (!filter_chain_index_set ||
|
||||||
|
filter_chain_index != chain_index)
|
||||||
|
fprintf(fp, "chain %u ", chain_index);
|
||||||
|
}
|
||||||
|
|
||||||
q = get_filter_kind(RTA_DATA(tb[TCA_KIND]));
|
q = get_filter_kind(RTA_DATA(tb[TCA_KIND]));
|
||||||
if (tb[TCA_OPTIONS]) {
|
if (tb[TCA_OPTIONS]) {
|
||||||
if (q)
|
if (q)
|
||||||
|
|
@ -311,6 +335,8 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
__u32 prio = 0;
|
__u32 prio = 0;
|
||||||
__u32 protocol = 0;
|
__u32 protocol = 0;
|
||||||
int protocol_set = 0;
|
int protocol_set = 0;
|
||||||
|
__u32 chain_index;
|
||||||
|
int chain_index_set = 0;
|
||||||
__u32 parent_handle = 0;
|
__u32 parent_handle = 0;
|
||||||
char *fhandle = NULL;
|
char *fhandle = NULL;
|
||||||
char d[16] = {};
|
char d[16] = {};
|
||||||
|
|
@ -375,6 +401,13 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
invarg("invalid protocol", *argv);
|
invarg("invalid protocol", *argv);
|
||||||
protocol = id;
|
protocol = id;
|
||||||
protocol_set = 1;
|
protocol_set = 1;
|
||||||
|
} else if (matches(*argv, "chain") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (chain_index_set)
|
||||||
|
duparg("chain", *argv);
|
||||||
|
if (get_u32(&chain_index, *argv, 0))
|
||||||
|
invarg("invalid chain index value", *argv);
|
||||||
|
chain_index_set = 1;
|
||||||
} else if (matches(*argv, "help") == 0) {
|
} else if (matches(*argv, "help") == 0) {
|
||||||
usage();
|
usage();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -401,6 +434,9 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
|
|
||||||
req.t.tcm_info = TC_H_MAKE(prio<<16, protocol);
|
req.t.tcm_info = TC_H_MAKE(prio<<16, protocol);
|
||||||
|
|
||||||
|
if (chain_index_set)
|
||||||
|
addattr32(&req.n, sizeof(req), TCA_CHAIN, chain_index);
|
||||||
|
|
||||||
if (req.t.tcm_parent == TC_H_UNSPEC) {
|
if (req.t.tcm_parent == TC_H_UNSPEC) {
|
||||||
fprintf(stderr, "Must specify filter parent\n");
|
fprintf(stderr, "Must specify filter parent\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -457,10 +493,20 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
|
||||||
|
|
||||||
static int tc_filter_list(int argc, char **argv)
|
static int tc_filter_list(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct tcmsg t = { .tcm_family = AF_UNSPEC };
|
struct {
|
||||||
|
struct nlmsghdr n;
|
||||||
|
struct tcmsg t;
|
||||||
|
char buf[MAX_MSG];
|
||||||
|
} req = {
|
||||||
|
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
|
||||||
|
.n.nlmsg_type = RTM_GETTFILTER,
|
||||||
|
.t.tcm_parent = TC_H_UNSPEC,
|
||||||
|
.t.tcm_family = AF_UNSPEC,
|
||||||
|
};
|
||||||
char d[16] = {};
|
char d[16] = {};
|
||||||
__u32 prio = 0;
|
__u32 prio = 0;
|
||||||
__u32 protocol = 0;
|
__u32 protocol = 0;
|
||||||
|
__u32 chain_index;
|
||||||
char *fhandle = NULL;
|
char *fhandle = NULL;
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
|
|
@ -470,39 +516,39 @@ static int tc_filter_list(int argc, char **argv)
|
||||||
duparg("dev", *argv);
|
duparg("dev", *argv);
|
||||||
strncpy(d, *argv, sizeof(d)-1);
|
strncpy(d, *argv, sizeof(d)-1);
|
||||||
} else if (strcmp(*argv, "root") == 0) {
|
} else if (strcmp(*argv, "root") == 0) {
|
||||||
if (t.tcm_parent) {
|
if (req.t.tcm_parent) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: \"root\" is duplicate parent ID\n");
|
"Error: \"root\" is duplicate parent ID\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
filter_parent = t.tcm_parent = TC_H_ROOT;
|
filter_parent = req.t.tcm_parent = TC_H_ROOT;
|
||||||
} else if (strcmp(*argv, "ingress") == 0) {
|
} else if (strcmp(*argv, "ingress") == 0) {
|
||||||
if (t.tcm_parent) {
|
if (req.t.tcm_parent) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: \"ingress\" is duplicate parent ID\n");
|
"Error: \"ingress\" is duplicate parent ID\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
filter_parent = TC_H_MAKE(TC_H_CLSACT,
|
filter_parent = TC_H_MAKE(TC_H_CLSACT,
|
||||||
TC_H_MIN_INGRESS);
|
TC_H_MIN_INGRESS);
|
||||||
t.tcm_parent = filter_parent;
|
req.t.tcm_parent = filter_parent;
|
||||||
} else if (strcmp(*argv, "egress") == 0) {
|
} else if (strcmp(*argv, "egress") == 0) {
|
||||||
if (t.tcm_parent) {
|
if (req.t.tcm_parent) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: \"egress\" is duplicate parent ID\n");
|
"Error: \"egress\" is duplicate parent ID\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
filter_parent = TC_H_MAKE(TC_H_CLSACT,
|
filter_parent = TC_H_MAKE(TC_H_CLSACT,
|
||||||
TC_H_MIN_EGRESS);
|
TC_H_MIN_EGRESS);
|
||||||
t.tcm_parent = filter_parent;
|
req.t.tcm_parent = filter_parent;
|
||||||
} else if (strcmp(*argv, "parent") == 0) {
|
} else if (strcmp(*argv, "parent") == 0) {
|
||||||
__u32 handle;
|
__u32 handle;
|
||||||
|
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (t.tcm_parent)
|
if (req.t.tcm_parent)
|
||||||
duparg("parent", *argv);
|
duparg("parent", *argv);
|
||||||
if (get_tc_classid(&handle, *argv))
|
if (get_tc_classid(&handle, *argv))
|
||||||
invarg("invalid parent ID", *argv);
|
invarg("invalid parent ID", *argv);
|
||||||
filter_parent = t.tcm_parent = handle;
|
filter_parent = req.t.tcm_parent = handle;
|
||||||
} else if (strcmp(*argv, "handle") == 0) {
|
} else if (strcmp(*argv, "handle") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (fhandle)
|
if (fhandle)
|
||||||
|
|
@ -526,6 +572,14 @@ static int tc_filter_list(int argc, char **argv)
|
||||||
invarg("invalid protocol", *argv);
|
invarg("invalid protocol", *argv);
|
||||||
protocol = res;
|
protocol = res;
|
||||||
filter_protocol = protocol;
|
filter_protocol = protocol;
|
||||||
|
} else if (matches(*argv, "chain") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (filter_chain_index_set)
|
||||||
|
duparg("chain", *argv);
|
||||||
|
if (get_u32(&chain_index, *argv, 0))
|
||||||
|
invarg("invalid chain index value", *argv);
|
||||||
|
filter_chain_index_set = 1;
|
||||||
|
filter_chain_index = chain_index;
|
||||||
} else if (matches(*argv, "help") == 0) {
|
} else if (matches(*argv, "help") == 0) {
|
||||||
usage();
|
usage();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -538,20 +592,23 @@ static int tc_filter_list(int argc, char **argv)
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
}
|
}
|
||||||
|
|
||||||
t.tcm_info = TC_H_MAKE(prio<<16, protocol);
|
req.t.tcm_info = TC_H_MAKE(prio<<16, protocol);
|
||||||
|
|
||||||
ll_init_map(&rth);
|
ll_init_map(&rth);
|
||||||
|
|
||||||
if (d[0]) {
|
if (d[0]) {
|
||||||
t.tcm_ifindex = ll_name_to_index(d);
|
req.t.tcm_ifindex = ll_name_to_index(d);
|
||||||
if (t.tcm_ifindex == 0) {
|
if (req.t.tcm_ifindex == 0) {
|
||||||
fprintf(stderr, "Cannot find device \"%s\"\n", d);
|
fprintf(stderr, "Cannot find device \"%s\"\n", d);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
filter_ifindex = t.tcm_ifindex;
|
filter_ifindex = req.t.tcm_ifindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtnl_dump_request(&rth, RTM_GETTFILTER, &t, sizeof(t)) < 0) {
|
if (filter_chain_index_set)
|
||||||
|
addattr32(&req.n, sizeof(req), TCA_CHAIN, chain_index);
|
||||||
|
|
||||||
|
if (rtnl_dump_request_n(&rth, &req.n) < 0) {
|
||||||
perror("Cannot send dump request");
|
perror("Cannot send dump request");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue