From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
To: netdev@vger.kernel.org
Cc: roopa@cumulusnetworks.com, davem@davemloft.net,
makita.toshiaki@lab.ntt.co.jp, 3chas3@gmail.com,
stephen@networkplumber.org, bridge@lists.linux-foundation.org,
Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Subject: [PATCH net-next 1/2] net: bridge: set min MTU on port events and allow user to set max
Date: Fri, 30 Mar 2018 13:46:18 +0300 [thread overview]
Message-ID: <20180330104619.31479-2-nikolay@cumulusnetworks.com> (raw)
In-Reply-To: <20180330104619.31479-1-nikolay@cumulusnetworks.com>
Recently the bridge was changed to automatically set maximum MTU on port
events (add/del/changemtu) when vlan filtering is enabled, but that
actually changes behaviour in a way which breaks some setups and can lead
to packet drops. In order to still allow that maximum to be set while being
compatible, we add the ability for the user to tune the bridge MTU up to
the maximum when vlan filtering is enabled, but that has to be done
explicitly and all port events (add/del/changemtu) lead to resetting that
MTU to the minimum as before.
Suggested-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
---
net/bridge/br.c | 2 +-
net/bridge/br_device.c | 3 ++-
net/bridge/br_if.c | 43 ++++++++++++++-----------------------------
net/bridge/br_private.h | 2 +-
4 files changed, 18 insertions(+), 32 deletions(-)
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 26e1616b2c90..565ff055813b 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -52,7 +52,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
switch (event) {
case NETDEV_CHANGEMTU:
- dev_set_mtu(br->dev, br_mtu(br));
+ dev_set_mtu(br->dev, br_mtu(br, false));
break;
case NETDEV_CHANGEADDR:
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 278fc999d355..edb9967eb165 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -224,7 +224,8 @@ static void br_get_stats64(struct net_device *dev,
static int br_change_mtu(struct net_device *dev, int new_mtu)
{
struct net_bridge *br = netdev_priv(dev);
- if (new_mtu > br_mtu(br))
+
+ if (new_mtu > br_mtu(br, br_vlan_enabled(dev)))
return -EINVAL;
dev->mtu = new_mtu;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 87b2afd455c7..7d5dc5a91084 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -424,41 +424,26 @@ int br_del_bridge(struct net *net, const char *name)
return ret;
}
-static bool min_mtu(int a, int b)
-{
- return a < b ? 1 : 0;
-}
-
-static bool max_mtu(int a, int b)
-{
- return a > b ? 1 : 0;
-}
-
-/* MTU of the bridge pseudo-device: ETH_DATA_LEN or the minimum of the ports */
-static int __br_mtu(const struct net_bridge *br, bool (compare_fn)(int, int))
+/* MTU of the bridge pseudo-device: ETH_DATA_LEN if there are no ports, the
+ * minimum of the ports if @max is false or the maximum if it's true
+ */
+int br_mtu(const struct net_bridge *br, bool max)
{
const struct net_bridge_port *p;
- int mtu = 0;
+ int ret_mtu = 0;
ASSERT_RTNL();
- if (list_empty(&br->port_list))
- mtu = ETH_DATA_LEN;
- else {
- list_for_each_entry(p, &br->port_list, list) {
- if (!mtu || compare_fn(p->dev->mtu, mtu))
- mtu = p->dev->mtu;
+ list_for_each_entry(p, &br->port_list, list) {
+ if (!max) {
+ if (!ret_mtu || ret_mtu > p->dev->mtu)
+ ret_mtu = p->dev->mtu;
+ } else if (p->dev->mtu > ret_mtu) {
+ ret_mtu = p->dev->mtu;
}
}
- return mtu;
-}
-int br_mtu(const struct net_bridge *br)
-{
- if (br_vlan_enabled(br->dev))
- return __br_mtu(br, max_mtu);
- else
- return __br_mtu(br, min_mtu);
+ return ret_mtu ? ret_mtu : ETH_DATA_LEN;
}
static void br_set_gso_limits(struct net_bridge *br)
@@ -612,7 +597,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
if (changed_addr)
call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
- dev_set_mtu(br->dev, br_mtu(br));
+ dev_set_mtu(br->dev, br_mtu(br, false));
br_set_gso_limits(br);
kobject_uevent(&p->kobj, KOBJ_ADD);
@@ -659,7 +644,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
*/
del_nbp(p);
- dev_set_mtu(br->dev, br_mtu(br));
+ dev_set_mtu(br->dev, br_mtu(br, false));
br_set_gso_limits(br);
spin_lock_bh(&br->lock);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 048d5b51813b..586f84b9670d 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -578,7 +578,7 @@ int br_del_bridge(struct net *net, const char *name);
int br_add_if(struct net_bridge *br, struct net_device *dev,
struct netlink_ext_ack *extack);
int br_del_if(struct net_bridge *br, struct net_device *dev);
-int br_mtu(const struct net_bridge *br);
+int br_mtu(const struct net_bridge *br, bool max);
netdev_features_t br_features_recompute(struct net_bridge *br,
netdev_features_t features);
void br_port_flags_change(struct net_bridge_port *port, unsigned long mask);
--
2.11.0
next prev parent reply other threads:[~2018-03-30 10:48 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-30 10:46 [PATCH net-next 0/2] net: bridge: MTU handling changes Nikolay Aleksandrov
2018-03-30 10:46 ` Nikolay Aleksandrov [this message]
2018-03-30 10:46 ` [PATCH net-next 2/2] net: bridge: disable bridge MTU auto tuning if it was set manually Nikolay Aleksandrov
2018-04-01 2:05 ` [PATCH net-next 0/2] net: bridge: MTU handling changes David Miller
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=20180330104619.31479-2-nikolay@cumulusnetworks.com \
--to=nikolay@cumulusnetworks.com \
--cc=3chas3@gmail.com \
--cc=bridge@lists.linux-foundation.org \
--cc=davem@davemloft.net \
--cc=makita.toshiaki@lab.ntt.co.jp \
--cc=netdev@vger.kernel.org \
--cc=roopa@cumulusnetworks.com \
--cc=stephen@networkplumber.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