summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2021-09-01 19:00:41 +0200
committerFelix Fietkau <nbd@nbd.name>2021-09-01 19:03:30 +0200
commit300b1220fab38600f102bb8cfcc59a29ce41b095 (patch)
tree103ae559ccdf4f34065fb761bcd25057b3d5ddb0
parentf8ff6d82028367620893872636d455702a1c1ea1 (diff)
downloadnetifd-300b1220fab38600f102bb8cfcc59a29ce41b095.tar.gz
wireless: improve reliability of proxyarp support
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>
-rw-r--r--device.h1
-rw-r--r--scripts/netifd-wireless.sh4
-rw-r--r--system-linux.c11
-rw-r--r--wireless.c7
-rw-r--r--wireless.h1
5 files changed, 20 insertions, 4 deletions
diff --git a/device.h b/device.h
index 88cce9a..0496e89 100644
--- 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;
diff --git a/scripts/netifd-wireless.sh b/scripts/netifd-wireless.sh
index 5527791..80fbf75 100644
--- a/scripts/netifd-wireless.sh
+++ b/scripts/netifd-wireless.sh
@@ -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() {
diff --git a/system-linux.c b/system-linux.c
index 7c91008..6c6f1ec 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -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)
diff --git a/wireless.c b/wireless.c
index 61125a4..0e6447d 100644
--- a/wireless.c
+++ b/wireless.c
@@ -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");
diff --git a/wireless.h b/wireless.h
index 5969218..7b87611 100644
--- a/wireless.h
+++ b/wireless.h
@@ -88,6 +88,7 @@ struct wireless_interface {
const char *ifname;
struct blob_attr *network;
+ bool proxyarp;
bool isolate;
bool ap_mode;
};