Signed-off-by: Felix Fietkau <n...@nbd.name> --- vlan.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/vlan.c b/vlan.c index 6270d95d755d..7d37fef33e2f 100644 --- a/vlan.c +++ b/vlan.c @@ -18,6 +18,8 @@ #include "netifd.h" #include "system.h" +static struct blob_buf b; + struct vlan_device { struct device dev; struct device_user dep; @@ -36,6 +38,66 @@ static void free_vlan_if(struct device *iface) free(vldev); } +static int +vlan_hotplug_add(struct device *dev, struct device *member, struct blob_attr *vlan) +{ + struct vlan_device *vldev = container_of(dev, struct vlan_device, dev); + void *a; + + dev = vldev->dep.dev; + if (!dev || !dev->hotplug_ops) + return UBUS_STATUS_NOT_SUPPORTED; + + blob_buf_init(&b, 0); + a = blobmsg_open_array(&b, "vlans"); + blobmsg_printf(&b, NULL, "%d", vldev->id); + blobmsg_close_array(&b, a); + + return dev->hotplug_ops->add(dev, member, blobmsg_data(b.head)); +} + +static int +vlan_hotplug_del(struct device *dev, struct device *member) +{ + struct vlan_device *vldev = container_of(dev, struct vlan_device, dev); + + dev = vldev->dep.dev; + if (!dev || !dev->hotplug_ops) + return UBUS_STATUS_NOT_SUPPORTED; + + return dev->hotplug_ops->del(dev, member); +} + +static int +vlan_hotplug_prepare(struct device *dev) +{ + struct vlan_device *vldev = container_of(dev, struct vlan_device, dev); + + dev = vldev->dep.dev; + if (!dev || !dev->hotplug_ops) + return UBUS_STATUS_NOT_SUPPORTED; + + return dev->hotplug_ops->prepare(dev); +} + +static void vlan_hotplug_check(struct vlan_device *vldev) +{ + static const struct device_hotplug_ops hotplug_ops = { + .prepare = vlan_hotplug_prepare, + .add = vlan_hotplug_add, + .del = vlan_hotplug_del + }; + struct device *dev = vldev->dep.dev; + + if (!dev || !dev->hotplug_ops || avl_is_empty(&dev->vlans.avl)) { + vldev->dev.hotplug_ops = NULL; + return; + } + + vldev->dev.hotplug_ops = &hotplug_ops; +} + + static int vlan_set_device_state(struct device *dev, bool up) { struct vlan_device *vldev; @@ -75,6 +137,7 @@ static void vlan_dev_cb(struct device_user *dep, enum device_event ev) device_set_present(&vldev->dev, false); break; case DEV_EVENT_UPDATE_IFNAME: + vlan_hotplug_check(vldev); vldev->dev.hidden = dep->dev->hidden; if (snprintf(name, sizeof(name), "%s.%d", dep->dev->ifname, vldev->id) >= sizeof(name) - 1 || @@ -139,6 +202,7 @@ static struct device *get_vlan_device(struct device *dev, int id, bool create) vldev->dep.cb = vlan_dev_cb; device_add_user(&vldev->dep, dev); + vlan_hotplug_check(vldev); return &vldev->dev; -- 2.28.0 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel