From e82488f10f20f464961c5c7b381b4a419bca0bbc Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Thu, 18 Jan 2018 03:38:45 -0800 Subject: NAT44: asymmetrical static mapping rule (VPP-1135) add option to NAT44 static mapping API/CLI to make rule asymmetrical (rule match only out2in direction) Change-Id: If262a3ff375a24d3059f0de1f1ac387a4fe09475 Signed-off-by: Matus Fabian --- src/plugins/nat/nat.api | 6 +++++- src/plugins/nat/nat.c | 46 ++++++++++++++++++++++++++++------------------ src/plugins/nat/nat.h | 2 +- src/plugins/nat/nat_api.c | 10 ++++++---- 4 files changed, 40 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/plugins/nat/nat.api b/src/plugins/nat/nat.api index 78f34509b69..1de70edaaad 100644 --- a/src/plugins/nat/nat.api +++ b/src/plugins/nat/nat.api @@ -13,7 +13,7 @@ * limitations under the License. */ -vl_api_version 2.2.0 +vl_api_version 2.3.0 /** * @file nat.api @@ -352,6 +352,7 @@ define nat44_interface_output_feature_details { @param vfr_id - VRF ID @param twice_nat - if 1 translate external host address and port, only for 1:1 NAPT (addr_only must be 0) + @param out2in_only - if 1 rule match only out2in direction */ autoreply define nat44_add_del_static_mapping { u32 client_index; @@ -366,6 +367,7 @@ autoreply define nat44_add_del_static_mapping { u32 external_sw_if_index; u32 vrf_id; u8 twice_nat; + u8 out2in_only; }; /** \brief Dump NAT44 static mappings @@ -388,6 +390,7 @@ define nat44_static_mapping_dump { @param external_sw_if_index - external interface @param vfr_id - VRF ID @param twice_nat - if 1 translate external host address and port + @param out2in_only - if 1 rule match only out2in direction */ define nat44_static_mapping_details { u32 context; @@ -400,6 +403,7 @@ define nat44_static_mapping_details { u32 external_sw_if_index; u32 vrf_id; u8 twice_nat; + u8 out2in_only; }; /** \brief Add/delete NAT44 identity mapping diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index 99c5f63cf12..6ed4877eafa 100644 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -643,13 +643,14 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm, * @param sw_if_index External port instead of specific IP address. * @param is_add If 0 delete static mapping, otherwise add. * @param twice_nat If 1 translate external host address and port. + * @param out2in_only If 1 rule match only out2in direction * * @returns */ 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, - u8 twice_nat) + u8 twice_nat, u8 out2in_only) { snat_main_t * sm = &snat_main; snat_static_mapping_t *m; @@ -723,7 +724,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, /* Find external address in allocated addresses and reserve port for address and port pair mapping when dynamic translations enabled */ - if (!addr_only && !(sm->static_mapping_only)) + if (!(addr_only || sm->static_mapping_only || out2in_only)) { for (i = 0; i < vec_len (sm->addresses); i++) { @@ -766,6 +767,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, m->vrf_id = vrf_id; m->fib_index = fib_index; m->twice_nat = twice_nat; + m->out2in_only = out2in_only; if (!addr_only) { m->local_port = l_port; @@ -790,8 +792,9 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, m_key.fib_index = m->fib_index; kv.key = m_key.as_u64; kv.value = m - sm->static_mappings; - clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1); - if (twice_nat) + if (!out2in_only) + clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1); + if (twice_nat || out2in_only) { m_key.port = clib_host_to_net_u16 (l_port); kv.key = m_key.as_u64; @@ -806,7 +809,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, kv.key = m_key.as_u64; kv.value = m - sm->static_mappings; clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1); - if (twice_nat) + if (twice_nat || out2in_only) { m_key.port = clib_host_to_net_u16 (e_port); kv.key = m_key.as_u64; @@ -822,7 +825,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, return VNET_API_ERROR_NO_SUCH_ENTRY; /* Free external address port */ - if (!addr_only && !(sm->static_mapping_only)) + if (!(addr_only || sm->static_mapping_only || out2in_only)) { for (i = 0; i < vec_len (sm->addresses); i++) { @@ -861,8 +864,9 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, m_key.protocol = m->proto; m_key.fib_index = m->fib_index; kv.key = m_key.as_u64; - clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0); - if (twice_nat) + if (!out2in_only) + clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0); + if (twice_nat || out2in_only) { m_key.port = clib_host_to_net_u16 (m->local_port); kv.key = m_key.as_u64; @@ -876,7 +880,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, m_key.fib_index = sm->outside_fib_index; kv.key = m_key.as_u64; clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0); - if (twice_nat) + if (twice_nat || out2in_only) { m_key.port = clib_host_to_net_u16 (m->external_port); kv.key = m_key.as_u64; @@ -1273,7 +1277,8 @@ snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm, (void) snat_add_static_mapping (m->local_addr, m->external_addr, m->local_port, m->external_port, m->vrf_id, m->addr_only, ~0, - m->proto, 0, m->twice_nat); + m->proto, 0, m->twice_nat, + m->out2in_only); })); } else @@ -2299,6 +2304,7 @@ add_static_mapping_command_fn (vlib_main_t * vm, snat_protocol_t proto = ~0; u8 proto_set = 0; u8 twice_nat = 0; + u8 out2in_only = 0; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -2331,6 +2337,8 @@ add_static_mapping_command_fn (vlib_main_t * vm, proto_set = 1; else if (unformat (line_input, "twice-nat")) twice_nat = 1; + else if (unformat (line_input, "out2in-only")) + out2in_only = 1; else if (unformat (line_input, "del")) is_add = 0; else @@ -2355,7 +2363,7 @@ add_static_mapping_command_fn (vlib_main_t * vm, rv = snat_add_static_mapping(l_addr, e_addr, (u16) l_port, (u16) e_port, vrf_id, addr_only, sw_if_index, proto, is_add, - twice_nat); + twice_nat, out2in_only); switch (rv) { @@ -2403,7 +2411,7 @@ VLIB_CLI_COMMAND (add_static_mapping_command, static) = { .function = add_static_mapping_command_fn, .short_help = "nat44 add static mapping tcp|udp|icmp local [] " - "external [] [vrf ] [twice-nat] [del]", + "external [] [vrf ] [twice-nat] [out2in-only] [del]", }; static clib_error_t * @@ -2452,7 +2460,7 @@ add_identity_mapping_command_fn (vlib_main_t * vm, rv = snat_add_static_mapping(addr, addr, (u16) port, (u16) port, vrf_id, addr_only, sw_if_index, proto, is_add, - 0); + 0, 0); switch (rv) { @@ -3175,22 +3183,24 @@ u8 * format_snat_static_mapping (u8 * s, va_list * args) { if (vec_len (m->locals)) { - s = format (s, "%U vrf %d external %U:%d %s", + s = format (s, "%U vrf %d external %U:%d %s %s", format_snat_protocol, m->proto, m->vrf_id, format_ip4_address, &m->external_addr, m->external_port, - m->twice_nat ? "twice-nat" : ""); + m->twice_nat ? "twice-nat" : "", + m->out2in_only ? "out2in-only" : ""); vec_foreach (local, m->locals) s = format (s, "\n local %U:%d probability %d\%", format_ip4_address, &local->addr, local->port, local->probability); } else - s = format (s, "%U local %U:%d external %U:%d vrf %d %s", + s = format (s, "%U local %U:%d external %U:%d vrf %d %s %s", format_snat_protocol, m->proto, format_ip4_address, &m->local_addr, m->local_port, format_ip4_address, &m->external_addr, m->external_port, - m->vrf_id, m->twice_nat ? "twice-nat" : ""); + m->vrf_id, m->twice_nat ? "twice-nat" : "", + m->out2in_only ? "out2in-only" : ""); } return s; } @@ -3562,7 +3572,7 @@ match: ~0 /* sw_if_index */, rp->proto, rp->is_add, - 0); + 0, 0); if (rv) clib_warning ("snat_add_static_mapping returned %d", rv); diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index ff7888a9128..eba005128de 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -545,7 +545,7 @@ 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, - u8 twice_nat); + u8 twice_nat, u8 out2in_only); clib_error_t * snat_api_init(vlib_main_t * vm, snat_main_t * sm); int snat_set_workers (uword * bitmap); int snat_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del); diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index f3d353fa20e..f23efa8d89f 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -711,7 +711,7 @@ static void rv = snat_add_static_mapping (local_addr, external_addr, local_port, external_port, vrf_id, mp->addr_only, external_sw_if_index, proto, mp->is_add, - mp->twice_nat); + mp->twice_nat, mp->out2in_only); REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY); } @@ -732,7 +732,8 @@ static void *vl_api_nat44_add_del_static_mapping_t_print clib_net_to_host_u16 (mp->local_port), clib_net_to_host_u16 (mp->external_port)); - s = format (s, "twice_nat %d ", mp->twice_nat); + s = format (s, "twice_nat %d out2in_only %d ", + mp->twice_nat, mp->out2in_only); if (mp->vrf_id != ~0) s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id)); @@ -764,6 +765,7 @@ send_nat44_static_mapping_details (snat_static_mapping_t * m, rmp->protocol = snat_proto_to_ip_proto (m->proto); rmp->context = context; rmp->twice_nat = m->twice_nat; + rmp->out2in_only = m->out2in_only; vl_api_send_msg (reg, (u8 *) rmp); } @@ -861,7 +863,7 @@ static void rv = snat_add_static_mapping (addr, addr, port, port, vrf_id, mp->addr_only, - sw_if_index, proto, mp->is_add, 0); + sw_if_index, proto, mp->is_add, 0, 0); REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY); } @@ -1259,7 +1261,7 @@ static void *vl_api_nat44_add_del_lb_static_mapping_t_print u8 *s; s = format (0, "SCRIPT: nat44_add_del_lb_static_mapping "); - s = format (s, "is_add %d twice_nat %d out2in_only ", + s = format (s, "is_add %d twice_nat %d out2in_only %d ", mp->is_add, mp->twice_nat, mp->out2in_only); FINISH; -- cgit 1.2.3-korg