wireless: improve reliability of proxyarp support
authorFelix Fietkau <nbd@nbd.name>
Wed, 1 Sep 2021 17:00:41 +0000 (19:00 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 1 Sep 2021 17:03:30 +0000 (19:03 +0200)
instead of relying on hostapd to manipulate bridge attributes (which can race
against netifd adding/removing of member ports), set the proxyarp related
attributes in netifd directly when bringing up the member port

Signed-off-by: Felix Fietkau <nbd@nbd.name>
device.h
scripts/netifd-wireless.sh
system-linux.c
wireless.c
wireless.h

index 88cce9ad6552a5d43cc18c4788a207f4e2fef761..0496e893cbc93f53691649c8096f7d0a7af0c5c0 100644 (file)
--- a/device.h
+++ b/device.h
@@ -243,6 +243,7 @@ struct device {
        bool default_config;
        bool wireless;
        bool wireless_ap;
+       bool wireless_proxyarp;
        bool wireless_isolate;
        bool bpdu_filter;
 
index 552779162251c7e67c04733f3238aa4dcc0a7e00..80fbf7561b97f1d66d33e1b84b269a8231523f11 100644 (file)
@@ -294,10 +294,10 @@ _wireless_set_brsnoop_isolation() {
        local multicast_to_unicast="$1"
        local isolate
 
-       json_get_var isolate isolate
+       json_get_vars isolate proxy_arp
 
        [ ${isolate:-0} -gt 0 -o -z "$network_bridge" ] && return
-       [ ${multicast_to_unicast:-1} -gt 0 ] && json_add_boolean isolate 1
+       [ ${multicast_to_unicast:-1} -gt 0 -o ${proxy_arp:-0} -gt 0 ] && json_add_boolean isolate 1
 }
 
 for_each_interface() {
index 7c9100892cfb9ccb510de69cfedb57363c28a348..6c6f1ec6d350742d03fd0d05a93a6c6dd6618a2b 100644 (file)
@@ -464,6 +464,11 @@ static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
        system_set_dev_sysfs("brport/hairpin_mode", dev->ifname, val);
 }
 
+static void system_bridge_set_proxyarp_wifi(struct device *dev, const char *val)
+{
+       system_set_dev_sysfs("brport/proxyarp_wifi", dev->ifname, val);
+}
+
 static void system_bridge_set_bpdu_filter(struct device *dev, const char *val)
 {
        system_set_dev_sysfs("brport/bpdu_filter", dev->ifname, val);
@@ -870,17 +875,19 @@ static void
 system_bridge_set_wireless(struct device *bridge, struct device *dev)
 {
        bool mcast_to_ucast = dev->wireless_ap;
-       bool hairpin = true;
+       bool hairpin;
 
        if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
            !bridge->settings.multicast_to_unicast)
                mcast_to_ucast = false;
 
-       if (!mcast_to_ucast || dev->wireless_isolate)
+       hairpin = mcast_to_ucast || dev->wireless_proxyarp;
+       if (dev->wireless_isolate)
                hairpin = false;
 
        system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
        system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
+       system_bridge_set_proxyarp_wifi(dev, dev->wireless_proxyarp ? "1" : "0");
 }
 
 int system_bridge_addif(struct device *bridge, struct device *dev)
index 61125a489259a99309dbce9c2e1c101c2797bef0..0e6447d5584d7ec707bf8d0e7d2c460b6daf8d6c 100644 (file)
@@ -64,6 +64,7 @@ enum {
        VIF_ATTR_NETWORK,
        VIF_ATTR_ISOLATE,
        VIF_ATTR_MODE,
+       VIF_ATTR_PROXYARP,
        __VIF_ATTR_MAX,
 };
 
@@ -72,6 +73,7 @@ static const struct blobmsg_policy vif_policy[__VIF_ATTR_MAX] = {
        [VIF_ATTR_NETWORK] = { .name = "network", .type = BLOBMSG_TYPE_ARRAY },
        [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 },
 };
 
 static const struct uci_blob_param_list vif_param = {
@@ -330,6 +332,7 @@ static void wireless_interface_handle_link(struct wireless_interface *vif, const
                struct device *dev = device_get(ifname, 2);
                if (dev) {
                        dev->wireless_isolate = vif->isolate;
+                       dev->wireless_proxyarp = vif->proxyarp;
                        dev->wireless = true;
                        dev->wireless_ap = vif->ap_mode;
                        dev->bpdu_filter = dev->wireless_ap && ifname == vif->ifname;
@@ -794,6 +797,10 @@ wireless_interface_init_config(struct wireless_interface *vif)
        if (cur)
                vif->isolate = blobmsg_get_bool(cur);
 
+       cur = tb[VIF_ATTR_PROXYARP];
+       if (cur)
+               vif->proxyarp = blobmsg_get_bool(cur);
+
        cur = tb[VIF_ATTR_MODE];
        if (cur)
                vif->ap_mode = !strcmp(blobmsg_get_string(cur), "ap");
index 59692180b667e54bbd42cabdc6b225b884258e80..7b87611adacdb25e4f2ecb2ce9405e2308b33bf7 100644 (file)
@@ -88,6 +88,7 @@ struct wireless_interface {
 
        const char *ifname;
        struct blob_attr *network;
+       bool proxyarp;
        bool isolate;
        bool ap_mode;
 };