From 63e15818bbf05e5bb5ecde5af0e9eec7b1084fec Mon Sep 17 00:00:00 2001 From: Filip Varga Date: Tue, 29 Jun 2021 14:28:21 +0200 Subject: [PATCH] nat: refactoring NAT44ED cfg functions Refactored & fixed NAT44ED configuration functions used for handling interfaces and nodes. Type: refactor Signed-off-by: Filip Varga Change-Id: I6fbbb7f0fe35d572675997745d53290152987424 --- src/plugins/nat/nat44-ed/nat44_ed.c | 733 +++++++++++++++++++------------- src/plugins/nat/nat44-ed/nat44_ed.h | 26 +- src/plugins/nat/nat44-ed/nat44_ed_api.c | 40 +- src/plugins/nat/nat44-ed/nat44_ed_cli.c | 45 +- test/test_nat44_ed.py | 13 +- 5 files changed, 502 insertions(+), 355 deletions(-) diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index 1a996cd16f7..41028d50a90 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.c +++ b/src/plugins/nat/nat44-ed/nat44_ed.c @@ -1393,17 +1393,46 @@ update_per_vrf_sessions_vec (u32 fib_index, int is_del) } } +static_always_inline nat_outside_fib_t * +nat44_ed_get_outside_fib (nat_outside_fib_t *outside_fibs, u32 fib_index) +{ + nat_outside_fib_t *f; + vec_foreach (f, outside_fibs) + { + if (f->fib_index == fib_index) + { + return f; + } + } + return 0; +} + +static_always_inline snat_interface_t * +nat44_ed_get_interface (snat_interface_t *interfaces, u32 sw_if_index) +{ + snat_interface_t *i; + pool_foreach (i, interfaces) + { + if (i->sw_if_index == sw_if_index) + { + return i; + } + } + return 0; +} + int -snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) +nat44_ed_add_interface (u32 sw_if_index, u8 is_inside) { + const char *del_feature_name, *feature_name; snat_main_t *sm = &snat_main; + + nat_outside_fib_t *outside_fib; + snat_static_mapping_t *m; snat_interface_t *i; - const char *feature_name, *del_feature_name; snat_address_t *ap; - snat_static_mapping_t *m; - nat_outside_fib_t *outside_fib; - u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, - sw_if_index); + u32 fib_index; + int rv; if (!sm->enabled) { @@ -1411,197 +1440,238 @@ snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) return VNET_API_ERROR_UNSUPPORTED; } - pool_foreach (i, sm->output_feature_interfaces) - { - if (i->sw_if_index == sw_if_index) - { - nat_log_err ("error interface already configured"); - return VNET_API_ERROR_VALUE_EXIST; - } - } + if (nat44_ed_get_interface (sm->output_feature_interfaces, sw_if_index)) + { + nat_log_err ("error interface already configured"); + 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 + i = nat44_ed_get_interface (sm->interfaces, sw_if_index); + if (i) { + if ((nat_interface_is_inside (i) && is_inside) || + (nat_interface_is_outside (i) && !is_inside)) + { + return 0; + } if (sm->num_workers > 1) - feature_name = - is_inside ? "nat44-in2out-worker-handoff" : - "nat44-out2in-worker-handoff"; + { + del_feature_name = !is_inside ? "nat44-in2out-worker-handoff" : + "nat44-out2in-worker-handoff"; + feature_name = "nat44-handoff-classify"; + } else - feature_name = is_inside ? "nat-pre-in2out" : "nat-pre-out2in"; + { + del_feature_name = !is_inside ? "nat-pre-in2out" : "nat-pre-out2in"; + + feature_name = "nat44-ed-classify"; + } + + rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1); + if (rv) + return rv; + vnet_feature_enable_disable ("ip4-unicast", del_feature_name, + sw_if_index, 0, 0, 0); + vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, + 0, 0); } + else + { + if (sm->num_workers > 1) + { + feature_name = is_inside ? "nat44-in2out-worker-handoff" : + "nat44-out2in-worker-handoff"; + } + else + { + feature_name = is_inside ? "nat-pre-in2out" : "nat-pre-out2in"; + } - ASSERT (sm->frame_queue_nelts > 0); + nat_validate_interface_counters (sm, sw_if_index); + rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1); + if (rv) + return rv; + vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, + 0, 0); - if (sm->fq_in2out_index == ~0 && sm->num_workers > 1) - sm->fq_in2out_index = vlib_frame_queue_main_init (sm->in2out_node_index, - sm->frame_queue_nelts); + pool_get (sm->interfaces, i); + i->sw_if_index = sw_if_index; + i->flags = 0; + } - if (sm->fq_out2in_index == ~0 && sm->num_workers > 1) - sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index, - sm->frame_queue_nelts); + fib_index = + fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); - update_per_vrf_sessions_vec (fib_index, is_del); + update_per_vrf_sessions_vec (fib_index, 0 /*is_del*/); if (!is_inside) { - vec_foreach (outside_fib, sm->outside_fibs) - { - if (outside_fib->fib_index == fib_index) - { - if (is_del) - { - outside_fib->refcount--; - if (!outside_fib->refcount) - vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); - } - else - outside_fib->refcount++; - goto feature_set; - } - } - if (!is_del) + i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE; + + outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index); + if (outside_fib) + { + outside_fib->refcount++; + } + else { vec_add2 (sm->outside_fibs, outside_fib, 1); - outside_fib->refcount = 1; outside_fib->fib_index = fib_index; + outside_fib->refcount = 1; } - } -feature_set: - pool_foreach (i, sm->interfaces) - { - if (i->sw_if_index == sw_if_index) - { - if (is_del) - { - if (nat_interface_is_inside(i) && nat_interface_is_outside(i)) - { - if (is_inside) - i->flags &= ~NAT_INTERFACE_FLAG_IS_INSIDE; - else - i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE; - - if (sm->num_workers > 1) - { - del_feature_name = "nat44-handoff-classify"; - feature_name = !is_inside ? "nat44-in2out-worker-handoff" : - "nat44-out2in-worker-handoff"; - } - else - { - del_feature_name = "nat44-ed-classify"; - feature_name = - !is_inside ? "nat-pre-in2out" : "nat-pre-out2in"; - } - - int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0); - if (rv) - return rv; - vnet_feature_enable_disable ("ip4-unicast", del_feature_name, - sw_if_index, 0, 0, 0); - vnet_feature_enable_disable ("ip4-unicast", feature_name, - sw_if_index, 1, 0, 0); - } - else - { - int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0); - if (rv) - return rv; - vnet_feature_enable_disable ("ip4-unicast", feature_name, - sw_if_index, 0, 0, 0); - pool_put (sm->interfaces, i); - } - } - else - { - if ((nat_interface_is_inside (i) && is_inside) || - (nat_interface_is_outside (i) && !is_inside)) - return 0; + vec_foreach (ap, sm->addresses) + { + snat_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, 1); + } + pool_foreach (m, sm->static_mappings) + { + if (!(is_addr_only_static_mapping (m)) || + (m->local_addr.as_u32 == m->external_addr.as_u32)) + { + continue; + } + snat_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index, 1); + } + } + else + { + i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE; + } - if (sm->num_workers > 1) - { - del_feature_name = !is_inside ? "nat44-in2out-worker-handoff" : - "nat44-out2in-worker-handoff"; - feature_name = "nat44-handoff-classify"; - } - else - { - del_feature_name = - !is_inside ? "nat-pre-in2out" : "nat-pre-out2in"; + return 0; +} - feature_name = "nat44-ed-classify"; - } +int +nat44_ed_del_interface (u32 sw_if_index, u8 is_inside) +{ + const char *del_feature_name, *feature_name; + snat_main_t *sm = &snat_main; - int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1); - if (rv) - return rv; - vnet_feature_enable_disable ("ip4-unicast", del_feature_name, - sw_if_index, 0, 0, 0); - vnet_feature_enable_disable ("ip4-unicast", feature_name, - sw_if_index, 1, 0, 0); - goto set_flags; - } + nat_outside_fib_t *outside_fib; + snat_static_mapping_t *m; + snat_interface_t *i; + snat_address_t *ap; + u32 fib_index; + int rv; - goto fib; - } - } + if (!sm->enabled) + { + nat_log_err ("nat44 is disabled"); + return VNET_API_ERROR_UNSUPPORTED; + } - if (is_del) + i = nat44_ed_get_interface (sm->interfaces, sw_if_index); + if (i == 0) { nat_log_err ("error interface couldn't be found"); return VNET_API_ERROR_NO_SUCH_ENTRY; } - pool_get (sm->interfaces, i); - i->sw_if_index = sw_if_index; - i->flags = 0; - nat_validate_interface_counters (sm, sw_if_index); - - vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, 0, - 0); + if (nat_interface_is_inside (i) && nat_interface_is_outside (i)) + { + if (sm->num_workers > 1) + { + del_feature_name = "nat44-handoff-classify"; + feature_name = !is_inside ? "nat44-in2out-worker-handoff" : + "nat44-out2in-worker-handoff"; + } + else + { + del_feature_name = "nat44-ed-classify"; + feature_name = !is_inside ? "nat-pre-in2out" : "nat-pre-out2in"; + } - int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1); - if (rv) - return rv; + rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0); + if (rv) + { + return rv; + } + vnet_feature_enable_disable ("ip4-unicast", del_feature_name, + sw_if_index, 0, 0, 0); + vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 1, + 0, 0); -set_flags: - if (is_inside) - { - i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE; - return 0; + if (is_inside) + { + i->flags &= ~NAT_INTERFACE_FLAG_IS_INSIDE; + } + else + { + i->flags &= ~NAT_INTERFACE_FLAG_IS_OUTSIDE; + } } else - i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE; + { + if (sm->num_workers > 1) + { + feature_name = is_inside ? "nat44-in2out-worker-handoff" : + "nat44-out2in-worker-handoff"; + } + else + { + feature_name = is_inside ? "nat-pre-in2out" : "nat-pre-out2in"; + } - /* Add/delete external addresses to FIB */ -fib: - vec_foreach (ap, sm->addresses) - snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del); + rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0); + if (rv) + { + return rv; + } + vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, 0, + 0, 0); - pool_foreach (m, sm->static_mappings) - { - if (!(is_addr_only_static_mapping(m)) || (m->local_addr.as_u32 == m->external_addr.as_u32)) - continue; + // remove interface + pool_put (sm->interfaces, i); + } - snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del); - } + fib_index = + fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); + + update_per_vrf_sessions_vec (fib_index, 1 /*is_del*/); + + if (!is_inside) + { + outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index); + if (outside_fib) + { + outside_fib->refcount--; + if (!outside_fib->refcount) + { + vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); + } + } + + vec_foreach (ap, sm->addresses) + { + snat_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, 0); + } + + pool_foreach (m, sm->static_mappings) + { + if (!(is_addr_only_static_mapping (m)) || + (m->local_addr.as_u32 == m->external_addr.as_u32)) + { + continue; + } + snat_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index, 0); + } + } return 0; } int -snat_interface_add_del_output_feature (u32 sw_if_index, - u8 is_inside, int is_del) +nat44_ed_add_output_interface (u32 sw_if_index) { snat_main_t *sm = &snat_main; + + nat_outside_fib_t *outside_fib; + snat_static_mapping_t *m; snat_interface_t *i; snat_address_t *ap; - snat_static_mapping_t *m; - nat_outside_fib_t *outside_fib; - u32 fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, - sw_if_index); + u32 fib_index; + int rv; if (!sm->enabled) { @@ -1609,148 +1679,196 @@ snat_interface_add_del_output_feature (u32 sw_if_index, return VNET_API_ERROR_UNSUPPORTED; } - if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking)) + if (nat44_ed_get_interface (sm->interfaces, sw_if_index)) { - nat_log_err ("error unsupported"); - return VNET_API_ERROR_UNSUPPORTED; + nat_log_err ("error interface already configured"); + return VNET_API_ERROR_VALUE_EXIST; } - pool_foreach (i, sm->interfaces) - { - if (i->sw_if_index == sw_if_index) - { - nat_log_err ("error interface already configured"); - return VNET_API_ERROR_VALUE_EXIST; - } - } + if (nat44_ed_get_interface (sm->output_feature_interfaces, sw_if_index)) + { + nat_log_err ("error interface already configured"); + return VNET_API_ERROR_VALUE_EXIST; + } + + if (sm->num_workers > 1) + { + rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1); + if (rv) + { + return rv; + } - update_per_vrf_sessions_vec (fib_index, is_del); + rv = ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, 1); + if (rv) + { + return rv; + } - if (!is_inside) + vnet_feature_enable_disable ( + "ip4-unicast", "nat44-out2in-worker-handoff", sw_if_index, 1, 0, 0); + vnet_feature_enable_disable ("ip4-output", + "nat44-in2out-output-worker-handoff", + sw_if_index, 1, 0, 0); + } + else { - vec_foreach (outside_fib, sm->outside_fibs) - { - if (outside_fib->fib_index == fib_index) - { - if (is_del) - { - outside_fib->refcount--; - if (!outside_fib->refcount) - vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); - } - else - outside_fib->refcount++; - goto feature_set; - } - } - if (!is_del) + rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1); + if (rv) { - vec_add2 (sm->outside_fibs, outside_fib, 1); - outside_fib->refcount = 1; - outside_fib->fib_index = fib_index; + return rv; } + + rv = ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, 1); + if (rv) + { + return rv; + } + + vnet_feature_enable_disable ("ip4-unicast", "nat-pre-out2in", + sw_if_index, 1, 0, 0); + vnet_feature_enable_disable ("ip4-output", "nat-pre-in2out-output", + sw_if_index, 1, 0, 0); + } + + nat_validate_interface_counters (sm, sw_if_index); + + pool_get (sm->output_feature_interfaces, i); + i->sw_if_index = sw_if_index; + i->flags = 0; + i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE; + i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE; + + fib_index = + fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); + update_per_vrf_sessions_vec (fib_index, 0 /*is_del*/); + + outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index); + if (outside_fib) + { + outside_fib->refcount++; + } + else + { + vec_add2 (sm->outside_fibs, outside_fib, 1); + outside_fib->fib_index = fib_index; + outside_fib->refcount = 1; + } + + vec_foreach (ap, sm->addresses) + { + snat_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, 1); + } + + pool_foreach (m, sm->static_mappings) + { + if (!((is_addr_only_static_mapping (m))) || + (m->local_addr.as_u32 == m->external_addr.as_u32)) + { + continue; + } + snat_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index, 1); + } + + return 0; +} + +int +nat44_ed_del_output_interface (u32 sw_if_index) +{ + snat_main_t *sm = &snat_main; + + nat_outside_fib_t *outside_fib; + snat_static_mapping_t *m; + snat_interface_t *i; + snat_address_t *ap; + u32 fib_index; + int rv; + + if (!sm->enabled) + { + nat_log_err ("nat44 is disabled"); + return VNET_API_ERROR_UNSUPPORTED; } -feature_set: - if (is_inside) + i = nat44_ed_get_interface (sm->output_feature_interfaces, sw_if_index); + if (!i) { - int rv = - ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del); - if (rv) - return rv; - rv = - ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, - !is_del); - if (rv) - return rv; - goto fq; + nat_log_err ("error interface couldn't be found"); + return VNET_API_ERROR_NO_SUCH_ENTRY; } if (sm->num_workers > 1) { - int rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del); + rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0); if (rv) - return rv; - rv = - ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, !is_del); + { + return rv; + } + + rv = ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, 0); if (rv) - return rv; - vnet_feature_enable_disable ("ip4-unicast", - "nat44-out2in-worker-handoff", - sw_if_index, !is_del, 0, 0); + { + return rv; + } + + vnet_feature_enable_disable ( + "ip4-unicast", "nat44-out2in-worker-handoff", sw_if_index, 0, 0, 0); vnet_feature_enable_disable ("ip4-output", "nat44-in2out-output-worker-handoff", - sw_if_index, !is_del, 0, 0); + sw_if_index, 0, 0, 0); } else { - int rv = - ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, !is_del); - if (rv) - return rv; - rv = - ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, - !is_del); - if (rv) - return rv; - vnet_feature_enable_disable ("ip4-unicast", "nat-pre-out2in", - sw_if_index, !is_del, 0, 0); - vnet_feature_enable_disable ("ip4-output", "nat-pre-in2out-output", - sw_if_index, !is_del, 0, 0); - } - -fq: - if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1) - sm->fq_in2out_output_index = - vlib_frame_queue_main_init (sm->in2out_output_node_index, 0); - - if (sm->fq_out2in_index == ~0 && sm->num_workers > 1) - sm->fq_out2in_index = - vlib_frame_queue_main_init (sm->out2in_node_index, 0); - - pool_foreach (i, sm->output_feature_interfaces) - { - if (i->sw_if_index == sw_if_index) - { - if (is_del) - pool_put (sm->output_feature_interfaces, i); - else - return VNET_API_ERROR_VALUE_EXIST; + rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0); + if (rv) + { + return rv; + } - goto fib; - } - } + rv = ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, 0); + if (rv) + { + return rv; + } - if (is_del) - { - nat_log_err ("error interface couldn't be found"); - return VNET_API_ERROR_NO_SUCH_ENTRY; + vnet_feature_enable_disable ("ip4-unicast", "nat-pre-out2in", + sw_if_index, 0, 0, 0); + vnet_feature_enable_disable ("ip4-output", "nat-pre-in2out-output", + sw_if_index, 0, 0, 0); } - pool_get (sm->output_feature_interfaces, i); - i->sw_if_index = sw_if_index; - i->flags = 0; - nat_validate_interface_counters (sm, sw_if_index); - if (is_inside) - i->flags |= NAT_INTERFACE_FLAG_IS_INSIDE; - else - i->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE; + // remove interface + pool_put (sm->output_feature_interfaces, i); - /* Add/delete external addresses to FIB */ -fib: - if (is_inside) - return 0; + fib_index = + fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); + update_per_vrf_sessions_vec (fib_index, 1 /*is_del*/); + + outside_fib = nat44_ed_get_outside_fib (sm->outside_fibs, fib_index); + if (outside_fib) + { + outside_fib->refcount--; + if (!outside_fib->refcount) + { + vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs); + } + } vec_foreach (ap, sm->addresses) - snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del); + { + snat_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, 0); + } pool_foreach (m, sm->static_mappings) - { - if (!((is_addr_only_static_mapping(m))) || (m->local_addr.as_u32 == m->external_addr.as_u32)) - continue; - - snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del); - } + { + if (!((is_addr_only_static_mapping (m))) || + (m->local_addr.as_u32 == m->external_addr.as_u32)) + { + continue; + } + snat_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index, 0); + } return 0; } @@ -1936,14 +2054,14 @@ static clib_error_t * nat_ip_table_add_del (vnet_main_t * vnm, u32 table_id, u32 is_add) { u32 fib_index; - - // TODO: consider removing all NAT interfaces - if (!is_add) + if (!is_add) + { + fib_index = ip4_fib_index_from_table_id (table_id); + if (fib_index != ~0) { - fib_index = ip4_fib_index_from_table_id (table_id); - if (fib_index != ~0) - expire_per_vrf_sessions (fib_index); + expire_per_vrf_sessions (fib_index); } + } return 0; } @@ -2022,6 +2140,7 @@ nat_init (vlib_main_t * vm) sm->log_level = NAT_LOG_ERROR; nat44_set_node_indexes (sm, vm); + sm->log_class = vlib_log_register_class ("nat", 0); nat_ipfix_logging_init (vm); @@ -2061,14 +2180,15 @@ nat_init (vlib_main_t * vm) /* Use all available workers by default */ if (sm->num_workers > 1) { - for (i = 0; i < sm->num_workers; i++) bitmap = clib_bitmap_set (bitmap, i, 1); snat_set_workers (bitmap); clib_bitmap_free (bitmap); } else - sm->per_thread_data[0].snat_thread_index = 0; + { + sm->per_thread_data[0].snat_thread_index = 0; + } /* callbacks to call when interface address changes. */ cbi.function = snat_ip4_add_del_interface_address_cb; @@ -2102,19 +2222,12 @@ nat44_plugin_enable (nat44_config_t c) fail_if_enabled (); - // UPDATE based on these appropriate API/CLI - // c.static_mapping_only + c.connection_tracking - // - supported in NAT EI & NAT ED - // c.out2in_dpo, c.static_mapping_only - // - supported in NAT EI - if (c.static_mapping_only && !c.connection_tracking) { nat_log_err ("unsupported combination of configuration"); return 1; } - // nat44 feature configuration sm->static_mapping_only = c.static_mapping_only; sm->static_mapping_connection_tracking = c.connection_tracking; @@ -2131,7 +2244,6 @@ nat44_plugin_enable (nat44_config_t c) sm->max_translations_per_thread); sm->translation_buckets = nat_calc_bihash_buckets (c.sessions); - // ED only feature vec_add1 (sm->max_translations_per_fib, sm->max_translations_per_thread); sm->inside_vrf_id = c.inside_vrf; @@ -2152,7 +2264,28 @@ nat44_plugin_enable (nat44_config_t c) vlib_zero_simple_counter (&sm->total_sessions, 0); if (!sm->frame_queue_nelts) - sm->frame_queue_nelts = NAT_FQ_NELTS_DEFAULT; + { + sm->frame_queue_nelts = NAT_FQ_NELTS_DEFAULT; + } + + if (sm->num_workers > 1) + { + if (sm->fq_in2out_index == ~0) + { + sm->fq_in2out_index = vlib_frame_queue_main_init ( + sm->in2out_node_index, sm->frame_queue_nelts); + } + if (sm->fq_out2in_index == ~0) + { + sm->fq_out2in_index = vlib_frame_queue_main_init ( + sm->out2in_node_index, sm->frame_queue_nelts); + } + if (sm->fq_in2out_output_index == ~0) + { + sm->fq_in2out_output_index = vlib_frame_queue_main_init ( + sm->in2out_output_node_index, sm->frame_queue_nelts); + } + } sm->enabled = 1; sm->rconfig = c; @@ -2179,44 +2312,44 @@ int nat44_plugin_disable () { snat_main_t *sm = &snat_main; - snat_interface_t *i, *vec; + snat_interface_t *i, *pool; int error = 0; fail_if_disabled (); - // first unregister all nodes from interfaces - vec = vec_dup (sm->interfaces); - vec_foreach (i, vec) + pool = pool_dup (sm->interfaces); + pool_foreach (i, pool) { - if (nat_interface_is_inside(i)) - error = snat_interface_add_del (i->sw_if_index, 1, 1); - if (nat_interface_is_outside(i)) - error = snat_interface_add_del (i->sw_if_index, 0, 1); - + if (nat_interface_is_inside (i)) + { + error = nat44_ed_del_interface (i->sw_if_index, 1); + } + if (nat_interface_is_outside (i)) + { + error = nat44_ed_del_interface (i->sw_if_index, 0); + } if (error) { nat_log_err ("error occurred while removing interface %u", i->sw_if_index); } } - vec_free (vec); + pool_free (sm->interfaces); + pool_free (pool); sm->interfaces = 0; - vec = vec_dup (sm->output_feature_interfaces); - vec_foreach (i, vec) + pool = pool_dup (sm->output_feature_interfaces); + pool_foreach (i, pool) { - if (nat_interface_is_inside(i)) - error = snat_interface_add_del_output_feature (i->sw_if_index, 1, 1); - if (nat_interface_is_outside(i)) - error = snat_interface_add_del_output_feature (i->sw_if_index, 0, 1); - + error = nat44_ed_del_output_interface (i->sw_if_index); if (error) { nat_log_err ("error occurred while removing interface %u", i->sw_if_index); } } - vec_free (vec); + pool_free (sm->output_feature_interfaces); + pool_free (pool); sm->output_feature_interfaces = 0; vec_free (sm->max_translations_per_fib); diff --git a/src/plugins/nat/nat44-ed/nat44_ed.h b/src/plugins/nat/nat44-ed/nat44_ed.h index 420f84c591f..15e8e480b4e 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.h +++ b/src/plugins/nat/nat44-ed/nat44_ed.h @@ -954,28 +954,10 @@ clib_error_t *nat44_api_hookup (vlib_main_t * vm); */ int snat_set_workers (uword * bitmap); -/** - * @brief Enable/disable NAT44 feature on the interface - * - * @param sw_if_index software index of the interface - * @param is_inside 1 = inside, 0 = outside - * @param is_del 1 = delete, 0 = add - * - * @return 0 on success, non-zero value otherwise - */ -int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del); - -/** - * @brief Enable/disable NAT44 output feature on the interface (postrouting NAT) - * - * @param sw_if_index software index of the interface - * @param is_inside 1 = inside, 0 = outside - * @param is_del 1 = delete, 0 = add - * - * @return 0 on success, non-zero value otherwise - */ -int snat_interface_add_del_output_feature (u32 sw_if_index, u8 is_inside, - int is_del); +int nat44_ed_add_interface (u32 sw_if_index, u8 is_inside); +int nat44_ed_del_interface (u32 sw_if_index, u8 is_inside); +int nat44_ed_add_output_interface (u32 sw_if_index); +int nat44_ed_del_output_interface (u32 sw_if_index); /** * @brief Add/delete NAT44 pool address from specific interface diff --git a/src/plugins/nat/nat44-ed/nat44_ed_api.c b/src/plugins/nat/nat44-ed/nat44_ed_api.c index 22737ad7e56..f92de51ea44 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_api.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_api.c @@ -364,22 +364,27 @@ static void vl_api_nat44_interface_add_del_feature_t_handler (vl_api_nat44_interface_add_del_feature_t * mp) { - snat_main_t *sm = &snat_main; vl_api_nat44_interface_add_del_feature_reply_t *rmp; - u32 sw_if_index = ntohl (mp->sw_if_index); - u8 is_del; + snat_main_t *sm = &snat_main; + u32 sw_if_index; + u8 is_inside; int rv = 0; - is_del = !mp->is_add; - VALIDATE_SW_IF_INDEX (mp); - rv = - snat_interface_add_del (sw_if_index, mp->flags & NAT_API_IS_INSIDE, - is_del); + is_inside = mp->flags & NAT_API_IS_INSIDE; + sw_if_index = ntohl (mp->sw_if_index); - BAD_SW_IF_INDEX_LABEL; + if (mp->is_add) + { + rv = nat44_ed_add_interface (sw_if_index, is_inside); + } + else + { + rv = nat44_ed_del_interface (sw_if_index, is_inside); + } + BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_FEATURE_REPLY); } @@ -426,16 +431,23 @@ static void vl_api_nat44_interface_add_del_output_feature_t_handler (vl_api_nat44_interface_add_del_output_feature_t * mp) { - snat_main_t *sm = &snat_main; vl_api_nat44_interface_add_del_output_feature_reply_t *rmp; - u32 sw_if_index = ntohl (mp->sw_if_index); + snat_main_t *sm = &snat_main; + u32 sw_if_index; int rv = 0; VALIDATE_SW_IF_INDEX (mp); - rv = snat_interface_add_del_output_feature (sw_if_index, - mp->flags & NAT_API_IS_INSIDE, - !mp->is_add); + sw_if_index = ntohl (mp->sw_if_index); + + if (mp->is_add) + { + rv = nat44_ed_add_output_interface (sw_if_index); + } + else + { + rv = nat44_ed_del_output_interface (sw_if_index); + } BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY); diff --git a/src/plugins/nat/nat44-ed/nat44_ed_cli.c b/src/plugins/nat/nat44-ed/nat44_ed_cli.c index 1d54f99d113..cb0fe9ec12c 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_cli.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_cli.c @@ -665,8 +665,7 @@ snat_feature_command_fn (vlib_main_t * vm, u32 *inside_sw_if_indices = 0; u32 *outside_sw_if_indices = 0; u8 is_output_feature = 0; - int is_del = 0; - int i; + int i, rv, is_del = 0; sw_if_index = ~0; @@ -701,8 +700,15 @@ snat_feature_command_fn (vlib_main_t * vm, sw_if_index = inside_sw_if_indices[i]; if (is_output_feature) { - if (snat_interface_add_del_output_feature - (sw_if_index, 1, is_del)) + if (is_del) + { + rv = nat44_ed_del_output_interface (sw_if_index); + } + else + { + rv = nat44_ed_add_output_interface (sw_if_index); + } + if (rv) { error = clib_error_return (0, "%s %U failed", is_del ? "del" : "add", @@ -713,7 +719,15 @@ snat_feature_command_fn (vlib_main_t * vm, } else { - if (snat_interface_add_del (sw_if_index, 1, is_del)) + if (is_del) + { + rv = nat44_ed_del_interface (sw_if_index, 1); + } + else + { + rv = nat44_ed_add_interface (sw_if_index, 1); + } + if (rv) { error = clib_error_return (0, "%s %U failed", is_del ? "del" : "add", @@ -732,8 +746,15 @@ snat_feature_command_fn (vlib_main_t * vm, sw_if_index = outside_sw_if_indices[i]; if (is_output_feature) { - if (snat_interface_add_del_output_feature - (sw_if_index, 0, is_del)) + if (is_del) + { + rv = nat44_ed_del_output_interface (sw_if_index); + } + else + { + rv = nat44_ed_add_output_interface (sw_if_index); + } + if (rv) { error = clib_error_return (0, "%s %U failed", is_del ? "del" : "add", @@ -744,7 +765,15 @@ snat_feature_command_fn (vlib_main_t * vm, } else { - if (snat_interface_add_del (sw_if_index, 0, is_del)) + if (is_del) + { + rv = nat44_ed_del_interface (sw_if_index, 0); + } + else + { + rv = nat44_ed_add_interface (sw_if_index, 0); + } + if (rv) { error = clib_error_return (0, "%s %U failed", is_del ? "del" : "add", diff --git a/test/test_nat44_ed.py b/test/test_nat44_ed.py index 9eea7c820ae..76561eabedd 100644 --- a/test/test_nat44_ed.py +++ b/test/test_nat44_ed.py @@ -3033,11 +3033,7 @@ class TestNAT44EDMW(TestNAT44ED): self.nat_add_address(self.nat_addr) self.vapi.nat44_interface_add_del_output_feature( - sw_if_index=self.pg0.sw_if_index, - flags=self.config_flags.NAT_IS_INSIDE, is_add=1) - self.vapi.nat44_interface_add_del_output_feature( - sw_if_index=self.pg1.sw_if_index, - flags=self.config_flags.NAT_IS_OUTSIDE, is_add=1) + sw_if_index=self.pg1.sw_if_index, is_add=1) # First ensure that the NAT is working sans ACL @@ -3582,13 +3578,8 @@ class TestNAT44EDMW(TestNAT44ED): new_vrf_id = 22 self.nat_add_address(self.nat_addr) - flags = self.config_flags.NAT_IS_INSIDE - self.vapi.nat44_interface_add_del_output_feature( - sw_if_index=self.pg7.sw_if_index, - flags=flags, is_add=1) self.vapi.nat44_interface_add_del_output_feature( - sw_if_index=self.pg8.sw_if_index, - is_add=1) + sw_if_index=self.pg8.sw_if_index, is_add=1) try: self.configure_ip4_interface(self.pg7, table_id=new_vrf_id) -- 2.16.6