diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 52194c4fc0..ba10b7cd9d 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -4644,6 +4644,15 @@ ServerAddress=192.168.0.1/24
clearing the locked flag. Requires Learning to be enabled. When unset, the kernel's default will be
used.
+
+
+
+
+ VLANTunnel=
+
+ Takes a boolean. Configures whether vlan tunnel mode is to be enabled on this port.
+ When unset, the kernel's default will be used.
+
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 8e99a059c1..c1aff5c02d 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -386,6 +386,7 @@ Bridge.Priority, config_parse_bridge_port_priority,
Bridge.MulticastRouter, config_parse_multicast_router, 0, offsetof(Network, multicast_router)
Bridge.Locked, config_parse_tristate, 0, offsetof(Network, bridge_locked)
Bridge.MACAuthenticationBypass, config_parse_tristate, 0, offsetof(Network, bridge_mac_authentication_bypass)
+Bridge.VLANTunnel, config_parse_tristate, 0, offsetof(Network, bridge_vlan_tunnel)
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 080e184ae1..00851243b5 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -458,6 +458,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.multicast_router = _MULTICAST_ROUTER_INVALID,
.bridge_locked = -1,
.bridge_mac_authentication_bypass = -1,
+ .bridge_vlan_tunnel = -1,
.bridge_vlan_pvid = BRIDGE_VLAN_KEEP_PVID,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index cec5f98d5b..c83281441e 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -299,6 +299,7 @@ struct Network {
MulticastRouter multicast_router;
int bridge_locked;
int bridge_mac_authentication_bypass;
+ int bridge_vlan_tunnel;
/* Bridge VLAN */
uint16_t bridge_vlan_pvid;
diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c
index 17c2b4b10e..c0c1da1b16 100644
--- a/src/network/networkd-setlink.c
+++ b/src/network/networkd-setlink.c
@@ -332,6 +332,12 @@ static int link_configure_fill_message(
return r;
}
+ if (link->network->bridge_vlan_tunnel >= 0) {
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_VLAN_TUNNEL, link->network->bridge_vlan_tunnel);
+ if (r < 0)
+ return r;
+ }
+
r = sd_netlink_message_close_container(req);
if (r < 0)
return r;
diff --git a/test/test-network/conf/14-dummy.netdev b/test/test-network/conf/14-dummy.netdev
new file mode 100644
index 0000000000..2420ab7400
--- /dev/null
+++ b/test/test-network/conf/14-dummy.netdev
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[NetDev]
+Name=dummy97
+Kind=dummy
diff --git a/test/test-network/conf/26-bridge-vlan-tunnel.network b/test/test-network/conf/26-bridge-vlan-tunnel.network
new file mode 100644
index 0000000000..93be9cc578
--- /dev/null
+++ b/test/test-network/conf/26-bridge-vlan-tunnel.network
@@ -0,0 +1,11 @@
+[Match]
+Name=dummy97
+
+[Link]
+MTUBytes=9000
+
+[Network]
+Bridge=bridge99
+
+[Bridge]
+VLANTunnel=true
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index 71ae689156..a91d45e995 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -6027,7 +6027,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
def test_bridge_property(self):
copy_network_unit('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
'26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
- '25-bridge99.network')
+ '25-bridge99.network', '14-dummy.netdev', '26-bridge-vlan-tunnel.network')
start_networkd()
self.check_bridge_property()
@@ -6038,6 +6038,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
'26-bridge.netdev',
'26-bridge-slave-interface-1.network',
'26-bridge-slave-interface-2.network',
+ '26-bridge-vlan-tunnel.network',
'25-bridge99.network')
networkctl_reload()
self.check_bridge_property()
@@ -6066,7 +6067,11 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
self.assertIn('bridge_slave', output)
self.assertIn('mtu 9000 ', output)
+ output = check_output('ip -d link show dummy97')
+ self.assertIn('vlan_tunnel on ', output)
+
remove_link('dummy98')
+ remove_link('dummy97')
self.wait_operstate('bridge99', 'no-carrier')
output = check_output('ip -d link show bridge99')