From 98406eda8ac64491833b89d04b29d4b8c9748875 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 31 May 2022 23:08:28 +0900 Subject: [PATCH 1/3] network/erspan: support erspan version 0 and 2 This also makes networkd accepts erspan index 0. Closes #23570. --- man/systemd.netdev.xml | 28 ++- src/network/netdev/netdev-gperf.gperf | 5 +- src/network/netdev/tunnel.c | 170 +++++++++++++++++- src/network/netdev/tunnel.h | 10 +- .../fuzz/fuzz-netdev-parser/directives.netdev | 3 + 5 files changed, 207 insertions(+), 9 deletions(-) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 3a776b3f42..0855cf17a8 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -1369,12 +1369,34 @@ + + ERSPANVersion= + + Specifies the ERSPAN version number. Takes 0 for version 0 (a.k.a. type I), 1 for version 1 + (a.k.a. type II), or 2 for version 2 (a.k.a. type III). Defaults to 1. + + ERSPANIndex= - Specifies the ERSPAN index field for the interface, an integer in the range 1…1048575 associated with - the ERSPAN traffic's source port and direction. This field is mandatory. - + Specifies the ERSPAN v1 index field for the interface. Takes an integer in the range + 0…1048575, which is associated with the ERSPAN traffic's source port and direction. Only used when + ERSPANVersion=1. Defaults to 0. + + + + ERSPANDirection= + + Specifies the ERSPAN v2 mirrored traffic's direction. Takes ingress or + egress. Only used when ERSPANVersion=2. Defaults to + ingress. + + + + ERSPANHardwareId= + + Specifies an unique identifier of the ERSPAN v2 engine. Takes an integer in the range 0…63. + Only used when ERSPANVersion=2. Defaults to 0. diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index 77140be400..55ad60ddc8 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -89,7 +89,10 @@ Tunnel.FOUDestinationPort, config_parse_ip_port, Tunnel.FOUSourcePort, config_parse_ip_port, 0, offsetof(Tunnel, encap_src_port) Tunnel.Encapsulation, config_parse_fou_encap_type, 0, offsetof(Tunnel, fou_encap_type) Tunnel.IPv6RapidDeploymentPrefix, config_parse_6rd_prefix, 0, 0 -Tunnel.ERSPANIndex, config_parse_uint32, 0, offsetof(Tunnel, erspan_index) +Tunnel.ERSPANVersion, config_parse_erspan_version, 0, offsetof(Tunnel, erspan_version) +Tunnel.ERSPANIndex, config_parse_erspan_index, 0, offsetof(Tunnel, erspan_index) +Tunnel.ERSPANDirection, config_parse_erspan_direction, 0, offsetof(Tunnel, erspan_direction) +Tunnel.ERSPANHardwareId, config_parse_erspan_hwid, 0, offsetof(Tunnel, erspan_hwid) Tunnel.SerializeTunneledPackets, config_parse_tristate, 0, offsetof(Tunnel, gre_erspan_sequence) Tunnel.ISATAP, config_parse_tristate, 0, offsetof(Tunnel, isatap) Tunnel.External, config_parse_bool, 0, offsetof(Tunnel, external) diff --git a/src/network/netdev/tunnel.c b/src/network/netdev/tunnel.c index 747acb1e80..78a8708b21 100644 --- a/src/network/netdev/tunnel.c +++ b/src/network/netdev/tunnel.c @@ -335,9 +335,24 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_ } if (netdev->kind == NETDEV_KIND_ERSPAN) { - r = sd_netlink_message_append_u32(m, IFLA_GRE_ERSPAN_INDEX, t->erspan_index); + r = sd_netlink_message_append_u8(m, IFLA_GRE_ERSPAN_VER, t->erspan_version); if (r < 0) return r; + + if (t->erspan_version == 1) { + r = sd_netlink_message_append_u32(m, IFLA_GRE_ERSPAN_INDEX, t->erspan_index); + if (r < 0) + return r; + + } else if (t->erspan_version == 2) { + r = sd_netlink_message_append_u8(m, IFLA_GRE_ERSPAN_DIR, t->erspan_direction); + if (r < 0) + return r; + + r = sd_netlink_message_append_u16(m, IFLA_GRE_ERSPAN_HWID, t->erspan_hwid); + if (r < 0) + return r; + } } r = tunnel_get_local_address(t, link, &local); @@ -720,9 +735,6 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) { return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "FooOverUDP missing port configured in %s. Ignoring", filename); - if (netdev->kind == NETDEV_KIND_ERSPAN && (t->erspan_index >= (1 << 20) || t->erspan_index == 0)) - return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Invalid erspan index %d. Ignoring", t->erspan_index); - /* netlink_message_append_in_addr_union() is used for vti/vti6. So, t->family cannot be AF_UNSPEC. */ if (netdev->kind == NETDEV_KIND_VTI) t->family = AF_INET; @@ -1021,6 +1033,155 @@ int config_parse_6rd_prefix( return 0; } +int config_parse_erspan_version( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint8_t n, *v = ASSERT_PTR(data); + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + *v = 1; /* defaults to 1 */ + return 0; + } + + r = safe_atou8(rvalue, &n); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse erspan version \"%s\", ignoring: %m", rvalue); + return 0; + } + if (!IN_SET(n, 0, 1, 2)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid erspan version \"%s\", which must be 0, 1 or 2, ignoring.", rvalue); + return 0; + } + + *v = n; + return 0; +} + +int config_parse_erspan_index( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint32_t n, *v = ASSERT_PTR(data); + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + *v = 0; /* defaults to 0 */ + return 0; + } + + r = safe_atou32(rvalue, &n); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse erspan index \"%s\", ignoring: %m", rvalue); + return 0; + } + if (n >= 0x100000) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid erspan index \"%s\", which must be less than 0x100000, ignoring.", rvalue); + return 0; + } + + *v = n; + return 0; +} + +int config_parse_erspan_direction( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint8_t *v = ASSERT_PTR(data); + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue) || streq(rvalue, "ingress")) + *v = 0; /* defaults to ingress */ + else if (streq(rvalue, "egress")) + *v = 1; + else + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid erspan direction \"%s\", which must be \"ingress\" or \"egress\", ignoring.", rvalue); + + return 0; +} + +int config_parse_erspan_hwid( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint16_t n, *v = ASSERT_PTR(data); + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + *v = 0; /* defaults to 0 */ + return 0; + } + + r = safe_atou16(rvalue, &n); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse erspan hwid \"%s\", ignoring: %m", rvalue); + return 0; + } + if (n >= 64) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid erspan index \"%s\", which must be less than 64, ignoring.", rvalue); + return 0; + } + + *v = n; + return 0; +} + static void netdev_tunnel_init(NetDev *netdev) { Tunnel *t; @@ -1039,6 +1200,7 @@ static void netdev_tunnel_init(NetDev *netdev) { t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID; t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID; t->allow_localremote = -1; + t->erspan_version = 1; if (IN_SET(netdev->kind, NETDEV_KIND_IP6GRE, NETDEV_KIND_IP6GRETAP, NETDEV_KIND_IP6TNL)) t->ttl = DEFAULT_IPV6_TTL; diff --git a/src/network/netdev/tunnel.h b/src/network/netdev/tunnel.h index e25dfb215a..7c81f22391 100644 --- a/src/network/netdev/tunnel.h +++ b/src/network/netdev/tunnel.h @@ -41,7 +41,11 @@ typedef struct Tunnel { uint32_t key; uint32_t ikey; uint32_t okey; - uint32_t erspan_index; + + uint8_t erspan_version; + uint32_t erspan_index; /* version 1 */ + uint8_t erspan_direction; /* version 2 */ + uint16_t erspan_hwid; /* version 2 */ NetDevLocalAddressType local_type; union in_addr_union local; @@ -128,3 +132,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_flowlabel); CONFIG_PARSER_PROTOTYPE(config_parse_encap_limit); CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_key); CONFIG_PARSER_PROTOTYPE(config_parse_6rd_prefix); +CONFIG_PARSER_PROTOTYPE(config_parse_erspan_version); +CONFIG_PARSER_PROTOTYPE(config_parse_erspan_index); +CONFIG_PARSER_PROTOTYPE(config_parse_erspan_direction); +CONFIG_PARSER_PROTOTYPE(config_parse_erspan_hwid); diff --git a/test/fuzz/fuzz-netdev-parser/directives.netdev b/test/fuzz/fuzz-netdev-parser/directives.netdev index d6c2e18464..d97f81512b 100644 --- a/test/fuzz/fuzz-netdev-parser/directives.netdev +++ b/test/fuzz/fuzz-netdev-parser/directives.netdev @@ -92,7 +92,10 @@ EncapsulationLimit= TTL= FOUSourcePort= IPv6RapidDeploymentPrefix= +ERSPANVersion= ERSPANIndex= +ERSPANDirection= +ERSPANHardwareId= SerializeTunneledPackets= ISATAP= External= From 2f0260c1bb5c584df08bad17a0afb23052ec9b9c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 31 May 2022 23:36:16 +0900 Subject: [PATCH 2/3] test-network: add tests for erspan version 0 and 2 --- .../conf/25-erspan0-tunnel-local-any.netdev | 15 +++ .../conf/25-erspan0-tunnel.netdev | 15 +++ .../conf/25-erspan1-tunnel-local-any.netdev | 15 +++ .../conf/25-erspan1-tunnel.netdev | 15 +++ ...dev => 25-erspan2-tunnel-local-any.netdev} | 4 + ...tunnel.netdev => 25-erspan2-tunnel.netdev} | 4 + test/test-network/systemd-networkd-tests.py | 119 +++++++++++++++--- 7 files changed, 168 insertions(+), 19 deletions(-) create mode 100644 test/test-network/conf/25-erspan0-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-erspan0-tunnel.netdev create mode 100644 test/test-network/conf/25-erspan1-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-erspan1-tunnel.netdev rename test/test-network/conf/{25-erspan-tunnel-local-any.netdev => 25-erspan2-tunnel-local-any.netdev} (65%) rename test/test-network/conf/{25-erspan-tunnel.netdev => 25-erspan2-tunnel.netdev} (66%) diff --git a/test/test-network/conf/25-erspan0-tunnel-local-any.netdev b/test/test-network/conf/25-erspan0-tunnel-local-any.netdev new file mode 100644 index 0000000000..03db72a8e1 --- /dev/null +++ b/test/test-network/conf/25-erspan0-tunnel-local-any.netdev @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[NetDev] +Name=erspan98 +Kind=erspan + +[Tunnel] +ERSPANVersion=0 +# The three settings below will be ignored +ERSPANIndex=124 +ERSPANDirection=egress +ERSPANHardwareId=0x2f +Local = any +Remote = 172.16.1.100 +Key=102 +SerializeTunneledPackets=true diff --git a/test/test-network/conf/25-erspan0-tunnel.netdev b/test/test-network/conf/25-erspan0-tunnel.netdev new file mode 100644 index 0000000000..ee295d901f --- /dev/null +++ b/test/test-network/conf/25-erspan0-tunnel.netdev @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[NetDev] +Name=erspan99 +Kind=erspan + +[Tunnel] +ERSPANVersion=0 +# The three settings below will be ignored +ERSPANIndex=123 +ERSPANDirection=ingress +ERSPANHardwareId=0x1f +Local = 172.16.1.200 +Remote = 172.16.1.100 +Key=101 +SerializeTunneledPackets=true diff --git a/test/test-network/conf/25-erspan1-tunnel-local-any.netdev b/test/test-network/conf/25-erspan1-tunnel-local-any.netdev new file mode 100644 index 0000000000..beac91b7b4 --- /dev/null +++ b/test/test-network/conf/25-erspan1-tunnel-local-any.netdev @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[NetDev] +Name=erspan98 +Kind=erspan + +[Tunnel] +ERSPANVersion=1 +ERSPANIndex=124 +# The two settings below will be ignored +ERSPANDirection=egress +ERSPANHardwareId=0x2f +Local = any +Remote = 172.16.1.100 +Key=102 +SerializeTunneledPackets=true diff --git a/test/test-network/conf/25-erspan1-tunnel.netdev b/test/test-network/conf/25-erspan1-tunnel.netdev new file mode 100644 index 0000000000..661ae90af0 --- /dev/null +++ b/test/test-network/conf/25-erspan1-tunnel.netdev @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[NetDev] +Name=erspan99 +Kind=erspan + +[Tunnel] +ERSPANVersion=1 +ERSPANIndex=123 +# The two settings below will be ignored +ERSPANDirection=ingress +ERSPANHardwareId=0x1f +Local = 172.16.1.200 +Remote = 172.16.1.100 +Key=101 +SerializeTunneledPackets=true diff --git a/test/test-network/conf/25-erspan-tunnel-local-any.netdev b/test/test-network/conf/25-erspan2-tunnel-local-any.netdev similarity index 65% rename from test/test-network/conf/25-erspan-tunnel-local-any.netdev rename to test/test-network/conf/25-erspan2-tunnel-local-any.netdev index d16983cbc3..010cf6761b 100644 --- a/test/test-network/conf/25-erspan-tunnel-local-any.netdev +++ b/test/test-network/conf/25-erspan2-tunnel-local-any.netdev @@ -4,7 +4,11 @@ Name=erspan98 Kind=erspan [Tunnel] +ERSPANVersion=2 +# ERSPANIndex= will be ignored ERSPANIndex=124 +ERSPANDirection=egress +ERSPANHardwareId=0x2f Local = any Remote = 172.16.1.100 Key=102 diff --git a/test/test-network/conf/25-erspan-tunnel.netdev b/test/test-network/conf/25-erspan2-tunnel.netdev similarity index 66% rename from test/test-network/conf/25-erspan-tunnel.netdev rename to test/test-network/conf/25-erspan2-tunnel.netdev index 7127488439..b91bbaf4dc 100644 --- a/test/test-network/conf/25-erspan-tunnel.netdev +++ b/test/test-network/conf/25-erspan2-tunnel.netdev @@ -4,7 +4,11 @@ Name=erspan99 Kind=erspan [Tunnel] +ERSPANVersion=2 +# ERSPANIndex= will be ignored ERSPANIndex=123 +ERSPANDirection=ingress +ERSPANHardwareId=0x1f Local = 172.16.1.200 Remote = 172.16.1.100 Key=101 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 51f379f26a..7be99f2509 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -85,9 +85,22 @@ def expectedFailureIfModuleIsNotAvailable(module_name): return f -def expectedFailureIfERSPANModuleIsNotAvailable(): +def expectedFailureIfERSPANv0IsNotSupported(): + # erspan version 0 is supported since f989d546a2d5a9f001f6f8be49d98c10ab9b1897 (v5.8) def f(func): - rc = call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 1 erspan 123', stderr=subprocess.DEVNULL) + rc = call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 0', stderr=subprocess.DEVNULL) + if rc == 0: + call('ip link del erspan99') + return func + + return unittest.expectedFailure(func) + + return f + +def expectedFailureIfERSPANv2IsNotSupported(): + # erspan version 2 is supported since f551c91de262ba36b20c3ac19538afb4f4507441 (v4.16) + def f(func): + rc = call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 2', stderr=subprocess.DEVNULL) if rc == 0: call('ip link del erspan99') return func @@ -993,8 +1006,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-bridge.netdev', '25-bridge-configure-without-carrier.network', '25-bridge.network', - '25-erspan-tunnel-local-any.netdev', - '25-erspan-tunnel.netdev', + '25-erspan0-tunnel-local-any.netdev', + '25-erspan0-tunnel.netdev', + '25-erspan1-tunnel-local-any.netdev', + '25-erspan1-tunnel.netdev', + '25-erspan2-tunnel-local-any.netdev', + '25-erspan2-tunnel.netdev', '25-fou-gretap.netdev', '25-fou-gre.netdev', '25-fou-ipip.netdev', @@ -1795,29 +1812,93 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, '6rd-prefix 2602::/24') - @expectedFailureIfERSPANModuleIsNotAvailable() - def test_erspan_tunnel(self): + @expectedFailureIfERSPANv0IsNotSupported() + def test_erspan_tunnel_v0(self): copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-erspan.network', - '25-erspan-tunnel.netdev', '25-tunnel.network', - '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network') + '25-erspan0-tunnel.netdev', '25-tunnel.network', + '25-erspan0-tunnel-local-any.netdev', '25-tunnel-local-any.network') start_networkd() self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded']) output = check_output('ip -d link show erspan99') print(output) - self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200') - self.assertRegex(output, 'ikey 0.0.0.101') - self.assertRegex(output, 'okey 0.0.0.101') - self.assertRegex(output, 'iseq') - self.assertRegex(output, 'oseq') + self.assertIn('erspan remote 172.16.1.100 local 172.16.1.200', output) + self.assertIn('erspan_ver 0', output) + self.assertNotIn('erspan_index 123', output) + self.assertNotIn('erspan_dir ingress', output) + self.assertNotIn('erspan_hwid 1f', output) + self.assertIn('ikey 0.0.0.101', output) + self.assertIn('iseq', output) output = check_output('ip -d link show erspan98') print(output) - self.assertRegex(output, 'erspan remote 172.16.1.100 local any') - self.assertRegex(output, '102') - self.assertRegex(output, 'ikey 0.0.0.102') - self.assertRegex(output, 'okey 0.0.0.102') - self.assertRegex(output, 'iseq') - self.assertRegex(output, 'oseq') + self.assertIn('erspan remote 172.16.1.100 local any', output) + self.assertIn('erspan_ver 0', output) + self.assertNotIn('erspan_index 124', output) + self.assertNotIn('erspan_dir egress', output) + self.assertNotIn('erspan_hwid 2f', output) + self.assertIn('ikey 0.0.0.102', output) + self.assertIn('iseq', output) + + def test_erspan_tunnel_v1(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-erspan.network', + '25-erspan1-tunnel.netdev', '25-tunnel.network', + '25-erspan1-tunnel-local-any.netdev', '25-tunnel-local-any.network') + start_networkd() + self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show erspan99') + print(output) + self.assertIn('erspan remote 172.16.1.100 local 172.16.1.200', output) + self.assertIn('erspan_ver 1', output) + self.assertIn('erspan_index 123', output) + self.assertNotIn('erspan_dir ingress', output) + self.assertNotIn('erspan_hwid 1f', output) + self.assertIn('ikey 0.0.0.101', output) + self.assertIn('okey 0.0.0.101', output) + self.assertIn('iseq', output) + self.assertIn('oseq', output) + output = check_output('ip -d link show erspan98') + print(output) + self.assertIn('erspan remote 172.16.1.100 local any', output) + self.assertIn('erspan_ver 1', output) + self.assertIn('erspan_index 124', output) + self.assertNotIn('erspan_dir egress', output) + self.assertNotIn('erspan_hwid 2f', output) + self.assertIn('ikey 0.0.0.102', output) + self.assertIn('okey 0.0.0.102', output) + self.assertIn('iseq', output) + self.assertIn('oseq', output) + + @expectedFailureIfERSPANv2IsNotSupported() + def test_erspan_tunnel_v2(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-erspan.network', + '25-erspan2-tunnel.netdev', '25-tunnel.network', + '25-erspan2-tunnel-local-any.netdev', '25-tunnel-local-any.network') + start_networkd() + self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show erspan99') + print(output) + self.assertIn('erspan remote 172.16.1.100 local 172.16.1.200', output) + self.assertIn('erspan_ver 2', output) + self.assertNotIn('erspan_index 123', output) + self.assertIn('erspan_dir ingress', output) + self.assertIn('erspan_hwid 0x1f', output) + self.assertIn('ikey 0.0.0.101', output) + self.assertIn('okey 0.0.0.101', output) + self.assertIn('iseq', output) + self.assertIn('oseq', output) + output = check_output('ip -d link show erspan98') + print(output) + self.assertIn('erspan remote 172.16.1.100 local any', output) + self.assertIn('erspan_ver 2', output) + self.assertNotIn('erspan_index 124', output) + self.assertIn('erspan_dir egress', output) + self.assertIn('erspan_hwid 0x2f', output) + self.assertIn('ikey 0.0.0.102', output) + self.assertIn('okey 0.0.0.102', output) + self.assertIn('iseq', output) + self.assertIn('oseq', output) def test_tunnel_independent(self): copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', '26-netdev-link-local-addressing-yes.network') From 66dc5d82b54744a053230dfc34b12b88f1521947 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 1 Jun 2022 04:01:10 +0900 Subject: [PATCH 3/3] test-network: call networkctl only when specified interface exists Otherwise, this easily trigger another exception: ``` ====================================================================== ERROR: test_erspan_tunnel_v0 (__main__.NetworkdNetDevTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "./test/test-network/systemd-networkd-tests.py", line 686, in wait_online check_output(*args, env=env) File "./test/test-network/systemd-networkd-tests.py", line 65, in check_output return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip() File "/usr/lib64/python3.6/subprocess.py", line 356, in check_output **kwargs).stdout File "/usr/lib64/python3.6/subprocess.py", line 438, in run output=stdout, stderr=stderr) subprocess.CalledProcessError: Command '['/usr/lib/systemd/systemd-networkd-wait-online', '--timeout=20s', '--interface=erspan99:routable', '--interface=erspan98:routable', '--interface=dummy98:degraded']' returned non-zero exit status 1. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "./test/test-network/systemd-networkd-tests.py", line 1808, in test_erspan_tunnel_v0 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded']) File "./test/test-network/systemd-networkd-tests.py", line 689, in wait_online output = check_output(*networkctl_cmd, '-n', '0', 'status', link.split(':')[0], env=env) File "./test/test-network/systemd-networkd-tests.py", line 65, in check_output return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip() File "/usr/lib64/python3.6/subprocess.py", line 356, in check_output **kwargs).stdout File "/usr/lib64/python3.6/subprocess.py", line 438, in run output=stdout, stderr=stderr) subprocess.CalledProcessError: Command '['/usr/bin/networkctl', '-n', '0', 'status', 'erspan99']' returned non-zero exit status 1. ``` --- test/test-network/systemd-networkd-tests.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 7be99f2509..7a962ba708 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -699,8 +699,10 @@ class Utilities(): check_output(*args, env=env) except subprocess.CalledProcessError: for link in links_with_operstate: - output = check_output(*networkctl_cmd, '-n', '0', 'status', link.split(':')[0], env=env) - print(output) + name = link.split(':')[0] + if link_exists(name): + output = check_output(*networkctl_cmd, '-n', '0', 'status', name, env=env) + print(output) raise if not bool_any and setup_state: for link in links_with_operstate: