From patchwork Thu Jun 18 15:23:00 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Linus_L=C3=BCssing?= X-Patchwork-Id: 486347 X-Patchwork-Delegate: nbd@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 136961401E7 for ; Fri, 19 Jun 2015 01:25:02 +1000 (AEST) Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id A8ACC28BF89; Thu, 18 Jun 2015 17:23:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00 autolearn=unavailable version=3.3.2 Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id DF52A28BF84 for ; Thu, 18 Jun 2015 17:23:25 +0200 (CEST) X-policyd-weight: using cached result; rate: -7.6 Received: from mail.passe0815.de (mail.passe0815.de [188.40.49.9]) by arrakis.dune.hu (Postfix) with ESMTPS for ; Thu, 18 Jun 2015 17:23:25 +0200 (CEST) Received: from mail.passe0815.de (localhost [127.0.0.1]) by mail.passe0815.de (Postfix) with ESMTP id 99DBB586704 for ; Thu, 18 Jun 2015 17:23:26 +0200 (CEST) Received: from localhost (unknown [IPv6:2001:67c:2d50:0:156d:c208:a1b7:785d]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by mail.passe0815.de (Postfix) with ESMTPSA id 9BD90586702; Thu, 18 Jun 2015 17:23:25 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: openwrt-devel@lists.openwrt.org Date: Thu, 18 Jun 2015 17:23:00 +0200 Message-Id: <1434640983-7929-3-git-send-email-linus.luessing@c0d3.blue> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1434640983-7929-1-git-send-email-linus.luessing@c0d3.blue> References: <1434640983-7929-1-git-send-email-linus.luessing@c0d3.blue> MIME-Version: 1.0 X-GPG-Mailgate: Not encrypted, public key not found Subject: [OpenWrt-Devel] [PATCH netifd 2/2] bridge: Allow setting multicast_router option X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openwrt-devel-bounces@lists.openwrt.org Sender: "openwrt-devel" The multicast_router option of a bridge allows to control the forwarding behaviour of multicast packets independant of the listener state: * 0: Only forward if specific listener is present * 1 (default): Forward if specific listener or a multicast router was detected (currently only learned via query messages, no MRD support yet) * 2: Always forward any multicast traffic on this port Since MRD is not mandated you might end up with silent multicast routers (e.g. if your link has more than one multicast router; only one can become the selected, "noisy" querier). Here you might need a manual configuration option like the "multicast_router" option. Other scenarios where this can be useful are for instance: * Segmentation of IGMP/MLD domains together with ebtables * Dedicated bridge port for monitoring/debugging purposes Signed-off-by: Linus Lüssing --- device.c | 12 ++++++++++++ device.h | 3 +++ system-linux.c | 17 +++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/device.c b/device.c index 776829d..bf643ef 100644 --- a/device.c +++ b/device.c @@ -47,6 +47,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_RPS] = { .name = "rps", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_XPS] = { .name = "xps", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_MULTICAST_TO_UNICAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_MULTICAST_ROUTER] = { .name = "multicast_router", .type = BLOBMSG_TYPE_INT32 }, }; const struct uci_blob_param_list device_attr_list = { @@ -171,6 +172,7 @@ device_merge_settings(struct device *dev, struct device_settings *n) n->neigh6reachabletime = s->flags & DEV_OPT_NEIGHREACHABLETIME ? s->neigh6reachabletime : os->neigh6reachabletime; n->multicast_to_unicast = s->multicast_to_unicast; + n->multicast_router = s->multicast_router; n->flags = s->flags | os->flags; } @@ -266,6 +268,14 @@ device_init_settings(struct device *dev, struct blob_attr **tb) s->flags |= DEV_OPT_MULTICAST_TO_UNICAST; } + if ((cur = tb[DEV_ATTR_MULTICAST_ROUTER])) { + s->multicast_router = blobmsg_get_u32(cur); + if (s->multicast_router >= 0 && s->multicast_router <= 2) + s->flags |= DEV_OPT_MULTICAST_ROUTER; + else + DPRINTF("Invalid value: %d - (Use 0: never, 1: learn, 2: always)\n", blobmsg_get_u32(cur)); + } + device_set_disabled(dev, disabled); } @@ -872,6 +882,8 @@ device_dump_status(struct blob_buf *b, struct device *dev) } if (st.flags & DEV_OPT_MULTICAST_TO_UNICAST) blobmsg_add_u8(b, "multicast_to_unicast", st.multicast_to_unicast); + if (st.flags & DEV_OPT_MULTICAST_ROUTER) + blobmsg_add_u32(b, "multicast_router", st.multicast_router); } s = blobmsg_open_table(b, "statistics"); diff --git a/device.h b/device.h index 55ef1cf..a487466 100644 --- a/device.h +++ b/device.h @@ -41,6 +41,7 @@ enum { DEV_ATTR_RPS, DEV_ATTR_XPS, DEV_ATTR_MULTICAST_TO_UNICAST, + DEV_ATTR_MULTICAST_ROUTER, __DEV_ATTR_MAX, }; @@ -82,6 +83,7 @@ enum { DEV_OPT_RPS = (1 << 10), DEV_OPT_XPS = (1 << 11), DEV_OPT_MULTICAST_TO_UNICAST = (1 << 12), + DEV_OPT_MULTICAST_ROUTER = (1 << 13), }; /* events broadcasted to all users of a device */ @@ -138,6 +140,7 @@ struct device_settings { bool rps; bool xps; bool multicast_to_unicast; + unsigned int multicast_router; }; /* diff --git a/system-linux.c b/system-linux.c index 9e21ab0..eb4b682 100644 --- a/system-linux.c +++ b/system-linux.c @@ -320,6 +320,13 @@ static void system_bridge_set_hairpin_mode(struct device *dev, const char *val) system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val); } +static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge) +{ + system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" : + "/sys/class/net/%s/brport/multicast_router", + dev->ifname, val); +} + static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz) { int fd = -1, ret = -1; @@ -584,6 +591,11 @@ int system_bridge_addif(struct device *bridge, struct device *dev) if (dev->wireless) system_bridge_set_wireless(dev); + if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) { + snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router); + system_bridge_set_multicast_router(dev, buf, false); + } + return ret; } @@ -834,6 +846,11 @@ int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg) system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max", bridge->ifname, buf); + if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) { + snprintf(buf, sizeof(buf), "%i", bridge->settings.multicast_router); + system_bridge_set_multicast_router(bridge, buf, true); + } + args[0] = BRCTL_SET_BRIDGE_PRIORITY; args[1] = cfg->priority; system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);