Index: linux-4.19.118/net/bridge/br_forward.c
===================================================================
--- linux-4.19.118.orig/net/bridge/br_forward.c
+++ linux-4.19.118/net/bridge/br_forward.c
@@ -195,9 +195,33 @@ void br_flood(struct net_bridge *br, str
 {
 	u8 igmp_type = br_multicast_igmp_type(skb);
 	struct net_bridge_port *prev = NULL;
-	struct net_bridge_port *p;
+	struct net_bridge_port *p, *op = NULL;
+	u16 vid = 0;
+
+	(void) br_vlan_get_tag(skb, &vid);
 
 	list_for_each_entry_rcu(p, &br->port_list, list) {
+		/* Extra checks not to flood back to originating bridge member port */
+		if (br->flood_check || p->flags & BR_FLOOD_CHECK) {
+			op = br_port_get_rcu(skb->dev);
+			if ((op == p) && !should_deliver(p, skb)) {
+				netdev_dbg_ratelimited(br->dev, "flood_check:1 %s from %s blocked (addr:%pM, vlan:%u),"
+						                " prev %s, local_rcv %d, local_orig %d",
+					   p->dev->name, op->dev->name,
+					   eth_hdr(skb)->h_source, vid,
+					   (prev) ? prev->dev->name : "(nil)",
+					   local_rcv, local_orig);
+				continue;
+			}
+			if (prev && (op == prev) && !should_deliver(prev, skb)) {
+				netdev_dbg_ratelimited(br->dev, "flood_check:2 %s from %s blocked (addr:%pM, vlan:%u),"
+							        " local_rcv %d, local_orig %d\n",
+					   prev->dev->name, op->dev->name,
+					   eth_hdr(skb)->h_source, vid,
+					   local_rcv, local_orig);
+				prev = NULL;
+			}
+		}
 		/* Do not flood unicast traffic to ports that turn it off, nor
 		 * other traffic if flood off, except for traffic we originate
 		 */
@@ -223,6 +247,17 @@ void br_flood(struct net_bridge *br, str
 		    BR_INPUT_SKB_CB(skb)->proxyarp_replied)
 			continue;
 
+		if (op && op == prev) {
+			netdev_dbg_ratelimited(br->dev, "flood_check:3 %s from %s blocked (addr:%pM, vlan:%u),"
+					                " prev %s, local_rcv %d, local_orig %d,"
+					    		" should_deliver p %d, should_deliver prev %d\n",
+				   p->dev->name, op->dev->name,
+				   eth_hdr(skb)->h_source, vid,
+				   (prev) ? prev->dev->name : "(nil)",
+				   local_rcv, local_orig, should_deliver(p, skb),
+				   should_deliver(prev, skb));
+			prev = NULL;
+		}
 		prev = maybe_deliver(prev, p, skb, local_orig);
 		if (IS_ERR(prev))
 			goto out;
@@ -234,6 +269,19 @@ void br_flood(struct net_bridge *br, str
 	if (!prev)
 		goto out;
 
+	if (br->flood_check || p->flags & BR_FLOOD_CHECK) {
+		/* Extra checks not to flood back to originating bridge member port */
+		op = br_port_get_rcu(skb->dev);
+		if ((op == prev) && !should_deliver(prev, skb)) {
+			netdev_dbg_ratelimited(br->dev, "flood_check:4 %s from prev %s blocked (addr:%pM, vlan:%u),"
+							" local_rcv %d, local_orig %d\n",
+				   prev->dev->name, op->dev->name,
+				   eth_hdr(skb)->h_source, vid,
+				   local_rcv, local_orig);
+			goto out;
+		}
+	}
+
 	if (local_rcv)
 		deliver_clone(prev, skb, local_orig);
 	else
Index: linux-4.19.118/net/bridge/br_private.h
===================================================================
--- linux-4.19.118.orig/net/bridge/br_private.h
+++ linux-4.19.118/net/bridge/br_private.h
@@ -415,6 +415,7 @@ struct net_bridge {
 #endif
 	bool				neigh_suppress_enabled;
 	bool				mtu_set_by_user;
+	bool				flood_check;
 	struct hlist_head		fdb_list;
 };
 
Index: linux-4.19.118/net/bridge/br_sysfs_br.c
===================================================================
--- linux-4.19.118.orig/net/bridge/br_sysfs_br.c
+++ linux-4.19.118/net/bridge/br_sysfs_br.c
@@ -120,6 +120,27 @@ static ssize_t ageing_time_store(struct
 }
 static DEVICE_ATTR_RW(ageing_time);
 
+static ssize_t flood_check_show(struct device *d,
+				  struct device_attribute *attr, char *buf)
+{
+	struct net_bridge *br = to_bridge(d);
+	return sprintf(buf, "%u\n", br->flood_check);
+}
+
+static int set_flood_check(struct net_bridge *br, unsigned long val)
+{
+	br->flood_check = (val) ? true : false;
+	return 0;
+}
+
+static ssize_t flood_check_store(struct device *d,
+				 struct device_attribute *attr,
+				 const char *buf, size_t len)
+{
+	return store_bridge_parm(d, buf, len, set_flood_check);
+}
+static DEVICE_ATTR_RW(flood_check);
+
 static ssize_t stp_state_show(struct device *d,
 			      struct device_attribute *attr, char *buf)
 {
@@ -855,6 +876,7 @@ static struct attribute *bridge_attrs[]
 	&dev_attr_default_pvid.attr,
 	&dev_attr_vlan_stats_enabled.attr,
 #endif
+	&dev_attr_flood_check.attr,
 	NULL
 };
 
Index: linux-4.19.118/include/linux/if_bridge.h
===================================================================
--- linux-4.19.118.orig/include/linux/if_bridge.h
+++ linux-4.19.118/include/linux/if_bridge.h
@@ -51,6 +51,7 @@ struct br_ip_list {
 #define BR_BCAST_FLOOD		BIT(14)
 #define BR_NEIGH_SUPPRESS	BIT(15)
 #define BR_ISOLATED		BIT(16)
+#define BR_FLOOD_CHECK		BIT(17)
 
 #define BR_DEFAULT_AGEING_TIME	(300 * HZ)
 
Index: linux-4.19.118/net/bridge/br_sysfs_if.c
===================================================================
--- linux-4.19.118.orig/net/bridge/br_sysfs_if.c
+++ linux-4.19.118/net/bridge/br_sysfs_if.c
@@ -234,6 +234,7 @@ BRPORT_ATTR_FLAG(multicast_flood, BR_MCA
 BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD);
 BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS);
 BRPORT_ATTR_FLAG(isolated, BR_ISOLATED);
+BRPORT_ATTR_FLAG(flood_check, BR_FLOOD_CHECK);
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
@@ -286,6 +287,7 @@ static const struct brport_attribute *br
 	&brport_attr_group_fwd_mask,
 	&brport_attr_neigh_suppress,
 	&brport_attr_isolated,
+	&brport_attr_flood_check,
 	&brport_attr_backup_port,
 	NULL
 };
Index: linux-4.19.118/net/bridge/br_netlink.c
===================================================================
--- linux-4.19.118.orig/net/bridge/br_netlink.c
+++ linux-4.19.118/net/bridge/br_netlink.c
@@ -140,6 +140,7 @@ static inline size_t br_port_info_size(v
 		+ nla_total_size(1)	/* IFLA_BRPORT_VLAN_TUNNEL */
 		+ nla_total_size(1)	/* IFLA_BRPORT_NEIGH_SUPPRESS */
 		+ nla_total_size(1)	/* IFLA_BRPORT_ISOLATED */
+		+ nla_total_size(1)	/* IFLA_BRPORT_FLOOD_CHECK */
 		+ nla_total_size(sizeof(struct ifla_bridge_id))	/* IFLA_BRPORT_ROOT_ID */
 		+ nla_total_size(sizeof(struct ifla_bridge_id))	/* IFLA_BRPORT_BRIDGE_ID */
 		+ nla_total_size(sizeof(u16))	/* IFLA_BRPORT_DESIGNATED_PORT */
@@ -192,6 +193,8 @@ static int br_port_fill_attrs(struct sk_
 	    nla_put_u8(skb, IFLA_BRPORT_MCAST_TO_UCAST,
 		       !!(p->flags & BR_MULTICAST_TO_UNICAST)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) ||
+	    nla_put_u8(skb, IFLA_BRPORT_FLOOD_CHECK,
+		       !!(p->flags & BR_FLOOD_CHECK)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
 		       !!(p->flags & BR_FLOOD)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_MCAST_FLOOD,
@@ -671,6 +674,7 @@ static const struct nla_policy br_port_p
 	[IFLA_BRPORT_BCAST_FLOOD] = { .type = NLA_U8 },
 	[IFLA_BRPORT_VLAN_TUNNEL] = { .type = NLA_U8 },
 	[IFLA_BRPORT_GROUP_FWD_MASK] = { .type = NLA_U16 },
+	[IFLA_BRPORT_FLOOD_CHECK] = { .type = NLA_U8 },
 	[IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NLA_U8 },
 	[IFLA_BRPORT_ISOLATED]	= { .type = NLA_U8 },
 	[IFLA_BRPORT_BACKUP_PORT] = { .type = NLA_U32 },
@@ -752,6 +756,10 @@ static int br_setport(struct net_bridge_
 	if (err)
 		return err;
 
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_FLOOD_CHECK, BR_FLOOD_CHECK);
+	if (err)
+		return err;
+
 	err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
 	if (err)
 		return err;
@@ -1026,6 +1034,7 @@ static const struct nla_policy br_policy
 	[IFLA_BR_MCAST_QUERY_INTVL] = { .type = NLA_U64 },
 	[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = { .type = NLA_U64 },
 	[IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = { .type = NLA_U64 },
+	[IFLA_BR_FLOOD_CHECK]	= { .type = NLA_U8 },
 	[IFLA_BR_NF_CALL_IPTABLES] = { .type = NLA_U8 },
 	[IFLA_BR_NF_CALL_IP6TABLES] = { .type = NLA_U8 },
 	[IFLA_BR_NF_CALL_ARPTABLES] = { .type = NLA_U8 },
@@ -1267,6 +1276,11 @@ static int br_changelink(struct net_devi
 	}
 #endif
 #endif
+	if (data[IFLA_BR_FLOOD_CHECK]) {
+		u8 val = nla_get_u8(data[IFLA_BR_FLOOD_CHECK]);
+
+		br->flood_check = val ? true : false;
+	}
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 	if (data[IFLA_BR_NF_CALL_IPTABLES]) {
 		u8 val = nla_get_u8(data[IFLA_BR_NF_CALL_IPTABLES]);
@@ -1359,6 +1373,7 @@ static size_t br_get_size(const struct n
 	       nla_total_size(sizeof(u8)) +	/* IFLA_BR_MCAST_IGMP_VERSION */
 	       nla_total_size(sizeof(u8)) +	/* IFLA_BR_MCAST_MLD_VERSION */
 #endif
+	       nla_total_size(sizeof(u8)) +	/* IFLA_BR_FLOOD_CHECK */
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 	       nla_total_size(sizeof(u8)) +     /* IFLA_BR_NF_CALL_IPTABLES */
 	       nla_total_size(sizeof(u8)) +     /* IFLA_BR_NF_CALL_IP6TABLES */
@@ -1467,6 +1482,9 @@ static int br_fill_info(struct sk_buff *
 			      IFLA_BR_PAD))
 		return -EMSGSIZE;
 #endif
+	if (nla_put_u8(skb, IFLA_BR_FLOOD_CHECK,
+			br->flood_check ? 1 : 0))
+		return -EMSGSIZE;
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 	if (nla_put_u8(skb, IFLA_BR_NF_CALL_IPTABLES,
 		       br->nf_call_iptables ? 1 : 0) ||
Index: linux-4.19.118/include/uapi/linux/if_link.h
===================================================================
--- linux-4.19.118.orig/include/uapi/linux/if_link.h
+++ linux-4.19.118/include/uapi/linux/if_link.h
@@ -286,6 +286,7 @@ enum {
 	IFLA_BR_MCAST_STATS_ENABLED,
 	IFLA_BR_MCAST_IGMP_VERSION,
 	IFLA_BR_MCAST_MLD_VERSION,
+	IFLA_BR_FLOOD_CHECK,
 	__IFLA_BR_MAX,
 };
 
@@ -337,6 +338,7 @@ enum {
 	IFLA_BRPORT_NEIGH_SUPPRESS,
 	IFLA_BRPORT_ISOLATED,
 	IFLA_BRPORT_BACKUP_PORT,
+	IFLA_BRPORT_FLOOD_CHECK,
 	__IFLA_BRPORT_MAX
 };
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
Index: linux-4.19.118/tools/include/uapi/linux/if_link.h
===================================================================
--- linux-4.19.118.orig/tools/include/uapi/linux/if_link.h
+++ linux-4.19.118/tools/include/uapi/linux/if_link.h
@@ -286,6 +286,7 @@ enum {
 	IFLA_BR_MCAST_STATS_ENABLED,
 	IFLA_BR_MCAST_IGMP_VERSION,
 	IFLA_BR_MCAST_MLD_VERSION,
+	IFLA_BR_FLOOD_CHECK,
 	__IFLA_BR_MAX,
 };
 
@@ -337,6 +338,7 @@ enum {
 	IFLA_BRPORT_NEIGH_SUPPRESS,
 	IFLA_BRPORT_ISOLATED,
 	IFLA_BRPORT_BACKUP_PORT,
+	IFLA_BRPORT_FLOOD_CHECK,
 	__IFLA_BRPORT_MAX
 };
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
