X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat.c;h=2ed65a13974f6ecd731f65b018e4762500ebb547;hb=039cbfe254be998f7311bc4638bb262b44efac19;hp=95004da26d838a19f29379fe4d33e41a27b2b894;hpb=5f22499e8836066a268dcb3f4d16cfcd0244b2a2;p=vpp.git diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index 95004da26d8..2ed65a13974 100644 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -38,79 +39,79 @@ snat_main_t snat_main; VNET_FEATURE_INIT (ip4_snat_in2out, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-in2out", - .runs_before = VNET_FEATURES ("nat44-out2in"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_out2in, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-out2in", - .runs_before = VNET_FEATURES ("ip4-lookup"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_nat_classify, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-classify", - .runs_before = VNET_FEATURES ("ip4-lookup"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-det-in2out", - .runs_before = VNET_FEATURES ("nat44-det-out2in"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-det-out2in", - .runs_before = VNET_FEATURES ("ip4-lookup"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_nat_det_classify, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-det-classify", - .runs_before = VNET_FEATURES ("ip4-lookup"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_in2out_worker_handoff, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-in2out-worker-handoff", - .runs_before = VNET_FEATURES ("nat44-out2in-worker-handoff"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_out2in_worker_handoff, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-out2in-worker-handoff", - .runs_before = VNET_FEATURES ("ip4-lookup"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-handoff-classify", - .runs_before = VNET_FEATURES ("ip4-lookup"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-in2out-fast", - .runs_before = VNET_FEATURES ("nat44-out2in-fast"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-out2in-fast", - .runs_before = VNET_FEATURES ("ip4-lookup"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-hairpin-dst", - .runs_before = VNET_FEATURES ("ip4-lookup"), + .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; /* Hook up output features */ VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = { .arc_name = "ip4-output", .node_name = "nat44-in2out-output", - .runs_before = VNET_FEATURES ("interface-output"), + .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = { .arc_name = "ip4-output", .node_name = "nat44-in2out-output-worker-handoff", - .runs_before = VNET_FEATURES ("interface-output"), + .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"), }; VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = { .arc_name = "ip4-output", .node_name = "nat44-hairpin-src", - .runs_before = VNET_FEATURES ("interface-output"), + .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"), }; /* Hook up ip4-local features */ @@ -674,6 +675,13 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, snat_interface_t *interface; int i; snat_main_per_thread_data_t *tsm; + snat_user_key_t u_key; + snat_user_t *u; + dlist_elt_t * head, * elt; + u32 elt_index, head_index; + u32 ses_index; + u64 user_index; + snat_session_t * s; /* If the external address is a specific interface address */ if (sw_if_index != ~0) @@ -767,7 +775,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, } } /* External address must be allocated */ - if (!a) + if (!a && (l_addr.as_u32 != e_addr.as_u32)) return VNET_API_ERROR_NO_SUCH_ENTRY; } @@ -831,6 +839,51 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, clib_warning ("out2in key add failed"); } + /* Delete dynamic sessions matching local address (+ local port) */ + if (!(sm->static_mapping_only)) + { + u_key.addr = m->local_addr; + u_key.fib_index = m->fib_index; + kv.key = u_key.as_u64; + if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value)) + { + user_index = value.value; + u = pool_elt_at_index (tsm->users, user_index); + if (u->nsessions) + { + head_index = u->sessions_per_user_list_head_index; + head = pool_elt_at_index (tsm->list_pool, head_index); + elt_index = head->next; + elt = pool_elt_at_index (tsm->list_pool, elt_index); + ses_index = elt->value; + while (ses_index != ~0) + { + s = pool_elt_at_index (tsm->sessions, ses_index); + elt = pool_elt_at_index (tsm->list_pool, elt->next); + ses_index = elt->value; + + if (snat_is_session_static (s)) + continue; + + if (!addr_only) + { + if ((s->out2in.addr.as_u32 != e_addr.as_u32) && + (clib_net_to_host_u16 (s->out2in.port) != e_port)) + continue; + } + + nat_free_session_data (sm, s, tsm - sm->per_thread_data); + clib_dlist_remove (tsm->list_pool, s->per_user_index); + pool_put_index (tsm->list_pool, s->per_user_index); + pool_put (tsm->sessions, s); + u->nsessions--; + + if (!addr_only) + break; + } + } + } + } } else { @@ -906,14 +959,6 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr, if (!(sm->static_mapping_only) || (sm->static_mapping_only && sm->static_mapping_connection_tracking)) { - snat_user_key_t u_key; - snat_user_t *u; - dlist_elt_t * head, * elt; - u32 elt_index, head_index; - u32 ses_index; - u64 user_index; - snat_session_t * s; - u_key.addr = m->local_addr; u_key.fib_index = m->fib_index; kv.key = u_key.as_u64; @@ -1383,6 +1428,12 @@ int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) if (sm->out2in_dpo && !is_inside) return VNET_API_ERROR_UNSUPPORTED; + pool_foreach (i, sm->output_feature_interfaces, + ({ + if (i->sw_if_index == sw_if_index) + return VNET_API_ERROR_VALUE_EXIST; + })); + if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking)) feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast"; else @@ -1534,6 +1585,12 @@ int snat_interface_add_del_output_feature (u32 sw_if_index, (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))) return VNET_API_ERROR_UNSUPPORTED; + pool_foreach (i, sm->interfaces, + ({ + if (i->sw_if_index == sw_if_index) + return VNET_API_ERROR_VALUE_EXIST; + })); + if (is_inside) { vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst", @@ -1735,6 +1792,8 @@ static clib_error_t * snat_init (vlib_main_t * vm) dslite_init(vm); + nat66_init(); + /* Init virtual fragmenentation reassembly */ return nat_reass_init(vm); } @@ -2560,16 +2619,14 @@ u8 * format_snat_static_map_to_resolve (u8 * s, va_list * args) if (m->addr_only) s = format (s, "local %U external %U vrf %d", format_ip4_address, &m->l_addr, - format_vnet_sw_interface_name, vnm, - vnet_get_sw_interface (vnm, m->sw_if_index), + format_vnet_sw_if_index_name, vnm, m->sw_if_index, m->vrf_id); else s = format (s, "%U local %U:%d external %U:%d vrf %d", format_snat_protocol, m->proto, format_ip4_address, &m->l_addr, m->l_port, - format_vnet_sw_interface_name, vnm, - vnet_get_sw_interface (vnm, m->sw_if_index), m->e_port, - m->vrf_id); + format_vnet_sw_if_index_name, vnm, m->sw_if_index, + m->e_port, m->vrf_id); return s; }