Commit fa59b27c authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

net_sched: do not broadcast RTM_GETTFILTER result

There are two ways to get tc filters from kernel to user space.

1) Full dump (tc_dump_tfilter())
2) RTM_GETTFILTER to get one precise filter, reducing overhead.

The second operation is unfortunately broadcasting its result,
polluting "tc monitor" users.

This patch makes sure only the requester gets the result, using
netlink_unicast() instead of rtnetlink_send()

Jamal cooked an iproute2 patch to implement "tc filter get" operation,
but other user space libraries already use RTM_GETTFILTER when a single
filter is queried, instead of dumping all filters.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Acked-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6d3a4c40
...@@ -101,7 +101,7 @@ EXPORT_SYMBOL(unregister_tcf_proto_ops); ...@@ -101,7 +101,7 @@ EXPORT_SYMBOL(unregister_tcf_proto_ops);
static int tfilter_notify(struct net *net, struct sk_buff *oskb, static int tfilter_notify(struct net *net, struct sk_buff *oskb,
struct nlmsghdr *n, struct tcf_proto *tp, struct nlmsghdr *n, struct tcf_proto *tp,
unsigned long fh, int event); unsigned long fh, int event, bool unicast);
static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb, static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
struct nlmsghdr *n, struct nlmsghdr *n,
...@@ -112,7 +112,7 @@ static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb, ...@@ -112,7 +112,7 @@ static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
for (it_chain = chain; (tp = rtnl_dereference(*it_chain)) != NULL; for (it_chain = chain; (tp = rtnl_dereference(*it_chain)) != NULL;
it_chain = &tp->next) it_chain = &tp->next)
tfilter_notify(net, oskb, n, tp, 0, event); tfilter_notify(net, oskb, n, tp, 0, event, false);
} }
/* Select new prio value from the range, managed by kernel. */ /* Select new prio value from the range, managed by kernel. */
...@@ -319,7 +319,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -319,7 +319,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
RCU_INIT_POINTER(*back, next); RCU_INIT_POINTER(*back, next);
tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); tfilter_notify(net, skb, n, tp, fh,
RTM_DELTFILTER, false);
tcf_destroy(tp, true); tcf_destroy(tp, true);
err = 0; err = 0;
goto errout; goto errout;
...@@ -345,14 +346,14 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -345,14 +346,14 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
struct tcf_proto *next = rtnl_dereference(tp->next); struct tcf_proto *next = rtnl_dereference(tp->next);
tfilter_notify(net, skb, n, tp, fh, tfilter_notify(net, skb, n, tp, fh,
RTM_DELTFILTER); RTM_DELTFILTER, false);
if (tcf_destroy(tp, false)) if (tcf_destroy(tp, false))
RCU_INIT_POINTER(*back, next); RCU_INIT_POINTER(*back, next);
} }
goto errout; goto errout;
case RTM_GETTFILTER: case RTM_GETTFILTER:
err = tfilter_notify(net, skb, n, tp, fh, err = tfilter_notify(net, skb, n, tp, fh,
RTM_NEWTFILTER); RTM_NEWTFILTER, true);
goto errout; goto errout;
default: default:
err = -EINVAL; err = -EINVAL;
...@@ -367,7 +368,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -367,7 +368,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
RCU_INIT_POINTER(tp->next, rtnl_dereference(*back)); RCU_INIT_POINTER(tp->next, rtnl_dereference(*back));
rcu_assign_pointer(*back, tp); rcu_assign_pointer(*back, tp);
} }
tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER); tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER, false);
} else { } else {
if (tp_created) if (tp_created)
tcf_destroy(tp, true); tcf_destroy(tp, true);
...@@ -419,7 +420,7 @@ static int tcf_fill_node(struct net *net, struct sk_buff *skb, ...@@ -419,7 +420,7 @@ static int tcf_fill_node(struct net *net, struct sk_buff *skb,
static int tfilter_notify(struct net *net, struct sk_buff *oskb, static int tfilter_notify(struct net *net, struct sk_buff *oskb,
struct nlmsghdr *n, struct tcf_proto *tp, struct nlmsghdr *n, struct tcf_proto *tp,
unsigned long fh, int event) unsigned long fh, int event, bool unicast)
{ {
struct sk_buff *skb; struct sk_buff *skb;
u32 portid = oskb ? NETLINK_CB(oskb).portid : 0; u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
...@@ -433,6 +434,9 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb, ...@@ -433,6 +434,9 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb,
return -EINVAL; return -EINVAL;
} }
if (unicast)
return netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT);
return rtnetlink_send(skb, net, portid, RTNLGRP_TC, return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
n->nlmsg_flags & NLM_F_ECHO); n->nlmsg_flags & NLM_F_ECHO);
} }
......
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