Skip to content

Commit 419d14a

Browse files
3chas3davem330
authored andcommitted
bridge: Allow max MTU when multiple VLANs present
If the bridge is allowing multiple VLANs, some VLANs may have different MTUs. Instead of choosing the minimum MTU for the bridge interface, choose the maximum MTU of the bridge members. With this the user only needs to set a larger MTU on the member ports that are participating in the large MTU VLANS. Signed-off-by: Chas Williams <[email protected]> Reviewed-by: Nikolay Aleksandrov <[email protected]> Acked-by: Roopa Prabhu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bda7fab commit 419d14a

File tree

4 files changed

+25
-7
lines changed

4 files changed

+25
-7
lines changed

net/bridge/br.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
5252

5353
switch (event) {
5454
case NETDEV_CHANGEMTU:
55-
dev_set_mtu(br->dev, br_min_mtu(br));
55+
dev_set_mtu(br->dev, br_mtu(br));
5656
break;
5757

5858
case NETDEV_CHANGEADDR:

net/bridge/br_device.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ static void br_get_stats64(struct net_device *dev,
224224
static int br_change_mtu(struct net_device *dev, int new_mtu)
225225
{
226226
struct net_bridge *br = netdev_priv(dev);
227-
if (new_mtu > br_min_mtu(br))
227+
if (new_mtu > br_mtu(br))
228228
return -EINVAL;
229229

230230
dev->mtu = new_mtu;

net/bridge/br_if.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,18 @@ int br_del_bridge(struct net *net, const char *name)
424424
return ret;
425425
}
426426

427+
static bool min_mtu(int a, int b)
428+
{
429+
return a < b ? 1 : 0;
430+
}
431+
432+
static bool max_mtu(int a, int b)
433+
{
434+
return a > b ? 1 : 0;
435+
}
436+
427437
/* MTU of the bridge pseudo-device: ETH_DATA_LEN or the minimum of the ports */
428-
int br_min_mtu(const struct net_bridge *br)
438+
static int __br_mtu(const struct net_bridge *br, bool (compare_fn)(int, int))
429439
{
430440
const struct net_bridge_port *p;
431441
int mtu = 0;
@@ -436,13 +446,21 @@ int br_min_mtu(const struct net_bridge *br)
436446
mtu = ETH_DATA_LEN;
437447
else {
438448
list_for_each_entry(p, &br->port_list, list) {
439-
if (!mtu || p->dev->mtu < mtu)
449+
if (!mtu || compare_fn(p->dev->mtu, mtu))
440450
mtu = p->dev->mtu;
441451
}
442452
}
443453
return mtu;
444454
}
445455

456+
int br_mtu(const struct net_bridge *br)
457+
{
458+
if (br->vlan_enabled)
459+
return __br_mtu(br, max_mtu);
460+
else
461+
return __br_mtu(br, min_mtu);
462+
}
463+
446464
static void br_set_gso_limits(struct net_bridge *br)
447465
{
448466
unsigned int gso_max_size = GSO_MAX_SIZE;
@@ -594,7 +612,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
594612
if (changed_addr)
595613
call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
596614

597-
dev_set_mtu(br->dev, br_min_mtu(br));
615+
dev_set_mtu(br->dev, br_mtu(br));
598616
br_set_gso_limits(br);
599617

600618
kobject_uevent(&p->kobj, KOBJ_ADD);
@@ -641,7 +659,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
641659
*/
642660
del_nbp(p);
643661

644-
dev_set_mtu(br->dev, br_min_mtu(br));
662+
dev_set_mtu(br->dev, br_mtu(br));
645663
br_set_gso_limits(br);
646664

647665
spin_lock_bh(&br->lock);

net/bridge/br_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ int br_del_bridge(struct net *net, const char *name);
578578
int br_add_if(struct net_bridge *br, struct net_device *dev,
579579
struct netlink_ext_ack *extack);
580580
int br_del_if(struct net_bridge *br, struct net_device *dev);
581-
int br_min_mtu(const struct net_bridge *br);
581+
int br_mtu(const struct net_bridge *br);
582582
netdev_features_t br_features_recompute(struct net_bridge *br,
583583
netdev_features_t features);
584584
void br_port_flags_change(struct net_bridge_port *port, unsigned long mask);

0 commit comments

Comments
 (0)