Roopa Prabhu
2015-Oct-06  15:16 UTC
[Bridge] [PATCH net-next] bridge: allow adding of fdb entries pointing to the bridge device
From: Roopa Prabhu <roopa at cumulusnetworks.com>
This patch enables adding of fdb entries pointing to the bridge device.
This can be used to propagate mac address of vlan interfaces
configured on top of the vlan filtering bridge.
Before:
$bridge fdb add 44:38:39:00:27:9f dev bridge
RTNETLINK answers: Invalid argument
After:
$bridge fdb add 44:38:39:00:27:9f dev bridge
Signed-off-by: Roopa Prabhu <roopa at cumulusnetworks.com>
---
 net/bridge/br_fdb.c | 106 ++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 83 insertions(+), 23 deletions(-)
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 7f7d551..5d0f6f9 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -608,13 +608,14 @@ void br_fdb_update(struct net_bridge *br, struct
net_bridge_port *source,
 	}
 }
 
-static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb)
+static int fdb_to_nud(const struct net_bridge *br,
+		      const struct net_bridge_fdb_entry *fdb)
 {
 	if (fdb->is_local)
 		return NUD_PERMANENT;
 	else if (fdb->is_static)
 		return NUD_NOARP;
-	else if (has_expired(fdb->dst->br, fdb))
+	else if (has_expired(br, fdb))
 		return NUD_STALE;
 	else
 		return NUD_REACHABLE;
@@ -640,7 +641,7 @@ static int fdb_fill_info(struct sk_buff *skb, const struct
net_bridge *br,
 	ndm->ndm_flags	 = fdb->added_by_external_learn ? NTF_EXT_LEARNED : 0;
 	ndm->ndm_type	 = 0;
 	ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex :
br->dev->ifindex;
-	ndm->ndm_state   = fdb_to_nud(fdb);
+	ndm->ndm_state   = fdb_to_nud(br, fdb);
 
 	if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr))
 		goto nla_put_failure;
@@ -785,7 +786,7 @@ static int fdb_add_entry(struct net_bridge_port *source,
const __u8 *addr,
 		}
 	}
 
