b.a.t.m.a.n.lists.open-mesh.org archive mirror
 help / color / mirror / Atom feed
From: "Linus Lüssing" <linus.luessing@c0d3.blue>
To: b.a.t.m.a.n@lists.open-mesh.org
Cc: "Linus Lüssing" <linus.luessing@c0d3.blue>
Subject: [PATCH v5 3/3] batman-adv: avoid adding bridge VLAN IDs through ndo_vlan_rx_add_vid()
Date: Sat,  1 Feb 2025 05:31:30 +0100	[thread overview]
Message-ID: <20250201043725.15217-4-linus.luessing@c0d3.blue> (raw)
In-Reply-To: <20250201043725.15217-1-linus.luessing@c0d3.blue>

The Linux bridge by default adds the PVID of a port (default VID 1) and
by that triggers our ndo_vlan_rx_add_vid() handler. The PVID is
for ingress traffic from bat0 to the bridge and other bridge ports.
However this makes no statement about what is received or send on bat0
itself, bat0 might as well be an untagged access port, even with a PVID
configured. Therefore ignoring here when a bridge is involved.

Also, similarly a "bridge vlan add vid 42 dev bat0 untagged" would call
this handler with VID 42. Even though we wouldn't be interested in this
VLAN as its traffic would be untagged on our side.

The issue is that any extra VLAN currently increases our own
OGM protocol overhead quite a bit, so we want to avoid that
by only adding VLANs that we are sure someone will be using.
So only add VLANs through snooping of actual, VLAN tagged
traffic, not through kernel internal network events
if we have a bridge on top.

Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
 net/batman-adv/multicast.c      | 30 +++------------------
 net/batman-adv/soft-interface.c | 47 +++++++++++++++++++++++++++++++++
 net/batman-adv/soft-interface.h |  1 +
 3 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index b39c214c0c6d..9b7290bf05bd 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -56,6 +56,7 @@
 #include "log.h"
 #include "netlink.h"
 #include "send.h"
+#include "soft-interface.h"
 #include "translation-table.h"
 #include "tvlv.h"
 
@@ -71,31 +72,6 @@ static void batadv_mcast_start_timer(struct batadv_priv *bat_priv)
 			   msecs_to_jiffies(BATADV_MCAST_WORK_PERIOD));
 }
 
