summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2021-06-17 10:39:26 +0200
committerFelix Fietkau <nbd@nbd.name>2021-06-17 10:39:28 +0200
commitb0d0906883021baca9ef6e80ba0480ac3e2a4b7a (patch)
treefffc8f111c2f1c6eb2c54265b8b044569b961df2
parentf12b073c0cc3b1ee8d652a342505ae0b14856c18 (diff)
downloadnetifd-b0d0906883021baca9ef6e80ba0480ac3e2a4b7a.tar.gz
bridge: fix setting pvid for updated vlans
defer adding back changed vlans until config processing is done Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--bridge.c19
-rw-r--r--device.c3
-rw-r--r--device.h2
3 files changed, 23 insertions, 1 deletions
diff --git a/bridge.c b/bridge.c
index ecb9b03..f3e2fed 100644
--- a/bridge.c
+++ b/bridge.c
@@ -79,6 +79,7 @@ static const struct uci_blob_param_list bridge_attr_list = {
static struct device *bridge_create(const char *name, struct device_type *devtype,
struct blob_attr *attr);
static void bridge_config_init(struct device *dev);
+static void bridge_dev_vlan_update(struct device *dev);
static void bridge_free(struct device *dev);
static void bridge_dump_info(struct device *dev, struct blob_buf *b);
static enum dev_change_type
@@ -93,6 +94,7 @@ static struct device_type bridge_device_type = {
.create = bridge_create,
.config_init = bridge_config_init,
+ .vlan_update = bridge_dev_vlan_update,
.reload = bridge_reload,
.free = bridge_free,
.dump_info = bridge_dump_info,
@@ -1185,7 +1187,7 @@ bridge_vlan_update(struct vlist_tree *tree, struct vlist_node *node_new,
list_splice_init(&vlan_old->hotplug_ports, &vlan_new->hotplug_ports);
if (node_new)
- bridge_set_vlan_state(bst, vlan_new, true);
+ vlan_new->pending = true;
bst->dev.config_pending = true;
@@ -1193,6 +1195,21 @@ out:
bridge_vlan_free(vlan_old);
}
+static void
+bridge_dev_vlan_update(struct device *dev)
+{
+ struct bridge_state *bst = container_of(dev, struct bridge_state, dev);
+ struct bridge_vlan *vlan;
+
+ vlist_for_each_element(&dev->vlans, vlan, node) {
+ if (!vlan->pending)
+ continue;
+
+ vlan->pending = false;
+ bridge_set_vlan_state(bst, vlan, true);
+ }
+}
+
static struct device *
bridge_create(const char *name, struct device_type *devtype,
struct blob_attr *attr)
diff --git a/device.c b/device.c
index 26254cc..9bad507 100644
--- a/device.c
+++ b/device.c
@@ -129,6 +129,9 @@ void device_vlan_update(bool done)
vlist_update(&dev->vlans);
} else {
vlist_flush(&dev->vlans);
+
+ if (dev->type->vlan_update)
+ dev->type->vlan_update(dev);
}
}
}
diff --git a/device.h b/device.h
index c6fc02b..db6dc33 100644
--- a/device.h
+++ b/device.h
@@ -83,6 +83,7 @@ struct device_type {
struct blob_attr *attr);
void (*config_init)(struct device *);
enum dev_change_type (*reload)(struct device *, struct blob_attr *);
+ void (*vlan_update)(struct device *);
void (*dump_info)(struct device *, struct blob_buf *buf);
void (*dump_stats)(struct device *, struct blob_buf *buf);
int (*check_state)(struct device *);
@@ -277,6 +278,7 @@ struct bridge_vlan {
uint16_t vid;
bool local;
+ bool pending;
};
extern const struct uci_blob_param_list device_attr_list;