diff options
author | Klement Sekera <ksekera@cisco.com> | 2021-03-15 16:34:01 +0100 |
---|---|---|
committer | Ole Tr�an <otroan@employees.org> | 2021-03-30 12:26:25 +0000 |
commit | eafb5db63f20975076de8e35932f1ed306a2743e (patch) | |
tree | 4c5f8d529c63bcb3d1fa29093ae7fd2dc6bf919b /src/plugins/nat/test | |
parent | 0b37034fef436e02dd739b3b2c05f03708229e4c (diff) |
nat: fix HA multi-worker issues
Use correct vlib_main() in various code parts. Fix tests.
Type: fix
Signed-off-by: Klement Sekera <ksekera@cisco.com>
Change-Id: Ia379f3b686599532dedaafad2278c4097a3f03f3
Diffstat (limited to 'src/plugins/nat/test')
-rw-r--r-- | src/plugins/nat/test/test_nat44_ei.py | 211 |
1 files changed, 119 insertions, 92 deletions
diff --git a/src/plugins/nat/test/test_nat44_ei.py b/src/plugins/nat/test/test_nat44_ei.py index cd1941a7f12..04ed9a33e01 100644 --- a/src/plugins/nat/test/test_nat44_ei.py +++ b/src/plugins/nat/test/test_nat44_ei.py @@ -632,9 +632,9 @@ class MethodHolder(VppTestCase): """ Verify that there is no NAT44EI user """ users = self.vapi.nat44_ei_user_dump() self.assertEqual(len(users), 0) - users = self.statistics.get_counter('/nat44-ei/total-users') + users = self.statistics['/nat44-ei/total-users'] self.assertEqual(users[0][0], 0) - sessions = self.statistics.get_counter('/nat44-ei/total-sessions') + sessions = self.statistics['/nat44-ei/total-sessions'] self.assertEqual(sessions[0][0], 0) def verify_syslog_apmap(self, data, is_add=True): @@ -852,6 +852,16 @@ class MethodHolder(VppTestCase): self.assertEqual(data, p[Raw].load) +def get_nat44_ei_in2out_worker_index(ip, vpp_worker_count): + if 0 == vpp_worker_count: + return 0 + numeric = socket.inet_aton(ip) + numeric = struct.unpack("!L", numeric)[0] + numeric = socket.htonl(numeric) + h = numeric + (numeric >> 8) + (numeric >> 16) + (numeric >> 24) + return 1 + h % vpp_worker_count + + @tag_fixme_vpp_workers class TestNAT44EI(MethodHolder): """ NAT44EI Test Cases """ @@ -963,14 +973,14 @@ class TestNAT44EI(MethodHolder): capture = self.pg1.get_capture(len(pkts)) self.verify_capture_out(capture) - sessions = self.statistics.get_counter('/nat44-ei/total-sessions') - self.assertTrue(sessions[0][0] > 0) + sessions = self.statistics['/nat44-ei/total-sessions'] + self.assertGreater(sessions[:, 0].sum(), 0, "Session count invalid") self.logger.info("sessions before clearing: %s" % sessions[0][0]) self.vapi.cli("clear nat44 ei sessions") - sessions = self.statistics.get_counter('/nat44-ei/total-sessions') - self.assertEqual(sessions[0][0], 0) + sessions = self.statistics['/nat44-ei/total-sessions'] + self.assertEqual(sessions[:, 0].sum(), 0, "Session count invalid") self.logger.info("sessions after clearing: %s" % sessions[0][0]) def test_dynamic(self): @@ -985,12 +995,10 @@ class TestNAT44EI(MethodHolder): is_add=1) # in2out - tcpn = self.statistics.get_counter('/nat44-ei/in2out/slowpath/tcp')[0] - udpn = self.statistics.get_counter('/nat44-ei/in2out/slowpath/udp')[0] - icmpn = self.statistics.get_counter( - '/nat44-ei/in2out/slowpath/icmp')[0] - drops = self.statistics.get_counter( - '/nat44-ei/in2out/slowpath/drops')[0] + tcpn = self.statistics['/nat44-ei/in2out/slowpath/tcp'] + udpn = self.statistics['/nat44-ei/in2out/slowpath/udp'] + icmpn = self.statistics['/nat44-ei/in2out/slowpath/icmp'] + drops = self.statistics['/nat44-ei/in2out/slowpath/drops'] pkts = self.create_stream_in(self.pg0, self.pg1) self.pg0.add_stream(pkts) @@ -1000,22 +1008,20 @@ class TestNAT44EI(MethodHolder): self.verify_capture_out(capture) if_idx = self.pg0.sw_if_index - cnt = self.statistics.get_counter('/nat44-ei/in2out/slowpath/tcp')[0] - self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2) - cnt = self.statistics.get_counter('/nat44-ei/in2out/slowpath/udp')[0] - self.assertEqual(cnt[if_idx] - udpn[if_idx], 1) - cnt = self.statistics.get_counter('/nat44-ei/in2out/slowpath/icmp')[0] - self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1) - cnt = self.statistics.get_counter('/nat44-ei/in2out/slowpath/drops')[0] - self.assertEqual(cnt[if_idx] - drops[if_idx], 0) + cnt = self.statistics['/nat44-ei/in2out/slowpath/tcp'] + self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2) + cnt = self.statistics['/nat44-ei/in2out/slowpath/udp'] + self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1) + cnt = self.statistics['/nat44-ei/in2out/slowpath/icmp'] + self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1) + cnt = self.statistics['/nat44-ei/in2out/slowpath/drops'] + self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0) # out2in - tcpn = self.statistics.get_counter('/nat44-ei/out2in/slowpath/tcp')[0] - udpn = self.statistics.get_counter('/nat44-ei/out2in/slowpath/udp')[0] - icmpn = self.statistics.get_counter( - '/nat44-ei/out2in/slowpath/icmp')[0] - drops = self.statistics.get_counter( - '/nat44-ei/out2in/slowpath/drops')[0] + tcpn = self.statistics['/nat44-ei/out2in/slowpath/tcp'] + udpn = self.statistics['/nat44-ei/out2in/slowpath/udp'] + icmpn = self.statistics['/nat44-ei/out2in/slowpath/icmp'] + drops = self.statistics['/nat44-ei/out2in/slowpath/drops'] pkts = self.create_stream_out(self.pg1) self.pg1.add_stream(pkts) @@ -1025,19 +1031,19 @@ class TestNAT44EI(MethodHolder): self.verify_capture_in(capture, self.pg0) if_idx = self.pg1.sw_if_index - cnt = self.statistics.get_counter('/nat44-ei/out2in/slowpath/tcp')[0] - self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2) - cnt = self.statistics.get_counter('/nat44-ei/out2in/slowpath/udp')[0] - self.assertEqual(cnt[if_idx] - udpn[if_idx], 1) - cnt = self.statistics.get_counter('/nat44-ei/out2in/slowpath/icmp')[0] - self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1) - cnt = self.statistics.get_counter('/nat44-ei/out2in/slowpath/drops')[0] - self.assertEqual(cnt[if_idx] - drops[if_idx], 0) - - users = self.statistics.get_counter('/nat44-ei/total-users') - self.assertEqual(users[0][0], 1) - sessions = self.statistics.get_counter('/nat44-ei/total-sessions') - self.assertEqual(sessions[0][0], 3) + cnt = self.statistics['/nat44-ei/out2in/slowpath/tcp'] + self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2) + cnt = self.statistics['/nat44-ei/out2in/slowpath/udp'] + self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1) + cnt = self.statistics['/nat44-ei/out2in/slowpath/icmp'] + self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1) + cnt = self.statistics['/nat44-ei/out2in/slowpath/drops'] + self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0) + + users = self.statistics['/nat44-ei/total-users'] + self.assertEqual(users[:, 0].sum(), 1) + sessions = self.statistics['/nat44-ei/total-sessions'] + self.assertEqual(sessions[:, 0].sum(), 3) def test_dynamic_icmp_errors_in2out_ttl_1(self): """ NAT44EI handling of client packets with TTL=1 """ @@ -1828,7 +1834,7 @@ class TestNAT44EI(MethodHolder): server_in_port, server_out_port, proto=IP_PROTOS.tcp) - cnt = self.statistics.get_counter('/nat44-ei/hairpinning')[0] + cnt = self.statistics['/nat44-ei/hairpinning'] # send packet from host to server p = (Ether(src=host.mac, dst=self.pg0.local_mac) / IP(src=host.ip4, dst=self.nat_addr) / @@ -1851,9 +1857,9 @@ class TestNAT44EI(MethodHolder): self.logger.error(ppp("Unexpected or invalid packet:", p)) raise - after = self.statistics.get_counter('/nat44-ei/hairpinning')[0] + after = self.statistics['/nat44-ei/hairpinning'] if_idx = self.pg0.sw_if_index - self.assertEqual(after[if_idx] - cnt[if_idx], 1) + self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1) # send reply from server to host p = (Ether(src=server.mac, dst=self.pg0.local_mac) / @@ -1876,9 +1882,10 @@ class TestNAT44EI(MethodHolder): self.logger.error(ppp("Unexpected or invalid packet:", p)) raise - after = self.statistics.get_counter('/nat44-ei/hairpinning')[0] + after = self.statistics['/nat44-ei/hairpinning'] if_idx = self.pg0.sw_if_index - self.assertEqual(after[if_idx] - cnt[if_idx], 2) + self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), + 2+(1 if self.vpp_worker_count > 0 else 0)) def test_hairpinning2(self): """ NAT44EI hairpinning - 1:1 NAT""" @@ -2086,7 +2093,7 @@ class TestNAT44EI(MethodHolder): self.pg_start() # Here VPP used to crash due to an infinite loop - cnt = self.statistics.get_counter('/nat44-ei/hairpinning')[0] + cnt = self.statistics['/nat44-ei/hairpinning'] # send packet from host to server p = (Ether(src=host.mac, dst=self.pg0.local_mac) / IP(src=host.ip4, dst=self.nat_addr) / @@ -2109,9 +2116,9 @@ class TestNAT44EI(MethodHolder): self.logger.error(ppp("Unexpected or invalid packet:", p)) raise - after = self.statistics.get_counter('/nat44-ei/hairpinning')[0] + after = self.statistics['/nat44-ei/hairpinning'] if_idx = self.pg0.sw_if_index - self.assertEqual(after[if_idx] - cnt[if_idx], 1) + self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), 1) # send reply from server to host p = (Ether(src=server.mac, dst=self.pg0.local_mac) / @@ -2134,9 +2141,10 @@ class TestNAT44EI(MethodHolder): self.logger.error(ppp("Unexpected or invalid packet:", p)) raise - after = self.statistics.get_counter('/nat44-ei/hairpinning')[0] + after = self.statistics['/nat44-ei/hairpinning'] if_idx = self.pg0.sw_if_index - self.assertEqual(after[if_idx] - cnt[if_idx], 2) + self.assertEqual(after[:, if_idx].sum() - cnt[:, if_idx].sum(), + 2+(1 if self.vpp_worker_count > 0 else 0)) def test_interface_addr(self): """ NAT44EI acquire addresses from interface """ @@ -2368,7 +2376,8 @@ class TestNAT44EI(MethodHolder): sw_if_index=self.pg1.sw_if_index, is_add=1) - max_sessions = self.max_translations + max_sessions_per_thread = self.max_translations + max_sessions = max(1, self.vpp_worker_count) * max_sessions_per_thread pkts = [] for i in range(0, max_sessions): @@ -2416,7 +2425,7 @@ class TestNAT44EI(MethodHolder): for p in capture: if p.haslayer(Data): data = ipfix.decode_data_set(p.getlayer(Set)) - self.verify_ipfix_max_sessions(data, max_sessions) + self.verify_ipfix_max_sessions(data, max_sessions_per_thread) def test_syslog_apmap(self): """ NAT44EI syslog address and port mapping creation and deletion """ @@ -3400,8 +3409,8 @@ class TestNAT44EI(MethodHolder): self.verify_capture_out(capture) # active send HA events self.vapi.nat44_ei_ha_flush() - stats = self.statistics.get_counter('/nat44-ei/ha/add-event-send') - self.assertEqual(stats[0][0], 3) + stats = self.statistics['/nat44-ei/ha/add-event-send'] + self.assertEqual(stats[:, 0].sum(), 3) capture = self.pg3.get_capture(1) p = capture[0] self.assert_packet_checksums_valid(p) @@ -3418,7 +3427,7 @@ class TestNAT44EI(MethodHolder): self.assertEqual(udp.sport, 12345) self.assertEqual(udp.dport, 12346) self.assertEqual(hanat.version, 1) - self.assertEqual(hanat.thread_index, 0) + # self.assertEqual(hanat.thread_index, 0) self.assertEqual(hanat.count, 3) seq = hanat.sequence_number for event in hanat.events: @@ -3431,11 +3440,12 @@ class TestNAT44EI(MethodHolder): ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) / IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) / UDP(sport=12346, dport=12345) / - HANATStateSync(sequence_number=seq, flags='ACK')) + HANATStateSync(sequence_number=seq, flags='ACK', + thread_index=hanat.thread_index)) self.pg3.add_stream(ack) self.pg_start() - stats = self.statistics.get_counter('/nat44-ei/ha/ack-recv') - self.assertEqual(stats[0][0], 1) + stats = self.statistics['/nat44-ei/ha/ack-recv'] + self.assertEqual(stats[:, 0].sum(), 1) # delete one session self.pg_enable_capture(self.pg_interfaces) @@ -3443,8 +3453,8 @@ class TestNAT44EI(MethodHolder): address=self.pg0.remote_ip4, port=self.tcp_port_in, protocol=IP_PROTOS.tcp, flags=self.config_flags.NAT44_EI_IF_INSIDE) self.vapi.nat44_ei_ha_flush() - stats = self.statistics.get_counter('/nat44-ei/ha/del-event-send') - self.assertEqual(stats[0][0], 1) + stats = self.statistics['/nat44-ei/ha/del-event-send'] + self.assertEqual(stats[:, 0].sum(), 1) capture = self.pg3.get_capture(1) p = capture[0] try: @@ -3458,10 +3468,10 @@ class TestNAT44EI(MethodHolder): # do not send ACK, active retry send HA event again self.pg_enable_capture(self.pg_interfaces) sleep(12) - stats = self.statistics.get_counter('/nat44-ei/ha/retry-count') - self.assertEqual(stats[0][0], 3) - stats = self.statistics.get_counter('/nat44-ei/ha/missed-count') - self.assertEqual(stats[0][0], 1) + stats = self.statistics['/nat44-ei/ha/retry-count'] + self.assertEqual(stats[:, 0].sum(), 3) + stats = self.statistics['/nat44-ei/ha/missed-count'] + self.assertEqual(stats[:, 0].sum(), 1) capture = self.pg3.get_capture(3) for packet in capture: self.assertEqual(packet, p) @@ -3473,8 +3483,8 @@ class TestNAT44EI(MethodHolder): self.pg_start() self.pg0.get_capture(2) self.vapi.nat44_ei_ha_flush() - stats = self.statistics.get_counter('/nat44-ei/ha/refresh-event-send') - self.assertEqual(stats[0][0], 2) + stats = self.statistics['/nat44-ei/ha/refresh-event-send'] + self.assertEqual(stats[:, 0].sum(), 2) capture = self.pg3.get_capture(1) p = capture[0] self.assert_packet_checksums_valid(p) @@ -3500,14 +3510,16 @@ class TestNAT44EI(MethodHolder): self.assertEqual(event.total_pkts, 2) self.assertGreater(event.total_bytes, 0) + stats = self.statistics['/nat44-ei/ha/ack-recv'] ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) / IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) / UDP(sport=12346, dport=12345) / - HANATStateSync(sequence_number=seq, flags='ACK')) + HANATStateSync(sequence_number=seq, flags='ACK', + thread_index=hanat.thread_index)) self.pg3.add_stream(ack) self.pg_start() - stats = self.statistics.get_counter('/nat44-ei/ha/ack-recv') - self.assertEqual(stats[0][0], 2) + stats = self.statistics['/nat44-ei/ha/ack-recv'] + self.assertEqual(stats[:, 0].sum(), 2) def test_ha_recv(self): """ NAT44EI Receive HA session synchronization events (passive) """ @@ -3523,8 +3535,23 @@ class TestNAT44EI(MethodHolder): port=12345, path_mtu=512) bind_layers(UDP, HANATStateSync, sport=12345) - self.tcp_port_out = random.randint(1025, 65535) - self.udp_port_out = random.randint(1025, 65535) + # this is a bit tricky - HA dictates thread index due to how it's + # designed, but once we use HA to create a session, we also want + # to pass a packet through said session. so the session must end + # up on the correct thread from both directions - in2out (based on + # IP address) and out2in (based on outside port) + + # first choose a thread index which is correct for IP + thread_index = get_nat44_ei_in2out_worker_index(self.pg0.remote_ip4, + self.vpp_worker_count) + + # now pick a port which is correct for given thread + port_per_thread = int((0xffff-1024) / max(1, self.vpp_worker_count)) + self.tcp_port_out = 1024 + random.randint(1, port_per_thread) + self.udp_port_out = 1024 + random.randint(1, port_per_thread) + if self.vpp_worker_count > 0: + self.tcp_port_out += port_per_thread * (thread_index - 1) + self.udp_port_out += port_per_thread * (thread_index - 1) # send HA session add events to failover/passive p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) / @@ -3544,7 +3571,8 @@ class TestNAT44EI(MethodHolder): eh_addr=self.pg1.remote_ip4, ehn_addr=self.pg1.remote_ip4, eh_port=self.udp_external_port, - ehn_port=self.udp_external_port, fib_index=0)])) + ehn_port=self.udp_external_port, fib_index=0)], + thread_index=thread_index)) self.pg3.add_stream(p) self.pg_enable_capture(self.pg_interfaces) @@ -3561,15 +3589,15 @@ class TestNAT44EI(MethodHolder): self.assertEqual(hanat.sequence_number, 1) self.assertEqual(hanat.flags, 'ACK') self.assertEqual(hanat.version, 1) - self.assertEqual(hanat.thread_index, 0) - stats = self.statistics.get_counter('/nat44-ei/ha/ack-send') - self.assertEqual(stats[0][0], 1) - stats = self.statistics.get_counter('/nat44-ei/ha/add-event-recv') - self.assertEqual(stats[0][0], 2) - users = self.statistics.get_counter('/nat44-ei/total-users') - self.assertEqual(users[0][0], 1) - sessions = self.statistics.get_counter('/nat44-ei/total-sessions') - self.assertEqual(sessions[0][0], 2) + self.assertEqual(hanat.thread_index, thread_index) + stats = self.statistics['/nat44-ei/ha/ack-send'] + self.assertEqual(stats[:, 0].sum(), 1) + stats = self.statistics['/nat44-ei/ha/add-event-recv'] + self.assertEqual(stats[:, 0].sum(), 2) + users = self.statistics['/nat44-ei/total-users'] + self.assertEqual(users[:, 0].sum(), 1) + sessions = self.statistics['/nat44-ei/total-sessions'] + self.assertEqual(sessions[:, 0].sum(), 2) users = self.vapi.nat44_ei_user_dump() self.assertEqual(len(users), 1) self.assertEqual(str(users[0].ip_address), @@ -3600,7 +3628,8 @@ class TestNAT44EI(MethodHolder): eh_addr=self.pg1.remote_ip4, ehn_addr=self.pg1.remote_ip4, eh_port=self.udp_external_port, - ehn_port=self.udp_external_port, fib_index=0)])) + ehn_port=self.udp_external_port, fib_index=0)], + thread_index=thread_index)) self.pg3.add_stream(p) self.pg_enable_capture(self.pg_interfaces) @@ -3625,8 +3654,8 @@ class TestNAT44EI(MethodHolder): sessions = self.vapi.nat44_ei_user_session_dump(users[0].ip_address, users[0].vrf_id) self.assertEqual(len(sessions), 1) - stats = self.statistics.get_counter('/nat44-ei/ha/del-event-recv') - self.assertEqual(stats[0][0], 1) + stats = self.statistics['/nat44-ei/ha/del-event-recv'] + self.assertEqual(stats[:, 0].sum(), 1) stats = self.statistics.get_err_counter( '/err/nat44-ei-ha/pkts-processed') @@ -3644,7 +3673,8 @@ class TestNAT44EI(MethodHolder): ehn_addr=self.pg1.remote_ip4, eh_port=self.tcp_external_port, ehn_port=self.tcp_external_port, fib_index=0, - total_bytes=1024, total_pkts=2)])) + total_bytes=1024, total_pkts=2)], + thread_index=thread_index)) self.pg3.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() @@ -3670,9 +3700,8 @@ class TestNAT44EI(MethodHolder): session = sessions[0] self.assertEqual(session.total_bytes, 1024) self.assertEqual(session.total_pkts, 2) - stats = self.statistics.get_counter( - '/nat44-ei/ha/refresh-event-recv') - self.assertEqual(stats[0][0], 1) + stats = self.statistics['/nat44-ei/ha/refresh-event-recv'] + self.assertEqual(stats[:, 0].sum(), 1) stats = self.statistics.get_err_counter( '/err/nat44-ei-ha/pkts-processed') @@ -3898,9 +3927,7 @@ class TestNAT44Out2InDPO(MethodHolder): class TestNAT44EIMW(MethodHolder): """ NAT44EI Test Cases (multiple workers) """ - vpp_worker_count = 2 - max_translations = 10240 max_users = 10240 @@ -4013,7 +4040,7 @@ class TestNAT44EIMW(MethodHolder): server_in_port, server_out_port, proto=IP_PROTOS.tcp) - cnt = self.statistics.get_counter('/nat44-ei/hairpinning') + cnt = self.statistics['/nat44-ei/hairpinning'] # send packet from host to server p = (Ether(src=host.mac, dst=self.pg0.local_mac) / IP(src=host.ip4, dst=self.nat_addr) / @@ -4036,7 +4063,7 @@ class TestNAT44EIMW(MethodHolder): self.logger.error(ppp("Unexpected or invalid packet:", p)) raise - after = self.statistics.get_counter('/nat44-ei/hairpinning') + after = self.statistics['/nat44-ei/hairpinning'] if_idx = self.pg0.sw_if_index self.assertEqual(after[worker_2][if_idx] - cnt[worker_1][if_idx], 1) @@ -4062,7 +4089,7 @@ class TestNAT44EIMW(MethodHolder): self.logger.error(ppp("Unexpected or invalid packet:", p)) raise - after = self.statistics.get_counter('/nat44-ei/hairpinning') + after = self.statistics['/nat44-ei/hairpinning'] if_idx = self.pg0.sw_if_index self.assertEqual(after[worker_1][if_idx] - cnt[worker_1][if_idx], 1) self.assertEqual(after[worker_2][if_idx] - cnt[worker_2][if_idx], 2) |