-/**
- * batadv_mcast_get_bridge() - get the bridge on top of the softif if it exists
- * @soft_iface: netdev struct of the mesh interface
- *
- * If the given soft interface has a bridge on top then the refcount
- * of the according net device is increased.
- *
- * Return: NULL if no such bridge exists. Otherwise the net device of the
- * bridge.
- */
-static struct net_device *batadv_mcast_get_bridge(struct net_device *soft_iface)
-{
-	struct net_device *upper = soft_iface;
-
-	rcu_read_lock();
-	do {
-		upper = netdev_master_upper_dev_get_rcu(upper);
-	} while (upper && !netif_is_bridge_master(upper));
-
-	dev_hold(upper);
-	rcu_read_unlock();
-
-	return upper;
-}
-
 /**
  * batadv_mcast_mla_rtr_flags_softif_get_ipv4() - get mcast router flags from
  *  node for IPv4
@@ -288,7 +264,7 @@ batadv_mcast_mla_flags_get(struct batadv_priv *bat_priv)
 	struct batadv_mcast_mla_flags mla_flags;
 	struct net_device *bridge;
 
-	bridge = batadv_mcast_get_bridge(dev);
+	bridge = batadv_softif_get_bridge(dev);
 
 	memset(&mla_flags, 0, sizeof(mla_flags));
 	mla_flags.enabled = 1;
@@ -530,7 +506,7 @@ batadv_mcast_mla_softif_get(struct net_device *dev,
 			    struct hlist_head *mcast_list,
 			    struct batadv_mcast_mla_flags *flags)
 {
-	struct net_device *bridge = batadv_mcast_get_bridge(dev);
+	struct net_device *bridge = batadv_softif_get_bridge(dev);
 	int ret4, ret6 = 0;
 
 	if (bridge)
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 806c30fd17ce..70a27eb1db8e 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -677,6 +677,31 @@ static void batadv_softif_destroy_vlan_own(struct batadv_priv *bat_priv,
 			       "vlan interface destroyed", false);
 }
 
+/**
+ * batadv_softif_get_bridge() - get the bridge on top of the softif if it exists
+ * @soft_iface: netdev struct of the mesh interface
+ *
+ * If the given soft interface has a bridge on top then the refcount
+ * of the according net device is increased.
+ *
+ * Return: NULL if no such bridge exists. Otherwise the net device of the
+ * bridge.
+ */
+struct net_device *batadv_softif_get_bridge(struct net_device *soft_iface)
+{
+	struct net_device *upper = soft_iface;
+
+	rcu_read_lock();
+	do {
+		upper = netdev_master_upper_dev_get_rcu(upper);
+	} while (upper && !netif_is_bridge_master(upper));
+
+	dev_hold(upper);
+	rcu_read_unlock();
+
+	return upper;
+}
+
 /**
  * batadv_interface_add_vid() - ndo_add_vid API implementation
  * @dev: the netdev of the mesh interface
@@ -692,6 +717,7 @@ static int batadv_interface_add_vid(struct net_device *dev, __be16 proto,
 				    unsigned short vid)
 {
 	struct batadv_priv *bat_priv = netdev_priv(dev);
+	struct net_device *bridge;
 
 	/* only 802.1Q vlans are supported.
 	 * batman-adv does not know how to handle other types
@@ -707,6 +733,20 @@ static int batadv_interface_add_vid(struct net_device *dev, __be16 proto,
 	if (vid == 0)
 		return 0;
 
+	/* The Linux bridge adds the PVID of a port (default VID 1) and
+	 * triggers this handler. The PVID is for ingress traffic from
+	 * bat0 to the bridge and other bridge ports. However this makes no
+	 * statement about what is received or send on bat0 itself, bat0
+	 * might as well be an untagged access port, even with a PVID
+	 * configured. Therefore ignoring here when a bridge is involved.
+	 * Instead learn VLANs on the fly from traffic.
+	 */
+	bridge = batadv_softif_get_bridge(dev);
+	if (bridge) {
+		dev_put(bridge);
+		return 0;
+	}
+
 	vid |= BATADV_VLAN_HAS_TAG;
 
 	return batadv_softif_create_vlan_own(bat_priv, vid);
@@ -728,6 +768,7 @@ static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto,
 				     unsigned short vid)
 {
 	struct batadv_priv *bat_priv = netdev_priv(dev);
+	struct net_device *bridge;
 
 	/* only 802.1Q vlans are supported. batman-adv does not know how to
 	 * handle other types
@@ -741,6 +782,12 @@ static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto,
 	if (vid == 0)
 		return 0;
 
+	bridge = batadv_softif_get_bridge(dev);
+	if (bridge) {
+		dev_put(bridge);
+		return 0;
+	}
+
 	batadv_softif_destroy_vlan_own(bat_priv, vid | BATADV_VLAN_HAS_TAG);
 	return 0;
 }
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index f5334d275229..130447cb22a8 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -19,6 +19,7 @@ int batadv_skb_head_push(struct sk_buff *skb, unsigned int len);
 void batadv_interface_rx(struct net_device *soft_iface,
 			 struct sk_buff *skb, int hdr_size,
 			 struct batadv_orig_node *orig_node);
+struct net_device *batadv_softif_get_bridge(struct net_device *soft_iface);
 bool batadv_softif_is_valid(const struct net_device *net_dev);
 extern struct rtnl_link_ops batadv_link_ops;
 int batadv_softif_create_vlan_own(struct batadv_priv *bat_priv,
-- 
2.47.2


  parent reply	other threads:[~2025-02-01  4:40 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-01  4:31 [PATCH v5 0/3] batman-adv: add dynamic, bridged-in TT VID detection Linus Lüssing
2025-02-01  4:31 ` [PATCH v5 1/3] batman-adv: add dynamic, bridged-in TT VID detection support Linus Lüssing
2025-02-01  4:31 ` [PATCH v5 2/3] batman-adv: limit number of learned VLANs from bridged-in clients Linus Lüssing
2025-02-01  4:31 ` Linus Lüssing [this message]
2025-02-01  9:42 ` [PATCH v5 0/3] batman-adv: add dynamic, bridged-in TT VID detection Sven Eckelmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250201043725.15217-4-linus.luessing@c0d3.blue \
    --to=linus.luessing@c0d3.blue \
    --cc=b.a.t.m.a.n@lists.open-mesh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).