wireless: add support for disabling multicast-to-unicast per virtual interface
authorFelix Fietkau <nbd@nbd.name>
Mon, 19 Dec 2022 17:15:01 +0000 (18:15 +0100)
committerFelix Fietkau <nbd@nbd.name>
Mon, 19 Dec 2022 17:15:24 +0000 (18:15 +0100)
Signed-off-by: Felix Fietkau <nbd@nbd.name>
system-linux.c
wireless.c
wireless.h

index 9fe869fd8d151d6df19bf725a9e616bde4276dcf..f16a9554bbbccaa85cb21cd916f2348271ec956e 100644 (file)
@@ -847,8 +847,10 @@ system_bridge_set_wireless(struct device *bridge, struct device *dev)
        bool mcast_to_ucast = dev->wireless_ap;
        bool hairpin;
 
-       if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
-           !bridge->settings.multicast_to_unicast)
+       if (dev->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST)
+               mcast_to_ucast = dev->settings.multicast_to_unicast;
+       else if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
+                !bridge->settings.multicast_to_unicast)
                mcast_to_ucast = false;
 
        hairpin = mcast_to_ucast || dev->wireless_proxyarp;
index 118f5a7cf135b836210a30ca4d8e3ffcc06df21d..705d6dd028e39d740526957d40b4623fe0b6ab04 100644 (file)
@@ -65,6 +65,7 @@ enum {
        VIF_ATTR_ISOLATE,
        VIF_ATTR_MODE,
        VIF_ATTR_PROXYARP,
+       VIF_ATTR_MCAST_TO_UCAST,
        __VIF_ATTR_MAX,
 };
 
@@ -74,6 +75,7 @@ static const struct blobmsg_policy vif_policy[__VIF_ATTR_MAX] = {
        [VIF_ATTR_ISOLATE] = { .name = "isolate", .type = BLOBMSG_TYPE_BOOL },
        [VIF_ATTR_MODE] = { .name = "mode", .type = BLOBMSG_TYPE_STRING },
        [VIF_ATTR_PROXYARP] = { .name = "proxy_arp", .type = BLOBMSG_TYPE_BOOL },
+       [VIF_ATTR_MCAST_TO_UCAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL },
 };
 
 static const struct uci_blob_param_list vif_param = {
@@ -85,6 +87,7 @@ enum {
        VLAN_ATTR_DISABLED,
        VLAN_ATTR_NETWORK,
        VLAN_ATTR_ISOLATE,
+       VLAN_ATTR_MCAST_TO_UCAST,
        __VLAN_ATTR_MAX,
 };
 
@@ -92,6 +95,7 @@ static const struct blobmsg_policy vlan_policy[__VLAN_ATTR_MAX] = {
        [VLAN_ATTR_DISABLED] = { .name = "disabled", .type = BLOBMSG_TYPE_BOOL },
        [VLAN_ATTR_NETWORK] = { .name = "network", .type = BLOBMSG_TYPE_ARRAY },
        [VLAN_ATTR_ISOLATE] = { .name = "isolate", .type = BLOBMSG_TYPE_BOOL },
+       [VLAN_ATTR_MCAST_TO_UCAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL },
 };
 
 static const struct uci_blob_param_list vlan_param = {
@@ -315,6 +319,17 @@ wireless_device_free_state(struct wireless_device *wdev)
        }
 }
 
+static void wireless_device_set_mcast_to_unicast(struct device *dev, int val)
+{
+       if (val < 0) {
+               dev->settings.flags &= ~DEV_OPT_MULTICAST_TO_UNICAST;
+               return;
+       }
+
+       dev->settings.multicast_to_unicast = !!val;
+       dev->settings.flags |= DEV_OPT_MULTICAST_TO_UNICAST;
+}
+
 static void wireless_interface_handle_link(struct wireless_interface *vif, const char *ifname, bool up)
 {
        struct interface *iface;
@@ -336,6 +351,7 @@ static void wireless_interface_handle_link(struct wireless_interface *vif, const
                        dev->wireless_proxyarp = vif->proxyarp;
                        dev->wireless = true;
                        dev->wireless_ap = vif->ap_mode;
+                       wireless_device_set_mcast_to_unicast(dev, vif->multicast_to_unicast);
                        dev->bpdu_filter = dev->wireless_ap;
                }
        }
@@ -368,6 +384,7 @@ static void wireless_vlan_handle_link(struct wireless_vlan *vlan, bool up)
                        dev->wireless = true;
                        dev->wireless_ap = true;
                        dev->bpdu_filter = true;
+                       wireless_device_set_mcast_to_unicast(dev, vlan->multicast_to_unicast);
                }
        }
 
@@ -811,6 +828,9 @@ wireless_interface_init_config(struct wireless_interface *vif)
 
        cur = tb[VIF_ATTR_PROXYARP];
        vif->proxyarp = vif->ap_mode && cur && blobmsg_get_bool(cur);
+
+       cur = tb[VIF_ATTR_MCAST_TO_UCAST];
+       vif->multicast_to_unicast = cur ? blobmsg_get_bool(cur) : -1;
 }
 
 /* vlist update call for wireless interface list */
@@ -873,6 +893,9 @@ wireless_vlan_init_config(struct wireless_vlan *vlan)
        cur = tb[VLAN_ATTR_ISOLATE];
        if (cur)
                vlan->isolate = blobmsg_get_bool(cur);
+
+       cur = tb[VLAN_ATTR_MCAST_TO_UCAST];
+       vlan->multicast_to_unicast = cur ? blobmsg_get_bool(cur) : -1;
 }
 
 /* vlist update call for vlan list */
index 7b87611adacdb25e4f2ecb2ce9405e2308b33bf7..690c79789cca0311e633b410dc24fbf1850a1e74 100644 (file)
@@ -91,6 +91,7 @@ struct wireless_interface {
        bool proxyarp;
        bool isolate;
        bool ap_mode;
+       int multicast_to_unicast;
 };
 
 struct wireless_vlan {
@@ -106,6 +107,7 @@ struct wireless_vlan {
 
        const char *ifname;
        struct blob_attr *network;
+       int multicast_to_unicast;
        bool isolate;
 };