-	if (fdb_to_nud(fdb) != state) {
+	if (fdb_to_nud(br, fdb) != state) {
 		if (state & NUD_PERMANENT) {
 			fdb->is_local = 1;
 			if (!fdb->is_static) {
@@ -848,6 +849,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 	struct net_bridge_vlan_group *vg;
 	struct net_bridge_port *p;
 	struct net_bridge_vlan *v;
+	struct net_bridge *br = NULL;
 	int err = 0;
 
 	if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
@@ -860,14 +862,19 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 		return -EINVAL;
 	}
 
-	p = br_port_get_rtnl(dev);
-	if (p == NULL) {
-		pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n",
-			dev->name);
-		return -EINVAL;
+	if (dev->priv_flags & IFF_EBRIDGE) {
+		br = netdev_priv(dev);
+		vg = br_vlan_group(br);
+	} else {
+		p = br_port_get_rtnl(dev);
+		if (!p) {
+			pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n",
+				dev->name);
+			return -EINVAL;
+		}
+		vg = nbp_vlan_group(p);
 	}
 
-	vg = nbp_vlan_group(p);
 	if (vid) {
 		v = br_vlan_find(vg, vid);
 		if (!v) {
@@ -877,9 +884,15 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 		}
 
 		/* VID was specified, so use it. */
-		err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
+		if (dev->priv_flags & IFF_EBRIDGE)
+			err = br_fdb_insert(br, NULL, addr, vid);
+		else
+			err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
 	} else {
-		err = __br_fdb_add(ndm, p, addr, nlh_flags, 0);
+		if (dev->priv_flags & IFF_EBRIDGE)
+			err = br_fdb_insert(br, NULL, addr, 0);
+		else
+			err = __br_fdb_add(ndm, p, addr, nlh_flags, 0);
 		if (err || !vg || !vg->num_vlans)
 			goto out;
 
@@ -888,7 +901,11 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 		 * vlan on this port.
 		 */
 		list_for_each_entry(v, &vg->vlan_list, vlist) {
-			err = __br_fdb_add(ndm, p, addr, nlh_flags, v->vid);
+			if (dev->priv_flags & IFF_EBRIDGE)
+				err = br_fdb_insert(br, NULL, addr, v->vid);
+			else
+				err = __br_fdb_add(ndm, p, addr, nlh_flags,
+						   v->vid);
 			if (err)
 				goto out;
 		}
@@ -898,6 +915,32 @@ out:
 	return err;
 }
 
+static int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr,
+			      u16 vid)
+{
+	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
+	struct net_bridge_fdb_entry *fdb;
+
+	fdb = fdb_find(head, addr, vid);
+	if (!fdb)
+		return -ENOENT;
+
+	fdb_delete(br, fdb);
+	return 0;
+}
+
+static int __br_fdb_delete_by_addr(struct net_bridge *br,
+				   const unsigned char *addr, u16 vid)
+{
+	int err;
+
+	spin_lock_bh(&br->hash_lock);
+	err = fdb_delete_by_addr(br, addr, vid);
+	spin_unlock_bh(&br->hash_lock);
+
+	return err;
+}
+
 static int fdb_delete_by_addr_and_port(struct net_bridge_port *p,
 				       const u8 *addr, u16 vlan)
 {
@@ -933,16 +976,22 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 	struct net_bridge_vlan_group *vg;
 	struct net_bridge_port *p;
 	struct net_bridge_vlan *v;
+	struct net_bridge *br;
 	int err;
 
-	p = br_port_get_rtnl(dev);
-	if (p == NULL) {
-		pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n",
-			dev->name);
-		return -EINVAL;
+	if (dev->priv_flags & IFF_EBRIDGE) {
+		br = netdev_priv(dev);
+		vg = br_vlan_group(br);
+	} else {
+		p = br_port_get_rtnl(dev);
+		if (!p) {
+			pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n",
+				dev->name);
+			return -EINVAL;
+		}
+		vg = nbp_vlan_group(p);
 	}
 
-	vg = nbp_vlan_group(p);
 	if (vid) {
 		v = br_vlan_find(vg, vid);
 		if (!v) {
@@ -951,15 +1000,26 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 			return -EINVAL;
 		}
 
-		err = __br_fdb_delete(p, addr, vid);
+		if (dev->priv_flags & IFF_EBRIDGE)
+			err = __br_fdb_delete_by_addr(br, addr, vid);
+		else
+			err = __br_fdb_delete(p, addr, vid);
 	} else {
 		err = -ENOENT;
-		err &= __br_fdb_delete(p, addr, 0);
+		if (dev->priv_flags & IFF_EBRIDGE)
+			err = __br_fdb_delete_by_addr(br, addr, 0);
+		else
+			err &= __br_fdb_delete(p, addr, 0);
+
 		if (!vg || !vg->num_vlans)
 			goto out;
 
-		list_for_each_entry(v, &vg->vlan_list, vlist)
-			err &= __br_fdb_delete(p, addr, v->vid);
+		list_for_each_entry(v, &vg->vlan_list, vlist) {
+			if (dev->priv_flags & IFF_EBRIDGE)
+				err = __br_fdb_delete_by_addr(br, addr, v->vid);
+			else
+				err &= __br_fdb_delete(p, addr, v->vid);
+		}
 	}
 out:
 	return err;
-- 
1.9.1
kbuild test robot
2015-Oct-06  15:29 UTC
[Bridge] [PATCH net-next] bridge: allow adding of fdb entries pointing to the bridge device
Hi Roopa,
[auto build test WARNING on next-20151006 -- if it's inappropriate base,
please ignore]
config: sh-titan_defconfig (attached as .config)
reproduce:
        wget
https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
-O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sh 
Note: it may well be a FALSE warning. FWIW you are at least aware of it now.
http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings
All warnings (new ones prefixed by >>):
   net/bridge/br_fdb.c: In function
'br_fdb_add':>> net/bridge/br_fdb.c:784:13: warning: 'p' may be used
uninitialized in this function [-Wuninitialized]
   net/bridge/br_fdb.c:850:26: note: 'p' was declared here
   net/bridge/br_fdb.c: In function 'br_fdb_delete':
   net/bridge/br_fdb.c:952:11: warning: 'p' may be used uninitialized in
this function [-Wuninitialized]
   net/bridge/br_fdb.c:977:26: note: 'p' was declared here
vim +/p +784 net/bridge/br_fdb.c
eb8d7baa Wilson Kok        2015-05-25  768  
2ba071ec Vlad Yasevich     2013-02-13  769  	fdb = fdb_find(head, addr, vid);
64af1bac stephen hemminger 2011-09-30  770  	if (fdb == NULL) {
64af1bac stephen hemminger 2011-09-30  771  		if (!(flags & NLM_F_CREATE))
64af1bac stephen hemminger 2011-09-30  772  			return -ENOENT;
36fd2b63 stephen hemminger 2011-04-04  773  
2ba071ec Vlad Yasevich     2013-02-13  774  		fdb = fdb_create(head, source,
addr, vid);
36fd2b63 stephen hemminger 2011-04-04  775  		if (!fdb)
36fd2b63 stephen hemminger 2011-04-04  776  			return -ENOMEM;
b0a397fb roopa             2013-04-22  777  
b0a397fb roopa             2013-04-22  778  		modified = true;
64af1bac stephen hemminger 2011-09-30  779  	} else {
64af1bac stephen hemminger 2011-09-30  780  		if (flags & NLM_F_EXCL)
64af1bac stephen hemminger 2011-09-30  781  			return -EEXIST;
b0a397fb roopa             2013-04-22  782  
b0a397fb roopa             2013-04-22  783  		if (fdb->dst != source) {
b0a397fb roopa             2013-04-22 @784  			fdb->dst = source;
b0a397fb roopa             2013-04-22  785  			modified = true;
b0a397fb roopa             2013-04-22  786  		}
64af1bac stephen hemminger 2011-09-30  787  	}
36fd2b63 stephen hemminger 2011-04-04  788  
0e29720e Roopa Prabhu      2015-10-06  789  	if (fdb_to_nud(br, fdb) != state) {
145beee8 Vlad Yasevich     2014-05-16  790  		if (state & NUD_PERMANENT) {
145beee8 Vlad Yasevich     2014-05-16  791  			fdb->is_local = 1;
145beee8 Vlad Yasevich     2014-05-16  792  			if (!fdb->is_static) {
:::::: The code at line 784 was first introduced by commit
:::::: b0a397fb352e65e3b6501dca9662617a18862ef1 bridge: Add fdb dst check during
fdb update
:::::: TO: roopa <roopa at cumulusnetworks.com>
:::::: CC: David S. Miller <davem at davemloft.net>
---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 15308 bytes
Desc: not available
URL:
<http://lists.linuxfoundation.org/pipermail/bridge/attachments/20151006/b2ccbcf0/attachment-0001.obj>
roopa
2015-Oct-06  15:55 UTC
[Bridge] [PATCH net-next] bridge: allow adding of fdb entries pointing to the bridge device
On 10/6/15, 8:29 AM, kbuild test robot wrote:> Hi Roopa, > > [auto build test WARNING on next-20151006 -- if it's inappropriate base, please ignore] > > config: sh-titan_defconfig (attached as .config) > reproduce: > wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross > chmod +x ~/bin/make.cross > # save the attached .config to linux build tree > make.cross ARCH=sh > > Note: it may well be a FALSE warning. FWIW you are at least aware of it now. > http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings > > All warnings (new ones prefixed by >>): > > net/bridge/br_fdb.c: In function 'br_fdb_add': >>> net/bridge/br_fdb.c:784:13: warning: 'p' may be used uninitialized in this function [-Wuninitialized] > net/bridge/br_fdb.c:850:26: note: 'p' was declared here > net/bridge/br_fdb.c: In function 'br_fdb_delete': > net/bridge/br_fdb.c:952:11: warning: 'p' may be used uninitialized in this function [-Wuninitialized] > net/bridge/br_fdb.c:977:26: note: 'p' was declared here > > vim +/p +784 net/bridge/br_fdb.c > > eb8d7baa Wilson Kok 2015-05-25 768 > 2ba071ec Vlad Yasevich 2013-02-13 769 fdb = fdb_find(head, addr, vid); > 64af1bac stephen hemminger 2011-09-30 770 if (fdb == NULL) { > 64af1bac stephen hemminger 2011-09-30 771 if (!(flags & NLM_F_CREATE)) > 64af1bac stephen hemminger 2011-09-30 772 return -ENOENT; > 36fd2b63 stephen hemminger 2011-04-04 773 > 2ba071ec Vlad Yasevich 2013-02-13 774 fdb = fdb_create(head, source, addr, vid); > 36fd2b63 stephen hemminger 2011-04-04 775 if (!fdb) > 36fd2b63 stephen hemminger 2011-04-04 776 return -ENOMEM; > b0a397fb roopa 2013-04-22 777 > b0a397fb roopa 2013-04-22 778 modified = true; > 64af1bac stephen hemminger 2011-09-30 779 } else { > 64af1bac stephen hemminger 2011-09-30 780 if (flags & NLM_F_EXCL) > 64af1bac stephen hemminger 2011-09-30 781 return -EEXIST; > b0a397fb roopa 2013-04-22 782 > b0a397fb roopa 2013-04-22 783 if (fdb->dst != source) { > b0a397fb roopa 2013-04-22 @784 fdb->dst = source; > b0a397fb roopa 2013-04-22 785 modified = true; > b0a397fb roopa 2013-04-22 786 } > 64af1bac stephen hemminger 2011-09-30 787 } > 36fd2b63 stephen hemminger 2011-04-04 788 > 0e29720e Roopa Prabhu 2015-10-06 789 if (fdb_to_nud(br, fdb) != state) { > 145beee8 Vlad Yasevich 2014-05-16 790 if (state & NUD_PERMANENT) { > 145beee8 Vlad Yasevich 2014-05-16 791 fdb->is_local = 1; > 145beee8 Vlad Yasevich 2014-05-16 792 if (!fdb->is_static) { > >It is not used when it is not initialized. But I will resubmit the patch by initializing it to NULL (thanks nikolay for the suggestion). Thanks.