From: Jonas Gorski Date: Tue, 10 Dec 2024 15:45:20 +0000 (+0100) Subject: network: bridge: add support for NO_LL_LEARN X-Git-Tag: v258-rc1~1460^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d7de242ce78ae2782ac483da76204d305ff49ac7;p=thirdparty%2Fsystemd.git network: bridge: add support for NO_LL_LEARN When using locked ports on a bridge link-local learning needs to be disabled to prevent the kernel from learning and automatically unlocking hosts based on link-local traffic. So add support for enabling NO_LL_LEARN for bridges. --- diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index d072501a458..b809bd220e0 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -456,6 +456,16 @@ + + LinkLocalLearning= + + Takes a boolean. This enables learning source addresses from link local frames. When unset, the + kernel's default will be used. + + + + + diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c index d3ba4989d94..06f9840d1c6 100644 --- a/src/network/netdev/bridge.c +++ b/src/network/netdev/bridge.c @@ -47,6 +47,7 @@ static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Ne static int netdev_bridge_post_create_message(NetDev *netdev, sd_netlink_message *req) { Bridge *b = BRIDGE(netdev); + struct br_boolopt_multi bm = {}; int r; r = sd_netlink_message_open_container(req, IFLA_LINKINFO); @@ -142,6 +143,17 @@ static int netdev_bridge_post_create_message(NetDev *netdev, sd_netlink_message return r; } + if (b->linklocal_learn >= 0) { + bm.optmask |= 1 << BR_BOOLOPT_NO_LL_LEARN; + SET_FLAG(bm.optval, 1 << BR_BOOLOPT_NO_LL_LEARN, !b->linklocal_learn); + } + + if (bm.optmask != 0) { + r = sd_netlink_message_append_data(req, IFLA_BR_MULTI_BOOLOPT, &bm, sizeof(bm)); + if (r < 0) + return r; + } + r = sd_netlink_message_close_container(req); if (r < 0) return r; @@ -279,6 +291,7 @@ static void bridge_init(NetDev *netdev) { b->default_pvid = VLANID_INVALID; b->forward_delay = USEC_INFINITY; b->ageing_time = USEC_INFINITY; + b->linklocal_learn = -1; } static bool bridge_can_set_mac(NetDev *netdev, const struct hw_addr_data *hw_addr) { diff --git a/src/network/netdev/bridge.h b/src/network/netdev/bridge.h index 7be00e10637..a1d682bf8f3 100644 --- a/src/network/netdev/bridge.h +++ b/src/network/netdev/bridge.h @@ -21,6 +21,7 @@ typedef struct Bridge { uint8_t igmp_version; uint32_t fdb_max_learned; bool fdb_max_learned_set; + int linklocal_learn; usec_t forward_delay; usec_t hello_time; diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index be61e208a01..dcd786d87f1 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -236,6 +236,7 @@ Bridge.VLANProtocol, config_parse_vlanprotocol, Bridge.STP, config_parse_tristate, 0, offsetof(Bridge, stp) Bridge.MulticastIGMPVersion, config_parse_uint8, 0, offsetof(Bridge, igmp_version) Bridge.FDBMaxLearned, config_parse_bridge_fdb_max_learned, 0, offsetof(Bridge, fdb_max_learned) +Bridge.LinkLocalLearning, config_parse_tristate, 0, offsetof(Bridge, linklocal_learn) VRF.TableId, config_parse_uint32, 0, offsetof(Vrf, table) /* deprecated */ VRF.Table, config_parse_uint32, 0, offsetof(Vrf, table) BareUDP.DestinationPort, config_parse_ip_port, 0, offsetof(BareUDP, dest_port) diff --git a/test/test-network/conf/25-bridge.netdev b/test/test-network/conf/25-bridge.netdev index 9e7fa545b24..398637b6435 100644 --- a/test/test-network/conf/25-bridge.netdev +++ b/test/test-network/conf/25-bridge.netdev @@ -18,3 +18,4 @@ VLANProtocol=802.1ad STP=true MulticastIGMPVersion=3 FDBMaxLearned=4 +LinkLocalLearning=no diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index a151e00a2f1..533945ed0d7 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1682,6 +1682,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping'))) self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state'))) self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version'))) + self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'no_linklocal_learn'))) output = networkctl_status('bridge99') print(output)