aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn Fastabend <john.r.fastabend@intel.com>2012-04-15 02:44:14 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-15 13:06:04 -0400
commit3ff661c38c8492a2859e39e0ea1e3b6d30e89bf5 (patch)
treeb9bbd41a8fd1764cc49e8a2bb7c777328800eaa8 /net
parentd83b060360485454fcd6870340ec01d6f96f2295 (diff)
net: rtnetlink notify events for FDB NTF_SELF adds and deletes
It is useful to be able to monitor for FDB events in user space. This patch adds support to generate netlink events when a change is made to a device supporting the FDB ops. This brings embedded switches inline with the SW net/bridge which triggers events on FDB updates as well. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/rtnetlink.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index e8488c7b092c..b442d35bbc8b 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2011,6 +2011,33 @@ nla_put_failure:
2011 return -EMSGSIZE; 2011 return -EMSGSIZE;
2012} 2012}
2013 2013
2014static inline size_t rtnl_fdb_nlmsg_size(void)
2015{
2016 return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN);
2017}
2018
2019static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type)
2020{
2021 struct net *net = dev_net(dev);
2022 struct sk_buff *skb;
2023 int err = -ENOBUFS;
2024
2025 skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC);
2026 if (!skb)
2027 goto errout;
2028
2029 err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF);
2030 if (err < 0) {
2031 kfree_skb(skb);
2032 goto errout;
2033 }
2034
2035 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2036 return;
2037errout:
2038 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
2039}
2040
2014static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 2041static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2015{ 2042{
2016 struct net *net = sock_net(skb->sk); 2043 struct net *net = sock_net(skb->sk);
@@ -2067,8 +2094,10 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2067 err = dev->netdev_ops->ndo_fdb_add(ndm, dev, addr, 2094 err = dev->netdev_ops->ndo_fdb_add(ndm, dev, addr,
2068 nlh->nlmsg_flags); 2095 nlh->nlmsg_flags);
2069 2096
2070 if (!err) 2097 if (!err) {
2098 rtnl_fdb_notify(dev, addr, RTM_NEWNEIGH);
2071 ndm->ndm_flags &= ~NTF_SELF; 2099 ndm->ndm_flags &= ~NTF_SELF;
2100 }
2072 } 2101 }
2073out: 2102out:
2074 return err; 2103 return err;
@@ -2125,8 +2154,10 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2125 if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) { 2154 if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) {
2126 err = dev->netdev_ops->ndo_fdb_del(ndm, dev, addr); 2155 err = dev->netdev_ops->ndo_fdb_del(ndm, dev, addr);
2127 2156
2128 if (!err) 2157 if (!err) {
2158 rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);
2129 ndm->ndm_flags &= ~NTF_SELF; 2159 ndm->ndm_flags &= ~NTF_SELF;
2160 }
2130 } 2161 }
2131out: 2162out:
2132 return err; 2163 return err;