netifd: Fix bridge MTU setting when a bridge member is added
authorHans Dedecker <dedeckeh@gmail.com>
Mon, 10 Mar 2014 15:27:51 +0000 (16:27 +0100)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 11 Mar 2014 09:22:57 +0000 (10:22 +0100)
Reapply bridge mtu setting as adding a bridge member will override the bridge mtu in the kernel

Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
bridge.c
device.c
interface.c
system-dummy.c
system-linux.c
system.h

index 7bd1cf0c17bb341bf3a60e97336e3f8a768719de..147fe0a0c6d0d01f5ce85ed7a1384ec00b763ae2 100644 (file)
--- 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:
index 6a770aceee979849335fe7d0e691fb2d2734948e..2fb68d771f59f6ac674192abc85e8ebba567c279 100644 (file)
--- 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) {
index f0fd43f36772c6a0cb06c87adcafa58c4bab4755..43ba773a3a93677f8e49cd89f0c1f535704bab15 100644 (file)
@@ -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);
index c8379ffc910f97e429a8bc77771a425f3699862b..3ab22b0da2509ed5de05bc3b1c97a67096f03688 100644 (file)
@@ -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)
 {
 }
 
index 12682dca33993c56f67dd07a28ccd9e3983c76f9..7cec649fdae76f5dff94d1695d65454401956281 100644 (file)
@@ -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;
 }
 
index ff83a1c93a2dbab107cc153c2e64c7b1162e956d..1ad861a79736877cec00466c343e723f4eec9374 100644 (file)
--- 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);