From 9341e34b500ce7c68fc6857a24ee7b67cac121b1 Mon Sep 17 00:00:00 2001 From: Juraj Sloboda Date: Fri, 13 Apr 2018 12:00:46 +0200 Subject: NAT66: Do not translate if packet not aimed at outside interface Change-Id: Id5a2a90d81cc9cb87cb6fb89ac2f4ca3cbcb51e2 Signed-off-by: Juraj Sloboda --- src/plugins/nat/nat.c | 9 +++++++++ src/plugins/nat/nat66.h | 3 +++ src/plugins/nat/nat66_in2out.c | 43 ++++++++++++++++++++++++++++++++++++++++++ test/test_nat.py | 23 ++++++++++++++++++++++ 4 files changed, 78 insertions(+) diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index 96a69282077..764bc1db6bb 100755 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -2441,12 +2441,14 @@ static clib_error_t * snat_config (vlib_main_t * vm, unformat_input_t * input) { snat_main_t * sm = &snat_main; + nat66_main_t * nm = &nat66_main; u32 translation_buckets = 1024; u32 translation_memory_size = 128<<20; u32 user_buckets = 128; u32 user_memory_size = 64<<20; u32 max_translations_per_user = 100; u32 outside_vrf_id = 0; + u32 outside_ip6_vrf_id = 0; u32 inside_vrf_id = 0; u32 static_mapping_buckets = 1024; u32 static_mapping_memory_size = 64<<20; @@ -2479,6 +2481,9 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) else if (unformat (input, "outside VRF id %d", &outside_vrf_id)) ; + else if (unformat (input, "outside ip6 VRF id %d", + &outside_ip6_vrf_id)) + ; else if (unformat (input, "inside VRF id %d", &inside_vrf_id)) ; @@ -2522,6 +2527,10 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, outside_vrf_id, FIB_SOURCE_PLUGIN_HI); + nm->outside_vrf_id = outside_ip6_vrf_id; + nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, + outside_ip6_vrf_id, + FIB_SOURCE_PLUGIN_HI); sm->inside_vrf_id = inside_vrf_id; sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, inside_vrf_id, diff --git a/src/plugins/nat/nat66.h b/src/plugins/nat/nat66.h index ac5557fc491..52befd5c166 100644 --- a/src/plugins/nat/nat66.h +++ b/src/plugins/nat/nat66.h @@ -55,6 +55,9 @@ typedef struct clib_bihash_24_8_t sm_e; /** Session counters */ vlib_combined_counter_main_t session_counters; + + u32 outside_vrf_id; + u32 outside_fib_index; } nat66_main_t; extern nat66_main_t nat66_main; diff --git a/src/plugins/nat/nat66_in2out.c b/src/plugins/nat/nat66_in2out.c index 1ec4da78d63..d606bf46260 100644 --- a/src/plugins/nat/nat66_in2out.c +++ b/src/plugins/nat/nat66_in2out.c @@ -69,6 +69,46 @@ typedef enum NAT66_IN2OUT_N_NEXT, } nat66_in2out_next_t; +static inline u8 +nat66_not_translate (u32 rx_fib_index, ip6_address_t ip6_addr) +{ + nat66_main_t *nm = &nat66_main; + u32 sw_if_index; + snat_interface_t *i; + fib_node_index_t fei = FIB_NODE_INDEX_INVALID; + fib_prefix_t pfx = { + .fp_proto = FIB_PROTOCOL_IP6, + .fp_len = 128, + .fp_addr = { + .ip6 = ip6_addr, + }, + }; + + fei = fib_table_lookup (rx_fib_index, &pfx); + if (FIB_NODE_INDEX_INVALID == fei) + return 1; + sw_if_index = fib_entry_get_resolving_interface (fei); + + if (sw_if_index == ~0) + { + fei = fib_table_lookup (nm->outside_fib_index, &pfx); + if (FIB_NODE_INDEX_INVALID == fei) + return 1; + sw_if_index = fib_entry_get_resolving_interface (fei); + } + + /* *INDENT-OFF* */ + pool_foreach (i, nm->interfaces, + ({ + /* NAT packet aimed at outside interface */ + if (nat_interface_is_outside (i) && sw_if_index == i->sw_if_index) + return 0; + })); + /* *INDENT-ON* */ + + return 1; +} + static inline uword nat66_in2out_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) @@ -131,6 +171,9 @@ nat66_in2out_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index0); + if (nat66_not_translate (fib_index0, ip60->dst_address)) + goto trace0; + sm0 = nat66_static_mapping_get (&ip60->src_address, fib_index0, 1); if (PREDICT_FALSE (!sm0)) { diff --git a/test/test_nat.py b/test/test_nat.py index 4470a054bed..7c126199072 100644 --- a/test/test_nat.py +++ b/test/test_nat.py @@ -6436,6 +6436,29 @@ class TestNAT66(MethodHolder): self.assertEqual(len(sm), 1) self.assertEqual(sm[0].total_pkts, 8) + def test_check_no_translate(self): + """ NAT66 translate only when egress interface is outside interface """ + self.vapi.nat66_add_del_interface(self.pg0.sw_if_index) + self.vapi.nat66_add_del_interface(self.pg1.sw_if_index) + self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n, + self.nat_addr_n) + + # in2out + p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / + IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) / + UDP()) + self.pg0.add_stream([p]) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + capture = self.pg1.get_capture(1) + packet = capture[0] + try: + self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6) + self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6) + except: + self.logger.error(ppp("Unexpected or invalid packet:", packet)) + raise + def clear_nat66(self): """ Clear NAT66 configuration. -- cgit 1.2.3-korg