b.a.t.m.a.n.lists.open-mesh.org archive mirror
 help / color / mirror / Atom feed
* [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports
@ 2014-05-25  5:03 Linus Lüssing
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 1/4] bridge: rename struct bridge_mcast_query/querier Linus Lüssing
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Linus Lüssing @ 2014-05-25  5:03 UTC (permalink / raw)
  To: netdev
  Cc: b.a.t.m.a.n, bridge, linux-kernel, Stephen Hemminger, David S. Miller

Changes in v2:

* fix a nasty typo in PATCH 1/4, br_multicast_update_query_timer():
  "br->multicast_query_interval" vs. "br->multicast_querier_interval"
  => this accidentally reduced the other querier present timer 
     from 255 to 125 seconds
* fix a typo in PATCH 2/4, br_ip{4,6}_multicast_query():
  ntohs(ETH_P_{IP,IPV6}) vs. htons(ETH_P_{IP,IPV6})
* add missing ntohl()s before address comparison in PATCH 2/4,
  br_ip4_multicast_select_querier() (thanks David!)

Cheers, Linus



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [B.A.T.M.A.N.] [PATCHv2 net-next 1/4] bridge: rename struct bridge_mcast_query/querier
  2014-05-25  5:03 [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports Linus Lüssing
@ 2014-05-25  5:03 ` Linus Lüssing
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 2/4] bridge: adhere to querier election mechanism specified by RFCs Linus Lüssing
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Linus Lüssing @ 2014-05-25  5:03 UTC (permalink / raw)
  To: netdev
  Cc: b.a.t.m.a.n, bridge, linux-kernel, Stephen Hemminger, David S. Miller

The current naming of these two structs is very random, in that
reversing their naming would not make any semantical difference.

This patch tries to make the naming less confusing by giving them a more
specific, distinguishable naming.

This is also useful for the upcoming patches reintroducing the
"struct bridge_mcast_querier" but for storing information about the
selected querier (no matter if our own or a foreign querier).

Signed-off-by: Linus Lüssing <linus.luessing@web.de>
---
 net/bridge/br_mdb.c       |    4 +-
 net/bridge/br_multicast.c |  169 +++++++++++++++++++++++----------------------
 net/bridge/br_private.h   |   22 +++---
 3 files changed, 100 insertions(+), 95 deletions(-)

diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index b7b1914..5df0526 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -418,13 +418,13 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
 
 	ip.proto = entry->addr.proto;
 	if (ip.proto == htons(ETH_P_IP)) {
-		if (timer_pending(&br->ip4_querier.timer))
+		if (timer_pending(&br->ip4_other_query.timer))
 			return -EBUSY;
 
 		ip.u.ip4 = entry->addr.u.ip4;
 #if IS_ENABLED(CONFIG_IPV6)
 	} else {
-		if (timer_pending(&br->ip6_querier.timer))
+		if (timer_pending(&br->ip6_other_query.timer))
 			return -EBUSY;
 
 		ip.u.ip6 = entry->addr.u.ip6;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 7b757b5..5ccac62 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -35,7 +35,7 @@
 #include "br_private.h"
 
 static void br_multicast_start_querier(struct net_bridge *br,
-				       struct bridge_mcast_query *query);
+				       struct bridge_mcast_own_query *query);
 unsigned int br_mdb_rehash_seq;
 
 static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
@@ -761,7 +761,7 @@ static void br_multicast_local_router_expired(unsigned long data)
 }
 
 static void br_multicast_querier_expired(struct net_bridge *br,
-					 struct bridge_mcast_query *query)
+					 struct bridge_mcast_own_query *query)
 {
 	spin_lock(&br->multicast_lock);
 	if (!netif_running(br->dev) || br->multicast_disabled)
@@ -777,7 +777,7 @@ static void br_ip4_multicast_querier_expired(unsigned long data)
 {
 	struct net_bridge *br = (void *)data;
 
-	br_multicast_querier_expired(br, &br->ip4_query);
+	br_multicast_querier_expired(br, &br->ip4_own_query);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -785,7 +785,7 @@ static void br_ip6_multicast_querier_expired(unsigned long data)
 {
 	struct net_bridge *br = (void *)data;
 
-	br_multicast_querier_expired(br, &br->ip6_query);
+	br_multicast_querier_expired(br, &br->ip6_own_query);
 }
 #endif
 
@@ -810,11 +810,11 @@ static void __br_multicast_send_query(struct net_bridge *br,
 
 static void br_multicast_send_query(struct net_bridge *br,
 				    struct net_bridge_port *port,
-				    struct bridge_mcast_query *query)
+				    struct bridge_mcast_own_query *own_query)
 {
 	unsigned long time;
 	struct br_ip br_group;
-	struct bridge_mcast_querier *querier = NULL;
+	struct bridge_mcast_other_query *other_query = NULL;
 
 	if (!netif_running(br->dev) || br->multicast_disabled ||
 	    !br->multicast_querier)
@@ -822,31 +822,32 @@ static void br_multicast_send_query(struct net_bridge *br,
 
 	memset(&br_group.u, 0, sizeof(br_group.u));
 
-	if (port ? (query == &port->ip4_query) :
-		   (query == &br->ip4_query)) {
-		querier = &br->ip4_querier;
+	if (port ? (own_query == &port->ip4_own_query) :
+		   (own_query == &br->ip4_own_query)) {
+		other_query = &br->ip4_other_query;
 		br_group.proto = htons(ETH_P_IP);
 #if IS_ENABLED(CONFIG_IPV6)
 	} else {
-		querier = &br->ip6_querier;
+		other_query = &br->ip6_other_query;
 		br_group.proto = htons(ETH_P_IPV6);
 #endif
 	}
 
-	if (!querier || timer_pending(&querier->timer))
+	if (!other_query || timer_pending(&other_query->timer))
 		return;
 
 	__br_multicast_send_query(br, port, &br_group);
 
 	time = jiffies;
-	time += query->startup_sent < br->multicast_startup_query_count ?
+	time += own_query->startup_sent < br->multicast_startup_query_count ?
 		br->multicast_startup_query_interval :
 		br->multicast_query_interval;
-	mod_timer(&query->timer, time);
+	mod_timer(&own_query->timer, time);
 }
 
-static void br_multicast_port_query_expired(struct net_bridge_port *port,
-					    struct bridge_mcast_query *query)
+static void
+br_multicast_port_query_expired(struct net_bridge_port *port,
+				struct bridge_mcast_own_query *query)
 {
 	struct net_bridge *br = port->br;
 
@@ -868,7 +869,7 @@ static void br_ip4_multicast_port_query_expired(unsigned long data)
 {
 	struct net_bridge_port *port = (void *)data;
 
-	br_multicast_port_query_expired(port, &port->ip4_query);
+	br_multicast_port_query_expired(port, &port->ip4_own_query);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -876,7 +877,7 @@ static void br_ip6_multicast_port_query_expired(unsigned long data)
 {
 	struct net_bridge_port *port = (void *)data;
 
-	br_multicast_port_query_expired(port, &port->ip6_query);
+	br_multicast_port_query_expired(port, &port->ip6_own_query);
 }
 #endif
 
@@ -886,11 +887,11 @@ void br_multicast_add_port(struct net_bridge_port *port)
 
 	setup_timer(&port->multicast_router_timer, br_multicast_router_expired,
 		    (unsigned long)port);
-	setup_timer(&port->ip4_query.timer, br_ip4_multicast_port_query_expired,
-		    (unsigned long)port);
+	setup_timer(&port->ip4_own_query.timer,
+		    br_ip4_multicast_port_query_expired, (unsigned long)port);
 #if IS_ENABLED(CONFIG_IPV6)
-	setup_timer(&port->ip6_query.timer, br_ip6_multicast_port_query_expired,
-		    (unsigned long)port);
+	setup_timer(&port->ip6_own_query.timer,
+		    br_ip6_multicast_port_query_expired, (unsigned long)port);
 #endif
 }
 
@@ -899,7 +900,7 @@ void br_multicast_del_port(struct net_bridge_port *port)
 	del_timer_sync(&port->multicast_router_timer);
 }
 
-static void br_multicast_enable(struct bridge_mcast_query *query)
+static void br_multicast_enable(struct bridge_mcast_own_query *query)
 {
 	query->startup_sent = 0;
 
@@ -916,9 +917,9 @@ void br_multicast_enable_port(struct net_bridge_port *port)
 	if (br->multicast_disabled || !netif_running(br->dev))
 		goto out;
 
-	br_multicast_enable(&port->ip4_query);
+	br_multicast_enable(&port->ip4_own_query);
 #if IS_ENABLED(CONFIG_IPV6)
-	br_multicast_enable(&port->ip6_query);
+	br_multicast_enable(&port->ip6_own_query);
 #endif
 
 out:
@@ -938,9 +939,9 @@ void br_multicast_disable_port(struct net_bridge_port *port)
 	if (!hlist_unhashed(&port->rlist))
 		hlist_del_init_rcu(&port->rlist);
 	del_timer(&port->multicast_router_timer);
-	del_timer(&port->ip4_query.timer);
+	del_timer(&port->ip4_own_query.timer);
 #if IS_ENABLED(CONFIG_IPV6)
-	del_timer(&port->ip6_query.timer);
+	del_timer(&port->ip6_own_query.timer);
 #endif
 	spin_unlock(&br->multicast_lock);
 }
@@ -1065,14 +1066,14 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
 #endif
 
 static void
-br_multicast_update_querier_timer(struct net_bridge *br,
-				  struct bridge_mcast_querier *querier,
-				  unsigned long max_delay)
+br_multicast_update_query_timer(struct net_bridge *br,
+				struct bridge_mcast_other_query *query,
+				unsigned long max_delay)
 {
-	if (!timer_pending(&querier->timer))
-		querier->delay_time = jiffies + max_delay;
+	if (!timer_pending(&query->timer))
+		query->delay_time = jiffies + max_delay;
 
-	mod_timer(&querier->timer, jiffies + br->multicast_querier_interval);
+	mod_timer(&query->timer, jiffies + br->multicast_querier_interval);
 }
 
 /*
@@ -1125,14 +1126,14 @@ timer:
 
 static void br_multicast_query_received(struct net_bridge *br,
 					struct net_bridge_port *port,
-					struct bridge_mcast_querier *querier,
+					struct bridge_mcast_other_query *query,
 					int saddr,
 					bool is_general_query,
 					unsigned long max_delay)
 {
 	if (saddr && is_general_query)
-		br_multicast_update_querier_timer(br, querier, max_delay);
-	else if (timer_pending(&querier->timer))
+		br_multicast_update_query_timer(br, query, max_delay);
+	else if (timer_pending(&query->timer))
 		return;
 
 	br_multicast_mark_router(br, port);
@@ -1190,8 +1191,8 @@ static int br_ip4_multicast_query(struct net_bridge *br,
 		goto out;
 	}
 
-	br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr,
-				    !group, max_delay);
+	br_multicast_query_received(br, port, &br->ip4_other_query,
+				    !!iph->saddr, !group, max_delay);
 
 	if (!group)
 		goto out;
@@ -1282,7 +1283,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
 		goto out;
 	}
 
-	br_multicast_query_received(br, port, &br->ip6_querier,
+	br_multicast_query_received(br, port, &br->ip6_other_query,
 				    !ipv6_addr_any(&ip6h->saddr),
 				    is_general_query, max_delay);
 
@@ -1315,11 +1316,12 @@ out:
 }
 #endif
 
-static void br_multicast_leave_group(struct net_bridge *br,
-				     struct net_bridge_port *port,
-				     struct br_ip *group,
-				     struct bridge_mcast_querier *querier,
-				     struct bridge_mcast_query *query)
+static void
+br_multicast_leave_group(struct net_bridge *br,
+			 struct net_bridge_port *port,
+			 struct br_ip *group,
+			 struct bridge_mcast_other_query *other_query,
+			 struct bridge_mcast_own_query *own_query)
 {
 	struct net_bridge_mdb_htable *mdb;
 	struct net_bridge_mdb_entry *mp;
@@ -1330,7 +1332,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
 	spin_lock(&br->multicast_lock);
 	if (!netif_running(br->dev) ||
 	    (port && port->state == BR_STATE_DISABLED) ||
-	    timer_pending(&querier->timer))
+	    timer_pending(&other_query->timer))
 		goto out;
 
 	mdb = mlock_dereference(br->mdb, br);
@@ -1344,7 +1346,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
 		time = jiffies + br->multicast_last_member_count *
 				 br->multicast_last_member_interval;
 
-		mod_timer(&query->timer, time);
+		mod_timer(&own_query->timer, time);
 
 		for (p = mlock_dereference(mp->ports, br);
 		     p != NULL;
@@ -1425,17 +1427,19 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
 					 __u16 vid)
 {
 	struct br_ip br_group;
-	struct bridge_mcast_query *query = port ? &port->ip4_query :
-						  &br->ip4_query;
+	struct bridge_mcast_own_query *own_query;
 
 	if (ipv4_is_local_multicast(group))
 		return;
 
+	own_query = port ? &port->ip4_own_query : &br->ip4_own_query;
+
 	br_group.u.ip4 = group;
 	br_group.proto = htons(ETH_P_IP);
 	br_group.vid = vid;
 
-	br_multicast_leave_group(br, port, &br_group, &br->ip4_querier, query);
+	br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
+				 own_query);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -1445,18 +1449,19 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
 					 __u16 vid)
 {
 	struct br_ip br_group;
-	struct bridge_mcast_query *query = port ? &port->ip6_query :
-						  &br->ip6_query;
-
+	struct bridge_mcast_own_query *own_query;
 
 	if (ipv6_addr_is_ll_all_nodes(group))
 		return;
 
+	own_query = port ? &port->ip6_own_query : &br->ip6_own_query;
+
 	br_group.u.ip6 = *group;
 	br_group.proto = htons(ETH_P_IPV6);
 	br_group.vid = vid;
 
-	br_multicast_leave_group(br, port, &br_group, &br->ip6_querier, query);
+	br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
+				 own_query);
 }
 #endif
 
@@ -1723,7 +1728,7 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
 }
 
 static void br_multicast_query_expired(struct net_bridge *br,
-				       struct bridge_mcast_query *query)
+				       struct bridge_mcast_own_query *query)
 {
 	spin_lock(&br->multicast_lock);
 	if (query->startup_sent < br->multicast_startup_query_count)
@@ -1737,7 +1742,7 @@ static void br_ip4_multicast_query_expired(unsigned long data)
 {
 	struct net_bridge *br = (void *)data;
 
-	br_multicast_query_expired(br, &br->ip4_query);
+	br_multicast_query_expired(br, &br->ip4_own_query);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -1745,7 +1750,7 @@ static void br_ip6_multicast_query_expired(unsigned long data)
 {
 	struct net_bridge *br = (void *)data;
 
-	br_multicast_query_expired(br, &br->ip6_query);
+	br_multicast_query_expired(br, &br->ip6_own_query);
 }
 #endif
 
@@ -1767,28 +1772,28 @@ void br_multicast_init(struct net_bridge *br)
 	br->multicast_querier_interval = 255 * HZ;
 	br->multicast_membership_interval = 260 * HZ;
 
-	br->ip4_querier.delay_time = 0;
+	br->ip4_other_query.delay_time = 0;
 #if IS_ENABLED(CONFIG_IPV6)
-	br->ip6_querier.delay_time = 0;
+	br->ip6_other_query.delay_time = 0;
 #endif
 
 	spin_lock_init(&br->multicast_lock);
 	setup_timer(&br->multicast_router_timer,
 		    br_multicast_local_router_expired, 0);
-	setup_timer(&br->ip4_querier.timer, br_ip4_multicast_querier_expired,
-		    (unsigned long)br);
-	setup_timer(&br->ip4_query.timer, br_ip4_multicast_query_expired,
+	setup_timer(&br->ip4_other_query.timer,
+		    br_ip4_multicast_querier_expired, (unsigned long)br);
+	setup_timer(&br->ip4_own_query.timer, br_ip4_multicast_query_expired,
 		    (unsigned long)br);
 #if IS_ENABLED(CONFIG_IPV6)
-	setup_timer(&br->ip6_querier.timer, br_ip6_multicast_querier_expired,
-		    (unsigned long)br);
-	setup_timer(&br->ip6_query.timer, br_ip6_multicast_query_expired,
+	setup_timer(&br->ip6_other_query.timer,
+		    br_ip6_multicast_querier_expired, (unsigned long)br);
+	setup_timer(&br->ip6_own_query.timer, br_ip6_multicast_query_expired,
 		    (unsigned long)br);
 #endif
 }
 
 static void __br_multicast_open(struct net_bridge *br,
-				struct bridge_mcast_query *query)
+				struct bridge_mcast_own_query *query)
 {
 	query->startup_sent = 0;
 
@@ -1800,9 +1805,9 @@ static void __br_multicast_open(struct net_bridge *br,
 
 void br_multicast_open(struct net_bridge *br)
 {
-	__br_multicast_open(br, &br->ip4_query);
+	__br_multicast_open(br, &br->ip4_own_query);
 #if IS_ENABLED(CONFIG_IPV6)
-	__br_multicast_open(br, &br->ip6_query);
+	__br_multicast_open(br, &br->ip6_own_query);
 #endif
 }
 
@@ -1815,11 +1820,11 @@ void br_multicast_stop(struct net_bridge *br)
 	int i;
 
 	del_timer_sync(&br->multicast_router_timer);
-	del_timer_sync(&br->ip4_querier.timer);
-	del_timer_sync(&br->ip4_query.timer);
+	del_timer_sync(&br->ip4_other_query.timer);
+	del_timer_sync(&br->ip4_own_query.timer);
 #if IS_ENABLED(CONFIG_IPV6)
-	del_timer_sync(&br->ip6_querier.timer);
-	del_timer_sync(&br->ip6_query.timer);
+	del_timer_sync(&br->ip6_other_query.timer);
+	del_timer_sync(&br->ip6_own_query.timer);
 #endif
 
 	spin_lock_bh(&br->multicast_lock);
@@ -1923,7 +1928,7 @@ unlock:
 }
 
 static void br_multicast_start_querier(struct net_bridge *br,
-				       struct bridge_mcast_query *query)
+				       struct bridge_mcast_own_query *query)
 {
 	struct net_bridge_port *port;
 
@@ -1934,11 +1939,11 @@ static void br_multicast_start_querier(struct net_bridge *br,
 		    port->state == BR_STATE_BLOCKING)
 			continue;
 
-		if (query == &br->ip4_query)
-			br_multicast_enable(&port->ip4_query);
+		if (query == &br->ip4_own_query)
+			br_multicast_enable(&port->ip4_own_query);
 #if IS_ENABLED(CONFIG_IPV6)
 		else
-			br_multicast_enable(&port->ip6_query);
+			br_multicast_enable(&port->ip6_own_query);
 #endif
 	}
 }
@@ -1974,9 +1979,9 @@ rollback:
 			goto rollback;
 	}
 
-	br_multicast_start_querier(br, &br->ip4_query);
+	br_multicast_start_querier(br, &br->ip4_own_query);
 #if IS_ENABLED(CONFIG_IPV6)
-	br_multicast_start_querier(br, &br->ip6_query);
+	br_multicast_start_querier(br, &br->ip6_own_query);
 #endif
 
 unlock:
@@ -2001,16 +2006,16 @@ int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
 
 	max_delay = br->multicast_query_response_interval;
 
-	if (!timer_pending(&br->ip4_querier.timer))
-		br->ip4_querier.delay_time = jiffies + max_delay;
+	if (!timer_pending(&br->ip4_other_query.timer))
+		br->ip4_other_query.delay_time = jiffies + max_delay;
 
-	br_multicast_start_querier(br, &br->ip4_query);
+	br_multicast_start_querier(br, &br->ip4_own_query);
 
 #if IS_ENABLED(CONFIG_IPV6)
-	if (!timer_pending(&br->ip6_querier.timer))
-		br->ip6_querier.delay_time = jiffies + max_delay;
+	if (!timer_pending(&br->ip6_other_query.timer))
+		br->ip6_other_query.delay_time = jiffies + max_delay;
 
-	br_multicast_start_querier(br, &br->ip6_query);
+	br_multicast_start_querier(br, &br->ip6_own_query);
 #endif
 
 unlock:
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index af067711..f186ce8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -68,13 +68,13 @@ struct br_ip
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 /* our own querier */
-struct bridge_mcast_query {
+struct bridge_mcast_own_query {
 	struct timer_list	timer;
 	u32			startup_sent;
 };
 
 /* other querier */
-struct bridge_mcast_querier {
+struct bridge_mcast_other_query {
 	struct timer_list		timer;
 	unsigned long			delay_time;
 };
@@ -178,9 +178,9 @@ struct net_bridge_port
 #define BR_PROMISC		0x00000080
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
-	struct bridge_mcast_query	ip4_query;
+	struct bridge_mcast_own_query	ip4_own_query;
 #if IS_ENABLED(CONFIG_IPV6)
-	struct bridge_mcast_query	ip6_query;
+	struct bridge_mcast_own_query	ip6_own_query;
 #endif /* IS_ENABLED(CONFIG_IPV6) */
 	unsigned char			multicast_router;
 	struct timer_list		multicast_router_timer;
@@ -282,11 +282,11 @@ struct net_bridge
 	struct hlist_head		router_list;
 
 	struct timer_list		multicast_router_timer;
-	struct bridge_mcast_querier	ip4_querier;
-	struct bridge_mcast_query	ip4_query;
+	struct bridge_mcast_other_query	ip4_other_query;
+	struct bridge_mcast_own_query	ip4_own_query;
 #if IS_ENABLED(CONFIG_IPV6)
-	struct bridge_mcast_querier	ip6_querier;
-	struct bridge_mcast_query	ip6_query;
+	struct bridge_mcast_other_query	ip6_other_query;
+	struct bridge_mcast_own_query	ip6_own_query;
 #endif /* IS_ENABLED(CONFIG_IPV6) */
 #endif
 
@@ -495,7 +495,7 @@ static inline bool br_multicast_is_router(struct net_bridge *br)
 
 static inline bool
 __br_multicast_querier_exists(struct net_bridge *br,
-			      struct bridge_mcast_querier *querier)
+			      struct bridge_mcast_other_query *querier)
 {
 	return time_is_before_jiffies(querier->delay_time) &&
 	       (br->multicast_querier || timer_pending(&querier->timer));
@@ -506,10 +506,10 @@ static inline bool br_multicast_querier_exists(struct net_bridge *br,
 {
 	switch (eth->h_proto) {
 	case (htons(ETH_P_IP)):
-		return __br_multicast_querier_exists(br, &br->ip4_querier);
+		return __br_multicast_querier_exists(br, &br->ip4_other_query);
 #if IS_ENABLED(CONFIG_IPV6)
 	case (htons(ETH_P_IPV6)):
-		return __br_multicast_querier_exists(br, &br->ip6_querier);
+		return __br_multicast_querier_exists(br, &br->ip6_other_query);
 #endif
 	default:
 		return false;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [B.A.T.M.A.N.] [PATCHv2 net-next 2/4] bridge: adhere to querier election mechanism specified by RFCs
  2014-05-25  5:03 [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports Linus Lüssing
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 1/4] bridge: rename struct bridge_mcast_query/querier Linus Lüssing
@ 2014-05-25  5:03 ` Linus Lüssing
       [not found]   ` <CADAe=+KViC7uej0KM4TrQXxrk-amU7CX73buviMU17jpQm61bw@mail.gmail.com>
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 3/4] bridge: add export of multicast database adjacent to net_dev Linus Lüssing
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Linus Lüssing @ 2014-05-25  5:03 UTC (permalink / raw)
  To: netdev
  Cc: b.a.t.m.a.n, bridge, linux-kernel, Stephen Hemminger, David S. Miller

MLDv1 (RFC2710 section 6), MLDv2 (RFC3810 section 7.6.2), IGMPv2
(RFC2236 section 3) and IGMPv3 (RFC3376 section 6.6.2) specify that the
querier with lowest source address shall become the selected
querier.

So far the bridge stopped its querier as soon as it heard another
querier regardless of its source address. This results in the "wrong"
querier potentially becoming the active querier or a potential,
unnecessary querying delay.

With this patch the bridge memorizes the source address of the currently
selected querier and ignores queries from queriers with a higher source
address than the currently selected one. This slight optimization is
supposed to make it more RFC compliant (but is rather uncritical and
therefore probably not necessary to be queued for stable kernels).

Signed-off-by: Linus Lüssing <linus.luessing@web.de>
---
 net/bridge/br_multicast.c |  101 +++++++++++++++++++++++++++++++++++++++------
 net/bridge/br_private.h   |    7 ++++
 2 files changed, 95 insertions(+), 13 deletions(-)

diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 5ccac62..b3f17c9 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -789,6 +789,18 @@ static void br_ip6_multicast_querier_expired(unsigned long data)
 }
 #endif
 
+static void br_multicast_select_own_querier(struct net_bridge *br,
+					    struct br_ip *ip,
+					    struct sk_buff *skb)
+{
+	if (ip->proto == htons(ETH_P_IP))
+		br->ip4_querier.addr.u.ip4 = ip_hdr(skb)->saddr;
+#if IS_ENABLED(CONFIG_IPV6)
+	else
+		br->ip6_querier.addr.u.ip6 = ipv6_hdr(skb)->saddr;
+#endif
+}
+
 static void __br_multicast_send_query(struct net_bridge *br,
 				      struct net_bridge_port *port,
 				      struct br_ip *ip)
@@ -804,8 +816,10 @@ static void __br_multicast_send_query(struct net_bridge *br,
 		skb->dev = port->dev;
 		NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
 			dev_queue_xmit);
-	} else
+	} else {
+		br_multicast_select_own_querier(br, ip, skb);
 		netif_rx(skb);
+	}
 }
 
 static void br_multicast_send_query(struct net_bridge *br,
@@ -1065,6 +1079,62 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
 }
 #endif
 
+static bool br_ip4_multicast_select_querier(struct net_bridge *br,
+					    __be32 saddr)
+{
+	if (!timer_pending(&br->ip4_own_query.timer) &&
+	    !timer_pending(&br->ip4_other_query.timer))
+		goto update;
+
+	if (!br->ip4_querier.addr.u.ip4)
+		goto update;
+
+	if (ntohl(saddr) <= ntohl(br->ip4_querier.addr.u.ip4))
+		goto update;
+
+	return false;
+
+update:
+	br->ip4_querier.addr.u.ip4 = saddr;
+
+	return true;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static bool br_ip6_multicast_select_querier(struct net_bridge *br,
+					    struct in6_addr *saddr)
+{
+	if (!timer_pending(&br->ip6_own_query.timer) &&
+	    !timer_pending(&br->ip6_other_query.timer))
+		goto update;
+
+	if (ipv6_addr_cmp(saddr, &br->ip6_querier.addr.u.ip6) <= 0)
+		goto update;
+
+	return false;
+
+update:
+	br->ip6_querier.addr.u.ip6 = *saddr;
+
+	return true;
+}
+#endif
+
+static bool br_multicast_select_querier(struct net_bridge *br,
+					struct br_ip *saddr)
+{
+	switch (saddr->proto) {
+	case htons(ETH_P_IP):
+		return br_ip4_multicast_select_querier(br, saddr->u.ip4);
+#if IS_ENABLED(CONFIG_IPV6)
+	case htons(ETH_P_IPV6):
+		return br_ip6_multicast_select_querier(br, &saddr->u.ip6);
+#endif
+	}
+
+	return false;
+}
+
 static void
 br_multicast_update_query_timer(struct net_bridge *br,
 				struct bridge_mcast_other_query *query,
@@ -1127,15 +1197,13 @@ timer:
 static void br_multicast_query_received(struct net_bridge *br,
 					struct net_bridge_port *port,
 					struct bridge_mcast_other_query *query,
-					int saddr,
-					bool is_general_query,
+					struct br_ip *saddr,
 					unsigned long max_delay)
 {
-	if (saddr && is_general_query)
-		br_multicast_update_query_timer(br, query, max_delay);
-	else if (timer_pending(&query->timer))
+	if (!br_multicast_select_querier(br, saddr))
 		return;
 
+	br_multicast_update_query_timer(br, query, max_delay);
 	br_multicast_mark_router(br, port);
 }
 
@@ -1150,6 +1218,7 @@ static int br_ip4_multicast_query(struct net_bridge *br,
 	struct igmpv3_query *ih3;
 	struct net_bridge_port_group *p;
 	struct net_bridge_port_group __rcu **pp;
+	struct br_ip saddr;
 	unsigned long max_delay;
 	unsigned long now = jiffies;
 	__be32 group;
@@ -1191,11 +1260,14 @@ static int br_ip4_multicast_query(struct net_bridge *br,
 		goto out;
 	}
 
-	br_multicast_query_received(br, port, &br->ip4_other_query,
-				    !!iph->saddr, !group, max_delay);
+	if (!group) {
+		saddr.proto = htons(ETH_P_IP);
+		saddr.u.ip4 = iph->saddr;
 
-	if (!group)
+		br_multicast_query_received(br, port, &br->ip4_other_query,
+					    &saddr, max_delay);
 		goto out;
+	}
 
 	mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid);
 	if (!mp)
@@ -1235,6 +1307,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
 	struct mld2_query *mld2q;
 	struct net_bridge_port_group *p;
 	struct net_bridge_port_group __rcu **pp;
+	struct br_ip saddr;
 	unsigned long max_delay;
 	unsigned long now = jiffies;
 	const struct in6_addr *group = NULL;
@@ -1283,12 +1356,14 @@ static int br_ip6_multicast_query(struct net_bridge *br,
 		goto out;
 	}
 
-	br_multicast_query_received(br, port, &br->ip6_other_query,
-				    !ipv6_addr_any(&ip6h->saddr),
-				    is_general_query, max_delay);
+	if (is_general_query) {
+		saddr.proto = htons(ETH_P_IPV6);
+		saddr.u.ip6 = ip6h->saddr;
 
-	if (!group)
+		br_multicast_query_received(br, port, &br->ip6_other_query,
+					    &saddr, max_delay);
 		goto out;
+	}
 
 	mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid);
 	if (!mp)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index f186ce8..bc1803b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -78,6 +78,11 @@ struct bridge_mcast_other_query {
 	struct timer_list		timer;
 	unsigned long			delay_time;
 };
+
+/* selected querier */
+struct bridge_mcast_querier {
+	struct br_ip addr;
+};
 #endif
 
 struct net_port_vlans {
@@ -284,9 +289,11 @@ struct net_bridge
 	struct timer_list		multicast_router_timer;
 	struct bridge_mcast_other_query	ip4_other_query;
 	struct bridge_mcast_own_query	ip4_own_query;
+	struct bridge_mcast_querier	ip4_querier;
 #if IS_ENABLED(CONFIG_IPV6)
 	struct bridge_mcast_other_query	ip6_other_query;
 	struct bridge_mcast_own_query	ip6_own_query;
+	struct bridge_mcast_querier	ip6_querier;
 #endif /* IS_ENABLED(CONFIG_IPV6) */
 #endif
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [B.A.T.M.A.N.] [PATCHv2 net-next 3/4] bridge: add export of multicast database adjacent to net_dev
  2014-05-25  5:03 [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports Linus Lüssing
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 1/4] bridge: rename struct bridge_mcast_query/querier Linus Lüssing
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 2/4] bridge: adhere to querier election mechanism specified by RFCs Linus Lüssing
@ 2014-05-25  5:03 ` Linus Lüssing
  2014-05-30 14:38   ` Stephen Hemminger
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 4/4] bridge: memorize and export selected IGMP/MLD querier port Linus Lüssing
  2014-05-29 22:36 ` [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports David Miller
  4 siblings, 1 reply; 9+ messages in thread
From: Linus Lüssing @ 2014-05-25  5:03 UTC (permalink / raw)
  To: netdev
  Cc: b.a.t.m.a.n, bridge, linux-kernel, Stephen Hemminger, David S. Miller

With this new, exported function br_multicast_list_adjacent(net_dev) a
list of IPv4/6 addresses is returned. This list contains all multicast
addresses sensed by the bridge multicast snooping feature on all bridge
ports of the bridge interface of net_dev, excluding addresses from the
specified net_device itself.

Adding bridge support to the batman-adv multicast optimization requires
batman-adv knowing about the existence of bridged-in multicast
listeners to be able to reliably serve them with multicast packets.

Signed-off-by: Linus Lüssing <linus.luessing@web.de>
---
 include/linux/if_bridge.h |   18 ++++++++++++++
 net/bridge/br_multicast.c |   58 +++++++++++++++++++++++++++++++++++++++++++++
 net/bridge/br_private.h   |   12 ----------
 3 files changed, 76 insertions(+), 12 deletions(-)

diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 1085ffe..44d6eb0 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -16,9 +16,27 @@
 #include <linux/netdevice.h>
 #include <uapi/linux/if_bridge.h>
 
+struct br_ip {
+	union {
+		__be32	ip4;
+#if IS_ENABLED(CONFIG_IPV6)
+		struct in6_addr ip6;
+#endif
+	} u;
+	__be16		proto;
+	__u16           vid;
+};
+
+struct br_ip_list {
+	struct list_head list;
+	struct br_ip addr;
+};
+
 extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
 
 typedef int br_should_route_hook_t(struct sk_buff *skb);
 extern br_should_route_hook_t __rcu *br_should_route_hook;
+int br_multicast_list_adjacent(struct net_device *dev,
+			       struct list_head *br_ip_list);
 
 #endif
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index b3f17c9..807e535 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/export.h>
 #include <linux/if_ether.h>
 #include <linux/igmp.h>
 #include <linux/jhash.h>
@@ -2141,3 +2142,60 @@ unlock:
 
 	return err;
 }
+
+/**
+ * br_multicast_list_adjacent - Returns snooped multicast addresses
+ * @dev:	The bridge port adjacent to which to retrieve addresses
+ * @br_ip_list:	The list to store found, snooped multicast IP addresses in
+ *
+ * Creates a list of IP addresses (struct br_ip_list) sensed by the multicast
+ * snooping feature on all bridge ports of dev's bridge device, excluding
+ * the addresses from dev itself.
+ *
+ * Returns the number of items added to br_ip_list.
+ *
+ * Notes:
+ * - br_ip_list needs to be initialized by caller
+ * - br_ip_list might contain duplicates in the end
+ *   (needs to be taken care of by caller)
+ * - br_ip_list needs to be freed by caller
+ */
+int br_multicast_list_adjacent(struct net_device *dev,
+			       struct list_head *br_ip_list)
+{
+	struct net_bridge *br;
+	struct net_bridge_port *port;
+	struct net_bridge_port_group *group;
+	struct br_ip_list *entry;
+	int count = 0;
+
+	rcu_read_lock();
+	if (!br_ip_list || !br_port_exists(dev))
+		goto unlock;
+
+	port = br_port_get_rcu(dev);
+	if (!port || !port->br)
+		goto unlock;
+
+	br = port->br;
+
+	list_for_each_entry_rcu(port, &br->port_list, list) {
+		if (!port->dev || port->dev == dev)
+			continue;
+
+		hlist_for_each_entry_rcu(group, &port->mglist, mglist) {
+			entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+			if (!entry)
+				goto unlock;
+
+			entry->addr = group->addr;
+			list_add(&entry->list, br_ip_list);
+			count++;
+		}
+	}
+
+unlock:
+	rcu_read_unlock();
+	return count;
+}
+EXPORT_SYMBOL(br_multicast_list_adjacent);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bc1803b..cb704a6 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -54,18 +54,6 @@ struct mac_addr
 	unsigned char	addr[ETH_ALEN];
 };
 
