From nobody Wed May 21 03:40:22 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4b2HHp5W1Xz5wjh4; Wed, 21 May 2025 03:40:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4b2HHp3rXVz43Wj; Wed, 21 May 2025 03:40:22 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1747798822; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=jitpSsIDbrEM4QMrcXSiuhd+cXp50QCcGPhfVMRV66Y=; b=p1IA8bvgzMlhGrcFRYfXcI7bCXiixfjDgSt7+zm6TZ4kTGx3h9T18e/Src/b5FnzkDY2dX sXVa5MnzX8PB3wTyCppW0CuPCxdq0upBjxh9yN8u4HOxeMDIZQqHu+Dm6PT7hgeNmTCHkx H8aRn6DQbVLsLbJx5BY2qrr9mThPxgAa+UWiiIWQlitnULa7N0PCWnyoryTwf9Q+gkyqdY 5Al+L5bJzaVabOj7JGQmQxPbgM377WldYpP1Qg7ezCNMB8zIEiyGj1bx5+3bD7DSEg0Q97 FkkHD7zgKdL7BpGdA8Dw9oEDS5hKhlC2d1rdHs6XHHyaccuDK2PRGNVFqt7gng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1747798822; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=jitpSsIDbrEM4QMrcXSiuhd+cXp50QCcGPhfVMRV66Y=; b=e+GFalUWdzT++yZld14tp96hrmneDmMzEYj8NxQ/cKd6F+v1r/20NQJ1ea+bbfFdmRVRam E3dx3fRc4wtyMP2W3PbBhd1guazdcn0QhoFmUZIvzWqhG8rxs2A8m0yrvjNOGTRZVNIRGb qQVi6nuH8tqp1/MeFvjXyI2SC4mO7gIiKn88WLGjOjOMvbfDwhtKCt1ZPS847HSb8I3A00 oiTTewszDPnpvyJ+90vWDNMb3kFGjjmoN9JOIBMp9u0Ls860pMi5OTaoQD+JKwth3i8/g7 Nev9NYXXXbdDwdJzePrENlIzC/SN2IwVatSK6SCVzFjdaP8AK9gnfzyXpN0ueg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1747798822; a=rsa-sha256; cv=none; b=BMSc+SEUHJhP9/mKQdPeoqU39cjGNNLiTX1zKZoD4NkLDlF+8P3yQr6s1tfiW6NZRj07nt +mFBfKU4f3AUyVmoo1Bf/8xdC3yofDlP/qztAwBTfgRVWxYcD79566QpSH60p7wrt6hV0o 8Qk5ALdk2iBk68q9Y7aWUu2dkvR6xpvfokUZ0qP7+mGDcVO9vbGr4hLXrePjhgceQjFGE0 GCTQh/hJMUKhzXQkjICBG++JRcIy3S1zxLMrpofeFk2mTJpgjZ7Ni4JDPDjgdR6kWqUaG7 q4u6WXFpausixheFE7xoHDqNf5WT0Un6g8X4JVFn1T7CKQ2u9o1XregGG/NWoA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4b2HHp2D7Fz3FB; Wed, 21 May 2025 03:40:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 54L3eMQX088511; Wed, 21 May 2025 03:40:22 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 54L3eMKO088508; Wed, 21 May 2025 03:40:22 GMT (envelope-from git) Date: Wed, 21 May 2025 03:40:22 GMT Message-Id: <202505210340.54L3eMKO088508@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Lexi Winter Subject: git: ff1980d569c8 - stable/14 - bridge: allow IP addresses on members to be disabled List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: ivy X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: ff1980d569c8167d38cda5f2713664866d9802bc Auto-Submitted: auto-generated The branch stable/14 has been updated by ivy: URL: https://cgit.FreeBSD.org/src/commit/?id=ff1980d569c8167d38cda5f2713664866d9802bc commit ff1980d569c8167d38cda5f2713664866d9802bc Author: Lexi Winter AuthorDate: 2025-05-05 21:44:44 +0000 Commit: Lexi Winter CommitDate: 2025-05-21 02:55:42 +0000 bridge: allow IP addresses on members to be disabled add a new sysctl, net.link.bridge.member_ifaddrs, which defaults to 1. if it is set to 1, bridge behaviour is unchanged. if it is set to 0: - an interface which has AF_INET6 or AF_INET addresses assigned cannot be added to a bridge. - an interface in a bridge cannot have an AF_INET6 or AF_INET address assigned to it. - the bridge will no longer consider the lladdrs on bridge members to be local addresses, i.e. frames sent to member lladdrs will not be processed by the host. update bridge.4 to document this behaviour, as well as the existing recommendation that IP addresses should not be configured on bridge members anyway, even if it currently partially works. in testing, setting this to 0 on a bridge with 50 member interfaces improved throughput by 22% (4.61Gb/s -> 5.67Gb/s) across two member epairs due to eliding the bridge member list walk in GRAB_OUR_PACKETS. Reviewed by: kp, des Approved by: des (mentor) Differential Revision: https://reviews.freebsd.org/D49995 (cherry picked from commit 0a1294f6c610948d7447ae276df74a6d5269b62e) --- share/man/man4/bridge.4 | 15 +++++++- sys/net/if_bridge.c | 61 +++++++++++++++++++++++++++----- sys/net/if_bridgevar.h | 1 + sys/net/if_ethersubr.c | 1 + sys/netinet/in.c | 8 +++++ sys/netinet6/in6.c | 8 +++++ tests/sys/net/if_bridge_test.sh | 78 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 162 insertions(+), 10 deletions(-) diff --git a/share/man/man4/bridge.4 b/share/man/man4/bridge.4 index b741ec0b73c8..2c3bfd6aedfa 100644 --- a/share/man/man4/bridge.4 +++ b/share/man/man4/bridge.4 @@ -36,7 +36,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd April 10, 2024 +.Dd May 5, 2025 .Dt IF_BRIDGE 4 .Os .Sh NAME @@ -158,6 +158,19 @@ This can be used to multiplex the input of two or more interfaces into a single stream. This is useful for reconstructing the traffic for network taps that transmit the RX/TX signals out through two separate interfaces. +.Pp +To allow the host to communicate with bridge members, IP addresses +should be assigned to the +.Nm +interface itself, not to the bridge's member interfaces. +Assigning IP addresses to bridge member interfaces is unsupported, but +for backward compatibility, it is permitted if the +.Xr sysctl 8 +variable +.Va net.link.bridge.member_ifaddrs +is set to 1, which is the default. +In a future release, this sysctl may be set to 0 by default, or may be +removed entirely. .Sh IPV6 SUPPORT .Nm supports the diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 3e562aae9056..b4e4c5fb2f4c 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -331,6 +331,7 @@ static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp, int); static void bridge_forward(struct bridge_softc *, struct bridge_iflist *, struct mbuf *m); +static bool bridge_member_ifaddrs(void); static void bridge_timer(void *); @@ -497,6 +498,19 @@ SYSCTL_BOOL(_net_link_bridge, OID_AUTO, log_mac_flap, CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(log_mac_flap), true, "Log MAC address port flapping"); +/* allow IP addresses on bridge members */ +VNET_DEFINE_STATIC(bool, member_ifaddrs) = true; +#define V_member_ifaddrs VNET(member_ifaddrs) +SYSCTL_BOOL(_net_link_bridge, OID_AUTO, member_ifaddrs, + CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(member_ifaddrs), true, + "Allow layer 3 addresses on bridge members"); + +static bool +bridge_member_ifaddrs(void) +{ + return (V_member_ifaddrs); +} + VNET_DEFINE_STATIC(int, log_interval) = 5; VNET_DEFINE_STATIC(int, log_count) = 0; VNET_DEFINE_STATIC(struct timeval, log_last) = { 0 }; @@ -658,6 +672,7 @@ bridge_modevent(module_t mod, int type, void *data) switch (type) { case MOD_LOAD: bridge_dn_p = bridge_dummynet; + bridge_member_ifaddrs_p = bridge_member_ifaddrs; bridge_detach_cookie = EVENTHANDLER_REGISTER( ifnet_departure_event, bridge_ifdetach, NULL, EVENTHANDLER_PRI_ANY); @@ -666,6 +681,7 @@ bridge_modevent(module_t mod, int type, void *data) EVENTHANDLER_DEREGISTER(ifnet_departure_event, bridge_detach_cookie); bridge_dn_p = NULL; + bridge_member_ifaddrs_p = NULL; break; default: return (EOPNOTSUPP); @@ -1273,6 +1289,25 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) return (EINVAL); } + /* + * If member_ifaddrs is disabled, do not allow an interface with + * assigned IP addresses to be added to a bridge. + */ + if (!V_member_ifaddrs) { + struct ifaddr *ifa; + + CK_STAILQ_FOREACH(ifa, &ifs->if_addrhead, ifa_link) { +#ifdef INET + if (ifa->ifa_addr->sa_family == AF_INET) + return (EINVAL); +#endif +#ifdef INET6 + if (ifa->ifa_addr->sa_family == AF_INET6) + return (EINVAL); +#endif + } + } + #ifdef INET6 /* * Two valid inet6 addresses with link-local scope must not be @@ -2699,17 +2734,25 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) do { GRAB_OUR_PACKETS(bifp) } while (0); /* - * Give a chance for ifp at first priority. This will help when the - * packet comes through the interface like VLAN's with the same MACs - * on several interfaces from the same bridge. This also will save - * some CPU cycles in case the destination interface and the input - * interface (eq ifp) are the same. + * We only need to check members interfaces if member_ifaddrs is + * enabled; otherwise we should have never traffic destined for a + * member's lladdr. */ - do { GRAB_OUR_PACKETS(ifp) } while (0); - /* Now check the all bridge members. */ - CK_LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) { - GRAB_OUR_PACKETS(bif2->bif_ifp) + if (V_member_ifaddrs) { + /* + * Give a chance for ifp at first priority. This will help when + * the packet comes through the interface like VLAN's with the + * same MACs on several interfaces from the same bridge. This + * also will save some CPU cycles in case the destination + * interface and the input interface (eq ifp) are the same. + */ + do { GRAB_OUR_PACKETS(ifp) } while (0); + + /* Now check the all bridge members. */ + CK_LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) { + GRAB_OUR_PACKETS(bif2->bif_ifp) + } } #undef CARP_CHECK_WE_ARE_DST diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h index 27815cd37c83..4eed6ec07ade 100644 --- a/sys/net/if_bridgevar.h +++ b/sys/net/if_bridgevar.h @@ -320,5 +320,6 @@ struct ifbpstpconf { } while (0) extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *); +extern bool (*bridge_member_ifaddrs_p)(void); #endif /* _KERNEL */ diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 4d82bb0cfdca..9210f1378666 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -112,6 +112,7 @@ void (*vlan_input_p)(struct ifnet *, struct mbuf *); /* if_bridge(4) support */ void (*bridge_dn_p)(struct mbuf *, struct ifnet *); +bool (*bridge_member_ifaddrs_p)(void); /* if_lagg(4) support */ struct mbuf *(*lagg_input_ethernet_p)(struct ifnet *, struct mbuf *); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index bafd1b549848..21555a0714b6 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -499,6 +500,13 @@ in_aifaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct ucred *cred return (error); #endif + /* + * Check if bridge wants to allow adding addrs to member interfaces. + */ + if (ifp->if_bridge && bridge_member_ifaddrs_p && + !bridge_member_ifaddrs_p()) + return (EINVAL); + /* * See whether address already exist. */ diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 326153b1d2f6..60497ae29852 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -88,6 +88,7 @@ #include #include #include +#include #include #include #include @@ -1236,6 +1237,13 @@ in6_addifaddr(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *i int carp_attached = 0; int error; + /* Check if this interface is a bridge member */ + if (ifp->if_bridge && bridge_member_ifaddrs_p && + !bridge_member_ifaddrs_p()) { + error = EINVAL; + goto out; + } + /* * first, make or update the interface address structure, * and link it to the list. diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh index 66656be1d84f..715c8810f11d 100755 --- a/tests/sys/net/if_bridge_test.sh +++ b/tests/sys/net/if_bridge_test.sh @@ -703,6 +703,82 @@ many_bridge_members_cleanup() vnet_cleanup } +atf_test_case "member_ifaddrs_enabled" "cleanup" +member_ifaddrs_enabled_head() +{ + atf_set descr 'bridge with member_ifaddrs=1' + atf_set require.user root +} + +member_ifaddrs_enabled_body() +{ + vnet_init + vnet_init_bridge + + ep=$(vnet_mkepair) + ifconfig ${ep}a inet 192.0.2.1/24 up + + vnet_mkjail one ${ep}b + jexec one sysctl net.link.bridge.member_ifaddrs=1 + jexec one ifconfig ${ep}b inet 192.0.2.2/24 up + jexec one ifconfig bridge0 create addm ${ep}b + + atf_check -s exit:0 -o ignore ping -c3 -t1 192.0.2.2 +} + +member_ifaddrs_enabled_cleanup() +{ + vnet_cleanup +} + +atf_test_case "member_ifaddrs_disabled" "cleanup" +member_ifaddrs_disabled_head() +{ + atf_set descr 'bridge with member_ifaddrs=0' + atf_set require.user root +} + +member_ifaddrs_disabled_body() +{ + vnet_init + vnet_init_bridge + + vnet_mkjail one + jexec one sysctl net.link.bridge.member_ifaddrs=0 + + bridge=$(jexec one ifconfig bridge create) + + # adding an interface with an IPv4 address + ep=$(jexec one ifconfig epair create) + jexec one ifconfig ${ep} 192.0.2.1/32 + atf_check -s exit:1 -e ignore jexec one ifconfig ${bridge} addm ${ep} + + # adding an interface with an IPv6 address + ep=$(jexec one ifconfig epair create) + jexec one ifconfig ${ep} inet6 2001:db8::1/128 + atf_check -s exit:1 -e ignore jexec one ifconfig ${bridge} addm ${ep} + + # adding an interface with an IPv6 link-local address + ep=$(jexec one ifconfig epair create) + jexec one ifconfig ${ep} inet6 -ifdisabled auto_linklocal up + atf_check -s exit:1 -e ignore jexec one ifconfig ${bridge} addm ${ep} + + # adding an IPv4 address to a member + ep=$(jexec one ifconfig epair create) + jexec one ifconfig ${bridge} addm ${ep} + atf_check -s exit:1 -e ignore jexec one ifconfig ${ep} inet 192.0.2.2/32 + + # adding an IPv6 address to a member + ep=$(jexec one ifconfig epair create) + jexec one ifconfig ${bridge} addm ${ep} + atf_check -s exit:1 -e ignore jexec one ifconfig ${ep} inet6 2001:db8::1/128 +} + +member_ifaddrs_disabled_cleanup() +{ + vnet_cleanup +} + atf_init_test_cases() { atf_add_test_case "bridge_transmit_ipv4_unicast" @@ -718,4 +794,6 @@ atf_init_test_cases() atf_add_test_case "mtu" atf_add_test_case "vlan" atf_add_test_case "many_bridge_members" + atf_add_test_case "member_ifaddrs_enabled" + atf_add_test_case "member_ifaddrs_disabled" }