diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 3cce776cc22..ff37f26990c 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -1215,6 +1215,13 @@ + + AssignToLoopback= + + Takes a boolean. If set to yes, the loopback interface lo + is used as the underlying device of the tunnel interface. Defaults to no. + + AllowLocalRemote= diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index 33f7b3058d5..8641d18026b 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -70,6 +70,7 @@ Tunnel.IPv6FlowLabel, config_parse_ipv6_flowlabel, Tunnel.CopyDSCP, config_parse_bool, 0, offsetof(Tunnel, copy_dscp) Tunnel.EncapsulationLimit, config_parse_encap_limit, 0, offsetof(Tunnel, encap_limit) Tunnel.Independent, config_parse_bool, 0, offsetof(Tunnel, independent) +Tunnel.AssignToLoopback, config_parse_bool, 0, offsetof(Tunnel, assign_to_loopback) Tunnel.AllowLocalRemote, config_parse_tristate, 0, offsetof(Tunnel, allow_localremote) Tunnel.FooOverUDP, config_parse_bool, 0, offsetof(Tunnel, fou_tunnel) Tunnel.FOUDestinationPort, config_parse_ip_port, 0, offsetof(Tunnel, fou_destination_port) diff --git a/src/network/netdev/tunnel.c b/src/network/netdev/tunnel.c index a59d18d5d90..9ea4d19a2e0 100644 --- a/src/network/netdev/tunnel.c +++ b/src/network/netdev/tunnel.c @@ -46,8 +46,8 @@ static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_ne assert(t); assert(t->family == AF_INET); - if (link) { - r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); } @@ -138,8 +138,8 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_ assert(t); assert(t->family == AF_INET); - if (link) { - r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); } @@ -242,8 +242,8 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl assert(t->family == AF_INET6); assert(m); - if (link) { - r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); } @@ -290,8 +290,8 @@ static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink assert((netdev->kind == NETDEV_KIND_VTI && t->family == AF_INET) || (netdev->kind == NETDEV_KIND_VTI6 && t->family == AF_INET6)); - if (link) { - r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link->ifindex); + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_LINK attribute: %m"); } @@ -332,8 +332,8 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl assert(t); assert(t->family == AF_INET6); - if (link) { - r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); } diff --git a/src/network/netdev/tunnel.h b/src/network/netdev/tunnel.h index 3637e4f3772..681e80b0159 100644 --- a/src/network/netdev/tunnel.h +++ b/src/network/netdev/tunnel.h @@ -51,6 +51,7 @@ typedef struct Tunnel { bool copy_dscp; bool independent; bool fou_tunnel; + bool assign_to_loopback; uint16_t encap_src_port; uint16_t fou_destination_port; diff --git a/src/network/netdev/xfrm.c b/src/network/netdev/xfrm.c index c60b0b1ab7e..afedb4b4247 100644 --- a/src/network/netdev/xfrm.c +++ b/src/network/netdev/xfrm.c @@ -4,24 +4,17 @@ #include "netdev/xfrm.h" static int xfrm_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *message) { - int if_idx, r; Xfrm *x; + int r; assert(netdev); assert(message); x = XFRM(netdev); - if (x->independent) - if_idx = LOOPBACK_IFINDEX; - else { - assert(link); - if (link->ifindex == 0) - return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(ENODEV), "Could not get interface index: %m"); - if_idx = link->ifindex; - } + assert(link || x->independent); - r = sd_netlink_message_append_u32(message, IFLA_XFRM_LINK, if_idx); + r = sd_netlink_message_append_u32(message, IFLA_XFRM_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_XFRM_LINK: %m"); diff --git a/test/fuzz/fuzz-netdev-parser/directives.netdev b/test/fuzz/fuzz-netdev-parser/directives.netdev index 07e54d9e44f..874c3e5f8ff 100644 --- a/test/fuzz/fuzz-netdev-parser/directives.netdev +++ b/test/fuzz/fuzz-netdev-parser/directives.netdev @@ -66,6 +66,7 @@ AllowLocalRemote= Local= TOS= Independent= +AssignToLoopback= Key= InputKey= Encapsulation= diff --git a/test/test-network/conf/25-ipip-tunnel-independent-loopback.netdev b/test/test-network/conf/25-ipip-tunnel-independent-loopback.netdev new file mode 100644 index 00000000000..9ee26c90c86 --- /dev/null +++ b/test/test-network/conf/25-ipip-tunnel-independent-loopback.netdev @@ -0,0 +1,10 @@ +[NetDev] +Name=ipiptun99 +Kind=ipip +MTUBytes=1480 + +[Tunnel] +Local=192.168.223.238 +Remote=192.169.224.239 +Independent=true +AssignToLoopback=yes diff --git a/test/test-network/conf/25-xfrm-independent.netdev b/test/test-network/conf/25-xfrm-independent.netdev new file mode 100644 index 00000000000..8ed4321493b --- /dev/null +++ b/test/test-network/conf/25-xfrm-independent.netdev @@ -0,0 +1,6 @@ +[NetDev] +Kind=xfrm +Name=xfrm99 + +[Xfrm] +Independent=yes diff --git a/test/test-network/conf/25-xfrm.netdev b/test/test-network/conf/25-xfrm.netdev new file mode 100644 index 00000000000..81b32dea602 --- /dev/null +++ b/test/test-network/conf/25-xfrm.netdev @@ -0,0 +1,3 @@ +[NetDev] +Kind=xfrm +Name=xfrm99 diff --git a/test/test-network/conf/netdev-link-local-addressing-yes.network b/test/test-network/conf/netdev-link-local-addressing-yes.network index b76bfb3bd3b..d7dfa7ea97b 100644 --- a/test/test-network/conf/netdev-link-local-addressing-yes.network +++ b/test/test-network/conf/netdev-link-local-addressing-yes.network @@ -12,6 +12,7 @@ Name=vrf99 Name=geneve99 Name=ipiptun99 Name=nlmon99 +Name=xfrm99 [Network] LinkLocalAddressing=yes diff --git a/test/test-network/conf/xfrm.network b/test/test-network/conf/xfrm.network new file mode 100644 index 00000000000..bfb2956ae9d --- /dev/null +++ b/test/test-network/conf/xfrm.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Xfrm=xfrm99 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 92f1a5bd8db..2139c5f9d3c 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -461,7 +461,11 @@ class NetworkctlTests(unittest.TestCase, Utilities): class NetworkdNetDevTests(unittest.TestCase, Utilities): - links =[ + links_remove_earlier = [ + 'xfrm99', + ] + + links = [ '6rdtun99', 'bond99', 'bridge99', @@ -515,7 +519,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): 'vxcan99', 'vxlan99', 'wg98', - 'wg99'] + 'wg99', + ] units = [ '10-dropin-test.netdev', @@ -559,6 +564,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-ip6tnl-tunnel-local-any.netdev', '25-ip6tnl-tunnel.netdev', '25-ipip-tunnel-independent.netdev', + '25-ipip-tunnel-independent-loopback.netdev', '25-ipip-tunnel-local-any.netdev', '25-ipip-tunnel-remote-any.netdev', '25-ipip-tunnel.netdev', @@ -594,6 +600,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-wireguard-private-key.txt', '25-wireguard.netdev', '25-wireguard.network', + '25-xfrm.netdev', + '25-xfrm-independent.netdev', '6rd.network', 'erspan.network', 'gre.network', @@ -614,7 +622,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): 'vti6.network', 'vti.network', 'vxlan-test1.network', - 'vxlan.network'] + 'vxlan.network', + 'xfrm.network', + ] fou_ports = [ '55555', @@ -622,11 +632,13 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): def setUp(self): remove_fou_ports(self.fou_ports) + remove_links(self.links_remove_earlier) remove_links(self.links) stop_networkd(show_logs=False) def tearDown(self): remove_fou_ports(self.fou_ports) + remove_links(self.links_remove_earlier) remove_links(self.links) remove_unit_from_networkd_path(self.units) stop_networkd(show_logs=True) @@ -1130,6 +1142,30 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): wait_online(['ipiptun99:carrier']) + def test_tunnel_independent_loopback(self): + copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + wait_online(['ipiptun99:carrier']) + + @expectedFailureIfModuleIsNotAvailable('xfrm_interface') + def test_xfrm(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network', + '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + wait_online(['xfrm99:degraded', 'dummy98:degraded']) + + output = check_output('ip link show dev xfrm99') + print(output) + + @expectedFailureIfModuleIsNotAvailable('xfrm_interface') + def test_xfrm_independent(self): + copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + wait_online(['xfrm99:degraded']) + @expectedFailureIfModuleIsNotAvailable('fou') def test_fou(self): # The following redundant check is necessary for CentOS CI.