From 02021e2069d0ee315b0ff263b6c010bef63b879c Mon Sep 17 00:00:00 2001 From: Hans Dedecker Date: Mon, 10 Mar 2014 16:27:51 +0100 Subject: [PATCH] netifd: Fix bridge MTU setting when a bridge member is added Reapply bridge mtu setting as adding a bridge member will override the bridge mtu in the kernel Signed-off-by: Hans Dedecker --- bridge.c | 11 +++++++++-- device.c | 2 +- interface.c | 2 +- system-dummy.c | 2 +- system-linux.c | 15 +++++++++------ system.h | 4 ++-- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/bridge.c b/bridge.c index 7bd1cf0..147fe0a 100644 --- a/bridge.c +++ b/bridge.c @@ -233,8 +233,15 @@ bridge_member_cb(struct device_user *dev, enum device_event ev) if (bst->n_present == 1) device_set_present(&bst->dev, true); - if (bst->dev.active) - bridge_enable_member(bm); + if (bst->dev.active && !bridge_enable_member(bm)) { + /* + * Adding a bridge member can overwrite the bridge mtu + * in the kernel, apply the bridge settings in case the + * bridge mtu is set + */ + system_if_apply_settings(&bst->dev, &bst->dev.settings, + DEV_OPT_MTU); + } break; case DEV_EVENT_REMOVE: diff --git a/device.c b/device.c index 6a770ac..2fb68d7 100644 --- a/device.c +++ b/device.c @@ -623,7 +623,7 @@ device_create(const char *name, const struct device_type *type, odev->current_config = true; change = device_set_config(odev, type, config); if (odev->external) { - system_if_apply_settings(odev, &odev->settings); + system_if_apply_settings(odev, &odev->settings, odev->settings.flags); change = DEV_CONFIG_APPLIED; } switch (change) { diff --git a/interface.c b/interface.c index f0fd43f..43ba773 100644 --- a/interface.c +++ b/interface.c @@ -839,7 +839,7 @@ interface_handle_link(struct interface *iface, const char *name, bool add) if (iface->device_config) device_set_config(dev, &simple_device_type, iface->config); - system_if_apply_settings(dev, &dev->settings); + system_if_apply_settings(dev, &dev->settings, dev->settings.flags); ret = interface_add_link(iface, dev); } else { ret = interface_remove_link(iface, dev); diff --git a/system-dummy.c b/system-dummy.c index c8379ff..3ab22b0 100644 --- a/system-dummy.c +++ b/system-dummy.c @@ -120,7 +120,7 @@ system_if_dump_stats(struct device *dev, struct blob_buf *b) } void -system_if_apply_settings(struct device *dev, struct device_settings *s) +system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask) { } diff --git a/system-linux.c b/system-linux.c index 12682dc..7cec649 100644 --- a/system-linux.c +++ b/system-linux.c @@ -798,23 +798,26 @@ system_if_get_settings(struct device *dev, struct device_settings *s) } void -system_if_apply_settings(struct device *dev, struct device_settings *s) +system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask) { struct ifreq ifr; + if (!apply_mask) + return; + memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)); - if (s->flags & DEV_OPT_MTU) { + if (s->flags & DEV_OPT_MTU & apply_mask) { ifr.ifr_mtu = s->mtu; if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0) s->flags &= ~DEV_OPT_MTU; } - if (s->flags & DEV_OPT_TXQUEUELEN) { + if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) { ifr.ifr_qlen = s->txqueuelen; if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0) s->flags &= ~DEV_OPT_TXQUEUELEN; } - if ((s->flags & DEV_OPT_MACADDR) && !dev->external) { + if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) { ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr)); if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0) @@ -825,7 +828,7 @@ system_if_apply_settings(struct device *dev, struct device_settings *s) int system_if_up(struct device *dev) { system_if_get_settings(dev, &dev->orig_settings); - system_if_apply_settings(dev, &dev->settings); + system_if_apply_settings(dev, &dev->settings, dev->settings.flags); device_set_ifindex(dev, system_if_resolve(dev)); return system_if_flags(dev->ifname, IFF_UP, 0); } @@ -834,7 +837,7 @@ int system_if_down(struct device *dev) { int ret = system_if_flags(dev->ifname, 0, IFF_UP); dev->orig_settings.flags &= dev->settings.flags; - system_if_apply_settings(dev, &dev->orig_settings); + system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags); return ret; } diff --git a/system.h b/system.h index ff83a1c..1ad861a 100644 --- a/system.h +++ b/system.h @@ -104,8 +104,8 @@ int system_if_dump_info(struct device *dev, struct blob_buf *b); int system_if_dump_stats(struct device *dev, struct blob_buf *b); struct device *system_if_get_parent(struct device *dev); bool system_if_force_external(const char *ifname); -void system_if_apply_settings(struct device *dev, struct device_settings *s); - +void system_if_apply_settings(struct device *dev, struct device_settings *s, + unsigned int apply_mask); int system_add_address(struct device *dev, struct device_addr *addr); int system_del_address(struct device *dev, struct device_addr *addr); -- 2.11.0