summaryrefslogtreecommitdiff
path: root/bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'bridge.c')
-rw-r--r--bridge.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/bridge.c b/bridge.c
index 6c8e79a..32796bf 100644
--- a/bridge.c
+++ b/bridge.c
@@ -122,17 +122,13 @@ struct bridge_member {
struct vlist_node node;
struct bridge_state *bst;
struct device_user dev;
+ struct uloop_timeout check_timer;
uint16_t pvid;
bool present;
bool active;
char name[];
};
-struct bridge_vlan_hotplug_port {
- struct list_head list;
- struct bridge_vlan_port port;
-};
-
static void
bridge_reset_primary(struct bridge_state *bst)
{
@@ -477,6 +473,7 @@ restart:
device_lock();
device_remove_user(&bm->dev);
+ uloop_timeout_cancel(&bm->check_timer);
/*
* When reloading the config and moving a device from one bridge to
@@ -505,6 +502,22 @@ bridge_check_retry(struct bridge_state *bst)
}
static void
+bridge_member_check_cb(struct uloop_timeout *t)
+{
+ struct bridge_member *bm;
+ struct bridge_state *bst;
+
+ bm = container_of(t, struct bridge_member, check_timer);
+ bst = bm->bst;
+
+ if (!system_bridge_vlan_check(&bst->dev, bm->dev.dev->ifname))
+ return;
+
+ bridge_disable_member(bm, true);
+ bridge_enable_member(bm);
+}
+
+static void
bridge_member_cb(struct device_user *dep, enum device_event ev)
{
struct bridge_member *bm = container_of(dep, struct bridge_member, dev);
@@ -521,6 +534,9 @@ bridge_member_cb(struct device_user *dep, enum device_event ev)
if (bst->n_present == 1)
device_set_present(&bst->dev, true);
fallthrough;
+ case DEV_EVENT_LINK_UP:
+ uloop_timeout_set(&bm->check_timer, 1000);
+ break;
case DEV_EVENT_AUTH_UP:
if (!bst->dev.active)
break;
@@ -634,6 +650,7 @@ bridge_create_member(struct bridge_state *bst, const char *name,
bm->bst = bst;
bm->dev.cb = bridge_member_cb;
bm->dev.hotplug = hotplug;
+ bm->check_timer.cb = bridge_member_check_cb;
strcpy(bm->name, name);
bm->dev.dev = dev;
vlist_add(&bst->members, &bm->node, bm->name);