From a0ffacb6882fb0d7ad92ca663804ed775d59c05a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20H=C3=B6glund?= <jonas.hoglund@embeddednation.com>
Date: Mon, 5 Nov 2018 13:07:23 +0100
Subject: [PATCH] mcast-pa: bridge mdb src addr

---
 include/linux/if_bridge.h |  1 +
 net/bridge/br_mdb.c       |  4 +++-
 net/bridge/br_multicast.c | 20 ++++++++++----------
 net/bridge/br_private.h   |  2 +-
 4 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 0911c8cd5..b1419eb81 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -26,6 +26,7 @@ struct br_ip {
 	} u;
 	__be16		proto;
 	__u16           vid;
+	unsigned char src[ETH_ALEN];
 };
 
 struct br_ip_list {
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 57e94a1b5..8c919b8db 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -347,7 +347,8 @@ errout:
 }
 
 void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
-		   struct br_ip *group, int type, u8 flags)
+				   struct br_ip *group, int type, u8 flags,
+				   const unsigned char *src)
 {
 	struct br_mdb_entry entry;
 
@@ -359,6 +360,7 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
 	entry.addr.u.ip6 = group->u.ip6;
 #endif
 	entry.vid = group->vid;
+	if (src) memcpy(&entry.src_addr.eth_addr, src, ETH_ALEN);
 	__mdb_entry_fill_flags(&entry, flags);
 	__br_mdb_notify(dev, port, &entry, type);
 }
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 8cc0c252f..b1687794e 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -285,8 +285,9 @@ static void br_multicast_del_pg(struct net_bridge *br,
 		rcu_assign_pointer(*pp, p->next);
 		hlist_del_init(&p->mglist);
 		del_timer(&p->timer);
+		memcpy(mp->addr.src, pg->addr.src, ETH_ALEN);
 		br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB,
-			      p->flags);
+					  p->flags, pg->addr.src);
 		call_rcu_bh(&p->rcu, br_multicast_free_pg);
 
 		if (!mp->ports && !mp->mglist &&
@@ -669,6 +670,10 @@ struct net_bridge_port_group *br_multicast_new_port_group(
 	if (unlikely(!p))
 		return NULL;
 
+	if (src) {
+		memcpy(group->src, src, ETH_ALEN);
+		memcpy(p->eth_addr, src, ETH_ALEN);
+	}
 	p->addr = *group;
 	p->port = port;
 	p->flags = flags;
@@ -692,13 +697,6 @@ static bool br_port_group_equal(struct net_bridge_port_group *p,
 	if (p->port != port)
 		return false;
 
-	if (!(p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) !=
-	    !(port->flags & BR_MULTICAST_TO_UNICAST))
-		return false;
-
-	if (!(p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST))
-		return true;
-
 	if (!src)
 		return false;
 
@@ -745,7 +743,7 @@ static int br_multicast_add_group(struct net_bridge *br,
 	if (unlikely(!p))
 		goto err;
 	rcu_assign_pointer(*pp, p);
-	br_mdb_notify(br->dev, port, group, RTM_NEWMDB, 0);
+	br_mdb_notify(br->dev, port, group, RTM_NEWMDB, 0,);
 
 found:
 	mod_timer(&p->timer, now + br->multicast_membership_interval);
@@ -1527,8 +1525,9 @@ br_multicast_leave_group(struct net_bridge *br,
 			hlist_del_init(&p->mglist);
 			del_timer(&p->timer);
 			call_rcu_bh(&p->rcu, br_multicast_free_pg);
+			memcpy(group->src, src, ETH_ALEN);
 			br_mdb_notify(br->dev, port, group, RTM_DELMDB,
-				      p->flags);
+						  p->flags, src);
 
 			if (!mp->ports && !mp->mglist &&
 			    netif_running(br->dev))
@@ -1616,6 +1615,7 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
 	br_group.u.ip4 = group;
 	br_group.proto = htons(ETH_P_IP);
 	br_group.vid = vid;
+	memcpy(bc_group.src, src, ETH_ALEN);
 
 	br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
 				 own_query, src);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 6acd965fd..757fecbce 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -661,7 +661,7 @@ br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group,
 void br_mdb_init(void);
 void br_mdb_uninit(void);
 void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
-		   struct br_ip *group, int type, u8 flags);
+				   struct br_ip *group, int type, u8 flags, const unsigned char *src);
 void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
 		   int type);
 void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p,
-- 
GitLab