summaryrefslogtreecommitdiffstats
path: root/src/plugins/nat
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/nat')
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei.api39
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei.c2004
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei.h107
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei_api.c278
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei_cli.c171
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei_handoff.c2
6 files changed, 1574 insertions, 1027 deletions
diff --git a/src/plugins/nat/nat44-ei/nat44_ei.api b/src/plugins/nat/nat44-ei/nat44_ei.api
index 9ea1a3a1dde..e535906321a 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei.api
+++ b/src/plugins/nat/nat44-ei/nat44_ei.api
@@ -550,6 +550,45 @@ define nat44_ei_interface_output_feature_details {
vl_api_interface_index_t sw_if_index;
};
+/** \brief add/del NAT output interface (postrouting
+ in2out translation)
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param is_add - true if add, false if delete
+ @param sw_if_index - software index of the interface
+*/
+autoendian autoreply define nat44_ei_add_del_output_interface {
+ u32 client_index;
+ u32 context;
+ bool is_add;
+ vl_api_interface_index_t sw_if_index;
+};
+
+service {
+ rpc nat44_ei_output_interface_get returns nat44_ei_output_interface_get_reply
+ stream nat44_ei_output_interface_details;
+};
+
+define nat44_ei_output_interface_get
+{
+ u32 client_index;
+ u32 context;
+ u32 cursor;
+};
+
+define nat44_ei_output_interface_get_reply
+{
+ u32 context;
+ i32 retval;
+ u32 cursor;
+};
+
+define nat44_ei_output_interface_details
+{
+ u32 context;
+ vl_api_interface_index_t sw_if_index;
+};
+
/** \brief Add/delete NAT44 static mapping
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
diff --git a/src/plugins/nat/nat44-ei/nat44_ei.c b/src/plugins/nat/nat44-ei/nat44_ei.c
index 3691af3a53e..694bc6bec5a 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei.c
+++ b/src/plugins/nat/nat44-ei/nat44_ei.c
@@ -304,6 +304,76 @@ nat_validate_interface_counters (nat44_ei_main_t *nm, u32 sw_if_index)
nat_validate_simple_counter (nm->counters.hairpinning, sw_if_index);
}
+static void
+nat44_ei_add_del_addr_to_fib_foreach_out_if (ip4_address_t *addr, u8 is_add)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_interface_t *i;
+
+ pool_foreach (i, nm->interfaces)
+ {
+ if (nat44_ei_interface_is_outside (i) && !nm->out2in_dpo)
+ {
+ nat44_ei_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add);
+ }
+ }
+ pool_foreach (i, nm->output_feature_interfaces)
+ {
+ if (nat44_ei_interface_is_outside (i) && !nm->out2in_dpo)
+ {
+ nat44_ei_add_del_addr_to_fib (addr, 32, i->sw_if_index, is_add);
+ }
+ }
+}
+
+static_always_inline void
+nat44_ei_add_del_addr_to_fib_foreach_addr (u32 sw_if_index, u8 is_add)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_address_t *ap;
+
+ vec_foreach (ap, nm->addresses)
+ {
+ nat44_ei_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, is_add);
+ }
+}
+
+static_always_inline void
+nat44_ei_add_del_addr_to_fib_foreach_addr_only_sm (u32 sw_if_index, u8 is_add)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_static_mapping_t *m;
+
+ pool_foreach (m, nm->static_mappings)
+ {
+ if (is_sm_addr_only (m->flags) &&
+ !(m->local_addr.as_u32 == m->external_addr.as_u32))
+ {
+ nat44_ei_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index,
+ is_add);
+ }
+ }
+}
+
+static int
+nat44_ei_is_address_used_in_static_mapping (ip4_address_t addr)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_static_mapping_t *m;
+ pool_foreach (m, nm->static_mappings)
+ {
+ if (is_sm_addr_only (m->flags) || is_sm_identity_nat (m->flags))
+ {
+ continue;
+ }
+ if (m->external_addr.as_u32 == addr.as_u32)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
clib_error_t *
nat44_ei_init (vlib_main_t *vm)
{
@@ -372,14 +442,15 @@ nat44_ei_init (vlib_main_t *vm)
/* Use all available workers by default */
if (nm->num_workers > 1)
{
-
for (i = 0; i < nm->num_workers; i++)
bitmap = clib_bitmap_set (bitmap, i, 1);
nat44_ei_set_workers (bitmap);
clib_bitmap_free (bitmap);
}
else
- nm->per_thread_data[0].snat_thread_index = 0;
+ {
+ nm->per_thread_data[0].snat_thread_index = 0;
+ }
/* callbacks to call when interface address changes. */
cbi.function = nat44_ei_ip4_add_del_interface_address_cb;
@@ -472,6 +543,25 @@ nat44_ei_plugin_enable (nat44_ei_config_t c)
vlib_zero_simple_counter (&nm->total_sessions, 0);
vlib_zero_simple_counter (&nm->user_limit_reached, 0);
+ if (nm->num_workers > 1)
+ {
+ if (nm->fq_in2out_index == ~0)
+ {
+ nm->fq_in2out_index = vlib_frame_queue_main_init (
+ nm->in2out_node_index, nm->frame_queue_nelts);
+ }
+ if (nm->fq_out2in_index == ~0)
+ {
+ nm->fq_out2in_index = vlib_frame_queue_main_init (
+ nm->out2in_node_index, nm->frame_queue_nelts);
+ }
+ if (nm->fq_in2out_output_index == ~0)
+ {
+ nm->fq_in2out_output_index = vlib_frame_queue_main_init (
+ nm->in2out_output_node_index, nm->frame_queue_nelts);
+ }
+ }
+
nat_ha_enable ();
nm->enabled = 1;
@@ -492,17 +582,44 @@ nat44_ei_addresses_free (nat44_ei_address_t **addresses)
*addresses = 0;
}
-int
-nat44_ei_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
+static_always_inline nat44_ei_outside_fib_t *
+nat44_ei_get_outside_fib (nat44_ei_outside_fib_t *outside_fibs, u32 fib_index)
+{
+ nat44_ei_outside_fib_t *f;
+ vec_foreach (f, outside_fibs)
+ {
+ if (f->fib_index == fib_index)
+ {
+ return f;
+ }
+ }
+ return 0;
+}
+
+static_always_inline nat44_ei_interface_t *
+nat44_ei_get_interface (nat44_ei_interface_t *interfaces, u32 sw_if_index)
+{
+ nat44_ei_interface_t *i;
+ pool_foreach (i, interfaces)
+ {
+ if (i->sw_if_index == sw_if_index)
+ {
+ return i;
+ }
+ }
+ return 0;
+}
+
+static_always_inline int
+nat44_ei_add_interface (u32 sw_if_index, u8 is_inside)
{
const char *feature_name, *del_feature_name;
nat44_ei_main_t *nm = &nat44_ei_main;
- nat44_ei_interface_t *i;
- nat44_ei_address_t *ap;
- nat44_ei_static_mapping_t *m;
+
nat44_ei_outside_fib_t *outside_fib;
- u32 fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
+ nat44_ei_interface_t *i;
+ u32 fib_index;
+ int rv;
fail_if_disabled ();
@@ -512,408 +629,479 @@ nat44_ei_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
return VNET_API_ERROR_UNSUPPORTED;
}
- pool_foreach (i, nm->output_feature_interfaces)
+ if (nat44_ei_get_interface (nm->output_feature_interfaces, sw_if_index))
{
- if (i->sw_if_index == sw_if_index)
+ nat44_ei_log_err ("error interface already configured");
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
+
+ i = nat44_ei_get_interface (nm->interfaces, sw_if_index);
+ if (i)
+ {
+ if ((nat44_ei_interface_is_inside (i) && is_inside) ||
+ (nat44_ei_interface_is_outside (i) && !is_inside))
{
- nat44_ei_log_err ("error interface already configured");
- return VNET_API_ERROR_VALUE_EXIST;
+ return 0;
+ }
+ if (nm->num_workers > 1)
+ {
+ del_feature_name = !is_inside ? "nat44-ei-in2out-worker-handoff" :
+ "nat44-ei-out2in-worker-handoff";
+ feature_name = "nat44-ei-handoff-classify";
+ }
+ else
+ {
+ del_feature_name =
+ !is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
+
+ feature_name = "nat44-ei-classify";
}
- }
- if (nm->static_mapping_only && !(nm->static_mapping_connection_tracking))
- feature_name = is_inside ? "nat44-ei-in2out-fast" : "nat44-ei-out2in-fast";
+ rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1);
+ if (rv)
+ {
+ return rv;
+ }
+ rv = vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
+ sw_if_index, 0, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ rv = vnet_feature_enable_disable ("ip4-unicast", feature_name,
+ sw_if_index, 1, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ if (!is_inside)
+ {
+ rv = vnet_feature_enable_disable (
+ "ip4-local", "nat44-ei-hairpinning", sw_if_index, 0, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ }
+ }
else
{
if (nm->num_workers > 1)
- feature_name = is_inside ? "nat44-ei-in2out-worker-handoff" :
- "nat44-ei-out2in-worker-handoff";
+ {
+ feature_name = is_inside ? "nat44-ei-in2out-worker-handoff" :
+ "nat44-ei-out2in-worker-handoff";
+ }
else
- feature_name = is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
- }
+ {
+ feature_name = is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
+ }
+ nat_validate_interface_counters (nm, sw_if_index);
- if (nm->fq_in2out_index == ~0 && nm->num_workers > 1)
- nm->fq_in2out_index = vlib_frame_queue_main_init (nm->in2out_node_index,
- nm->frame_queue_nelts);
+ rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1);
+ if (rv)
+ {
+ return rv;
+ }
+ rv = vnet_feature_enable_disable ("ip4-unicast", feature_name,
+ sw_if_index, 1, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ if (is_inside && !nm->out2in_dpo)
+ {
+ rv = vnet_feature_enable_disable (
+ "ip4-local", "nat44-ei-hairpinning", sw_if_index, 1, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ }
+
+ pool_get (nm->interfaces, i);
+ i->sw_if_index = sw_if_index;
+ i->flags = 0;
+ }
- if (nm->fq_out2in_index == ~0 && nm->num_workers > 1)
- nm->fq_out2in_index = vlib_frame_queue_main_init (nm->out2in_node_index,
- nm->frame_queue_nelts);
+ fib_index =
+ fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
if (!is_inside)
{
- vec_foreach (outside_fib, nm->outside_fibs)
+ i->flags |= NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE;
+
+ outside_fib = nat44_ei_get_outside_fib (nm->outside_fibs, fib_index);
+ if (outside_fib)
{
- if (outside_fib->fib_index == fib_index)
- {
- if (is_del)
- {
- outside_fib->refcount--;
- if (!outside_fib->refcount)
- vec_del1 (nm->outside_fibs,
- outside_fib - nm->outside_fibs);
- }
- else
- outside_fib->refcount++;
- goto feature_set;
- }
+ outside_fib->refcount++;
}
- if (!is_del)
+ else
{
vec_add2 (nm->outside_fibs, outside_fib, 1);
- outside_fib->refcount = 1;
outside_fib->fib_index = fib_index;
+ outside_fib->refcount = 1;
}
- }
-feature_set:
- pool_foreach (i, nm->interfaces)
+ nat44_ei_add_del_addr_to_fib_foreach_addr (sw_if_index, 1);
+ nat44_ei_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1);
+ }
+ else
{
- if (i->sw_if_index == sw_if_index)
- {
- if (is_del)
- {
- if (nat44_ei_interface_is_inside (i) &&
- nat44_ei_interface_is_outside (i))
- {
- if (is_inside)
- i->flags &= ~NAT44_EI_INTERFACE_FLAG_IS_INSIDE;
- else
- i->flags &= ~NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE;
+ i->flags |= NAT44_EI_INTERFACE_FLAG_IS_INSIDE;
+ }
- if (nm->num_workers > 1)
- {
- del_feature_name = "nat44-ei-handoff-classify";
- clib_warning (
- "del_feature_name = nat44-ei-handoff-classify");
- feature_name = !is_inside ?
- "nat44-ei-in2out-worker-handoff" :
- "nat44-ei-out2in-worker-handoff";
- }
- else
- {
- del_feature_name = "nat44-ei-classify";
- clib_warning ("del_feature_name = nat44-ei-classify");
- feature_name =
- !is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
- }
+ return 0;
+}
- int rv =
- ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0);
- if (rv)
- return rv;
- rv = vnet_feature_enable_disable (
- "ip4-unicast", del_feature_name, sw_if_index, 0, 0, 0);
- if (rv)
- return rv;
- rv = vnet_feature_enable_disable (
- "ip4-unicast", feature_name, sw_if_index, 1, 0, 0);
- if (rv)
- return rv;
- if (!is_inside)
- {
- rv = vnet_feature_enable_disable ("ip4-local",
- "nat44-ei-hairpinning",
- sw_if_index, 1, 0, 0);
- if (rv)
- return rv;
- }
- }
- else
- {
- int rv =
- ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0);
- if (rv)
- return rv;
- rv = vnet_feature_enable_disable (
- "ip4-unicast", feature_name, sw_if_index, 0, 0, 0);
- if (rv)
- return rv;
- pool_put (nm->interfaces, i);
- if (is_inside)
- {
- rv = vnet_feature_enable_disable ("ip4-local",
- "nat44-ei-hairpinning",
- sw_if_index, 0, 0, 0);
- if (rv)
- return rv;
- }
- }
- }
- else
- {
- if ((nat44_ei_interface_is_inside (i) && is_inside) ||
- (nat44_ei_interface_is_outside (i) && !is_inside))
- return 0;
+static_always_inline int
+nat44_ei_del_interface (u32 sw_if_index, u8 is_inside)
+{
+ const char *feature_name, *del_feature_name;
+ nat44_ei_main_t *nm = &nat44_ei_main;
- if (nm->num_workers > 1)
- {
- del_feature_name = !is_inside ?
- "nat44-ei-in2out-worker-handoff" :
- "nat44-ei-out2in-worker-handoff";
- feature_name = "nat44-ei-handoff-classify";
- clib_warning ("feature_name = nat44-ei-handoff-classify");
- }
- else
- {
- del_feature_name =
- !is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
- feature_name = "nat44-ei-classify";
- clib_warning ("feature_name = nat44-ei-classify");
- }
+ nat44_ei_outside_fib_t *outside_fib;
+ nat44_ei_interface_t *i;
+ u32 fib_index;
+ int rv;
- int rv =
- ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1);
- if (rv)
- return rv;
- rv = vnet_feature_enable_disable (
- "ip4-unicast", del_feature_name, sw_if_index, 0, 0, 0);
- if (rv)
- return rv;
- rv = vnet_feature_enable_disable ("ip4-unicast", feature_name,
- sw_if_index, 1, 0, 0);
- if (rv)
- return rv;
- if (!is_inside)
- {
- rv = vnet_feature_enable_disable (
- "ip4-local", "nat44-ei-hairpinning", sw_if_index, 0, 0, 0);
- if (rv)
- return rv;
- }
- goto set_flags;
- }
+ fail_if_disabled ();
- goto fib;
- }
+ if (nm->out2in_dpo && !is_inside)
+ {
+ nat44_ei_log_err ("error unsupported");
+ return VNET_API_ERROR_UNSUPPORTED;
}
- if (is_del)
+ i = nat44_ei_get_interface (nm->interfaces, sw_if_index);
+ if (i == 0)
{
nat44_ei_log_err ("error interface couldn't be found");
return VNET_API_ERROR_NO_SUCH_ENTRY;
}
- pool_get (nm->interfaces, i);
- i->sw_if_index = sw_if_index;
- i->flags = 0;
- nat_validate_interface_counters (nm, sw_if_index);
-
- int rv = vnet_feature_enable_disable ("ip4-unicast", feature_name,
- sw_if_index, 1, 0, 0);
- if (rv)
- return rv;
-
- rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1);
- if (rv)
- return rv;
-
- if (is_inside && !nm->out2in_dpo)
+ if (nat44_ei_interface_is_inside (i) && nat44_ei_interface_is_outside (i))
{
- rv = vnet_feature_enable_disable ("ip4-local", "nat44-ei-hairpinning",
+ if (nm->num_workers > 1)
+ {
+ del_feature_name = "nat44-ei-handoff-classify";
+ feature_name = !is_inside ? "nat44-ei-in2out-worker-handoff" :
+ "nat44-ei-out2in-worker-handoff";
+ }
+ else
+ {
+ del_feature_name = "nat44-ei-classify";
+ feature_name = !is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
+ }
+
+ rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ rv = vnet_feature_enable_disable ("ip4-unicast", del_feature_name,
+ sw_if_index, 0, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ rv = vnet_feature_enable_disable ("ip4-unicast", feature_name,
sw_if_index, 1, 0, 0);
if (rv)
- return rv;
- }
-
-set_flags:
- if (is_inside)
- {
- i->flags |= NAT44_EI_INTERFACE_FLAG_IS_INSIDE;
- return 0;
+ {
+ return rv;
+ }
+ if (is_inside)
+ {
+ i->flags &= ~NAT44_EI_INTERFACE_FLAG_IS_INSIDE;
+ }
+ else
+ {
+ rv = vnet_feature_enable_disable (
+ "ip4-local", "nat44-ei-hairpinning", sw_if_index, 1, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ i->flags &= ~NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE;
+ }
}
else
- i->flags |= NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE;
+ {
+ if (nm->num_workers > 1)
+ {
+ feature_name = is_inside ? "nat44-ei-in2out-worker-handoff" :
+ "nat44-ei-out2in-worker-handoff";
+ }
+ else
+ {
+ feature_name = is_inside ? "nat44-ei-in2out" : "nat44-ei-out2in";
+ }
- /* Add/delete external addresses to FIB */
-fib:
- vec_foreach (ap, nm->addresses)
- nat44_ei_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;
+ }
+ rv = vnet_feature_enable_disable ("ip4-unicast", feature_name,
+ sw_if_index, 0, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ if (is_inside)
+ {
+ rv = vnet_feature_enable_disable (
+ "ip4-local", "nat44-ei-hairpinning", sw_if_index, 0, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ }
- pool_foreach (m, nm->static_mappings)
+ // remove interface
+ pool_put (nm->interfaces, i);
+ }
+
+ if (!is_inside)
{
- if (!(nat44_ei_is_addr_only_static_mapping (m)) ||
- (m->local_addr.as_u32 == m->external_addr.as_u32))
- continue;
+ fib_index =
+ fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
+ outside_fib = nat44_ei_get_outside_fib (nm->outside_fibs, fib_index);
+ if (outside_fib)
+ {
+ outside_fib->refcount--;
+ if (!outside_fib->refcount)
+ {
+ vec_del1 (nm->outside_fibs, outside_fib - nm->outside_fibs);
+ }
+ }
- nat44_ei_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index,
- !is_del);
+ nat44_ei_add_del_addr_to_fib_foreach_addr (sw_if_index, 0);
+ nat44_ei_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 0);
}
return 0;
}
int
-nat44_ei_interface_add_del_output_feature (u32 sw_if_index, u8 is_inside,
- int is_del)
+nat44_ei_add_del_interface (u32 sw_if_index, u8 is_inside, int is_del)
+{
+ if (is_del)
+ {
+ return nat44_ei_del_interface (sw_if_index, is_inside);
+ }
+ else
+ {
+ return nat44_ei_add_interface (sw_if_index, is_inside);
+ }
+}
+
+static_always_inline int
+nat44_ei_add_output_interface (u32 sw_if_index)
{
nat44_ei_main_t *nm = &nat44_ei_main;
- nat44_ei_interface_t *i;
- nat44_ei_address_t *ap;
- nat44_ei_static_mapping_t *m;
+
nat44_ei_outside_fib_t *outside_fib;
- u32 fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
+ nat44_ei_interface_t *i;
+ u32 fib_index;
+ int rv;
fail_if_disabled ();
- if (nm->static_mapping_only && !(nm->static_mapping_connection_tracking))
+ if (nat44_ei_get_interface (nm->interfaces, sw_if_index))
{
- nat44_ei_log_err ("error unsupported");
- return VNET_API_ERROR_UNSUPPORTED;
+ nat44_ei_log_err ("error interface already configured");
+ return VNET_API_ERROR_VALUE_EXIST;
}
- pool_foreach (i, nm->interfaces)
+ if (nat44_ei_get_interface (nm->output_feature_interfaces, sw_if_index))
{
- if (i->sw_if_index == sw_if_index)
- {
- nat44_ei_log_err ("error interface already configured");
- return VNET_API_ERROR_VALUE_EXIST;
- }
+ nat44_ei_log_err ("error interface already configured");
+ return VNET_API_ERROR_VALUE_EXIST;
}
- if (!is_inside)
+ if (nm->num_workers > 1)
{
- vec_foreach (outside_fib, nm->outside_fibs)
+ rv = ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, 1);
+ if (rv)
{
- if (outside_fib->fib_index == fib_index)
- {
- if (is_del)
- {
- outside_fib->refcount--;
- if (!outside_fib->refcount)
- vec_del1 (nm->outside_fibs,
- outside_fib - nm->outside_fibs);
- }
- else
- outside_fib->refcount++;
- goto feature_set;
- }
+ return rv;
}
- if (!is_del)
+ rv = ip4_sv_reass_output_enable_disable_with_refcnt (sw_if_index, 1);
+ if (rv)
{
- vec_add2 (nm->outside_fibs, outside_fib, 1);
- outside_fib->refcount = 1;
- outside_fib->fib_index = fib_index;
+ return rv;
+ }
+ rv = vnet_feature_enable_disable (
+ "ip4-unicast", "nat44-ei-out2in-worker-handoff", sw_if_index, 1, 0, 0);
+ if (rv)
+ {
+ return rv;
+ }
+ rv = vnet_feature_enable_disable (
+ "ip4-output", "nat44-ei-in2out-output-worker-handoff", sw_if_index, 1,
+ 0, 0);
+ if (rv)
+ {
+ return rv;
}
}
-
-feature_set:
- if (is_inside)
+ else
{
- 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, 1);
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, 1);
if (rv)
- return rv;
- rv = vnet_feature_enable_disable ("ip4-unicast", "nat44-ei-hairpin-dst",
- sw_if_index, !is_del, 0, 0);
+ {
+ return rv;
+ }
+ rv = vnet_feature_enable_disable ("ip4-unicast", "nat44-ei-out2in",
+ sw_if_index, 1, 0, 0);
if (rv)
- return rv;
- rv = vnet_feature_enable_disable ("ip4-output", "nat44-ei-hairpin-src",
- sw_if_index, !is_del, 0, 0);
+ {
+ return rv;
+ }
+ rv = vnet_feature_enable_disable ("ip4-output", "nat44-ei-in2out-output",
+ sw_if_index, 1, 0, 0);
if (rv)
- return rv;
- goto fq;
+ {
+ return rv;
+ }
+ }
+
+ nat_validate_interface_counters (nm, sw_if_index);
+
+ pool_get (nm->output_feature_interfaces, i);
+ i->sw_if_index = sw_if_index;
+ i->flags = 0;
+ i->flags |= NAT44_EI_INTERFACE_FLAG_IS_INSIDE;
+ i->flags |= NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE;
+
+ fib_index =
+ fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
+ outside_fib = nat44_ei_get_outside_fib (nm->outside_fibs, fib_index);
+ if (outside_fib)
+ {
+ outside_fib->refcount++;
+ }
+ else
+ {
+ vec_add2 (nm->outside_fibs, outside_fib, 1);
+ outside_fib->fib_index = fib_index;
+ outside_fib->refcount = 1;
+ }
+
+ nat44_ei_add_del_addr_to_fib_foreach_addr (sw_if_index, 1);
+ nat44_ei_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1);
+
+ return 0;
+}
+
+static_always_inline int
+nat44_ei_del_output_interface (u32 sw_if_index)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+
+ nat44_ei_outside_fib_t *outside_fib;
+ nat44_ei_interface_t *i;
+ u32 fib_index;
+ int rv;
+
+ fail_if_disabled ();
+
+ i = nat44_ei_get_interface (nm->output_feature_interfaces, sw_if_index);
+ if (!i)
+ {
+ nat44_ei_log_err ("error interface couldn't be found");
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
}
if (nm->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;
- rv = vnet_feature_enable_disable ("ip4-unicast",
- "nat44-ei-out2in-worker-handoff",
- sw_if_index, !is_del, 0, 0);
+ {
+ return rv;
+ }
+ rv = vnet_feature_enable_disable (
+ "ip4-unicast", "nat44-ei-out2in-worker-handoff", sw_if_index, 0, 0, 0);
if (rv)
- return rv;
+ {
+ return rv;
+ }
rv = vnet_feature_enable_disable (
- "ip4-output", "nat44-ei-in2out-output-worker-handoff", sw_if_index,
- !is_del, 0, 0);
+ "ip4-output", "nat44-ei-in2out-output-worker-handoff", sw_if_index, 0,
+ 0, 0);
if (rv)
- return rv;
+ {
+ return rv;
+ }
}
else
{
- 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;
+ {
+ return rv;
+ }
rv = vnet_feature_enable_disable ("ip4-unicast", "nat44-ei-out2in",
- sw_if_index, !is_del, 0, 0);
+ sw_if_index, 0, 0, 0);
if (rv)
- return rv;
+ {
+ return rv;
+ }
rv = vnet_feature_enable_disable ("ip4-output", "nat44-ei-in2out-output",
- sw_if_index, !is_del, 0, 0);
+ sw_if_index, 0, 0, 0);
if (rv)
- return rv;
+ {
+ return rv;
+ }
}
-fq:
- if (nm->fq_in2out_output_index == ~0 && nm->num_workers > 1)
- nm->fq_in2out_output_index =
- vlib_frame_queue_main_init (nm->in2out_output_node_index, 0);
+ pool_put (nm->output_feature_interfaces, i);
- if (nm->fq_out2in_index == ~0 && nm->num_workers > 1)
- nm->fq_out2in_index =
- vlib_frame_queue_main_init (nm->out2in_node_index, 0);
-
- pool_foreach (i, nm->output_feature_interfaces)
+ fib_index =
+ fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
+ outside_fib = nat44_ei_get_outside_fib (nm->outside_fibs, fib_index);
+ if (outside_fib)
{
- if (i->sw_if_index == sw_if_index)
+ outside_fib->refcount--;
+ if (!outside_fib->refcount)
{
- if (is_del)
- pool_put (nm->output_feature_interfaces, i);
- else
- return VNET_API_ERROR_VALUE_EXIST;
-
- goto fib;
+ vec_del1 (nm->outside_fibs, outside_fib - nm->outside_fibs);
}
}
+ nat44_ei_add_del_addr_to_fib_foreach_addr (sw_if_index, 1);
+ nat44_ei_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1);
+
+ return 0;
+}
+
+int
+nat44_ei_add_del_output_interface (u32 sw_if_index, int is_del)
+{
if (is_del)
{
- nat44_ei_log_err ("error interface couldn't be found");
- return VNET_API_ERROR_NO_SUCH_ENTRY;
+ return nat44_ei_del_output_interface (sw_if_index);
}
-
- pool_get (nm->output_feature_interfaces, i);
- i->sw_if_index = sw_if_index;
- i->flags = 0;
- nat_validate_interface_counters (nm, sw_if_index);
- if (is_inside)
- i->flags |= NAT44_EI_INTERFACE_FLAG_IS_INSIDE;
else
- i->flags |= NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE;
-
- /* Add/delete external addresses to FIB */
-fib:
- if (is_inside)
- return 0;
-
- vec_foreach (ap, nm->addresses)
- nat44_ei_add_del_addr_to_fib (&ap->addr, 32, sw_if_index, !is_del);
-
- pool_foreach (m, nm->static_mappings)
{
- if (!((nat44_ei_is_addr_only_static_mapping (m))) ||
- (m->local_addr.as_u32 == m->external_addr.as_u32))
- continue;
-
- nat44_ei_add_del_addr_to_fib (&m->external_addr, 32, sw_if_index,
- !is_del);
+ return nat44_ei_add_output_interface (sw_if_index);
}
-
- return 0;
}
int
@@ -928,9 +1116,13 @@ nat44_ei_plugin_disable ()
pool_foreach (i, pool)
{
if (nat44_ei_interface_is_inside (i))
- error = nat44_ei_interface_add_del (i->sw_if_index, 1, 1);
+ {
+ error = nat44_ei_del_interface (i->sw_if_index, 1);
+ }
if (nat44_ei_interface_is_outside (i))
- error = nat44_ei_interface_add_del (i->sw_if_index, 0, 1);
+ {
+ error = nat44_ei_del_interface (i->sw_if_index, 0);
+ }
if (error)
{
@@ -944,13 +1136,7 @@ nat44_ei_plugin_disable ()
pool = pool_dup (nm->output_feature_interfaces);
pool_foreach (i, pool)
{
- if (nat44_ei_interface_is_inside (i))
- error =
- nat44_ei_interface_add_del_output_feature (i->sw_if_index, 1, 1);
- if (nat44_ei_interface_is_outside (i))
- error =
- nat44_ei_interface_add_del_output_feature (i->sw_if_index, 0, 1);
-
+ error = nat44_ei_del_output_interface (i->sw_if_index);
if (error)
{
nat44_ei_log_err ("error occurred while removing interface %u",
@@ -1727,30 +1913,6 @@ nat44_ei_set_alloc_mape (u16 psid, u16 psid_offset, u16 psid_length)
nm->psid_length = psid_length;
}
-static void
-nat44_ei_add_static_mapping_when_resolved (ip4_address_t l_addr, u16 l_port,
- u16 e_port, nat_protocol_t proto,
- u32 sw_if_index, u32 vrf_id,
- int addr_only, int identity_nat,
- u8 *tag)
-{
- nat44_ei_main_t *nm = &nat44_ei_main;
- nat44_ei_static_map_resolve_t *rp;
-
- vec_add2 (nm->to_resolve, rp, 1);
- clib_memset (rp, 0, sizeof (*rp));
-
- rp->l_addr.as_u32 = l_addr.as_u32;
- rp->l_port = l_port;
- rp->e_port = e_port;
- rp->sw_if_index = sw_if_index;
- rp->vrf_id = vrf_id;
- rp->proto = proto;
- rp->addr_only = addr_only;
- rp->identity_nat = identity_nat;
- rp->tag = vec_dup (tag);
-}
-
void
nat44_ei_delete_session (nat44_ei_main_t *nm, nat44_ei_session_t *ses,
u32 thread_index)
@@ -1789,10 +1951,13 @@ nat44_ei_del_session (nat44_ei_main_t *nm, ip4_address_t *addr, u16 port,
{
nat44_ei_main_per_thread_data_t *tnm;
clib_bihash_kv_8_8_t kv, value;
- u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
+ u32 fib_index;
nat44_ei_session_t *s;
clib_bihash_8_8_t *t;
+ fail_if_disabled ();
+
+ fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
init_nat_k (&kv, *addr, port, fib_index, proto);
t = is_in ? &nm->in2out : &nm->out2in;
if (!clib_bihash_search_8_8 (t, &kv, &value))
@@ -1842,412 +2007,563 @@ nat44_ei_add_del_addr_to_fib (ip4_address_t *addr, u8 p_len, u32 sw_if_index,
u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
if (is_add)
- fib_table_entry_update_one_path (
- fib_index, &prefix, nm->fib_src_low,
- (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL |
- FIB_ENTRY_FLAG_EXCLUSIVE),
- DPO_PROTO_IP4, NULL, sw_if_index, ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
+ {
+ fib_table_entry_update_one_path (fib_index, &prefix, nm->fib_src_low,
+ (FIB_ENTRY_FLAG_CONNECTED |
+ FIB_ENTRY_FLAG_LOCAL |
+ FIB_ENTRY_FLAG_EXCLUSIVE),
+ DPO_PROTO_IP4, NULL, sw_if_index, ~0, 1,
+ NULL, FIB_ROUTE_PATH_FLAG_NONE);
+ }
else
- fib_table_entry_delete (fib_index, &prefix, nm->fib_src_low);
+ {
+ fib_table_entry_delete (fib_index, &prefix, nm->fib_src_low);
+ }
}
int
-nat44_ei_add_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
- u16 l_port, u16 e_port, nat_protocol_t proto,
- u32 sw_if_index, u32 vrf_id, u8 addr_only,
- u8 identity_nat, u8 *tag, u8 is_add)
+nat44_ei_reserve_port (ip4_address_t addr, u16 port, nat_protocol_t proto)
{
+ u32 ti = nat44_ei_get_thread_idx_by_port (port);
nat44_ei_main_t *nm = &nat44_ei_main;
- nat44_ei_static_mapping_t *m = 0;
- clib_bihash_kv_8_8_t kv, value;
nat44_ei_address_t *a = 0;
- u32 fib_index = ~0;
- nat44_ei_interface_t *interface;
- nat44_ei_main_per_thread_data_t *tnm;
- nat44_ei_user_key_t u_key;
- nat44_ei_user_t *u;
- dlist_elt_t *head, *elt;
- u32 elt_index, head_index;
- u32 ses_index;
- u64 user_index;
- nat44_ei_session_t *s;
- nat44_ei_static_map_resolve_t *rp, *rp_match = 0;
- nat44_ei_lb_addr_port_t *local;
- u32 find = ~0;
int i;
- if (sw_if_index != ~0)
+ for (i = 0; i < vec_len (nm->addresses); i++)
{
- ip4_address_t *first_int_addr;
-
- for (i = 0; i < vec_len (nm->to_resolve); i++)
- {
- rp = nm->to_resolve + i;
- if (rp->sw_if_index != sw_if_index ||
- rp->l_addr.as_u32 != l_addr.as_u32 || rp->vrf_id != vrf_id ||
- rp->addr_only != addr_only)
- continue;
-
- if (!addr_only)
- {
- if ((rp->l_port != l_port && rp->e_port != e_port) ||
- rp->proto != proto)
- continue;
- }
-
- rp_match = rp;
- break;
- }
+ a = nm->addresses + i;
- /* Might be already set... */
- first_int_addr = ip4_interface_first_address (
- nm->ip4_main, sw_if_index, 0 /* just want the address */);
+ if (a->addr.as_u32 != addr.as_u32)
+ continue;
- if (is_add)
+ switch (proto)
{
- if (rp_match)
- return VNET_API_ERROR_VALUE_EXIST;
+#define _(N, j, n, s) \
+ case NAT_PROTOCOL_##N: \
+ if (a->busy_##n##_port_refcounts[port]) \
+ goto done; \
+ ++a->busy_##n##_port_refcounts[port]; \
+ if (port > 1024) \
+ { \
+ a->busy_##n##_ports++; \
+ a->busy_##n##_ports_per_thread[ti]++; \
+ } \
+ break;
+ foreach_nat_protocol
+#undef _
+ default : nat_elog_info (nm, "unknown protocol");
+ goto done;
+ }
- nat44_ei_add_static_mapping_when_resolved (
- l_addr, l_port, e_port, proto, sw_if_index, vrf_id, addr_only,
- identity_nat, tag);
+ return 0;
+ }
- /* DHCP resolution required? */
- if (!first_int_addr)
- return 0;
+done:
+ return 1;
+}
- e_addr.as_u32 = first_int_addr->as_u32;
- /* Identity mapping? */
- if (l_addr.as_u32 == 0)
- l_addr.as_u32 = e_addr.as_u32;
- }
- else
- {
- if (!rp_match)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
+int
+nat44_ei_free_port (ip4_address_t addr, u16 port, nat_protocol_t proto)
+{
+ u32 ti = nat44_ei_get_thread_idx_by_port (port);
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_address_t *a = 0;
+ int i;
- vec_del1 (nm->to_resolve, i);
+ for (i = 0; i < vec_len (nm->addresses); i++)
+ {
+ a = nm->addresses + i;
- if (!first_int_addr)
- return 0;
+ if (a->addr.as_u32 != addr.as_u32)
+ continue;
- e_addr.as_u32 = first_int_addr->as_u32;
- /* Identity mapping? */
- if (l_addr.as_u32 == 0)
- l_addr.as_u32 = e_addr.as_u32;
+ switch (proto)
+ {
+#define _(N, j, n, s) \
+ case NAT_PROTOCOL_##N: \
+ --a->busy_##n##_port_refcounts[port]; \
+ if (port > 1024) \
+ { \
+ a->busy_##n##_ports--; \
+ a->busy_##n##_ports_per_thread[ti]--; \
+ } \
+ break;
+ foreach_nat_protocol
+#undef _
+ default : nat_elog_info (nm, "unknown protocol");
+ goto done;
}
+
+ return 0;
}
- init_nat_k (&kv, e_addr, addr_only ? 0 : e_port, 0, addr_only ? 0 : proto);
- if (!clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
- m = pool_elt_at_index (nm->static_mappings, value.value);
+done:
+ return 1;
+}
- if (is_add)
- {
- if (m)
- {
- // identity mapping for second vrf
- if (nat44_ei_is_identity_static_mapping (m))
- {
- pool_foreach (local, m->locals)
- {
- if (local->vrf_id == vrf_id)
- return VNET_API_ERROR_VALUE_EXIST;
- }
- pool_get (m->locals, local);
- local->vrf_id = vrf_id;
- local->fib_index = fib_table_find_or_create_and_lock (
- FIB_PROTOCOL_IP4, vrf_id, nm->fib_src_low);
- init_nat_kv (&kv, m->local_addr, m->local_port, local->fib_index,
- m->proto, 0, m - nm->static_mappings);
- clib_bihash_add_del_8_8 (&nm->static_mapping_by_local, &kv, 1);
- return 0;
- }
- return VNET_API_ERROR_VALUE_EXIST;
- }
+void
+nat44_ei_add_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port,
+ nat_protocol_t proto, u32 vrf_id, u32 sw_if_index,
+ u32 flags, ip4_address_t pool_addr, u8 *tag)
+{
+ nat44_ei_static_map_resolve_t *rp;
+ nat44_ei_main_t *nm = &nat44_ei_main;
- /* Convert VRF id to FIB index */
- if (vrf_id != ~0)
- {
- fib_index = fib_table_find_or_create_and_lock (
- FIB_PROTOCOL_IP4, vrf_id, nm->fib_src_low);
- }
- /* If not specified use inside VRF id from NAT44 plugin config */
- else
- {
- fib_index = nm->inside_fib_index;
- vrf_id = nm->inside_vrf_id;
- fib_table_lock (fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
- }
+ vec_add2 (nm->to_resolve, rp, 1);
+ rp->l_addr.as_u32 = l_addr.as_u32;
+ rp->l_port = l_port;
+ rp->e_port = e_port;
+ rp->sw_if_index = sw_if_index;
+ rp->vrf_id = vrf_id;
+ rp->proto = proto;
+ rp->flags = flags;
+ rp->pool_addr = pool_addr;
+ rp->tag = vec_dup (tag);
+}
- if (!identity_nat)
- {
- init_nat_k (&kv, l_addr, addr_only ? 0 : l_port, fib_index,
- addr_only ? 0 : proto);
- if (!clib_bihash_search_8_8 (&nm->static_mapping_by_local, &kv,
- &value))
- return VNET_API_ERROR_VALUE_EXIST;
- }
+int
+nat44_ei_get_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port,
+ nat_protocol_t proto, u32 vrf_id, u32 sw_if_index,
+ u32 flags, int *out)
+{
+ nat44_ei_static_map_resolve_t *rp;
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ int i;
+
+ for (i = 0; i < vec_len (nm->to_resolve); i++)
+ {
+ rp = nm->to_resolve + i;
- /* Find external address in allocated addresses and reserve port for
- address and port pair mapping when dynamic translations enabled */
- if (!(addr_only || nm->static_mapping_only))
+ if (rp->sw_if_index == sw_if_index && rp->vrf_id == vrf_id)
{
- for (i = 0; i < vec_len (nm->addresses); i++)
+ if (is_sm_identity_nat (rp->flags) && is_sm_identity_nat (flags))
{
- if (nm->addresses[i].addr.as_u32 == e_addr.as_u32)
+ if (!(is_sm_addr_only (rp->flags) && is_sm_addr_only (flags)))
{
- a = nm->addresses + i;
- /* External port must be unused */
- switch (proto)
+ if (rp->e_port != e_port || rp->proto != proto)
{
-#define _(N, j, n, s) \
- case NAT_PROTOCOL_##N: \
- if (a->busy_##n##_port_refcounts[e_port]) \
- return VNET_API_ERROR_INVALID_VALUE; \
- ++a->busy_##n##_port_refcounts[e_port]; \
- if (e_port > 1024) \
- { \
- a->busy_##n##_ports++; \
- a->busy_##n##_ports_per_thread[nat44_ei_get_thread_idx_by_port ( \
- e_port)]++; \
- } \
- break;
- foreach_nat_protocol
-#undef _
- default : nat_elog_info (nm, "unknown protocol");
- return VNET_API_ERROR_INVALID_VALUE_2;
+ continue;
}
- break;
}
}
- /* External address must be allocated */
- if (!a && (l_addr.as_u32 != e_addr.as_u32))
+ else if (rp->l_addr.as_u32 == l_addr.as_u32)
{
- if (sw_if_index != ~0)
+ if (!(is_sm_addr_only (rp->flags) && is_sm_addr_only (flags)))
{
- for (i = 0; i < vec_len (nm->to_resolve); i++)
+ if (rp->l_port != l_port || rp->e_port != e_port ||
+ rp->proto != proto)
{
- rp = nm->to_resolve + i;
- if (rp->addr_only)
- continue;
- if (rp->sw_if_index != sw_if_index &&
- rp->l_addr.as_u32 != l_addr.as_u32 &&
- rp->vrf_id != vrf_id && rp->l_port != l_port &&
- rp->e_port != e_port && rp->proto != proto)
- continue;
-
- vec_del1 (nm->to_resolve, i);
- break;
+ continue;
}
}
- return VNET_API_ERROR_NO_SUCH_ENTRY;
}
+ else
+ {
+ continue;
+ }
+ if (out)
+ {
+ *out = i;
+ }
+ return 0;
}
+ }
+ return 1;
+}
- pool_get (nm->static_mappings, m);
- clib_memset (m, 0, sizeof (*m));
- m->tag = vec_dup (tag);
- m->local_addr = l_addr;
- m->external_addr = e_addr;
+int
+nat44_ei_del_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port,
+ nat_protocol_t proto, u32 vrf_id, u32 sw_if_index,
+ u32 flags)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ int i;
+ if (!nat44_ei_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
+ sw_if_index, flags, &i))
+ {
+ vec_del1 (nm->to_resolve, i);
+ return 0;
+ }
+ return 1;
+}
- if (addr_only)
- m->flags |= NAT44_EI_STATIC_MAPPING_FLAG_ADDR_ONLY;
- else
+void
+delete_matching_dynamic_sessions (const nat44_ei_static_mapping_t *m,
+ u32 worker_index)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ clib_bihash_kv_8_8_t kv, value;
+ nat44_ei_session_t *s;
+ nat44_ei_user_key_t u_key;
+ nat44_ei_user_t *u;
+ nat44_ei_main_per_thread_data_t *tnm;
+ dlist_elt_t *head, *elt;
+ u32 elt_index, head_index;
+ u32 ses_index;
+ u64 user_index;
+
+ if (nm->static_mapping_only)
+ return;
+
+ tnm = vec_elt_at_index (nm->per_thread_data, worker_index);
+
+ 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 (&tnm->user_hash, &kv, &value))
+ {
+ user_index = value.value;
+ u = pool_elt_at_index (tnm->users, user_index);
+ if (u->nsessions)
{
- m->local_port = l_port;
- m->external_port = e_port;
- m->proto = proto;
+ head_index = u->sessions_per_user_list_head_index;
+ head = pool_elt_at_index (tnm->list_pool, head_index);
+ elt_index = head->next;
+ elt = pool_elt_at_index (tnm->list_pool, elt_index);
+ ses_index = elt->value;
+ while (ses_index != ~0)
+ {
+ s = pool_elt_at_index (tnm->sessions, ses_index);
+ elt = pool_elt_at_index (tnm->list_pool, elt->next);
+ ses_index = elt->value;
+
+ if (nat44_ei_is_session_static (s))
+ continue;
+
+ if (!is_sm_addr_only (m->flags) &&
+ s->in2out.port != m->local_port)
+ continue;
+
+ nat44_ei_free_session_data_v2 (nm, s, tnm - nm->per_thread_data,
+ 0);
+ nat44_ei_delete_session (nm, s, tnm - nm->per_thread_data);
+
+ if (!is_sm_addr_only (m->flags))
+ break;
+ }
}
+ }
+}
+
+int
+nat44_ei_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
+ u16 l_port, u16 e_port, nat_protocol_t proto,
+ u32 vrf_id, u32 sw_if_index, u32 flags,
+ ip4_address_t pool_addr, u8 *tag)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ clib_bihash_kv_8_8_t kv, value;
+ nat44_ei_lb_addr_port_t *local;
+ nat44_ei_static_mapping_t *m;
+ u32 fib_index = ~0;
+ u32 worker_index;
+
+ fail_if_disabled ();
+
+ if (is_sm_addr_only (flags))
+ {
+ e_port = l_port = proto = 0;
+ }
- if (identity_nat)
+ if (sw_if_index != ~0)
+ {
+ // this mapping is interface bound
+ ip4_address_t *first_int_addr;
+
+ // check if this record isn't registered for resolve
+ if (!nat44_ei_get_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
+ sw_if_index, flags, 0))
{
- m->flags |= NAT44_EI_STATIC_MAPPING_FLAG_IDENTITY_NAT;
- pool_get (m->locals, local);
- local->vrf_id = vrf_id;
- local->fib_index = fib_index;
+ return VNET_API_ERROR_VALUE_EXIST;
}
- else
+ // register record for resolve
+ nat44_ei_add_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
+ sw_if_index, flags, pool_addr, tag);
+
+ first_int_addr =
+ ip4_interface_first_address (nm->ip4_main, sw_if_index, 0);
+ if (!first_int_addr)
{
- m->vrf_id = vrf_id;
- m->fib_index = fib_index;
+ // dhcp resolution required
+ return 0;
}
- if (nm->num_workers > 1)
+ e_addr.as_u32 = first_int_addr->as_u32;
+ }
+
+ if (is_sm_identity_nat (flags))
+ {
+ l_port = e_port;
+ l_addr.as_u32 = e_addr.as_u32;
+ }
+
+ // fib index 0
+ init_nat_k (&kv, e_addr, e_port, 0, proto);
+
+ if (!clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
+ {
+ m = pool_elt_at_index (nm->static_mappings, value.value);
+ if (!is_sm_identity_nat (m->flags))
{
- ip4_header_t ip = {
- .src_address = m->local_addr,
- };
- vec_add1 (m->workers,
- nat44_ei_get_in2out_worker_index (&ip, m->fib_index, 0));
- tnm = vec_elt_at_index (nm->per_thread_data, m->workers[0]);
+ return VNET_API_ERROR_VALUE_EXIST;
}
- else
- tnm = vec_elt_at_index (nm->per_thread_data, nm->num_workers);
- init_nat_kv (&kv, m->local_addr, m->local_port, fib_index, m->proto, 0,
- m - nm->static_mappings);
+ // case:
+ // adding local identity nat record for different vrf table
+ pool_foreach (local, m->locals)
+ {
+ if (local->vrf_id == vrf_id)
+ {
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
+ }
+
+ pool_get (m->locals, local);
+
+ local->vrf_id = vrf_id;
+ local->fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP4, vrf_id, nm->fib_src_low);
+
+ init_nat_kv (&kv, m->local_addr, m->local_port, local->fib_index,
+ m->proto, 0, m - nm->static_mappings);
clib_bihash_add_del_8_8 (&nm->static_mapping_by_local, &kv, 1);
- init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto, 0,
- m - nm->static_mappings);
- clib_bihash_add_del_8_8 (&nm->static_mapping_by_external, &kv, 1);
+ return 0;
+ }
+
+ if (vrf_id != ~0)
+ {
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
+ nm->fib_src_low);
+ }
+ else
+ {
+ // fallback to default vrf
+ vrf_id = nm->inside_vrf_id;
+ fib_index = nm->inside_fib_index;
+ fib_table_lock (fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
+ }
+
+ if (!is_sm_identity_nat (flags))
+ {
+ init_nat_k (&kv, l_addr, l_port, fib_index, proto);
+ if (!clib_bihash_search_8_8 (&nm->static_mapping_by_local, &kv, &value))
+ {
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
+ }
- /* Delete dynamic sessions matching local address (+ local port) */
- // TODO: based on type of NAT EI/ED
- if (!(nm->static_mapping_only))
+ if (!(is_sm_addr_only (flags) || nm->static_mapping_only))
+ {
+ if (nat44_ei_reserve_port (e_addr, e_port, proto))
{
- 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 (&tnm->user_hash, &kv, &value))
+ // remove resolve record
+ if ((sw_if_index != ~0) && !is_sm_identity_nat (flags))
{
- user_index = value.value;
- u = pool_elt_at_index (tnm->users, user_index);
- if (u->nsessions)
- {
- head_index = u->sessions_per_user_list_head_index;
- head = pool_elt_at_index (tnm->list_pool, head_index);
- elt_index = head->next;
- elt = pool_elt_at_index (tnm->list_pool, elt_index);
- ses_index = elt->value;
- while (ses_index != ~0)
- {
- s = pool_elt_at_index (tnm->sessions, ses_index);
- elt = pool_elt_at_index (tnm->list_pool, elt->next);
- ses_index = elt->value;
+ nat44_ei_del_resolve_record (l_addr, l_port, e_port, proto,
+ vrf_id, sw_if_index, flags);
+ }
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+ }
- if (nat44_ei_is_session_static (s))
- continue;
+ pool_get (nm->static_mappings, m);
+ clib_memset (m, 0, sizeof (*m));
- if (!addr_only && s->in2out.port != m->local_port)
- continue;
+ m->flags = flags;
+ m->local_addr = l_addr;
+ m->external_addr = e_addr;
- nat44_ei_free_session_data_v2 (
- nm, s, tnm - nm->per_thread_data, 0);
- nat44_ei_delete_session (nm, s,
- tnm - nm->per_thread_data);
+ m->tag = vec_dup (tag);
- if (!addr_only)
- break;
- }
- }
- }
- }
+ if (!is_sm_addr_only (flags))
+ {
+ m->local_port = l_port;
+ m->external_port = e_port;
+ m->proto = proto;
+ }
+
+ if (is_sm_identity_nat (flags))
+ {
+ pool_get (m->locals, local);
+
+ local->vrf_id = vrf_id;
+ local->fib_index = fib_index;
}
else
{
- if (!m)
+ m->vrf_id = vrf_id;
+ m->fib_index = fib_index;
+ }
+
+ init_nat_kv (&kv, m->local_addr, m->local_port, fib_index, m->proto, 0,
+ m - nm->static_mappings);
+ clib_bihash_add_del_8_8 (&nm->static_mapping_by_local, &kv, 1);
+
+ init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto, 0,
+ m - nm->static_mappings);
+ clib_bihash_add_del_8_8 (&nm->static_mapping_by_external, &kv, 1);
+
+ if (nm->num_workers > 1)
+ {
+ // store worker index for this record
+ ip4_header_t ip = {
+ .src_address = m->local_addr,
+ };
+ worker_index = nat44_ei_get_in2out_worker_index (&ip, m->fib_index, 0);
+ vec_add1 (m->workers, worker_index);
+ }
+ else
+ {
+ worker_index = nm->num_workers;
+ }
+ delete_matching_dynamic_sessions (m, worker_index);
+
+ if (is_sm_addr_only (flags))
+ {
+ nat44_ei_add_del_addr_to_fib_foreach_out_if (&e_addr, 1);
+ }
+
+ return 0;
+}
+
+int
+nat44_ei_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
+ u16 l_port, u16 e_port, nat_protocol_t proto,
+ u32 vrf_id, u32 sw_if_index, u32 flags)
+{
+ nat44_ei_main_per_thread_data_t *tnm;
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ clib_bihash_kv_8_8_t kv, value;
+ nat44_ei_lb_addr_port_t *local;
+ nat44_ei_static_mapping_t *m;
+ u32 fib_index = ~0;
+ nat44_ei_user_key_t u_key;
+
+ fail_if_disabled ();
+
+ if (is_sm_addr_only (flags))
+ {
+ e_port = l_port = proto = 0;
+ }
+
+ if (sw_if_index != ~0)
+ {
+ // this mapping is interface bound
+ ip4_address_t *first_int_addr;
+
+ // delete record registered for resolve
+ if (nat44_ei_del_resolve_record (l_addr, l_port, e_port, proto, vrf_id,
+ sw_if_index, flags))
{
- if (sw_if_index != ~0)
- return 0;
- else
- return VNET_API_ERROR_NO_SUCH_ENTRY;
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
}
- if (identity_nat)
+ first_int_addr =
+ ip4_interface_first_address (nm->ip4_main, sw_if_index, 0);
+ if (!first_int_addr)
{
- if (vrf_id == ~0)
- vrf_id = nm->inside_vrf_id;
+ // dhcp resolution required
+ return 0;
+ }
- pool_foreach (local, m->locals)
- {
- if (local->vrf_id == vrf_id)
- find = local - m->locals;
- }
- if (find == ~0)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
+ e_addr.as_u32 = first_int_addr->as_u32;
+ }
+
+ if (is_sm_identity_nat (flags))
+ {
+ l_port = e_port;
+ l_addr.as_u32 = e_addr.as_u32;
+ }
- local = pool_elt_at_index (m->locals, find);
- fib_index = local->fib_index;
- pool_put (m->locals, local);
+ // fib index 0
+ init_nat_k (&kv, e_addr, e_port, 0, proto);
+
+ if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
+ {
+ if (sw_if_index != ~0)
+ {
+ return 0;
}
- else
- fib_index = m->fib_index;
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+
+ m = pool_elt_at_index (nm->static_mappings, value.value);
+
+ if (is_sm_identity_nat (flags))
+ {
+ u8 found = 0;
- /* Free external address port */
- if (!(addr_only || nm->static_mapping_only))
+ if (vrf_id == ~0)
{
- for (i = 0; i < vec_len (nm->addresses); i++)
+ vrf_id = nm->inside_vrf_id;
+ }
+
+ pool_foreach (local, m->locals)
+ {
+ if (local->vrf_id == vrf_id)
{
- if (nm->addresses[i].addr.as_u32 == e_addr.as_u32)
- {
- a = nm->addresses + i;
- switch (proto)
- {
-#define _(N, j, n, s) \
- case NAT_PROTOCOL_##N: \
- --a->busy_##n##_port_refcounts[e_port]; \
- if (e_port > 1024) \
- { \
- a->busy_##n##_ports--; \
- a->busy_##n##_ports_per_thread[nat44_ei_get_thread_idx_by_port ( \
- e_port)]--; \
- } \
- break;
- foreach_nat_protocol
-#undef _
- default : return VNET_API_ERROR_INVALID_VALUE_2;
- }
- break;
- }
+ local = pool_elt_at_index (m->locals, local - m->locals);
+ fib_index = local->fib_index;
+ pool_put (m->locals, local);
+ found = 1;
}
}
+ if (!found)
+ {
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
+ }
+ else
+ {
+ fib_index = m->fib_index;
+ }
+ if (!(is_sm_addr_only (flags) || nm->static_mapping_only))
+ {
+ if (nat44_ei_free_port (e_addr, e_port, proto))
+ {
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+ }
+
+ init_nat_k (&kv, l_addr, l_port, fib_index, proto);
+ clib_bihash_add_del_8_8 (&nm->static_mapping_by_local, &kv, 0);
+
+ if (!nm->static_mapping_only || nm->static_mapping_connection_tracking)
+ {
+ // delete sessions for static mapping
if (nm->num_workers > 1)
tnm = vec_elt_at_index (nm->per_thread_data, m->workers[0]);
else
tnm = vec_elt_at_index (nm->per_thread_data, nm->num_workers);
- init_nat_k (&kv, m->local_addr, m->local_port, fib_index, m->proto);
- clib_bihash_add_del_8_8 (&nm->static_mapping_by_local, &kv, 0);
-
- /* Delete session(s) for static mapping if exist */
- if (!(nm->static_mapping_only) ||
- (nm->static_mapping_only && nm->static_mapping_connection_tracking))
- {
- u_key.addr = m->local_addr;
- u_key.fib_index = fib_index;
- kv.key = u_key.as_u64;
- nat44_ei_static_mapping_del_sessions (nm, tnm, u_key, addr_only,
- e_addr, e_port);
- }
+ u_key.addr = m->local_addr;
+ u_key.fib_index = fib_index;
+ kv.key = u_key.as_u64;
+ nat44_ei_static_mapping_del_sessions (
+ nm, tnm, u_key, is_sm_addr_only (flags), e_addr, e_port);
+ }
- fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
- if (pool_elts (m->locals))
- return 0;
+ fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
- init_nat_k (&kv, m->external_addr, m->external_port, 0, m->proto);
+ if (!pool_elts (m->locals))
+ {
+ // this is last record remove all required stuff
+ // fib_index 0
+ init_nat_k (&kv, e_addr, e_port, 0, proto);
clib_bihash_add_del_8_8 (&nm->static_mapping_by_external, &kv, 0);
vec_free (m->tag);
vec_free (m->workers);
- /* Delete static mapping from pool */
pool_put (nm->static_mappings, m);
- }
-
- if (!addr_only || (l_addr.as_u32 == e_addr.as_u32))
- return 0;
-
- /* Add/delete external address to FIB */
- pool_foreach (interface, nm->interfaces)
- {
- if (nat44_ei_interface_is_inside (interface) || nm->out2in_dpo)
- continue;
- nat44_ei_add_del_addr_to_fib (&e_addr, 32, interface->sw_if_index,
- is_add);
- break;
+ if (is_sm_addr_only (flags) && !is_sm_identity_nat (flags))
+ {
+ nat44_ei_add_del_addr_to_fib_foreach_out_if (&e_addr, 0);
+ }
}
- pool_foreach (interface, nm->output_feature_interfaces)
- {
- if (nat44_ei_interface_is_inside (interface) || nm->out2in_dpo)
- continue;
- nat44_ei_add_del_addr_to_fib (&e_addr, 32, interface->sw_if_index,
- is_add);
- break;
- }
return 0;
}
@@ -2302,16 +2618,16 @@ nat44_ei_static_mapping_match (ip4_address_t match_addr, u16 match_port,
}
/* Address only mapping doesn't change port */
- if (nat44_ei_is_addr_only_static_mapping (m))
+ if (is_sm_addr_only (m->flags))
*mapping_port = match_port;
else
*mapping_port = port;
if (PREDICT_FALSE (is_addr_only != 0))
- *is_addr_only = nat44_ei_is_addr_only_static_mapping (m);
+ *is_addr_only = is_sm_addr_only (m->flags);
if (PREDICT_FALSE (is_identity_nat != 0))
- *is_identity_nat = nat44_ei_is_identity_static_mapping (m);
+ *is_identity_nat = is_sm_identity_nat (m->flags);
return 0;
}
@@ -2574,11 +2890,13 @@ nat44_ei_update_outside_fib (ip4_main_t *im, uword opaque, u32 sw_if_index,
}
int
-nat44_ei_add_address (nat44_ei_main_t *nm, ip4_address_t *addr, u32 vrf_id)
+nat44_ei_add_address (ip4_address_t *addr, u32 vrf_id)
{
- nat44_ei_address_t *ap;
- nat44_ei_interface_t *i;
+ nat44_ei_main_t *nm = &nat44_ei_main;
vlib_thread_main_t *tm = vlib_get_thread_main ();
+ nat44_ei_address_t *ap;
+
+ fail_if_disabled ();
/* Check if address already exists */
vec_foreach (ap, nm->addresses)
@@ -2592,12 +2910,14 @@ nat44_ei_add_address (nat44_ei_main_t *nm, ip4_address_t *addr, u32 vrf_id)
vec_add2 (nm->addresses, ap, 1);
+ ap->fib_index = ~0;
ap->addr = *addr;
+
if (vrf_id != ~0)
- ap->fib_index = fib_table_find_or_create_and_lock (
- FIB_PROTOCOL_IP4, vrf_id, nm->fib_src_low);
- else
- ap->fib_index = ~0;
+ {
+ ap->fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP4, vrf_id, nm->fib_src_low);
+ }
#define _(N, i, n, s) \
clib_memset (ap->busy_##n##_port_refcounts, 0, \
@@ -2609,120 +2929,30 @@ nat44_ei_add_address (nat44_ei_main_t *nm, ip4_address_t *addr, u32 vrf_id)
foreach_nat_protocol
#undef _
- /* Add external address to FIB */
- pool_foreach (i, nm->interfaces)
- {
- if (nat44_ei_interface_is_inside (i) || nm->out2in_dpo)
- continue;
-
- nat44_ei_add_del_addr_to_fib (addr, 32, i->sw_if_index, 1);
- break;
- }
- pool_foreach (i, nm->output_feature_interfaces)
- {
- if (nat44_ei_interface_is_inside (i) || nm->out2in_dpo)
- continue;
-
- nat44_ei_add_del_addr_to_fib (addr, 32, i->sw_if_index, 1);
- break;
- }
+ nat44_ei_add_del_addr_to_fib_foreach_out_if (addr, 1);
return 0;
}
int
-nat44_ei_add_interface_address (nat44_ei_main_t *nm, u32 sw_if_index,
- int is_del)
-{
- ip4_main_t *ip4_main = nm->ip4_main;
- ip4_address_t *first_int_addr;
- nat44_ei_static_map_resolve_t *rp;
- u32 *indices_to_delete = 0;
- int i, j;
- u32 *auto_add_sw_if_indices = nm->auto_add_sw_if_indices;
-
- first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index,
- 0 /* just want the address */);
-
- for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
- {
- if (auto_add_sw_if_indices[i] == sw_if_index)
- {
- if (is_del)
- {
- /* if have address remove it */
- if (first_int_addr)
- (void) nat44_ei_del_address (nm, first_int_addr[0], 1);
- else
- {
- for (j = 0; j < vec_len (nm->to_resolve); j++)
- {
- rp = nm->to_resolve + j;
- if (rp->sw_if_index == sw_if_index)
- vec_add1 (indices_to_delete, j);
- }
- if (vec_len (indices_to_delete))
- {
- for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
- vec_del1 (nm->to_resolve, j);
- vec_free (indices_to_delete);
- }
- }
- vec_del1 (nm->auto_add_sw_if_indices, i);
- }
- else
- return VNET_API_ERROR_VALUE_EXIST;
-
- return 0;
- }
- }
-
- if (is_del)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- /* add to the auto-address list */
- vec_add1 (nm->auto_add_sw_if_indices, sw_if_index);
-
- /* If the address is already bound - or static - add it now */
- if (first_int_addr)
- (void) nat44_ei_add_address (nm, first_int_addr, ~0);
-
- return 0;
-}
-
-static int
-nat44_ei_is_address_used_in_static_mapping (ip4_address_t addr)
+nat44_ei_del_address (ip4_address_t addr, u8 delete_sm)
{
nat44_ei_main_t *nm = &nat44_ei_main;
- nat44_ei_static_mapping_t *m;
- pool_foreach (m, nm->static_mappings)
- {
- if (nat44_ei_is_addr_only_static_mapping (m) ||
- nat44_ei_is_identity_static_mapping (m))
- continue;
- if (m->external_addr.as_u32 == addr.as_u32)
- return 1;
- }
- return 0;
-}
-
-int
-nat44_ei_del_address (nat44_ei_main_t *nm, ip4_address_t addr, u8 delete_sm)
-{
nat44_ei_address_t *a = 0;
nat44_ei_session_t *ses;
u32 *ses_to_be_removed = 0, *ses_index;
nat44_ei_main_per_thread_data_t *tnm;
- nat44_ei_interface_t *interface;
nat44_ei_static_mapping_t *m;
- int i;
+ int j;
+
+ fail_if_disabled ();
/* Find SNAT address */
- for (i = 0; i < vec_len (nm->addresses); i++)
+ for (j = 0; j < vec_len (nm->addresses); j++)
{
- if (nm->addresses[i].addr.as_u32 == addr.as_u32)
+ if (nm->addresses[j].addr.as_u32 == addr.as_u32)
{
- a = nm->addresses + i;
+ a = nm->addresses + j;
break;
}
}
@@ -2737,11 +2967,9 @@ nat44_ei_del_address (nat44_ei_main_t *nm, ip4_address_t addr, u8 delete_sm)
pool_foreach (m, nm->static_mappings)
{
if (m->external_addr.as_u32 == addr.as_u32)
- (void) nat44_ei_add_del_static_mapping (
- m->local_addr, m->external_addr, m->local_port, m->external_port,
- m->proto, ~0 /* sw_if_index */, m->vrf_id,
- nat44_ei_is_addr_only_static_mapping (m),
- nat44_ei_is_identity_static_mapping (m), m->tag, 0);
+ nat44_ei_del_static_mapping (m->local_addr, m->external_addr,
+ m->local_port, m->external_port,
+ m->proto, m->vrf_id, ~0, m->flags);
}
}
else
@@ -2755,7 +2983,9 @@ nat44_ei_del_address (nat44_ei_main_t *nm, ip4_address_t addr, u8 delete_sm)
}
if (a->fib_index != ~0)
- fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
+ {
+ fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP4, nm->fib_src_low);
+ }
/* Delete sessions using address */
if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
@@ -2783,25 +3013,107 @@ nat44_ei_del_address (nat44_ei_main_t *nm, ip4_address_t addr, u8 delete_sm)
#define _(N, i, n, s) vec_free (a->busy_##n##_ports_per_thread);
foreach_nat_protocol
#undef _
- vec_del1 (nm->addresses, i);
- /* Delete external address from FIB */
- pool_foreach (interface, nm->interfaces)
+ vec_del1 (nm->addresses, j);
+
+ nat44_ei_add_del_addr_to_fib_foreach_out_if (&addr, 0);
+
+ return 0;
+}
+
+int
+nat44_ei_add_interface_address (u32 sw_if_index)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ ip4_main_t *ip4_main = nm->ip4_main;
+ ip4_address_t *first_int_addr;
+ u32 *auto_add_sw_if_indices = nm->auto_add_sw_if_indices;
+ int i;
+
+ for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
{
- if (nat44_ei_interface_is_inside (interface) || nm->out2in_dpo)
- continue;
- nat44_ei_add_del_addr_to_fib (&addr, 32, interface->sw_if_index, 0);
- break;
+ if (auto_add_sw_if_indices[i] == sw_if_index)
+ {
+ return VNET_API_ERROR_VALUE_EXIST;
+ }
}
- pool_foreach (interface, nm->output_feature_interfaces)
+ /* add to the auto-address list */
+ vec_add1 (nm->auto_add_sw_if_indices, sw_if_index);
+
+ // if the address is already bound - or static - add it now
+ first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0);
+ if (first_int_addr)
{
- if (nat44_ei_interface_is_inside (interface) || nm->out2in_dpo)
- continue;
- nat44_ei_add_del_addr_to_fib (&addr, 32, interface->sw_if_index, 0);
- break;
+ (void) nat44_ei_add_address (first_int_addr, ~0);
+ }
+
+ return 0;
+}
+
+int
+nat44_ei_del_interface_address (u32 sw_if_index)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ ip4_main_t *ip4_main = nm->ip4_main;
+ ip4_address_t *first_int_addr;
+ nat44_ei_static_map_resolve_t *rp;
+ u32 *indices_to_delete = 0;
+ int i, j;
+ u32 *auto_add_sw_if_indices = nm->auto_add_sw_if_indices;
+
+ fail_if_disabled ();
+
+ first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0);
+
+ for (i = 0; i < vec_len (auto_add_sw_if_indices); i++)
+ {
+ if (auto_add_sw_if_indices[i] == sw_if_index)
+ {
+ first_int_addr =
+ ip4_interface_first_address (ip4_main, sw_if_index, 0);
+ if (first_int_addr)
+ {
+ (void) nat44_ei_del_address (first_int_addr[0], 1);
+ }
+ else
+ {
+ for (j = 0; j < vec_len (nm->to_resolve); j++)
+ {
+ rp = nm->to_resolve + j;
+ if (rp->sw_if_index == sw_if_index)
+ {
+ vec_add1 (indices_to_delete, j);
+ }
+ }
+ if (vec_len (indices_to_delete))
+ {
+ for (j = vec_len (indices_to_delete) - 1; j >= 0; j--)
+ {
+ vec_del1 (nm->to_resolve, j);
+ }
+ vec_free (indices_to_delete);
+ }
+ }
+
+ vec_del1 (nm->auto_add_sw_if_indices, i);
+ return 0;
+ }
}
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+}
+static_always_inline int
+is_sw_if_index_reg_for_auto_resolve (u32 *sw_if_indices, u32 sw_if_index)
+{
+ u32 *i;
+ vec_foreach (i, sw_if_indices)
+ {
+ if (*i == sw_if_index)
+ {
+ return 1;
+ }
+ }
return 0;
}
@@ -2814,61 +3126,59 @@ nat44_ei_ip4_add_del_interface_address_cb (ip4_main_t *im, uword opaque,
{
nat44_ei_main_t *nm = &nat44_ei_main;
nat44_ei_static_map_resolve_t *rp;
- ip4_address_t l_addr;
- int i, j;
- int rv;
nat44_ei_address_t *addresses = nm->addresses;
+ int rv, i;
if (!nm->enabled)
- return;
-
- for (i = 0; i < vec_len (nm->auto_add_sw_if_indices); i++)
{
- if (sw_if_index == nm->auto_add_sw_if_indices[i])
- goto match;
+ return;
}
- return;
+ if (!is_sw_if_index_reg_for_auto_resolve (nm->auto_add_sw_if_indices,
+ sw_if_index))
+ {
+ return;
+ }
-match:
if (!is_delete)
{
/* Don't trip over lease renewal, static config */
- for (j = 0; j < vec_len (addresses); j++)
- if (addresses[j].addr.as_u32 == address->as_u32)
- return;
+ for (i = 0; i < vec_len (addresses); i++)
+ {
+ if (addresses[i].addr.as_u32 == address->as_u32)
+ {
+ return;
+ }
+ }
+
+ (void) nat44_ei_add_address (address, ~0);
- (void) nat44_ei_add_address (nm, address, ~0);
/* Scan static map resolution vector */
- for (j = 0; j < vec_len (nm->to_resolve); j++)
+ for (i = 0; i < vec_len (nm->to_resolve); i++)
{
- rp = nm->to_resolve + j;
- if (rp->addr_only)
- continue;
+ rp = nm->to_resolve + i;
+ if (is_sm_addr_only (rp->flags))
+ {
+ continue;
+ }
/* On this interface? */
if (rp->sw_if_index == sw_if_index)
{
- /* Indetity mapping? */
- if (rp->l_addr.as_u32 == 0)
- l_addr.as_u32 = address[0].as_u32;
- else
- l_addr.as_u32 = rp->l_addr.as_u32;
- /* Add the static mapping */
- rv = nat44_ei_add_del_static_mapping (
- l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
- ~0 /* sw_if_index */, rp->vrf_id, rp->addr_only,
- rp->identity_nat, rp->tag, 1);
+ rv = nat44_ei_add_static_mapping (
+ rp->l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
+ rp->vrf_id, ~0, rp->flags, rp->pool_addr, rp->tag);
if (rv)
- nat_elog_notice_X1 (
- nm, "nat44_ei_add_del_static_mapping returned %d", "i4", rv);
+ {
+ nat_elog_notice_X1 (nm, "add_static_mapping returned %d",
+ "i4", rv);
+ }
}
}
- return;
}
else
{
- (void) nat44_ei_del_address (nm, address[0], 1);
- return;
+ // remove all static mapping records
+ (void) nat44_ei_del_address (address[0], 1);
}
}
@@ -2891,57 +3201,63 @@ nat44_ei_ip4_add_del_addr_only_sm_cb (ip4_main_t *im, uword opaque,
nat44_ei_static_map_resolve_t *rp;
nat44_ei_static_mapping_t *m;
clib_bihash_kv_8_8_t kv, value;
- int i, rv;
- ip4_address_t l_addr;
+ int i, rv = 0, match = 0;
if (!nm->enabled)
- return;
+ {
+ return;
+ }
for (i = 0; i < vec_len (nm->to_resolve); i++)
{
rp = nm->to_resolve + i;
- if (rp->addr_only == 0)
- continue;
- if (rp->sw_if_index == sw_if_index)
- goto match;
+
+ if (is_sm_addr_only (rp->flags) && rp->sw_if_index == sw_if_index)
+ {
+ match = 1;
+ break;
+ }
}
- return;
+ if (!match)
+ {
+ return;
+ }
-match:
- init_nat_k (&kv, *address, rp->addr_only ? 0 : rp->e_port,
- nm->outside_fib_index, rp->addr_only ? 0 : rp->proto);
+ init_nat_k (&kv, *address, is_sm_addr_only (rp->flags) ? 0 : rp->e_port,
+ nm->outside_fib_index,
+ is_sm_addr_only (rp->flags) ? 0 : rp->proto);
if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
m = 0;
else
m = pool_elt_at_index (nm->static_mappings, value.value);
- if (!is_delete)
+ if (is_delete)
{
- /* Don't trip over lease renewal, static config */
- if (m)
+ if (!m)
return;
+ rv = nat44_ei_del_static_mapping (rp->l_addr, address[0], rp->l_port,
+ rp->e_port, rp->proto, rp->vrf_id, ~0,
+ rp->flags);
+ if (rv)
+ {
+ nat_elog_notice_X1 (nm, "nat44_ei_del_static_mapping returned %d",
+ "i4", rv);
+ }
}
else
{
- if (!m)
+ if (m)
return;
+ rv = nat44_ei_add_static_mapping (rp->l_addr, address[0], rp->l_port,
+ rp->e_port, rp->proto, rp->vrf_id, ~0,
+ rp->flags, rp->pool_addr, rp->tag);
+ if (rv)
+ {
+ nat_elog_notice_X1 (nm, "nat44_ei_add_static_mapping returned %d",
+ "i4", rv);
+ }
}
-
- /* Indetity mapping? */
- if (rp->l_addr.as_u32 == 0)
- l_addr.as_u32 = address[0].as_u32;
- else
- l_addr.as_u32 = rp->l_addr.as_u32;
- /* Add the static mapping */
-
- rv = nat44_ei_add_del_static_mapping (
- l_addr, address[0], rp->l_port, rp->e_port, rp->proto,
- ~0 /* sw_if_index */, rp->vrf_id, rp->addr_only, rp->identity_nat, rp->tag,
- !is_delete);
- if (rv)
- nat_elog_notice_X1 (nm, "nat44_ei_add_del_static_mapping returned %d",
- "i4", rv);
}
static_always_inline uword
diff --git a/src/plugins/nat/nat44-ei/nat44_ei.h b/src/plugins/nat/nat44-ei/nat44_ei.h
index 2e95b1413ca..0134c7882dd 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei.h
+++ b/src/plugins/nat/nat44-ei/nat44_ei.h
@@ -63,8 +63,8 @@ typedef enum
#define NAT44_EI_SESSION_FLAG_UNKNOWN_PROTO (1 << 1)
/* Static mapping flags */
-#define NAT44_EI_STATIC_MAPPING_FLAG_ADDR_ONLY (1 << 0)
-#define NAT44_EI_STATIC_MAPPING_FLAG_IDENTITY_NAT (1 << 1)
+#define NAT44_EI_SM_FLAG_ADDR_ONLY (1 << 0)
+#define NAT44_EI_SM_FLAG_IDENTITY_NAT (1 << 1)
typedef struct
{
@@ -139,13 +139,9 @@ typedef struct
u32 vrf_id;
u32 flags;
nat_protocol_t proto;
- u8 addr_only;
- u8 identity_nat;
- u8 exact;
u8 *tag;
} nat44_ei_static_map_resolve_t;
-// TODO: cleanup/redo (there is no lb in EI nat)
typedef struct
{
/* backend IP address */
@@ -340,6 +336,8 @@ typedef struct nat44_ei_main_s
/* Interface pool */
nat44_ei_interface_t *interfaces;
nat44_ei_interface_t *output_feature_interfaces;
+ // broken api backward compatibility
+ nat44_ei_interface_t *output_feature_dummy_interfaces;
/* Is translation memory size calculated or user defined */
u8 translation_memory_size_set;
@@ -484,9 +482,16 @@ typedef struct nat44_ei_main_s
extern nat44_ei_main_t nat44_ei_main;
int nat44_ei_plugin_enable (nat44_ei_config_t c);
-
int nat44_ei_plugin_disable ();
+int nat44_ei_add_del_interface (u32 sw_if_index, u8 is_inside, int is_del);
+int nat44_ei_add_del_output_interface (u32 sw_if_index, int is_del);
+
+int nat44_ei_add_address (ip4_address_t *addr, u32 vrf_id);
+int nat44_ei_del_address (ip4_address_t addr, u8 delete_sm);
+int nat44_ei_add_interface_address (u32 sw_if_index);
+int nat44_ei_del_interface_address (u32 sw_if_index);
+
/**
* @brief Delete specific NAT44 EI user and his sessions
*
@@ -533,29 +538,14 @@ void nat44_ei_set_alloc_mape (u16 psid, u16 psid_offset, u16 psid_length);
*/
void nat44_ei_set_alloc_range (u16 start_port, u16 end_port);
-/**
- * @brief Add/delete NAT44-EI static mapping
- *
- * @param l_addr local IPv4 address
- * @param e_addr external IPv4 address
- * @param l_port local port number
- * @param e_port external port number
- * @param proto L4 protocol
- * @param sw_if_index use interface address as external IPv4 address
- * @param vrf_id local VRF ID
- * @param addr_only 1 = 1:1NAT, 0 = 1:1NAPT
- * @param identity_nat identity NAT
- * @param tag opaque string tag
- * @param is_add 1 = add, 0 = delete
- *
- * @return 0 on success, non-zero value otherwise
+int nat44_ei_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
+ u16 l_port, u16 e_port, nat_protocol_t proto,
+ u32 vrf_id, u32 sw_if_index, u32 flags,
+ ip4_address_t pool_addr, u8 *tag);
- */
-int nat44_ei_add_del_static_mapping (ip4_address_t l_addr,
- ip4_address_t e_addr, u16 l_port,
- u16 e_port, nat_protocol_t proto,
- u32 sw_if_index, u32 vrf_id, u8 addr_only,
- u8 identity_nat, u8 *tag, u8 is_add);
+int nat44_ei_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
+ u16 l_port, u16 e_port, nat_protocol_t proto,
+ u32 vrf_id, u32 sw_if_index, u32 flags);
/**
* @brief Delete NAT44-EI session
@@ -620,9 +610,6 @@ int nat44_ei_set_outside_address_and_port (nat44_ei_address_t *addresses,
ip4_address_t addr, u16 port,
nat_protocol_t protocol);
-int nat44_ei_del_address (nat44_ei_main_t *nm, ip4_address_t addr,
- u8 delete_sm);
-
void nat44_ei_free_session_data (nat44_ei_main_t *nm, nat44_ei_session_t *s,
u32 thread_index, u8 is_ha);
@@ -630,20 +617,9 @@ int nat44_ei_set_workers (uword *bitmap);
void nat44_ei_add_del_address_dpo (ip4_address_t addr, u8 is_add);
-int nat44_ei_add_address (nat44_ei_main_t *nm, ip4_address_t *addr,
- u32 vrf_id);
-
void nat44_ei_delete_session (nat44_ei_main_t *nm, nat44_ei_session_t *ses,
u32 thread_index);
-int nat44_ei_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del);
-
-int nat44_ei_interface_add_del_output_feature (u32 sw_if_index, u8 is_inside,
- int is_del);
-
-int nat44_ei_add_interface_address (nat44_ei_main_t *nm, u32 sw_if_index,
- int is_del);
-
/* Call back functions for clib_bihash_add_or_overwrite_stale */
int nat44_i2o_is_idle_session_cb (clib_bihash_kv_8_8_t *kv, void *arg);
int nat44_o2i_is_idle_session_cb (clib_bihash_kv_8_8_t *kv, void *arg);
@@ -665,20 +641,41 @@ u32 nat44_ei_icmp_hairpinning (nat44_ei_main_t *nm, vlib_buffer_t *b0,
int nat44_ei_set_frame_queue_nelts (u32 frame_queue_nelts);
-#define nat44_ei_is_session_static(sp) \
- (sp->flags & NAT44_EI_SESSION_FLAG_STATIC_MAPPING)
-#define nat44_ei_is_unk_proto_session(sp) \
- (sp->flags & NAT44_EI_SESSION_FLAG_UNKNOWN_PROTO)
+always_inline bool
+nat44_ei_is_session_static (nat44_ei_session_t *s)
+{
+ return (s->flags & NAT44_EI_SESSION_FLAG_STATIC_MAPPING);
+}
+
+always_inline bool
+nat44_ei_is_unk_proto_session (nat44_ei_session_t *s)
+{
+ return (s->flags & NAT44_EI_SESSION_FLAG_UNKNOWN_PROTO);
+}
-#define nat44_ei_interface_is_inside(ip) \
- (ip->flags & NAT44_EI_INTERFACE_FLAG_IS_INSIDE)
-#define nat44_ei_interface_is_outside(ip) \
- (ip->flags & NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE)
+always_inline bool
+nat44_ei_interface_is_inside (nat44_ei_interface_t *i)
+{
+ return (i->flags & NAT44_EI_INTERFACE_FLAG_IS_INSIDE);
+}
-#define nat44_ei_is_addr_only_static_mapping(mp) \
- (mp->flags & NAT44_EI_STATIC_MAPPING_FLAG_ADDR_ONLY)
-#define nat44_ei_is_identity_static_mapping(mp) \
- (mp->flags & NAT44_EI_STATIC_MAPPING_FLAG_IDENTITY_NAT)
+always_inline bool
+nat44_ei_interface_is_outside (nat44_ei_interface_t *i)
+{
+ return (i->flags & NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE);
+}
+
+always_inline bool
+is_sm_addr_only (u32 f)
+{
+ return (f & NAT44_EI_SM_FLAG_ADDR_ONLY);
+}
+
+always_inline bool
+is_sm_identity_nat (u32 f)
+{
+ return (f & NAT44_EI_SM_FLAG_IDENTITY_NAT);
+}
/* logging */
#define nat44_ei_log_err(...) \
diff --git a/src/plugins/nat/nat44-ei/nat44_ei_api.c b/src/plugins/nat/nat44-ei/nat44_ei_api.c
index 427140ffb92..c6d17c94205 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei_api.c
+++ b/src/plugins/nat/nat44-ei/nat44_ei_api.c
@@ -469,9 +469,9 @@ vl_api_nat44_ei_add_del_address_range_t_handler (
for (i = 0; i < count; i++)
{
if (is_add)
- rv = nat44_ei_add_address (nm, &this_addr, vrf_id);
+ rv = nat44_ei_add_address (&this_addr, vrf_id);
else
- rv = nat44_ei_del_address (nm, this_addr, 0);
+ rv = nat44_ei_del_address (this_addr, 0);
if (rv)
goto send_reply;
@@ -540,7 +540,7 @@ vl_api_nat44_ei_interface_add_del_feature_t_handler (
VALIDATE_SW_IF_INDEX (mp);
- rv = nat44_ei_interface_add_del (sw_if_index, mp->flags & NAT44_EI_IF_INSIDE,
+ rv = nat44_ei_add_del_interface (sw_if_index, mp->flags & NAT44_EI_IF_INSIDE,
is_del);
BAD_SW_IF_INDEX_LABEL;
@@ -588,19 +588,68 @@ vl_api_nat44_ei_interface_dump_t_handler (vl_api_nat44_ei_interface_dump_t *mp)
}
}
+static_always_inline int
+add_del_dummy_output_interface (u32 sw_if_index, u8 is_inside, u8 is_add)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ nat44_ei_interface_t *i;
+ int rv = 1;
+
+ pool_foreach (i, nm->output_feature_dummy_interfaces)
+ {
+ if (i->sw_if_index == sw_if_index)
+ {
+ if (!is_add)
+ {
+ pool_put (nm->output_feature_dummy_interfaces, i);
+ rv = 0;
+ }
+ goto done;
+ }
+ }
+
+ if (is_add)
+ {
+ pool_get (nm->output_feature_dummy_interfaces, i);
+ i->sw_if_index = sw_if_index;
+
+ if (is_inside)
+ {
+ i->flags |= NAT44_EI_INTERFACE_FLAG_IS_INSIDE;
+ }
+ else
+ {
+ i->flags |= NAT44_EI_INTERFACE_FLAG_IS_OUTSIDE;
+ }
+
+ rv = 0;
+ }
+
+done:
+ return rv;
+}
+
static void
vl_api_nat44_ei_interface_add_del_output_feature_t_handler (
vl_api_nat44_ei_interface_add_del_output_feature_t *mp)
{
- nat44_ei_main_t *nm = &nat44_ei_main;
vl_api_nat44_ei_interface_add_del_output_feature_reply_t *rmp;
- u32 sw_if_index = ntohl (mp->sw_if_index);
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ u32 sw_if_index;
int rv = 0;
VALIDATE_SW_IF_INDEX (mp);
- rv = nat44_ei_interface_add_del_output_feature (
- sw_if_index, mp->flags & NAT44_EI_IF_INSIDE, !mp->is_add);
+ sw_if_index = ntohl (mp->sw_if_index);
+
+ // register all interfaces in the dummy structure
+ rv = add_del_dummy_output_interface (
+ sw_if_index, mp->flags & NAT44_EI_IF_INSIDE, mp->is_add);
+
+ if (!(mp->flags & NAT44_EI_IF_INSIDE))
+ {
+ rv = nat44_ei_add_del_output_interface (sw_if_index, !mp->is_add);
+ }
BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_NAT44_EI_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
@@ -622,7 +671,9 @@ send_nat44_ei_interface_output_feature_details (nat44_ei_interface_t *i,
rmp->context = context;
if (nat44_ei_interface_is_inside (i))
- rmp->flags |= NAT44_EI_IF_INSIDE;
+ {
+ rmp->flags |= NAT44_EI_IF_INSIDE;
+ }
vl_api_send_msg (reg, (u8 *) rmp);
}
@@ -639,49 +690,131 @@ vl_api_nat44_ei_interface_output_feature_dump_t_handler (
if (!reg)
return;
- pool_foreach (i, nm->output_feature_interfaces)
+ pool_foreach (i, nm->output_feature_dummy_interfaces)
{
send_nat44_ei_interface_output_feature_details (i, reg, mp->context);
}
}
static void
+vl_api_nat44_ei_add_del_output_interface_t_handler (
+ vl_api_nat44_ei_add_del_output_interface_t *mp)
+{
+ vl_api_nat44_ei_add_del_output_interface_reply_t *rmp;
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ u32 sw_if_index;
+ int rv = 0;
+
+ VALIDATE_SW_IF_INDEX (mp);
+
+ sw_if_index = ntohl (mp->sw_if_index);
+
+ rv = nat44_ei_add_del_output_interface (sw_if_index, !mp->is_add);
+
+ BAD_SW_IF_INDEX_LABEL;
+ REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_OUTPUT_INTERFACE_REPLY);
+}
+
+#define vl_endianfun
+#include <nat/nat44-ei/nat44_ei.api.h>
+#undef vl_endianfun
+static void
+send_nat44_ei_output_interface_details (u32 index, vl_api_registration_t *rp,
+ u32 context)
+{
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ vl_api_nat44_ei_output_interface_details_t *rmp;
+ nat44_ei_interface_t *i =
+ pool_elt_at_index (nm->output_feature_interfaces, index);
+
+ /* Make sure every field is initiated (or don't skip the clib_memset()) */
+ REPLY_MACRO_DETAILS4 (
+ VL_API_NAT44_EI_OUTPUT_INTERFACE_DETAILS, rp, context, ({
+ rmp->sw_if_index = i->sw_if_index;
+
+ /* Endian hack until apigen registers _details
+ * endian functions */
+ vl_api_nat44_ei_output_interface_details_t_endian (rmp);
+ rmp->_vl_msg_id = htons (rmp->_vl_msg_id);
+ rmp->context = htonl (rmp->context);
+ }));
+}
+
+static void
+vl_api_nat44_ei_output_interface_get_t_handler (
+ vl_api_nat44_ei_output_interface_get_t *mp)
+{
+ vl_api_nat44_ei_output_interface_get_reply_t *rmp;
+ nat44_ei_main_t *nm = &nat44_ei_main;
+ i32 rv = 0;
+
+ if (pool_elts (nm->output_feature_interfaces) == 0)
+ {
+ REPLY_MACRO (VL_API_NAT44_EI_OUTPUT_INTERFACE_GET_REPLY);
+ return;
+ }
+
+ REPLY_AND_DETAILS_MACRO (
+ VL_API_NAT44_EI_OUTPUT_INTERFACE_GET_REPLY, nm->output_feature_interfaces,
+ ({ send_nat44_ei_output_interface_details (cursor, rp, mp->context); }));
+}
+
+static void
vl_api_nat44_ei_add_del_static_mapping_t_handler (
vl_api_nat44_ei_add_del_static_mapping_t *mp)
{
- nat44_ei_main_t *nm = &nat44_ei_main;
vl_api_nat44_ei_add_del_static_mapping_reply_t *rmp;
- ip4_address_t local_addr, external_addr;
- u16 local_port = 0, external_port = 0;
- u32 vrf_id, external_sw_if_index;
+
+ nat44_ei_main_t *nm = &nat44_ei_main;
int rv = 0;
- nat_protocol_t proto;
+
+ ip4_address_t l_addr, e_addr, pool_addr = { 0 };
+ u32 sw_if_index, flags = 0, vrf_id;
+ u16 l_port = 0, e_port = 0;
+ nat_protocol_t proto = 0;
u8 *tag = 0;
- memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
- memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
+ memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
- if (!(mp->flags & NAT44_EI_ADDR_ONLY_MAPPING))
+ if (mp->flags & NAT44_EI_ADDR_ONLY_MAPPING)
{
- local_port = mp->local_port;
- external_port = mp->external_port;
+ flags |= NAT44_EI_SM_FLAG_ADDR_ONLY;
+ }
+ else
+ {
+ l_port = mp->local_port;
+ e_port = mp->external_port;
+ proto = ip_proto_to_nat_proto (mp->protocol);
}
- vrf_id = clib_net_to_host_u32 (mp->vrf_id);
- external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
- proto = ip_proto_to_nat_proto (mp->protocol);
-
- mp->tag[sizeof (mp->tag) - 1] = 0;
- tag = format (0, "%s", mp->tag);
- vec_terminate_c_string (tag);
-
- rv = nat44_ei_add_del_static_mapping (
- local_addr, external_addr, local_port, external_port, proto,
- external_sw_if_index, vrf_id, mp->flags & NAT44_EI_ADDR_ONLY_MAPPING, 0,
- tag, mp->is_add);
+ sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
+ if (sw_if_index != ~0)
+ {
+ e_addr.as_u32 = 0;
+ }
+ else
+ {
+ memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
+ }
- vec_free (tag);
+ vrf_id = clib_net_to_host_u32 (mp->vrf_id);
+ if (mp->is_add)
+ {
+ mp->tag[sizeof (mp->tag) - 1] = 0;
+ tag = format (0, "%s", mp->tag);
+ vec_terminate_c_string (tag);
+
+ rv = nat44_ei_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
+ vrf_id, sw_if_index, flags, pool_addr,
+ tag);
+ vec_free (tag);
+ }
+ else
+ {
+ rv = nat44_ei_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
+ vrf_id, sw_if_index, flags);
+ }
REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_STATIC_MAPPING_REPLY);
}
@@ -704,7 +837,7 @@ send_nat44_ei_static_mapping_details (nat44_ei_static_mapping_t *m,
rmp->vrf_id = htonl (m->vrf_id);
rmp->context = context;
- if (nat44_ei_is_addr_only_static_mapping (m))
+ if (is_sm_addr_only (m->flags))
{
rmp->flags |= NAT44_EI_ADDR_ONLY_MAPPING;
}
@@ -738,7 +871,7 @@ send_nat44_ei_static_map_resolve_details (nat44_ei_static_map_resolve_t *m,
rmp->vrf_id = htonl (m->vrf_id);
rmp->context = context;
- if (m->addr_only)
+ if (is_sm_addr_only (m->flags))
{
rmp->flags |= NAT44_EI_ADDR_ONLY_MAPPING;
}
@@ -770,14 +903,14 @@ vl_api_nat44_ei_static_mapping_dump_t_handler (
pool_foreach (m, nm->static_mappings)
{
- if (!nat44_ei_is_identity_static_mapping (m))
+ if (!is_sm_identity_nat (m->flags))
send_nat44_ei_static_mapping_details (m, reg, mp->context);
}
for (j = 0; j < vec_len (nm->to_resolve); j++)
{
rp = nm->to_resolve + j;
- if (!rp->identity_nat)
+ if (!is_sm_identity_nat (rp->flags))
send_nat44_ei_static_map_resolve_details (rp, reg, mp->context);
}
}
@@ -786,35 +919,56 @@ static void
vl_api_nat44_ei_add_del_identity_mapping_t_handler (
vl_api_nat44_ei_add_del_identity_mapping_t *mp)
{
- nat44_ei_main_t *nm = &nat44_ei_main;
vl_api_nat44_ei_add_del_identity_mapping_reply_t *rmp;
- ip4_address_t addr;
- u16 port = 0;
- u32 vrf_id, sw_if_index;
+
+ nat44_ei_main_t *nm = &nat44_ei_main;
int rv = 0;
- nat_protocol_t proto = NAT_PROTOCOL_OTHER;
+
+ ip4_address_t addr, pool_addr = { 0 };
+ u32 sw_if_index, flags, vrf_id;
+ nat_protocol_t proto = 0;
+ u16 port = 0;
u8 *tag = 0;
- if (!(mp->flags & NAT44_EI_ADDR_ONLY_MAPPING))
+ flags = NAT44_EI_SM_FLAG_IDENTITY_NAT;
+
+ if (mp->flags & NAT44_EI_ADDR_ONLY_MAPPING)
+ {
+ flags |= NAT44_EI_SM_FLAG_ADDR_ONLY;
+ }
+ else
{
port = mp->port;
proto = ip_proto_to_nat_proto (mp->protocol);
}
- vrf_id = clib_net_to_host_u32 (mp->vrf_id);
+
sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
if (sw_if_index != ~0)
- addr.as_u32 = 0;
+ {
+ addr.as_u32 = 0;
+ }
else
- memcpy (&addr.as_u8, mp->ip_address, 4);
- mp->tag[sizeof (mp->tag) - 1] = 0;
- tag = format (0, "%s", mp->tag);
- vec_terminate_c_string (tag);
+ {
+ memcpy (&addr.as_u8, mp->ip_address, 4);
+ }
- rv = nat44_ei_add_del_static_mapping (
- addr, addr, port, port, proto, sw_if_index, vrf_id,
- mp->flags & NAT44_EI_ADDR_ONLY_MAPPING, 1, tag, mp->is_add);
+ vrf_id = clib_net_to_host_u32 (mp->vrf_id);
- vec_free (tag);
+ if (mp->is_add)
+ {
+ mp->tag[sizeof (mp->tag) - 1] = 0;
+ tag = format (0, "%s", mp->tag);
+ vec_terminate_c_string (tag);
+
+ rv = nat44_ei_add_static_mapping (addr, addr, port, port, proto, vrf_id,
+ sw_if_index, flags, pool_addr, tag);
+ vec_free (tag);
+ }
+ else
+ {
+ rv = nat44_ei_del_static_mapping (addr, addr, port, port, proto, vrf_id,
+ sw_if_index, flags);
+ }
REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_IDENTITY_MAPPING_REPLY);
}
@@ -833,7 +987,7 @@ send_nat44_ei_identity_mapping_details (nat44_ei_static_mapping_t *m,
rmp->_vl_msg_id =
ntohs (VL_API_NAT44_EI_IDENTITY_MAPPING_DETAILS + nm->msg_id_base);
- if (nat44_ei_is_addr_only_static_mapping (m))
+ if (is_sm_addr_only (m->flags))
rmp->flags |= NAT44_EI_ADDR_ONLY_MAPPING;
clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
@@ -860,7 +1014,7 @@ send_nat44_ei_identity_map_resolve_details (nat44_ei_static_map_resolve_t *m,
rmp->_vl_msg_id =
ntohs (VL_API_NAT44_EI_IDENTITY_MAPPING_DETAILS + nm->msg_id_base);
- if (m->addr_only)
+ if (is_sm_addr_only (m->flags))
rmp->flags = (vl_api_nat44_ei_config_flags_t) NAT44_EI_ADDR_ONLY_MAPPING;
rmp->port = m->l_port;
@@ -890,7 +1044,7 @@ vl_api_nat44_ei_identity_mapping_dump_t_handler (
pool_foreach (m, nm->static_mappings)
{
- if (nat44_ei_is_identity_static_mapping (m))
+ if (is_sm_identity_nat (m->flags))
{
pool_foreach_index (j, m->locals)
{
@@ -902,7 +1056,7 @@ vl_api_nat44_ei_identity_mapping_dump_t_handler (
for (j = 0; j < vec_len (nm->to_resolve); j++)
{
rp = nm->to_resolve + j;
- if (rp->identity_nat)
+ if (is_sm_identity_nat (rp->flags))
send_nat44_ei_identity_map_resolve_details (rp, reg, mp->context);
}
}
@@ -915,13 +1069,17 @@ vl_api_nat44_ei_add_del_interface_addr_t_handler (
vl_api_nat44_ei_add_del_interface_addr_reply_t *rmp;
u32 sw_if_index = ntohl (mp->sw_if_index);
int rv = 0;
- u8 is_del;
-
- is_del = !mp->is_add;
VALIDATE_SW_IF_INDEX (mp);
- rv = nat44_ei_add_interface_address (nm, sw_if_index, is_del);
+ if (mp->is_add)
+ {
+ rv = nat44_ei_add_interface_address (sw_if_index);
+ }
+ else
+ {
+ rv = nat44_ei_del_interface_address (sw_if_index);
+ }
BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_NAT44_EI_ADD_DEL_INTERFACE_ADDR_REPLY);
diff --git a/src/plugins/nat/nat44-ei/nat44_ei_cli.c b/src/plugins/nat/nat44-ei/nat44_ei_cli.c
index 0780e5d68b6..f3e71982e5c 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei_cli.c
+++ b/src/plugins/nat/nat44-ei/nat44_ei_cli.c
@@ -112,9 +112,9 @@ format_nat44_ei_static_mapping (u8 *s, va_list *args)
nat44_ei_static_mapping_t *m = va_arg (*args, nat44_ei_static_mapping_t *);
nat44_ei_lb_addr_port_t *local;
- if (nat44_ei_is_identity_static_mapping (m))
+ if (is_sm_identity_nat (m->flags))
{
- if (nat44_ei_is_addr_only_static_mapping (m))
+ if (is_sm_addr_only (m->flags))
s = format (s, "identity mapping %U", format_ip4_address,
&m->local_addr);
else
@@ -130,7 +130,7 @@ format_nat44_ei_static_mapping (u8 *s, va_list *args)
return s;
}
- if (nat44_ei_is_addr_only_static_mapping (m))
+ if (is_sm_addr_only (m->flags))
{
s = format (s, "local %U external %U vrf %d", format_ip4_address,
&m->local_addr, format_ip4_address, &m->external_addr,
@@ -154,7 +154,7 @@ format_nat44_ei_static_map_to_resolve (u8 *s, va_list *args)
va_arg (*args, nat44_ei_static_map_resolve_t *);
vnet_main_t *vnm = vnet_get_main ();
- if (m->addr_only)
+ if (is_sm_addr_only (m->flags))
s =
format (s, "local %U external %U vrf %d", format_ip4_address, &m->l_addr,
format_vnet_sw_if_index_name, vnm, m->sw_if_index, m->vrf_id);
@@ -790,9 +790,9 @@ add_address_command_fn (vlib_main_t *vm, unformat_input_t *input,
for (i = 0; i < count; i++)
{
if (is_add)
- rv = nat44_ei_add_address (nm, &this_addr, vrf_id);
+ rv = nat44_ei_add_address (&this_addr, vrf_id);
else
- rv = nat44_ei_del_address (nm, this_addr, 0);
+ rv = nat44_ei_del_address (this_addr, 0);
switch (rv)
{
@@ -894,8 +894,7 @@ nat44_ei_feature_command_fn (vlib_main_t *vm, unformat_input_t *input,
sw_if_index = inside_sw_if_indices[i];
if (is_output_feature)
{
- if (nat44_ei_interface_add_del_output_feature (sw_if_index, 1,
- is_del))
+ if (nat44_ei_add_del_output_interface (sw_if_index, is_del))
{
error = clib_error_return (
0, "%s %U failed", is_del ? "del" : "add",
@@ -905,7 +904,7 @@ nat44_ei_feature_command_fn (vlib_main_t *vm, unformat_input_t *input,
}
else
{
- if (nat44_ei_interface_add_del (sw_if_index, 1, is_del))
+ if (nat44_ei_add_del_interface (sw_if_index, 1, is_del))
{
error = clib_error_return (
0, "%s %U failed", is_del ? "del" : "add",
@@ -923,8 +922,7 @@ nat44_ei_feature_command_fn (vlib_main_t *vm, unformat_input_t *input,
sw_if_index = outside_sw_if_indices[i];
if (is_output_feature)
{
- if (nat44_ei_interface_add_del_output_feature (sw_if_index, 0,
- is_del))
+ if (nat44_ei_add_del_output_interface (sw_if_index, is_del))
{
error = clib_error_return (
0, "%s %U failed", is_del ? "del" : "add",
@@ -934,7 +932,7 @@ nat44_ei_feature_command_fn (vlib_main_t *vm, unformat_input_t *input,
}
else
{
- if (nat44_ei_interface_add_del (sw_if_index, 0, is_del))
+ if (nat44_ei_add_del_interface (sw_if_index, 0, is_del))
{
error = clib_error_return (
0, "%s %U failed", is_del ? "del" : "add",
@@ -990,14 +988,16 @@ add_static_mapping_command_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)
{
unformat_input_t _line_input, *line_input = &_line_input;
- clib_error_t *error = 0;
- ip4_address_t l_addr, e_addr;
- u32 l_port = 0, e_port = 0, vrf_id = ~0;
- int is_add = 1, addr_only = 1, rv;
- u32 sw_if_index = ~0;
vnet_main_t *vnm = vnet_get_main ();
+ clib_error_t *error = 0;
+ int rv;
+
nat_protocol_t proto = NAT_PROTOCOL_OTHER;
- u8 proto_set = 0;
+ ip4_address_t l_addr, e_addr, pool_addr = { 0 };
+ u32 l_port = 0, e_port = 0, vrf_id = ~0;
+ u8 l_port_set = 0, e_port_set = 0;
+ u32 sw_if_index = ~0, flags = 0;
+ int is_add = 1;
if (!unformat_user (input, unformat_line_input, line_input))
return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT);
@@ -1006,29 +1006,37 @@ add_static_mapping_command_fn (vlib_main_t *vm, unformat_input_t *input,
{
if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
&l_port))
- addr_only = 0;
+ {
+ l_port_set = 1;
+ }
else if (unformat (line_input, "local %U", unformat_ip4_address,
&l_addr))
;
else if (unformat (line_input, "external %U %u", unformat_ip4_address,
&e_addr, &e_port))
- addr_only = 0;
+ {
+ e_port_set = 1;
+ }
else if (unformat (line_input, "external %U", unformat_ip4_address,
&e_addr))
;
else if (unformat (line_input, "external %U %u",
unformat_vnet_sw_interface, vnm, &sw_if_index,
&e_port))
- addr_only = 0;
+ {
+ e_port_set = 1;
+ }
else if (unformat (line_input, "external %U", unformat_vnet_sw_interface,
vnm, &sw_if_index))
;
else if (unformat (line_input, "vrf %u", &vrf_id))
;
else if (unformat (line_input, "%U", unformat_nat_protocol, &proto))
- proto_set = 1;
+ ;
else if (unformat (line_input, "del"))
- is_add = 0;
+ {
+ is_add = 0;
+ }
else
{
error = clib_error_return (0, "unknown input: '%U'",
@@ -1037,25 +1045,33 @@ add_static_mapping_command_fn (vlib_main_t *vm, unformat_input_t *input,
}
}
- if (addr_only)
+ if (l_port_set != e_port_set)
{
- if (proto_set)
- {
- error = clib_error_return (
- 0, "address only mapping doesn't support protocol");
- goto done;
- }
+ error = clib_error_return (0, "Either both ports are set or none.");
+ goto done;
}
- else if (!proto_set)
+
+ if (!l_port_set)
{
- error = clib_error_return (0, "protocol is required");
- goto done;
+ flags |= NAT44_EI_SM_FLAG_ADDR_ONLY;
+ }
+ else
+ {
+ l_port = clib_host_to_net_u16 (l_port);
+ e_port = clib_host_to_net_u16 (e_port);
}
- rv = nat44_ei_add_del_static_mapping (
- l_addr, e_addr, clib_host_to_net_u16 (l_port),
- clib_host_to_net_u16 (e_port), proto, sw_if_index, vrf_id, addr_only, 0, 0,
- is_add);
+ if (is_add)
+ {
+ rv =
+ nat44_ei_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
+ vrf_id, sw_if_index, flags, pool_addr, 0);
+ }
+ else
+ {
+ rv = nat44_ei_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
+ vrf_id, sw_if_index, flags);
+ }
switch (rv)
{
@@ -1091,17 +1107,15 @@ add_identity_mapping_command_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)
{
unformat_input_t _line_input, *line_input = &_line_input;
- clib_error_t *error = 0;
- u32 port = 0, vrf_id = ~0;
- ip4_address_t addr;
- int is_add = 1;
- int addr_only = 1;
- u32 sw_if_index = ~0;
vnet_main_t *vnm = vnet_get_main ();
- int rv;
+ clib_error_t *error = 0;
+
+ int rv, is_add = 1, port_set = 0;
+ u32 sw_if_index = ~0, port, flags, vrf_id = ~0;
nat_protocol_t proto;
+ ip4_address_t addr;
- addr.as_u32 = 0;
+ flags = NAT44_EI_SM_FLAG_IDENTITY_NAT;
if (!unformat_user (input, unformat_line_input, line_input))
return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT);
@@ -1117,9 +1131,13 @@ add_identity_mapping_command_fn (vlib_main_t *vm, unformat_input_t *input,
;
else if (unformat (line_input, "%U %u", unformat_nat_protocol, &proto,
&port))
- addr_only = 0;
+ {
+ port_set = 1;
+ }
else if (unformat (line_input, "del"))
- is_add = 0;
+ {
+ is_add = 0;
+ }
else
{
error = clib_error_return (0, "unknown input: '%U'",
@@ -1128,9 +1146,26 @@ add_identity_mapping_command_fn (vlib_main_t *vm, unformat_input_t *input,
}
}
- rv = nat44_ei_add_del_static_mapping (
- addr, addr, clib_host_to_net_u16 (port), clib_host_to_net_u16 (port),
- proto, sw_if_index, vrf_id, addr_only, 1, 0, is_add);
+ if (!port_set)
+ {
+ flags |= NAT44_EI_SM_FLAG_ADDR_ONLY;
+ }
+ else
+ {
+ port = clib_host_to_net_u16 (port);
+ }
+
+ if (is_add)
+ {
+
+ rv = nat44_ei_add_static_mapping (addr, addr, port, port, proto, vrf_id,
+ sw_if_index, flags, addr, 0);
+ }
+ else
+ {
+ rv = nat44_ei_del_static_mapping (addr, addr, port, port, proto, vrf_id,
+ sw_if_index, flags);
+ }
switch (rv)
{
@@ -1184,12 +1219,11 @@ nat44_ei_add_interface_address_command_fn (vlib_main_t *vm,
unformat_input_t *input,
vlib_cli_command_t *cmd)
{
- nat44_ei_main_t *nm = &nat44_ei_main;
unformat_input_t _line_input, *line_input = &_line_input;
- u32 sw_if_index;
- int rv;
- int is_del = 0;
+ nat44_ei_main_t *nm = &nat44_ei_main;
clib_error_t *error = 0;
+ int rv, is_del = 0;
+ u32 sw_if_index;
if (!unformat_user (input, unformat_line_input, line_input))
return clib_error_return (0, NAT44_EI_EXPECTED_ARGUMENT);
@@ -1200,7 +1234,9 @@ nat44_ei_add_interface_address_command_fn (vlib_main_t *vm,
nm->vnet_main, &sw_if_index))
;
else if (unformat (line_input, "del"))
- is_del = 1;
+ {
+ is_del = 1;
+ }
else
{
error = clib_error_return (0, "unknown input '%U'",
@@ -1209,17 +1245,21 @@ nat44_ei_add_interface_address_command_fn (vlib_main_t *vm,
}
}
- rv = nat44_ei_add_interface_address (nm, sw_if_index, is_del);
-
- switch (rv)
+ if (!is_del)
{
- case 0:
- break;
-
- default:
- error = clib_error_return (
- 0, "nat44_ei_add_interface_address returned %d", rv);
- goto done;
+ rv = nat44_ei_add_interface_address (sw_if_index);
+ if (rv)
+ {
+ error = clib_error_return (0, "add address returned %d", rv);
+ }
+ }
+ else
+ {
+ rv = nat44_ei_del_interface_address (sw_if_index);
+ if (rv)
+ {
+ error = clib_error_return (0, "del address returned %d", rv);
+ }
}
done:
@@ -1493,7 +1533,6 @@ nat_show_timeouts_command_fn (vlib_main_t *vm, unformat_input_t *input,
{
nat44_ei_main_t *nm = &nat44_ei_main;
- // TODO: make format timeout function
vlib_cli_output (vm, "udp timeout: %dsec", nm->timeouts.udp);
vlib_cli_output (vm, "tcp-established timeout: %dsec",
nm->timeouts.tcp.established);
diff --git a/src/plugins/nat/nat44-ei/nat44_ei_handoff.c b/src/plugins/nat/nat44-ei/nat44_ei_handoff.c
index c7a1317026b..5c16d871c4d 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei_handoff.c
+++ b/src/plugins/nat/nat44-ei/nat44_ei_handoff.c
@@ -83,8 +83,6 @@ nat44_ei_worker_handoff_fn_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_get_buffers (vm, from, b, n_left_from);
- // TODO: move to nm
- // TODO: remove callbacks and use inlines that should be moved here
if (is_in2out)
{
fq_index = is_output ? nm->fq_in2out_output_index : nm->fq_in2out_index;