summaryrefslogtreecommitdiff
path: root/wireless.c
diff options
context:
space:
mode:
authorLinus Lüssing <linus.luessing@c0d3.blue>2015-08-23 17:19:26 +0200
committerFelix Fietkau <nbd@openwrt.org>2015-08-25 08:46:17 +0200
commit827145f01d849c663f18e356157fd71f1a7cc45d (patch)
tree3593b66ff746da1d3e66aad86490a4fa3e5a791e /wireless.c
parent6ed631e55686b909e6db25838e6e591316933c97 (diff)
downloadnetifd-827145f01d849c663f18e356157fd71f1a7cc45d.tar.gz
bridge: Fix multicast_to_unicast feature by hairpin+isolate
All IGMP and MLD versions suffer from a specific limitation (from a snooping switch perspective): Report suppression. Once a listener hears an IGMPv2/3 or MLDv1 report for the same group itself participates in then it might (if this listener is an IGMPv3 or MLDv2 listener) or will (if this is an IGMPv1/2 or MLDv1 listener) refrain from sending its own report. Therefore we might currently miss such surpressing listeners as they won't receive the multicast packet with the mangled, unicasted destination. Fixing this by first isolating the STAs and giving the bridge more control over traffic forwarding. E.g. refraining to forward listener reports to other STAs. For broadcast and unicast traffic to an STA on the same AP, the hairpin feature of the bridge will reflect such traffic back to the AP interface. However, if the AP interface is actually configured to isolate STAs, then hairpin is kept disabled. Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
Diffstat (limited to 'wireless.c')
-rw-r--r--wireless.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/wireless.c b/wireless.c
index fbd6191..337f563 100644
--- a/wireless.c
+++ b/wireless.c
@@ -35,12 +35,14 @@ static const struct uci_blob_param_list wdev_param = {
enum {
VIF_ATTR_DISABLED,
VIF_ATTR_NETWORK,
+ VIF_ATTR_ISOLATE,
__VIF_ATTR_MAX,
};
static const struct blobmsg_policy vif_policy[__VIF_ATTR_MAX] = {
[VIF_ATTR_DISABLED] = { .name = "disabled", .type = BLOBMSG_TYPE_BOOL },
[VIF_ATTR_NETWORK] = { .name = "network", .type = BLOBMSG_TYPE_ARRAY },
+ [VIF_ATTR_ISOLATE] = { .name = "isolate", .type = BLOBMSG_TYPE_BOOL },
};
static const struct uci_blob_param_list vif_param = {
@@ -204,8 +206,10 @@ static void wireless_interface_handle_link(struct wireless_interface *vif, bool
if (up) {
struct device *dev = device_get(vif->ifname, 2);
- if (dev)
+ if (dev) {
+ dev->wireless_isolate = vif->isolate;
dev->wireless = true;
+ }
}
blobmsg_for_each_attr(cur, vif->network, rem) {
@@ -700,6 +704,12 @@ void wireless_interface_create(struct wireless_device *wdev, struct blob_attr *d
vif->wdev = wdev;
vif->config = data;
vif->section = section;
+ vif->isolate = false;
+
+ cur = tb[VIF_ATTR_ISOLATE];
+ if (cur && blobmsg_get_bool(cur))
+ vif->isolate = blobmsg_get_bool(cur);
+
vlist_add(&wdev->interfaces, &vif->node, vif->name);
}