summaryrefslogtreecommitdiff
path: root/bridge.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2015-01-23 12:41:56 +0100
committerFelix Fietkau <nbd@openwrt.org>2015-01-23 13:02:10 +0100
commit8db8cbbb449ff1f2fd010846061cd2799aef3b43 (patch)
treea3e1d499649b163a60c54a0a6b9743ac37e84fc7 /bridge.c
parentbd92cd79a09d9eb943ce23a1d3edcbc2d95f2e5b (diff)
downloadnetifd-8db8cbbb449ff1f2fd010846061cd2799aef3b43.tar.gz
bridge: fix retrying member enable when the bridge is otherwise empty
Ensure that the bridge gets created before retrying Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Diffstat (limited to 'bridge.c')
-rw-r--r--bridge.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/bridge.c b/bridge.c
index f68d773..f8478ad 100644
--- a/bridge.c
+++ b/bridge.c
@@ -148,6 +148,32 @@ bridge_disable_member(struct bridge_member *bm)
}
static int
+bridge_enable_interface(struct bridge_state *bst)
+{
+ int ret;
+
+ if (bst->active)
+ return 0;
+
+ ret = system_bridge_addbr(&bst->dev, &bst->config);
+ if (ret < 0)
+ return ret;
+
+ bst->active = true;
+ return 0;
+}
+
+static void
+bridge_disable_interface(struct bridge_state *bst)
+{
+ if (!bst->active)
+ return;
+
+ system_bridge_delbr(&bst->dev);
+ bst->active = false;
+}
+
+static int
bridge_enable_member(struct bridge_member *bm)
{
struct bridge_state *bst = bm->bst;
@@ -156,6 +182,10 @@ bridge_enable_member(struct bridge_member *bm)
if (!bm->present)
return 0;
+ ret = bridge_enable_interface(bst);
+ if (ret)
+ goto error;
+
/* Disable IPv6 for bridge members */
if (!(bm->dev.dev->settings.flags & DEV_OPT_IPV6)) {
bm->dev.dev->settings.ipv6 = 0;
@@ -172,6 +202,7 @@ bridge_enable_member(struct bridge_member *bm)
goto error;
}
+ device_set_present(&bst->dev, true);
device_broadcast_event(&bst->dev, DEV_EVENT_TOPO_CHANGE);
return 0;
@@ -293,7 +324,7 @@ bridge_set_down(struct bridge_state *bst)
vlist_for_each_element(&bst->members, bm, node)
bridge_disable_member(bm);
- system_bridge_delbr(&bst->dev);
+ bridge_disable_interface(bst);
return 0;
}
@@ -304,12 +335,14 @@ bridge_set_up(struct bridge_state *bst)
struct bridge_member *bm;
int ret;
- if (!bst->force_active && !bst->n_present)
- return -ENOENT;
+ if (!bst->n_present) {
+ if (!bst->force_active)
+ return -ENOENT;
- ret = system_bridge_addbr(&bst->dev, &bst->config);
- if (ret < 0)
- goto out;
+ ret = bridge_enable_interface(bst);
+ if (ret)
+ return ret;
+ }
bst->n_failed = 0;
vlist_for_each_element(&bst->members, bm, node)
@@ -318,7 +351,7 @@ bridge_set_up(struct bridge_state *bst)
if (!bst->force_active && !bst->n_present) {
/* initialization of all member interfaces failed */
- system_bridge_delbr(&bst->dev);
+ bridge_disable_interface(bst);
device_set_present(&bst->dev, false);
return -ENOENT;
}
@@ -328,7 +361,6 @@ bridge_set_up(struct bridge_state *bst)
if (ret < 0)
bridge_set_down(bst);
-out:
return ret;
}