system-linux: add retry for adding member devices to a bridge
authorFelix Fietkau <nbd@nbd.name>
Mon, 23 Nov 2020 11:42:36 +0000 (12:42 +0100)
committerFelix Fietkau <nbd@nbd.name>
Mon, 23 Nov 2020 11:48:53 +0000 (12:48 +0100)
When netifd tries to add bridge members brought up by hostapd asynchronously
(e.g. after an autochannel run), the first try often fails with EBUSY or
EAGAIN, since it's racing against hostapd's own setup.
Add retry logic, which includes checking if the device was added to the
bridge in the meantime to deal with this issue

Signed-off-by: Felix Fietkau <nbd@nbd.name>
system-linux.c

index 7ca4c8b612953a8abecd9ce1836bfe5ce2ca8d40..1d5d2322e2d6a826ecd5c9e1f3aaaf75d40a91c9 100644 (file)
@@ -813,11 +813,20 @@ int system_bridge_addif(struct device *bridge, struct device *dev)
 {
        char buf[64];
        char *oldbr;
-       int ret = 0;
+       int tries = 0;
+       int ret;
 
+retry:
+       ret = 0;
        oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
-       if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
+       if (!oldbr || strcmp(oldbr, bridge->ifname) != 0) {
                ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
+               tries++;
+               D(SYSTEM, "Failed to add device '%s' to bridge '%s' (tries=%d): %s\n",
+                 dev->ifname, bridge->ifname, tries, strerror(errno));
+               if (tries <= 3)
+                       goto retry;
+       }
 
        if (dev->wireless)
                system_bridge_set_wireless(bridge, dev);