X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=bridge.c;h=1d02f8375753c156c22c6875059146f7d3420749;hp=1725162a5c62f9d3689898a4105e78aeaaf2aae8;hb=8e14def28d08c4bdb9997a518ad85afbc8ccfbc9;hpb=7db45fcc1faa7c62541b762aa7ba2e99b1bc6342 diff --git a/bridge.c b/bridge.c index 1725162..1d02f83 100644 --- a/bridge.c +++ b/bridge.c @@ -102,13 +102,24 @@ bridge_reset_primary(struct bridge_state *bst) { struct bridge_member *bm; + if (!bst->primary_port && + (bst->dev.settings.flags & DEV_OPT_MACADDR)) + return; + bst->primary_port = NULL; + bst->dev.settings.flags &= ~DEV_OPT_MACADDR; vlist_for_each_element(&bst->members, bm, node) { + uint8_t *macaddr; + if (!bm->present) continue; bst->primary_port = bm; - memcpy(bst->dev.settings.macaddr, bm->dev.dev->settings.macaddr, 6); + if (bm->dev.dev->settings.flags & DEV_OPT_MACADDR) + macaddr = bm->dev.dev->settings.macaddr; + else + macaddr = bm->dev.dev->orig_settings.macaddr; + memcpy(bst->dev.settings.macaddr, macaddr, 6); bst->dev.settings.flags |= DEV_OPT_MACADDR; return; } @@ -178,6 +189,29 @@ bridge_remove_member(struct bridge_member *bm) } static void +bridge_free_member(struct bridge_member *bm) +{ + struct device *dev = bm->dev.dev; + + bridge_remove_member(bm); + device_remove_user(&bm->dev); + + /* + * When reloading the config and moving a device from one bridge to + * another, the other bridge may have tried to claim this device + * before it was removed here. + * Ensure that claiming the device is retried by toggling its present + * state + */ + if (dev->present) { + device_set_present(dev, false); + device_set_present(dev, true); + } + + free(bm); +} + +static void bridge_member_cb(struct device_user *dev, enum device_event ev) { struct bridge_member *bm = container_of(dev, struct bridge_member, dev); @@ -312,9 +346,7 @@ bridge_member_update(struct vlist_tree *tree, struct vlist_node *node_new, if (node_old) { bm = container_of(node_old, struct bridge_member, node); - bridge_remove_member(bm); - device_remove_user(&bm->dev); - free(bm); + bridge_free_member(bm); } }