network/tunnel: several cleanups for Mode= setting and make sit and ipip tunnel support it (#37853)
Closing #37377.
This commit is contained in:
+55
-6
@@ -1654,12 +1654,61 @@ Ports=eth2</programlisting>
|
||||
<varlistentry>
|
||||
<term><varname>Mode=</varname></term>
|
||||
<listitem>
|
||||
<para>An <literal>ip6tnl</literal> tunnel can be in one of three
|
||||
modes
|
||||
<literal>ip6ip6</literal> for IPv6 over IPv6,
|
||||
<literal>ipip6</literal> for IPv4 over IPv6 or
|
||||
<literal>any</literal> for either.
|
||||
</para>
|
||||
<para>Specifies the tunnel mode. Acceptable values depend on the tunnel kind.</para>
|
||||
|
||||
<table>
|
||||
<title>Supported tunnel modes</title>
|
||||
|
||||
<tgroup cols='3'>
|
||||
<colspec colname='kind' />
|
||||
<colspec colname='mode' />
|
||||
<colspec colname='explanation' />
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Kind</entry>
|
||||
<entry>Mode</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry morerows="1"><literal>ipip</literal></entry>
|
||||
<entry><literal>ipip</literal></entry>
|
||||
<entry>IPv4 over IPv4 (default)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>any</literal></entry>
|
||||
<entry>both IPv4 and IPv6 over IPv4</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry morerows="2"><literal>sit</literal></entry>
|
||||
<entry><literal>ipip</literal></entry>
|
||||
<entry>IPv4 over IPv4</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>ip6ip</literal></entry>
|
||||
<entry>IPv6 over IPv4 (default)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>any</literal></entry>
|
||||
<entry>both IPv4 and IPv6 over IPv4</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry morerows="2"><literal>ip6tnl</literal></entry>
|
||||
<entry><literal>ipip6</literal></entry>
|
||||
<entry>IPv4 over IPv6</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>ip6ip6</literal></entry>
|
||||
<entry>IPv6 over IPv6</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>any</literal></entry>
|
||||
<entry>both IPv4 and IPv6 over IPv6 (default)</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v219"/>
|
||||
</listitem>
|
||||
|
||||
@@ -84,7 +84,7 @@ Tunnel.InputKey, config_parse_tunnel_key,
|
||||
Tunnel.OutputKey, config_parse_tunnel_key, 0, offsetof(Tunnel, okey)
|
||||
Tunnel.DiscoverPathMTU, config_parse_tristate, 0, offsetof(Tunnel, pmtudisc)
|
||||
Tunnel.IgnoreDontFragment, config_parse_bool, 0, offsetof(Tunnel, ignore_df)
|
||||
Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode)
|
||||
Tunnel.Mode, config_parse_tunnel_mode, 0, offsetof(Tunnel, mode)
|
||||
Tunnel.IPv6FlowLabel, config_parse_ipv6_flowlabel, 0, 0
|
||||
Tunnel.CopyDSCP, config_parse_bool, 0, offsetof(Tunnel, copy_dscp)
|
||||
Tunnel.EncapsulationLimit, config_parse_encap_limit, 0, 0
|
||||
|
||||
+56
-28
@@ -23,16 +23,26 @@
|
||||
#define IP6_FLOWINFO_FLOWLABEL htobe32(0x000FFFFF)
|
||||
#define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0x40
|
||||
|
||||
static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
|
||||
[NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
|
||||
[NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6",
|
||||
[NETDEV_IP6_TNL_MODE_ANYIP6] = "any",
|
||||
#define HASH_KEY SD_ID128_MAKE(74,c4,de,12,f3,d9,41,34,bb,3d,c1,a4,42,93,50,87)
|
||||
|
||||
static const uint8_t tunnel_mode_to_proto[_TUNNEL_MODE_MAX] = {
|
||||
[TUNNEL_MODE_ANY] = 0,
|
||||
[TUNNEL_MODE_IPIP] = IPPROTO_IPIP,
|
||||
[TUNNEL_MODE_IP6IP] = IPPROTO_IPV6,
|
||||
[TUNNEL_MODE_IPIP6] = IPPROTO_IPIP,
|
||||
[TUNNEL_MODE_IP6IP6] = IPPROTO_IPV6,
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode);
|
||||
static const char* const tunnel_mode_table[_TUNNEL_MODE_MAX] = {
|
||||
[TUNNEL_MODE_ANY] = "any",
|
||||
[TUNNEL_MODE_IPIP] = "ipip",
|
||||
[TUNNEL_MODE_IP6IP] = "ip6ip",
|
||||
[TUNNEL_MODE_IPIP6] = "ipip6",
|
||||
[TUNNEL_MODE_IP6IP6] = "ip6ip6",
|
||||
};
|
||||
|
||||
#define HASH_KEY SD_ID128_MAKE(74,c4,de,12,f3,d9,41,34,bb,3d,c1,a4,42,93,50,87)
|
||||
DEFINE_STRING_TABLE_LOOKUP(tunnel_mode, TunnelMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_tunnel_mode, tunnel_mode, TunnelMode);
|
||||
|
||||
static int dhcp4_pd_create_6rd_tunnel_name(Link *link) {
|
||||
_cleanup_free_ char *ifname_alloc = NULL;
|
||||
@@ -195,6 +205,12 @@ static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_ne
|
||||
Tunnel *t = ASSERT_PTR(netdev)->kind == NETDEV_KIND_IPIP ? IPIP(netdev) : SIT(netdev);
|
||||
int r;
|
||||
|
||||
if (t->mode >= 0) {
|
||||
r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, tunnel_mode_to_proto[t->mode]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (t->external) {
|
||||
r = sd_netlink_message_append_flag(m, IFLA_IPTUN_COLLECT_METADATA);
|
||||
if (r < 0)
|
||||
@@ -560,26 +576,15 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
|
||||
assert(m);
|
||||
|
||||
union in_addr_union local;
|
||||
uint8_t proto;
|
||||
Tunnel *t = IP6TNL(netdev);
|
||||
int r;
|
||||
|
||||
switch (t->ip6tnl_mode) {
|
||||
case NETDEV_IP6_TNL_MODE_IP6IP6:
|
||||
proto = IPPROTO_IPV6;
|
||||
break;
|
||||
case NETDEV_IP6_TNL_MODE_IPIP6:
|
||||
proto = IPPROTO_IPIP;
|
||||
break;
|
||||
case NETDEV_IP6_TNL_MODE_ANYIP6:
|
||||
default:
|
||||
proto = 0;
|
||||
if (t->mode >= 0) {
|
||||
r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, tunnel_mode_to_proto[t->mode]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (t->external) {
|
||||
r = sd_netlink_message_append_flag(m, IFLA_IPTUN_COLLECT_METADATA);
|
||||
if (r < 0)
|
||||
@@ -653,11 +658,6 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
|
||||
|
||||
Tunnel *t = ASSERT_PTR(TUNNEL(netdev));
|
||||
|
||||
if (netdev->kind == NETDEV_KIND_IP6TNL &&
|
||||
t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID)
|
||||
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
|
||||
"ip6tnl without mode configured in %s. Ignoring", filename);
|
||||
|
||||
if (t->external) {
|
||||
if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_VTI6))
|
||||
log_netdev_debug(netdev, "vti/vti6 tunnel do not support external mode, ignoring.");
|
||||
@@ -704,6 +704,34 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
|
||||
"IgnoreDontFragment= cannot be enabled when DiscoverPathMTU= is enabled");
|
||||
if (t->pmtudisc < 0)
|
||||
t->pmtudisc = !t->ignore_df;
|
||||
|
||||
if (t->mode >= 0)
|
||||
switch (netdev->kind) {
|
||||
case NETDEV_KIND_IPIP:
|
||||
if (!IN_SET(t->mode, TUNNEL_MODE_ANY, TUNNEL_MODE_IPIP))
|
||||
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Specified unsupported tunnel mode %s, ignoring.",
|
||||
tunnel_mode_to_string(t->mode));
|
||||
break;
|
||||
case NETDEV_KIND_SIT:
|
||||
if (!IN_SET(t->mode, TUNNEL_MODE_ANY, TUNNEL_MODE_IPIP, TUNNEL_MODE_IP6IP))
|
||||
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Specified unsupported tunnel mode %s, ignoring.",
|
||||
tunnel_mode_to_string(t->mode));
|
||||
break;
|
||||
case NETDEV_KIND_IP6TNL:
|
||||
if (!IN_SET(t->mode, TUNNEL_MODE_ANY, TUNNEL_MODE_IPIP6, TUNNEL_MODE_IP6IP6))
|
||||
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Specified unsupported tunnel mode %s, ignoring.",
|
||||
tunnel_mode_to_string(t->mode));
|
||||
break;
|
||||
default:
|
||||
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
|
||||
"%s tunnel does not support Mode= setting, ignoring: %s",
|
||||
netdev_kind_to_string(netdev->kind),
|
||||
tunnel_mode_to_string(t->mode));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1109,7 +1137,7 @@ static void netdev_tunnel_init(NetDev *netdev) {
|
||||
t->isatap = -1;
|
||||
t->gre_erspan_sequence = -1;
|
||||
t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
|
||||
t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
|
||||
t->mode = _TUNNEL_MODE_INVALID;
|
||||
t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
|
||||
t->allow_localremote = -1;
|
||||
t->erspan_version = 1;
|
||||
|
||||
+14
-11
@@ -6,13 +6,16 @@
|
||||
#include "netdev.h"
|
||||
#include "networkd-link.h"
|
||||
|
||||
typedef enum Ip6TnlMode {
|
||||
NETDEV_IP6_TNL_MODE_IP6IP6,
|
||||
NETDEV_IP6_TNL_MODE_IPIP6,
|
||||
NETDEV_IP6_TNL_MODE_ANYIP6,
|
||||
_NETDEV_IP6_TNL_MODE_MAX,
|
||||
_NETDEV_IP6_TNL_MODE_INVALID = -EINVAL,
|
||||
} Ip6TnlMode;
|
||||
/* For IFLA_IPTUN_PROTO attribute */
|
||||
typedef enum TunnelMode {
|
||||
TUNNEL_MODE_ANY, /* 0, "any" */
|
||||
TUNNEL_MODE_IPIP, /* IPPROTO_IPIP, "ipip", for ipip and sit */
|
||||
TUNNEL_MODE_IP6IP, /* IPPROTO_IPV6, "ip6ip", for sit */
|
||||
TUNNEL_MODE_IPIP6, /* IPPROTO_IPIP, "ipip6", for ip6tnl */
|
||||
TUNNEL_MODE_IP6IP6, /* IPPROTO_IPV6, "ip6ip6", for ip6tnl */
|
||||
_TUNNEL_MODE_MAX,
|
||||
_TUNNEL_MODE_INVALID = -EINVAL,
|
||||
} TunnelMode;
|
||||
|
||||
typedef enum IPv6FlowLabel {
|
||||
NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1,
|
||||
@@ -48,7 +51,7 @@ typedef struct Tunnel {
|
||||
union in_addr_union local;
|
||||
union in_addr_union remote;
|
||||
|
||||
Ip6TnlMode ip6tnl_mode;
|
||||
TunnelMode mode;
|
||||
FooOverUDPEncapType fou_encap_type;
|
||||
|
||||
int pmtudisc;
|
||||
@@ -119,10 +122,10 @@ extern const NetDevVTable ip6gretap_vtable;
|
||||
extern const NetDevVTable ip6tnl_vtable;
|
||||
extern const NetDevVTable erspan_vtable;
|
||||
|
||||
const char* ip6tnl_mode_to_string(Ip6TnlMode d) _const_;
|
||||
Ip6TnlMode ip6tnl_mode_from_string(const char *d) _pure_;
|
||||
const char* tunnel_mode_to_string(TunnelMode d) _const_;
|
||||
TunnelMode tunnel_mode_from_string(const char *d) _pure_;
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ip6tnl_mode);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_mode);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_local_address);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_remote_address);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_flowlabel);
|
||||
|
||||
@@ -34,7 +34,7 @@ int main(int argc, char **argv) {
|
||||
test_table_sparse(DHCP6MessageType, dhcp6_message_type, DHCP6_MESSAGE_TYPE); /* enum starts from 1 */
|
||||
test_table(UseDomains, use_domains, USE_DOMAINS);
|
||||
test_table(Duplex, duplex, DUP);
|
||||
test_table(Ip6TnlMode, ip6tnl_mode, NETDEV_IP6_TNL_MODE);
|
||||
test_table(TunnelMode, tunnel_mode, TUNNEL_MODE);
|
||||
test_table(IPv6PrivacyExtensions, ipv6_privacy_extensions, IPV6_PRIVACY_EXTENSIONS);
|
||||
test_table(IPVlanFlags, ipvlan_flags, NETDEV_IPVLAN_FLAGS);
|
||||
test_table(LinkOperationalState, link_operstate, LINK_OPERSTATE);
|
||||
|
||||
@@ -4,5 +4,4 @@ Name=ip6tnl-external
|
||||
Kind=ip6tnl
|
||||
|
||||
[Tunnel]
|
||||
Mode=ip6ip6
|
||||
External=yes
|
||||
|
||||
@@ -4,6 +4,5 @@ Name=ip6tnl98
|
||||
Kind=ip6tnl
|
||||
|
||||
[Tunnel]
|
||||
Mode=ip6ip6
|
||||
Local=any
|
||||
Remote=2001:473:fece:cafe::5179
|
||||
|
||||
@@ -4,6 +4,5 @@ Name=ip6tnl-slaac
|
||||
Kind=ip6tnl
|
||||
|
||||
[Tunnel]
|
||||
Mode=ip6ip6
|
||||
Local=slaac
|
||||
Remote=2001:473:fece:cafe::5179
|
||||
|
||||
@@ -4,6 +4,5 @@ Name=ip6tnl97
|
||||
Kind=ip6tnl
|
||||
|
||||
[Tunnel]
|
||||
Mode=ip6ip6
|
||||
Local=2a00:ffde:4567:edde::4987
|
||||
Remote=any
|
||||
|
||||
@@ -4,6 +4,5 @@ Name=ip6tnl99
|
||||
Kind=ip6tnl
|
||||
|
||||
[Tunnel]
|
||||
Mode=ip6ip6
|
||||
Local=2a00:ffde:4567:edde::4987
|
||||
Remote=2001:473:fece:cafe::5179
|
||||
|
||||
@@ -2460,27 +2460,38 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
networkctl_reload()
|
||||
self.wait_online('geneve99:degraded')
|
||||
|
||||
def test_ipip_tunnel(self):
|
||||
def _test_ipip_tunnel(self, mode):
|
||||
copy_network_unit('12-dummy.netdev', '25-ipip.network',
|
||||
'25-ipip-tunnel.netdev', '25-tunnel.network',
|
||||
'25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
|
||||
'25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
|
||||
'25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
|
||||
|
||||
if mode:
|
||||
for netdev in ['25-ipip-tunnel.netdev',
|
||||
'25-ipip-tunnel-local-any.netdev',
|
||||
'25-ipip-tunnel-remote-any.netdev',
|
||||
'25-ipip-tunnel-any-any.netdev']:
|
||||
with open(os.path.join(network_unit_dir, netdev), mode='a', encoding='utf-8') as f:
|
||||
f.write(f'[Tunnel]\nMode={mode}\n')
|
||||
else:
|
||||
mode = 'ipip' # kernel default
|
||||
|
||||
start_networkd()
|
||||
self.wait_online('ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded')
|
||||
|
||||
output = check_output('ip -d link show ipiptun99')
|
||||
print(output)
|
||||
self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
|
||||
self.assertIn(f'ipip {mode} remote 192.169.224.239 local 192.168.223.238 dev dummy98', output)
|
||||
output = check_output('ip -d link show ipiptun98')
|
||||
print(output)
|
||||
self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
|
||||
self.assertIn(f'ipip {mode} remote 192.169.224.239 local any dev dummy98', output)
|
||||
output = check_output('ip -d link show ipiptun97')
|
||||
print(output)
|
||||
self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
|
||||
self.assertIn(f'ipip {mode} remote any local 192.168.223.238 dev dummy98', output)
|
||||
output = check_output('ip -d link show ipiptun96')
|
||||
print(output)
|
||||
self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
|
||||
self.assertIn(f'ipip {mode} remote any local any dev dummy98', output)
|
||||
|
||||
touch_network_unit(
|
||||
'25-ipip-tunnel.netdev',
|
||||
@@ -2495,6 +2506,18 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
'ipiptun96:routable',
|
||||
'dummy98:degraded')
|
||||
|
||||
def test_ipip_tunnel(self):
|
||||
first = True
|
||||
for mode in [None, 'ipip', 'any']:
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
self.tearDown()
|
||||
|
||||
print(f'### test_ipip_tunnel(mode={mode})')
|
||||
with self.subTest(mode=mode):
|
||||
self._test_ipip_tunnel(mode)
|
||||
|
||||
def test_gre_tunnel(self):
|
||||
copy_network_unit('12-dummy.netdev', '25-gretun.network',
|
||||
'25-gre-tunnel.netdev', '25-tunnel.network',
|
||||
@@ -2724,7 +2747,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
'vti6tun97:routable',
|
||||
'dummy98:degraded')
|
||||
|
||||
def test_ip6tnl_tunnel(self):
|
||||
def _test_ip6tnl_tunnel(self, mode):
|
||||
copy_network_unit('12-dummy.netdev', '25-ip6tnl.network',
|
||||
'25-ip6tnl-tunnel.netdev', '25-tunnel.network',
|
||||
'25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
|
||||
@@ -2732,6 +2755,18 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
'25-veth.netdev', '25-ip6tnl-slaac.network', '25-ipv6-prefix.network',
|
||||
'25-ip6tnl-tunnel-local-slaac.netdev', '25-ip6tnl-tunnel-local-slaac.network',
|
||||
'25-ip6tnl-tunnel-external.netdev', '26-netdev-link-local-addressing-yes.network')
|
||||
|
||||
if mode:
|
||||
for netdev in ['25-ip6tnl-tunnel.netdev',
|
||||
'25-ip6tnl-tunnel-local-any.netdev',
|
||||
'25-ip6tnl-tunnel-remote-any.netdev',
|
||||
'25-ip6tnl-tunnel-local-slaac.netdev',
|
||||
'25-ip6tnl-tunnel-external.netdev']:
|
||||
with open(os.path.join(network_unit_dir, netdev), mode='a', encoding='utf-8') as f:
|
||||
f.write(f'[Tunnel]\nMode={mode}\n')
|
||||
else:
|
||||
mode = 'any' # kernel default
|
||||
|
||||
start_networkd()
|
||||
self.wait_online('ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable',
|
||||
'ip6tnl-slaac:degraded', 'ip6tnl-external:degraded',
|
||||
@@ -2747,20 +2782,20 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
|
||||
output = check_output('ip -d link show ip6tnl99')
|
||||
print(output)
|
||||
self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98', output)
|
||||
self.assertIn(f'ip6tnl {mode} remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98', output)
|
||||
output = check_output('ip -d link show ip6tnl98')
|
||||
print(output)
|
||||
self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
|
||||
self.assertIn(f'ip6tnl {mode} remote 2001:473:fece:cafe::5179 local any dev dummy98', output)
|
||||
output = check_output('ip -d link show ip6tnl97')
|
||||
print(output)
|
||||
self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
|
||||
self.assertIn(f'ip6tnl {mode} remote any local 2a00:ffde:4567:edde::4987 dev dummy98', output)
|
||||
output = check_output('ip -d link show ip6tnl-external')
|
||||
print(output)
|
||||
self.assertIn('ip6tnl-external@NONE:', output)
|
||||
self.assertIn('ip6tnl external ', output)
|
||||
output = check_output('ip -d link show ip6tnl-slaac')
|
||||
print(output)
|
||||
self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output)
|
||||
self.assertIn(f'ip6tnl {mode} remote 2001:473:fece:cafe::5179 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output)
|
||||
|
||||
output = check_output('ip -6 address show veth99')
|
||||
print(output)
|
||||
@@ -2787,12 +2822,35 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
'veth99:routable',
|
||||
'veth-peer:degraded')
|
||||
|
||||
def test_sit_tunnel(self):
|
||||
def test_ip6tnl_tunnel(self):
|
||||
first = True
|
||||
for mode in [None, 'ipip6', 'ip6ip6', 'any']:
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
self.tearDown()
|
||||
|
||||
print(f'### test_ip6tnl_tunnel(mode={mode})')
|
||||
with self.subTest(mode=mode):
|
||||
self._test_ip6tnl_tunnel(mode)
|
||||
|
||||
def _test_sit_tunnel(self, mode):
|
||||
copy_network_unit('12-dummy.netdev', '25-sit.network',
|
||||
'25-sit-tunnel.netdev', '25-tunnel.network',
|
||||
'25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
|
||||
'25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
|
||||
'25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
|
||||
|
||||
if mode:
|
||||
for netdev in ['25-sit-tunnel.netdev',
|
||||
'25-sit-tunnel-local-any.netdev',
|
||||
'25-sit-tunnel-remote-any.netdev',
|
||||
'25-sit-tunnel-any-any.netdev']:
|
||||
with open(os.path.join(network_unit_dir, netdev), mode='a', encoding='utf-8') as f:
|
||||
f.write(f'[Tunnel]\nMode={mode}\n')
|
||||
else:
|
||||
mode = 'ip6ip' # kernel default
|
||||
|
||||
start_networkd()
|
||||
self.wait_online('sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded')
|
||||
self.networkctl_check_unit('sittun99', '25-sit-tunnel', '25-tunnel')
|
||||
@@ -2803,16 +2861,16 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
|
||||
output = check_output('ip -d link show sittun99')
|
||||
print(output)
|
||||
self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
|
||||
self.assertIn(f'sit {mode} remote 10.65.223.239 local 10.65.223.238 dev dummy98', output)
|
||||
output = check_output('ip -d link show sittun98')
|
||||
print(output)
|
||||
self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
|
||||
self.assertIn(f'sit {mode} remote 10.65.223.239 local any dev dummy98', output)
|
||||
output = check_output('ip -d link show sittun97')
|
||||
print(output)
|
||||
self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
|
||||
self.assertIn(f'sit {mode} remote any local 10.65.223.238 dev dummy98', output)
|
||||
output = check_output('ip -d link show sittun96')
|
||||
print(output)
|
||||
self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
|
||||
self.assertIn(f'sit {mode} remote any local any dev dummy98', output)
|
||||
|
||||
touch_network_unit(
|
||||
'25-sit-tunnel.netdev',
|
||||
@@ -2827,6 +2885,18 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
'sittun96:routable',
|
||||
'dummy98:degraded')
|
||||
|
||||
def test_sit_tunnel(self):
|
||||
first = True
|
||||
for mode in [None, 'ipip', 'ip6ip', 'any']:
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
self.tearDown()
|
||||
|
||||
print(f'### test_sit_tunnel(mode={mode})')
|
||||
with self.subTest(mode=mode):
|
||||
self._test_sit_tunnel(mode)
|
||||
|
||||
def test_isatap_tunnel(self):
|
||||
copy_network_unit('12-dummy.netdev', '25-isatap.network',
|
||||
'25-isatap-tunnel.netdev', '25-tunnel.network')
|
||||
|
||||
Reference in New Issue
Block a user