-struct br_ip
-{
-	union {
-		__be32	ip4;
-#if IS_ENABLED(CONFIG_IPV6)
-		struct in6_addr ip6;
-#endif
-	} u;
-	__be16		proto;
-	__u16		vid;
-};
-
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 /* our own querier */
 struct bridge_mcast_own_query {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [B.A.T.M.A.N.] [PATCHv2 net-next 4/4] bridge: memorize and export selected IGMP/MLD querier port
  2014-05-25  5:03 [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports Linus Lüssing
                   ` (2 preceding siblings ...)
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 3/4] bridge: add export of multicast database adjacent to net_dev Linus Lüssing
@ 2014-05-25  5:03 ` Linus Lüssing
  2014-05-29 22:36 ` [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports David Miller
  4 siblings, 0 replies; 9+ messages in thread
From: Linus Lüssing @ 2014-05-25  5:03 UTC (permalink / raw)
  To: netdev
  Cc: b.a.t.m.a.n, bridge, linux-kernel, Stephen Hemminger, David S. Miller

Adding bridge support to the batman-adv multicast optimization requires
batman-adv knowing about the existence of bridged-in IGMP/MLD queriers
to be able to reliably serve any multicast listener behind this same
bridge.

Signed-off-by: Linus Lüssing <linus.luessing@web.de>
---
 include/linux/if_bridge.h |    1 +
 net/bridge/br_multicast.c |   72 +++++++++++++++++++++++++++++++++++++++++----
 net/bridge/br_private.h   |    1 +
 3 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 44d6eb0..fd22789 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -38,5 +38,6 @@ typedef int br_should_route_hook_t(struct sk_buff *skb);
 extern br_should_route_hook_t __rcu *br_should_route_hook;
 int br_multicast_list_adjacent(struct net_device *dev,
 			       struct list_head *br_ip_list);
+bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto);
 
 #endif
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 807e535..3c9b405 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1081,6 +1081,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
 #endif
 
 static bool br_ip4_multicast_select_querier(struct net_bridge *br,
+					    struct net_bridge_port *port,
 					    __be32 saddr)
 {
 	if (!timer_pending(&br->ip4_own_query.timer) &&
@@ -1098,11 +1099,15 @@ static bool br_ip4_multicast_select_querier(struct net_bridge *br,
 update:
 	br->ip4_querier.addr.u.ip4 = saddr;
 
+	/* update protected by general multicast_lock by caller */
+	rcu_assign_pointer(br->ip4_querier.port, port);
+
 	return true;
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
 static bool br_ip6_multicast_select_querier(struct net_bridge *br,
+					    struct net_bridge_port *port,
 					    struct in6_addr *saddr)
 {
 	if (!timer_pending(&br->ip6_own_query.timer) &&
@@ -1117,19 +1122,23 @@ static bool br_ip6_multicast_select_querier(struct net_bridge *br,
 update:
 	br->ip6_querier.addr.u.ip6 = *saddr;
 
+	/* update protected by general multicast_lock by caller */
+	rcu_assign_pointer(br->ip6_querier.port, port);
+
 	return true;
 }
 #endif
 
 static bool br_multicast_select_querier(struct net_bridge *br,
+					struct net_bridge_port *port,
 					struct br_ip *saddr)
 {
 	switch (saddr->proto) {
 	case htons(ETH_P_IP):
-		return br_ip4_multicast_select_querier(br, saddr->u.ip4);
+		return br_ip4_multicast_select_querier(br, port, saddr->u.ip4);
 #if IS_ENABLED(CONFIG_IPV6)
 	case htons(ETH_P_IPV6):
-		return br_ip6_multicast_select_querier(br, &saddr->u.ip6);
+		return br_ip6_multicast_select_querier(br, port, &saddr->u.ip6);
 #endif
 	}
 
@@ -1201,7 +1210,7 @@ static void br_multicast_query_received(struct net_bridge *br,
 					struct br_ip *saddr,
 					unsigned long max_delay)
 {
-	if (!br_multicast_select_querier(br, saddr))
+	if (!br_multicast_select_querier(br, port, saddr))
 		return;
 
 	br_multicast_update_query_timer(br, query, max_delay);
@@ -1804,12 +1813,14 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
 }
 
 static void br_multicast_query_expired(struct net_bridge *br,
-				       struct bridge_mcast_own_query *query)
+				       struct bridge_mcast_own_query *query,
+				       struct bridge_mcast_querier *querier)
 {
 	spin_lock(&br->multicast_lock);
 	if (query->startup_sent < br->multicast_startup_query_count)
 		query->startup_sent++;
 
+	rcu_assign_pointer(querier, NULL);
 	br_multicast_send_query(br, NULL, query);
 	spin_unlock(&br->multicast_lock);
 }
@@ -1818,7 +1829,7 @@ static void br_ip4_multicast_query_expired(unsigned long data)
 {
 	struct net_bridge *br = (void *)data;
 
-	br_multicast_query_expired(br, &br->ip4_own_query);
+	br_multicast_query_expired(br, &br->ip4_own_query, &br->ip4_querier);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -1826,7 +1837,7 @@ static void br_ip6_multicast_query_expired(unsigned long data)
 {
 	struct net_bridge *br = (void *)data;
 
-	br_multicast_query_expired(br, &br->ip6_own_query);
+	br_multicast_query_expired(br, &br->ip6_own_query, &br->ip6_querier);
 }
 #endif
 
@@ -1849,8 +1860,10 @@ void br_multicast_init(struct net_bridge *br)
 	br->multicast_membership_interval = 260 * HZ;
 
 	br->ip4_other_query.delay_time = 0;
+	br->ip4_querier.port = NULL;
 #if IS_ENABLED(CONFIG_IPV6)
 	br->ip6_other_query.delay_time = 0;
+	br->ip6_querier.port = NULL;
 #endif
 
 	spin_lock_init(&br->multicast_lock);
@@ -2199,3 +2212,50 @@ unlock:
 	return count;
 }
 EXPORT_SYMBOL(br_multicast_list_adjacent);
+
+/**
+ * br_multicast_has_querier_adjacent - Checks for a querier behind a bridge port
+ * @dev: The bridge port adjacent to which to check for a querier
+ * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6
+ *
+ * Checks whether the given interface has a bridge on top and if so returns
+ * true if a selected querier is behind one of the other ports of this
+ * bridge. Otherwise returns false.
+ */
+bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto)
+{
+	struct net_bridge *br;
+	struct net_bridge_port *port;
+	bool ret = false;
+
+	rcu_read_lock();
+	if (!br_port_exists(dev))
+		goto unlock;
+
+	port = br_port_get_rcu(dev);
+	if (!port || !port->br)
+		goto unlock;
+
+	br = port->br;
+
+	switch (proto) {
+	case ETH_P_IP:
+		if (!timer_pending(&br->ip4_other_query.timer) ||
+		    rcu_dereference(br->ip4_querier.port) == port)
+			goto unlock;
+		break;
+	case ETH_P_IPV6:
+		if (!timer_pending(&br->ip6_other_query.timer) ||
+		    rcu_dereference(br->ip6_querier.port) == port)
+			goto unlock;
+		break;
+	default:
+		goto unlock;
+	}
+
+	ret = true;
+unlock:
+	rcu_read_unlock();
+	return ret;
+}
+EXPORT_SYMBOL(br_multicast_has_querier_adjacent);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index cb704a6..625d1bf 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -70,6 +70,7 @@ struct bridge_mcast_other_query {
 /* selected querier */
 struct bridge_mcast_querier {
 	struct br_ip addr;
+	struct net_bridge_port __rcu	*port;
 };
 #endif
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports
  2014-05-25  5:03 [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports Linus Lüssing
                   ` (3 preceding siblings ...)
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 4/4] bridge: memorize and export selected IGMP/MLD querier port Linus Lüssing
@ 2014-05-29 22:36 ` David Miller
  2014-05-30 14:37   ` Stephen Hemminger
  4 siblings, 1 reply; 9+ messages in thread
From: David Miller @ 2014-05-29 22:36 UTC (permalink / raw)
  To: linus.luessing; +Cc: stephen, netdev, bridge, linux-kernel, b.a.t.m.a.n

From: Linus Lüssing <linus.luessing@web.de>
Date: Sun, 25 May 2014 07:03:21 +0200

> Changes in v2:

I really need a bridging expert to review this series, thank you.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports
  2014-05-29 22:36 ` [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports David Miller
@ 2014-05-30 14:37   ` Stephen Hemminger
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2014-05-30 14:37 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-kernel, b.a.t.m.a.n, bridge

On Thu, 29 May 2014 15:36:22 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:

> From: Linus Lüssing <linus.luessing@web.de>
> Date: Sun, 25 May 2014 07:03:21 +0200
> 
> > Changes in v2:
> 
> I really need a bridging expert to review this series, thank you.

I am fine with these, but would like original author of IGMP snooping
to weigh in.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCHv2 net-next 3/4] bridge: add export of multicast database adjacent to net_dev
  2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 3/4] bridge: add export of multicast database adjacent to net_dev Linus Lüssing
