diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 44354f8bf2..a12f72d0f2 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1908,6 +1908,17 @@
When unset, the kernel's default will be used.
+
+ MulticastRouter=
+
+ Configures this port for having multicast routers attached. A port with a multicast
+ router will receive all multicast traffic. Takes one of no
+ to disable multicast routers on this port, query to let the system detect
+ the presence of routers, permanent to permanently enable multicast traffic
+ forwarding on this port, or temporary to enable multicast routers temporarily
+ on this port, not depending on incoming queries. When unset, the kernel's default will be used.
+
+
Cost=
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 17657ed17d..b1c01b6a41 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1648,6 +1648,12 @@ static int link_set_bridge(Link *link) {
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
}
+ if (link->network->multicast_router != _MULTICAST_ROUTER_INVALID) {
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MULTICAST_ROUTER, link->network->multicast_router);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MULTICAST_ROUTER attribute: %m");
+ }
+
r = sd_netlink_message_close_container(req);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index dded4c701c..6be499add1 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -180,6 +180,7 @@ Bridge.Learning, config_parse_tristate,
Bridge.ProxyARP, config_parse_tristate, 0, offsetof(Network, bridge_proxy_arp)
Bridge.ProxyARPWiFi, config_parse_tristate, 0, offsetof(Network, bridge_proxy_arp_wifi)
Bridge.Priority, config_parse_bridge_port_priority, 0, offsetof(Network, priority)
+Bridge.MulticastRouter, config_parse_multicast_router, 0, offsetof(Network, multicast_router)
BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
BridgeFDB.Destination, config_parse_fdb_destination, 0, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index e67fbe4219..aafec5fc79 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -391,6 +391,7 @@ int network_load_one(Manager *manager, const char *filename) {
.bridge_proxy_arp = -1,
.bridge_proxy_arp_wifi = -1,
.priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
+ .multicast_router = _MULTICAST_ROUTER_INVALID,
.lldp_mode = LLDP_MODE_ROUTERS_ONLY,
@@ -1723,3 +1724,14 @@ int config_parse_required_for_online(
return 0;
}
+
+static const char* const multicast_router_table[_MULTICAST_ROUTER_MAX] = {
+ [MULTICAST_ROUTER_NONE] = "no",
+ [MULTICAST_ROUTER_TEMPORARY_QUERY] = "query",
+ [MULTICAST_ROUTER_PERMANENT] = "permanent",
+ [MULTICAST_ROUTER_TEMPORARY] = "temporary",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(multicast_router, MulticastRouter, _MULTICAST_ROUTER_INVALID);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_multicast_router, multicast_router, MulticastRouter,
+ "Failed to parse bridge multicast router setting");
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 3886d629a4..22a7046d3e 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -1,6 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include
+#include
+
#include "sd-bus.h"
#include "sd-device.h"
@@ -84,6 +87,15 @@ typedef enum RADVPrefixDelegation {
_RADV_PREFIX_DELEGATION_INVALID = -1,
} RADVPrefixDelegation;
+typedef enum MulticastRouter {
+ MULTICAST_ROUTER_NONE = MDB_RTR_TYPE_DISABLED,
+ MULTICAST_ROUTER_TEMPORARY_QUERY = MDB_RTR_TYPE_TEMP_QUERY,
+ MULTICAST_ROUTER_PERMANENT = MDB_RTR_TYPE_PERM,
+ MULTICAST_ROUTER_TEMPORARY = MDB_RTR_TYPE_TEMP,
+ _MULTICAST_ROUTER_MAX,
+ _MULTICAST_ROUTER_INVALID = -1,
+} MulticastRouter;
+
typedef struct Manager Manager;
struct Network {
@@ -185,6 +197,7 @@ struct Network {
int bridge_proxy_arp_wifi;
uint32_t cost;
uint16_t priority;
+ MulticastRouter multicast_router;
bool use_br_vlan;
uint16_t pvid;
@@ -319,6 +332,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
+CONFIG_PARSER_PROTOTYPE(config_parse_multicast_router);
/* Legacy IPv4LL support */
CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
@@ -340,3 +354,6 @@ LLDPMode lldp_mode_from_string(const char *s) _pure_;
const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
+
+const char* multicast_router_to_string(MulticastRouter i) _const_;
+MulticastRouter multicast_router_from_string(const char *s) _pure_;
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 0c468f579f..f66c58398b 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -12,6 +12,7 @@ NeighborSuppression=
Learning=
ProxyARP=
ProxyARPWiFi=
+MulticastRouter=
[Match]
KernelVersion=
Type=