From cba6936c45bc3265ae695e8266bdefc65e7a5116 Mon Sep 17 00:00:00 2001 From: Juraj Sloboda Date: Tue, 19 Dec 2017 02:09:32 +0100 Subject: Add support for 464XLAT NAT44 mode (VPP-1045) Change-Id: I24e7a26972bbbfcea100292b212b29ae7a349335 Signed-off-by: Juraj Sloboda --- src/plugins/nat.am | 1 + src/plugins/nat/in2out.c | 3 ++ src/plugins/nat/nat.c | 49 ++++++++++++++++++++++++----- src/plugins/nat/nat.h | 2 ++ src/plugins/nat/nat_api.c | 3 ++ src/plugins/nat/nat_dpo.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++ src/plugins/nat/nat_dpo.h | 36 +++++++++++++++++++++ 7 files changed, 166 insertions(+), 7 deletions(-) create mode 100644 src/plugins/nat/nat_dpo.c create mode 100644 src/plugins/nat/nat_dpo.h (limited to 'src') diff --git a/src/plugins/nat.am b/src/plugins/nat.am index b6c369fe324..a0e0568a5a1 100644 --- a/src/plugins/nat.am +++ b/src/plugins/nat.am @@ -23,6 +23,7 @@ nat_plugin_la_SOURCES = nat/nat.c \ nat/nat_ipfix_logging.c \ nat/nat_det.c \ nat/nat_reass.c \ + nat/nat_dpo.c \ nat/nat64.c \ nat/nat64_cli.c \ nat/nat64_in2out.c \ diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c index 517011eec06..b0dbbc8fa11 100755 --- a/src/plugins/nat/in2out.c +++ b/src/plugins/nat/in2out.c @@ -179,6 +179,9 @@ snat_not_translate_fast (snat_main_t * sm, vlib_node_runtime_t *node, u32 sw_if_index0, ip4_header_t * ip0, u32 proto0, u32 rx_fib_index0) { + if (sm->out2in_dpo) + return 0; + fib_node_index_t fei = FIB_NODE_INDEX_INVALID; fib_prefix_t pfx = { .fp_proto = FIB_PROTOCOL_IP4, diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index e9b2c2c07ba..721ad16d3dc 100644 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -567,7 +568,7 @@ void snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id, /* Add external address to FIB */ pool_foreach (i, sm->interfaces, ({ - if (nat_interface_is_inside(i)) + if (nat_interface_is_inside(i) || sm->out2in_dpo) continue; snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1); @@ -575,7 +576,7 @@ void snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id, })); pool_foreach (i, sm->output_feature_interfaces, ({ - if (nat_interface_is_inside(i)) + if (nat_interface_is_inside(i) || sm->out2in_dpo) continue; snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1); @@ -951,7 +952,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, /* Add/delete external address to FIB */ pool_foreach (interface, sm->interfaces, ({ - if (nat_interface_is_inside(interface)) + if (nat_interface_is_inside(interface) || sm->out2in_dpo) continue; snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add); @@ -959,7 +960,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, })); pool_foreach (interface, sm->output_feature_interfaces, ({ - if (nat_interface_is_inside(interface)) + if (nat_interface_is_inside(interface) || sm->out2in_dpo) continue; snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add); @@ -1324,7 +1325,7 @@ snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm, /* Delete external address from FIB */ pool_foreach (interface, sm->interfaces, ({ - if (nat_interface_is_inside(interface)) + if (nat_interface_is_inside(interface) || sm->out2in_dpo) continue; snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0); @@ -1332,7 +1333,7 @@ snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm, })); pool_foreach (interface, sm->output_feature_interfaces, ({ - if (nat_interface_is_inside(interface)) + if (nat_interface_is_inside(interface) || sm->out2in_dpo) continue; snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0); @@ -1351,6 +1352,9 @@ int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) snat_static_mapping_t * m; snat_det_map_t * dm; + if (sm->out2in_dpo && !is_inside) + return VNET_API_ERROR_UNSUPPORTED; + if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking)) feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast"; else @@ -1452,7 +1456,7 @@ set_flags: /* Add/delete external addresses to FIB */ fib: - if (is_inside) + if (is_inside && !sm->out2in_dpo) { vnet_feature_enable_disable ("ip4-local", "nat44-hairpinning", sw_if_index, !is_del, 0, 0); @@ -1680,6 +1684,8 @@ static clib_error_t * snat_init (vlib_main_t * vm) vec_add1 (im->add_del_interface_address_callbacks, cb4); + nat_dpo_module_init (); + /* Init IPFIX logging */ snat_ipfix_logging_init(vm); @@ -1988,6 +1994,29 @@ exhausted: return 1; } +void +nat44_add_del_address_dpo (ip4_address_t addr, u8 is_add) +{ + dpo_id_t dpo_v4 = DPO_INVALID; + fib_prefix_t pfx = { + .fp_proto = FIB_PROTOCOL_IP4, + .fp_len = 32, + .fp_addr.ip4.as_u32 = addr.as_u32, + }; + + if (is_add) + { + nat_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4); + fib_table_entry_special_dpo_add (0, &pfx, FIB_SOURCE_PLUGIN_HI, + FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4); + dpo_reset (&dpo_v4); + } + else + { + fib_table_entry_special_remove (0, &pfx, FIB_SOURCE_PLUGIN_HI); + } +} + static clib_error_t * add_address_command_fn (vlib_main_t * vm, unformat_input_t * input, @@ -2074,6 +2103,9 @@ add_address_command_fn (vlib_main_t * vm, break; } + if (sm->out2in_dpo) + nat44_add_del_address_dpo (this_addr, is_add); + increment_v4_address (&this_addr); } @@ -2866,6 +2898,7 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) snat_main_per_thread_data_t *tsm; sm->deterministic = 0; + sm->out2in_dpo = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -2906,6 +2939,8 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) else if (unformat (input, "nat64 st hash memory %d", &nat64_st_memory_size)) ; + else if (unformat (input, "out2in dpo")) + sm->out2in_dpo = 1; else return clib_error_return (0, "unknown input '%U'", format_unformat_error, input); diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index 1e8e3ca0403..614668d8421 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -357,6 +357,7 @@ typedef struct snat_main_s { u8 static_mapping_only; u8 static_mapping_connection_tracking; u8 deterministic; + u8 out2in_dpo; u32 translation_buckets; u32 translation_memory_size; u32 max_translations; @@ -539,6 +540,7 @@ void snat_add_address(snat_main_t *sm, ip4_address_t *addr, u32 vrf_id, u8 twice_nat); int snat_del_address(snat_main_t *sm, ip4_address_t addr, u8 delete_sm, u8 twice_nat); +void nat44_add_del_address_dpo (ip4_address_t addr, u8 is_add); int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, u32 vrf_id, int addr_only, u32 sw_if_index, snat_protocol_t proto, int is_add, diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index 2397663270a..d0efb001843 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -442,6 +442,9 @@ static void if (rv) goto send_reply; + if (sm->out2in_dpo) + nat44_add_del_address_dpo (this_addr, mp->is_add); + increment_v4_address (&this_addr); } diff --git a/src/plugins/nat/nat_dpo.c b/src/plugins/nat/nat_dpo.c new file mode 100644 index 00000000000..46ccda8845e --- /dev/null +++ b/src/plugins/nat/nat_dpo.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +dpo_type_t nat_dpo_type; + +void +nat_dpo_create (dpo_proto_t dproto, u32 aftr_index, dpo_id_t * dpo) +{ + dpo_set (dpo, nat_dpo_type, dproto, aftr_index); +} + +u8 * +format_nat_dpo (u8 * s, va_list * args) +{ + index_t index = va_arg (*args, index_t); + CLIB_UNUSED (u32 indent) = va_arg (*args, u32); + + return (format (s, "NAT44 out2in: AFTR:%d", index)); +} + +static void +nat_dpo_lock (dpo_id_t * dpo) +{ +} + +static void +nat_dpo_unlock (dpo_id_t * dpo) +{ +} + +const static dpo_vft_t nat_dpo_vft = { + .dv_lock = nat_dpo_lock, + .dv_unlock = nat_dpo_unlock, + .dv_format = format_nat_dpo, +}; + +const static char *const nat_ip4_nodes[] = { + "nat44-out2in", + NULL, +}; + +const static char *const nat_ip6_nodes[] = { + NULL, +}; + +const static char *const *const nat_nodes[DPO_PROTO_NUM] = { + [DPO_PROTO_IP4] = nat_ip4_nodes, + [DPO_PROTO_IP6] = nat_ip6_nodes, + [DPO_PROTO_MPLS] = NULL, +}; + +void +nat_dpo_module_init (void) +{ + nat_dpo_type = dpo_register_new_type (&nat_dpo_vft, nat_nodes); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/nat/nat_dpo.h b/src/plugins/nat/nat_dpo.h new file mode 100644 index 00000000000..e85b3e824f3 --- /dev/null +++ b/src/plugins/nat/nat_dpo.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __included_nat_dpo_h__ +#define __included_nat_dpo_h__ + +#include +#include + +void nat_dpo_create (dpo_proto_t dproto, u32 aftr_index, dpo_id_t * dpo); + +u8 *format_nat_dpo (u8 * s, va_list * args); + +void nat_dpo_module_init (void); + +#endif /* __included_nat_dpo_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg