X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat.c;h=bedf4e5d386a9438a85462e0c1847bbe9d6ce3fd;hb=2aa22909c70ff5c5eed6a7f7a0f8a587c9260da8;hp=e9b2c2c07ba77200cac4e751d7cf131be47ee8f1;hpb=529a425b04751d0590de2f398a20bd36d0e25308;p=vpp.git diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index e9b2c2c07ba..bedf4e5d386 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); @@ -642,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; @@ -722,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++) { @@ -765,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; @@ -789,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; @@ -805,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; @@ -821,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++) { @@ -860,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; @@ -875,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; @@ -951,7 +956,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 +964,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); @@ -972,7 +977,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, snat_protocol_t proto, u32 vrf_id, nat44_lb_addr_port_t *locals, u8 is_add, - u8 twice_nat) + u8 twice_nat, u8 out2in_only) { snat_main_t * sm = &snat_main; snat_static_mapping_t *m; @@ -1013,7 +1018,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, /* Find external address in allocated addresses and reserve port for address and port pair mapping when dynamic translations enabled */ - if (!sm->static_mapping_only) + if (!(sm->static_mapping_only || out2in_only)) { for (i = 0; i < vec_len (sm->addresses); i++) { @@ -1057,6 +1062,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, m->external_port = e_port; m->proto = proto; m->twice_nat = twice_nat; + m->out2in_only = out2in_only; m_key.addr = m->external_addr; m_key.port = m->external_port; @@ -1094,10 +1100,13 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, for (i = 0; i < vec_len (locals); i++) { m_key.addr = locals[i].addr; - m_key.port = locals[i].port; - 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 (!out2in_only) + { + m_key.port = locals[i].port; + 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); + } locals[i].prefix = (i == 0) ? locals[i].probability :\ (locals[i - 1].prefix + locals[i].probability); vec_add1 (m->locals, locals[i]); @@ -1120,7 +1129,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, fib_table_unlock (m->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_HI); /* Free external address port */ - if (!sm->static_mapping_only) + if (!(sm->static_mapping_only || out2in_only)) { for (i = 0; i < vec_len (sm->addresses); i++) { @@ -1172,13 +1181,16 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, vec_foreach (local, m->locals) { m_key.addr = local->addr; - m_key.port = local->port; - m_key.fib_index = m->fib_index; - kv.key = m_key.as_u64; - if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0)) + if (!out2in_only) { - clib_warning ("static_mapping_by_local key del failed"); - return VNET_API_ERROR_UNSPECIFIED; + m_key.port = local->port; + m_key.fib_index = m->fib_index; + kv.key = m_key.as_u64; + if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0)) + { + clib_warning ("static_mapping_by_local key del failed"); + return VNET_API_ERROR_UNSPECIFIED; + } } m_key.port = clib_host_to_net_u16 (local->port); @@ -1265,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 @@ -1324,7 +1337,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 +1345,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 +1364,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 @@ -1383,11 +1399,22 @@ int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE; if (sm->num_workers > 1 && !sm->deterministic) - del_feature_name = "nat44-handoff-classify"; + { + del_feature_name = "nat44-handoff-classify"; + feature_name = !is_inside ? "nat44-in2out-worker-handoff" : + "nat44-out2in-worker-handoff"; + } else if (sm->deterministic) - del_feature_name = "nat44-det-classify"; + { + del_feature_name = "nat44-det-classify"; + feature_name = !is_inside ? "nat44-det-in2out" : + "nat44-det-out2in"; + } else - del_feature_name = "nat44-classify"; + { + del_feature_name = "nat44-classify"; + feature_name = !is_inside ? "nat44-in2out" : "nat44-out2in"; + } vnet_feature_enable_disable ("ip4-unicast", del_feature_name, sw_if_index, 0, 0, 0); @@ -1452,7 +1479,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); @@ -1582,7 +1609,7 @@ int snat_set_workers (uword * bitmap) clib_bitmap_foreach (i, bitmap, ({ vec_add1(sm->workers, i); - sm->per_thread_data[i].snat_thread_index = j; + sm->per_thread_data[sm->first_worker_index + i].snat_thread_index = j; j++; })); @@ -1680,6 +1707,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 +2017,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 +2126,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); } @@ -2260,6 +2315,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)) @@ -2292,6 +2348,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 @@ -2316,7 +2374,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) { @@ -2364,7 +2422,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 * @@ -2413,7 +2471,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) { @@ -2477,6 +2535,7 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm, u8 proto_set = 0; nat44_lb_addr_port_t *locals = 0, local; u8 twice_nat = 0; + u8 out2in_only = 0; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -2503,6 +2562,8 @@ add_lb_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 @@ -2526,7 +2587,7 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm, } rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, vrf_id, - locals, is_add, twice_nat); + locals, is_add, twice_nat, out2in_only); switch (rv) { @@ -2559,7 +2620,7 @@ VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = { .short_help = "nat44 add load-balancing static mapping protocol tcp|udp " "external : local : probability [twice-nat] " - "[vrf ] [del]", + "[vrf ] [out2in-only] [del]", }; static clib_error_t * @@ -2726,6 +2787,7 @@ snat_get_worker_out2in_cb (ip4_header_t * ip0, u32 rx_fib_index0) snat_session_t *s; int i; u32 proto; + u32 next_worker_index = 0; /* first try static mappings without port */ if (PREDICT_FALSE (pool_elts (sm->static_mappings))) @@ -2841,7 +2903,10 @@ snat_get_worker_out2in_cb (ip4_header_t * ip0, u32 rx_fib_index0) } /* worker by outside port */ - return (u32) ((clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread); + next_worker_index = sm->first_worker_index; + next_worker_index += + sm->workers[(clib_net_to_host_u16 (port) - 1024) / sm->port_per_thread]; + return next_worker_index; } static clib_error_t * @@ -2864,8 +2929,10 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) u8 static_mapping_only = 0; u8 static_mapping_connection_tracking = 0; snat_main_per_thread_data_t *tsm; + dslite_main_t * dm = &dslite_main; sm->deterministic = 0; + sm->out2in_dpo = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -2906,6 +2973,10 @@ 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 if (unformat (input, "dslite ce")) + dslite_set_ce(dm, 1); else return clib_error_return (0, "unknown input '%U'", format_unformat_error, input); @@ -3123,22 +3194,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; } @@ -3510,7 +3583,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);