From 219fbb228f5274d2db740139a0d3258902370165 Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Wed, 13 May 2020 11:35:57 +0000 Subject: nat: "users" dump for ED-NAT Since the removal of "users" concept in ED-NAT nat44_user_dump API returns empty array. This brings back previous behaviour at a considerable runtime cost until a better API is introduced. Type: improvement Change-Id: I5a45923cfeb6b8ebe6fc906601264d6567386991 Signed-off-by: Klement Sekera --- src/plugins/nat/nat.h | 1 + src/plugins/nat/nat_api.c | 64 ++++++++++++++++++++++++ src/plugins/nat/test/test_nat.py | 105 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index d0882e07bab..8ec0c62a800 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -1428,6 +1428,7 @@ typedef struct u16 src_port, dst_port; } tcp_udp_header_t; +u8 *format_user_kvp (u8 * s, va_list * args); #endif /* __included_nat_h__ */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index 37af77d11c1..201c9d4730d 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -1585,6 +1585,62 @@ send_nat44_user_details (snat_user_t * u, vl_api_registration_t * reg, vl_api_send_msg (reg, (u8 *) rmp); } +static void +nat_ed_user_create_helper (snat_main_per_thread_data_t * tsm, + snat_session_t * s) +{ + snat_user_key_t k; + k.addr = s->in2out.addr; + k.fib_index = s->in2out.fib_index; + clib_bihash_kv_8_8_t key, value; + key.key = k.as_u64; + snat_user_t *u; + if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value)) + { + pool_get (tsm->users, u); + u->addr = k.addr; + u->fib_index = k.fib_index; + u->nsessions = 0; + u->nstaticsessions = 0; + key.value = u - tsm->users; + clib_bihash_add_del_8_8 (&tsm->user_hash, &key, 1); + } + else + { + u = pool_elt_at_index (tsm->users, value.value); + } + if (snat_is_session_static (s)) + { + ++u->nstaticsessions; + } + else + { + ++u->nsessions; + } +} + +static void +nat_ed_users_create (snat_main_per_thread_data_t * tsm) +{ + snat_session_t *s; + /* *INDENT-OFF* */ + pool_foreach (s, tsm->sessions, { nat_ed_user_create_helper (tsm, s); }); + /* *INDENT-ON* */ +} + +static void +nat_ed_users_destroy (snat_main_per_thread_data_t * tsm) +{ + snat_user_t *u; + /* *INDENT-OFF* */ + pool_flush (u, tsm->users, { }); + /* *INDENT-ON* */ + clib_bihash_free_8_8 (&tsm->user_hash); + clib_bihash_init_8_8 (&tsm->user_hash, "users", snat_main.user_buckets, + snat_main.user_memory_size); + clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash, format_user_kvp); +} + static void vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp) { @@ -1603,10 +1659,18 @@ vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp) /* *INDENT-OFF* */ vec_foreach (tsm, sm->per_thread_data) { + if (sm->endpoint_dependent) + { + nat_ed_users_create (tsm); + } pool_foreach (u, tsm->users, ({ send_nat44_user_details (u, reg, mp->context); })); + if (sm->endpoint_dependent) + { + nat_ed_users_destroy (tsm); + } } /* *INDENT-ON* */ } diff --git a/src/plugins/nat/test/test_nat.py b/src/plugins/nat/test/test_nat.py index 1b3c7e7a8b1..c2f5f51a054 100644 --- a/src/plugins/nat/test/test_nat.py +++ b/src/plugins/nat/test/test_nat.py @@ -7090,6 +7090,111 @@ class TestNAT44EndpointDependent(MethodHolder): capture = self.pg2.get_capture(1) self.verify_syslog_sess(capture[0][Raw].load, False) + def test_ed_users_dump(self): + """ API test - nat44_user_dump """ + flags = self.config_flags.NAT_IS_INSIDE + self.vapi.nat44_interface_add_del_feature( + sw_if_index=self.pg0.sw_if_index, + flags=flags, is_add=1) + self.vapi.nat44_interface_add_del_feature( + sw_if_index=self.pg1.sw_if_index, + is_add=1) + self.vapi.nat44_forwarding_enable_disable(enable=1) + + real_ip = self.pg0.remote_ip4 + alias_ip = self.nat_addr + flags = self.config_flags.NAT_IS_ADDR_ONLY + self.vapi.nat44_add_del_static_mapping(is_add=1, + local_ip_address=real_ip, + external_ip_address=alias_ip, + external_sw_if_index=0xFFFFFFFF, + flags=flags) + + users = self.vapi.nat44_user_dump() + self.assertEqual(len(users), 0) + try: + # in2out - static mapping match + + pkts = self.create_stream_out(self.pg1) + self.pg1.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg0.get_capture(len(pkts)) + self.verify_capture_in(capture, self.pg0) + + pkts = self.create_stream_in(self.pg0, self.pg1) + self.pg0.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(len(pkts)) + self.verify_capture_out(capture, same_port=True) + + users = self.vapi.nat44_user_dump() + self.assertEqual(len(users), 1) + static_user = users[0] + self.assertEqual(static_user.nstaticsessions, 3) + self.assertEqual(static_user.nsessions, 0) + + # in2out - no static mapping match + + host0 = self.pg0.remote_hosts[0] + self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1] + try: + pkts = self.create_stream_out(self.pg1, + dst_ip=self.pg0.remote_ip4, + use_inside_ports=True) + self.pg1.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg0.get_capture(len(pkts)) + self.verify_capture_in(capture, self.pg0) + + pkts = self.create_stream_in(self.pg0, self.pg1) + self.pg0.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(len(pkts)) + self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4, + same_port=True) + finally: + self.pg0.remote_hosts[0] = host0 + + users = self.vapi.nat44_user_dump() + self.assertEqual(len(users), 2) + if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4: + non_static_user = users[1] + static_user = users[0] + else: + non_static_user = users[0] + static_user = users[1] + self.assertEqual(static_user.nstaticsessions, 3) + self.assertEqual(static_user.nsessions, 0) + self.assertEqual(non_static_user.nstaticsessions, 0) + self.assertEqual(non_static_user.nsessions, 3) + + users = self.vapi.nat44_user_dump() + self.assertEqual(len(users), 2) + if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4: + non_static_user = users[1] + static_user = users[0] + else: + non_static_user = users[0] + static_user = users[1] + self.assertEqual(static_user.nstaticsessions, 3) + self.assertEqual(static_user.nsessions, 0) + self.assertEqual(non_static_user.nstaticsessions, 0) + self.assertEqual(non_static_user.nsessions, 3) + + finally: + self.vapi.nat44_forwarding_enable_disable(enable=0) + flags = self.config_flags.NAT_IS_ADDR_ONLY + self.vapi.nat44_add_del_static_mapping( + is_add=0, + local_ip_address=real_ip, + external_ip_address=alias_ip, + external_sw_if_index=0xFFFFFFFF, + flags=flags) + def tearDown(self): super(TestNAT44EndpointDependent, self).tearDown() if not self.vpp_dead: -- cgit 1.2.3-korg