@ 2014-05-30 14:38   ` Stephen Hemminger
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2014-05-30 14:38 UTC (permalink / raw)
  To: Linus Lüssing
  Cc: netdev, bridge, David S. Miller, b.a.t.m.a.n, linux-kernel

On Sun, 25 May 2014 07:03:24 +0200
Linus Lüssing <linus.luessing@web.de> wrote:

> With this new, exported function br_multicast_list_adjacent(net_dev) a
> list of IPv4/6 addresses is returned. This list contains all multicast
> addresses sensed by the bridge multicast snooping feature on all bridge
> ports of the bridge interface of net_dev, excluding addresses from the
> specified net_device itself.
> 
> Adding bridge support to the batman-adv multicast optimization requires
> batman-adv knowing about the existence of bridged-in multicast
> listeners to be able to reliably serve them with multicast packets.
> 
> Signed-off-by: Linus Lüssing <linus.luessing@web.de>

Please use EXPORT_SYMBOL_GPL

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCHv2 net-next 2/4] bridge: adhere to querier election mechanism specified by RFCs
       [not found]   ` <CADAe=+KViC7uej0KM4TrQXxrk-amU7CX73buviMU17jpQm61bw@mail.gmail.com>
@ 2014-06-27  0:12     ` Linus Lüssing
  0 siblings, 0 replies; 9+ messages in thread
From: Linus Lüssing @ 2014-06-27  0:12 UTC (permalink / raw)
  To: Ajith Adapa; +Cc: netdev, bridge, b.a.t.m.a.n

Hi Ajith,


On Mon, Jun 23, 2014 at 07:58:21AM +0530, Ajith Adapa wrote:
> Hi Luessing,
> 
> As per RFC 4541, snooping switches send query with source address as
> 0.0.0.0 since port in a L2 switch doesn't have ip-address configured.

Hm, I'm not quite sure whether this is true. Do you have a
section/paragraph in RFC4541 which says that?

To me, it seems that 0.0.0.0/:: should only be used when the
topology changes, on links becoming active (the RFC uses the example
of STP). As a performance optimization but not as the source
address for General Queries.

In section 2.1.1 1) b) says:

     "The 0.0.0.0 address represents a special case where the switch
      is proxying IGMP Queries for faster network convergence,
      but is not itself the Querier."

In section 2.1.1 4) it says:

     "If the switch is not the Querier, it should use the 'all-zeros' IP
      Source Address in these proxy queries (even though some hosts may
      elect to not process queries with a 0.0.0.0 IP Source Address)."

(which seems to imply that if a switch is the selected Querier, that
it should use something other than the 'all-zeros' IP Source
Address?)

Also, section 2.1.1 4) says:

"[...] even though some hosts may elect to not process queries with a
 0.0.0.0 IP Source Address"

Which seems to indicate that 0.0.0.0 might be a bad choice to get
reliable IGMP Reports and might only make sense for performance
optimizations (at least for IPv4 - for IPv6 it doesn't make sense
to me to send General Queries with '::' source address at all
since '::' is ignored by hosts per RFC).

(*)

> 
> With current changes linux bridge will always select a querier who sends a
> query message with 0.0.0.0. Right ?
> 
> +       if (ntohl(saddr) <= ntohl(br->ip4_querier.addr.u.ip4))
> +               goto update;

Yes. Which is what the querier election mechanism in the RFCs for
IGMPv2/IGMPv3 (RFC2236/RFC3376) specifies, I think. (**)

> 
> Currently linux bridge sends a query message with source address as
> 0.0.0.0. Right ?

For IPv4, this is currently the default, yes. (there's a sysfs switch
to change that, if desired) (***)

> 
> What should be the expected behaviour ?

Hm, good question.

Regarding (***): After rereading RFC4541 a few more times, I think
(*) would be the right choice: The bridge code should probably be
changed to always use an available, non-zero IPv4 source address
for General Queries. If none is available it, doesn't make sense
to me to become the selected Querier at all (should be changed for
IPv6, too: Currently it refrains from sending Query messages
then, but thinks a valid querier were in the network, enabling
the multicast snooping of the bridge).


Regarding (**): Now that you're mentioning that, you're right, my
change isn't quite straightforward in that regard, a few lines
earlier there is:

> +       if (!br->ip4_querier.addr.u.ip4)
> +               goto update;

So it would select the all-zeros Querier if it receives such
messages. But would happily switch to a non-all-zeros Querier as
well if receiving such messages...

And now, this baffles me, section 2.1.1 4) again:

     "When such proxy queries are received, they must not be included in
      the Querier election process."

If we were following that, a snooping switch and a true multicast
router could potentially have an argument about which becomes the
selected IGMP querier? (for IPv6/MLD this dilemma should not
exist, I think)

I'm currently unsure, whether we should follow
RFC2236(IGMPv2)+RFC3376(IGMPv3) or the informational (!) RFC4541.

Or am I overlooking something? What do others think?

Cheers, Linus

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-06-27  0:12 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-25  5:03 [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports Linus Lüssing
2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 1/4] bridge: rename struct bridge_mcast_query/querier Linus Lüssing
2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 2/4] bridge: adhere to querier election mechanism specified by RFCs Linus Lüssing
     [not found]   ` <CADAe=+KViC7uej0KM4TrQXxrk-amU7CX73buviMU17jpQm61bw@mail.gmail.com>
2014-06-27  0:12     ` Linus Lüssing
2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 3/4] bridge: add export of multicast database adjacent to net_dev Linus Lüssing
2014-05-30 14:38   ` Stephen Hemminger
2014-05-25  5:03 ` [B.A.T.M.A.N.] [PATCHv2 net-next 4/4] bridge: memorize and export selected IGMP/MLD querier port Linus Lüssing
2014-05-29 22:36 ` [B.A.T.M.A.N.] [PATCHv2 net-next 0/4] bridge: multicast snooping patches / exports David Miller
2014-05-30 14:37   ` Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).