#include <nat/nat_ipfix_logging.h>
#include <nat/nat_det.h>
#include <nat/nat64.h>
+#include <nat/nat66.h>
#include <nat/dslite.h>
#include <nat/nat_reass.h>
#include <vnet/fib/fib_table.h>
VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-in2out",
- .runs_before = VNET_FEATURES ("nat44-out2in"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-out2in",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_nat_classify, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-classify",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-det-in2out",
- .runs_before = VNET_FEATURES ("nat44-det-out2in"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-det-out2in",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_nat_det_classify, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-det-classify",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_in2out_worker_handoff, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-in2out-worker-handoff",
- .runs_before = VNET_FEATURES ("nat44-out2in-worker-handoff"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_out2in_worker_handoff, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-out2in-worker-handoff",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_nat_handoff_classify, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-handoff-classify",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-in2out-fast",
- .runs_before = VNET_FEATURES ("nat44-out2in-fast"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-out2in-fast",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = {
.arc_name = "ip4-unicast",
.node_name = "nat44-hairpin-dst",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
+ .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
};
/* Hook up output features */
VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = {
.arc_name = "ip4-output",
.node_name = "nat44-in2out-output",
- .runs_before = VNET_FEATURES ("interface-output"),
+ .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = {
.arc_name = "ip4-output",
.node_name = "nat44-in2out-output-worker-handoff",
- .runs_before = VNET_FEATURES ("interface-output"),
+ .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
};
VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = {
.arc_name = "ip4-output",
.node_name = "nat44-hairpin-src",
- .runs_before = VNET_FEATURES ("interface-output"),
+ .runs_after = VNET_FEATURES ("acl-plugin-out-ip4-fa"),
};
/* Hook up ip4-local features */
if (sw_if_index != ~0)
{
ip4_address_t * first_int_addr;
+ snat_static_map_resolve_t *rp, *rp_match = 0;
+
+ for (i = 0; i < vec_len (sm->to_resolve); i++)
+ {
+ rp = sm->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;
+ }
/* Might be already set... */
first_int_addr = ip4_interface_first_address
(sm->ip4_main, sw_if_index, 0 /* just want the address*/);
- /* DHCP resolution required? */
- if (first_int_addr == 0)
+ if (is_add)
{
- snat_add_static_mapping_when_resolved
- (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
- addr_only, is_add, tag);
- return 0;
+ if (rp_match)
+ return VNET_API_ERROR_VALUE_EXIST;
+
+ /* DHCP resolution required? */
+ if (first_int_addr == 0)
+ {
+ snat_add_static_mapping_when_resolved
+ (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
+ addr_only, is_add, tag);
+ return 0;
+ }
+ else
+ {
+ 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
+ else
{
- 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;
+ if (!rp_match)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ vec_del1 (sm->to_resolve, i);
+
+ if (first_int_addr)
+ {
+ 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
+ return 0;
}
}
return 0;
}
+static int lb_local_exists (nat44_lb_addr_port_t * local,
+ ip4_address_t * e_addr, u16 e_port)
+{
+ snat_main_t *sm = &snat_main;
+ snat_static_mapping_t *m;
+ nat44_lb_addr_port_t *ap;
+
+ /* *INDENT-OFF* */
+ pool_foreach (m, sm->static_mappings,
+ ({
+ if (vec_len(m->locals))
+ {
+ if (m->external_port == e_port && m->external_addr.as_u32 == e_addr->as_u32)
+ continue;
+
+ vec_foreach (ap, m->locals)
+ {
+ if (ap->port == local->port && ap->addr.as_u32 == local->addr.as_u32)
+ return 1;
+ }
+ }
+ }));
+ /* *INDENT-ON* */
+
+ return 0;
+}
+
int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
snat_protocol_t proto, u32 vrf_id,
nat44_lb_addr_port_t *locals, u8 is_add,
}
}
- m_key.port = clib_host_to_net_u16 (local->port);
- kv.key = m_key.as_u64;
- if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
+ if (!lb_local_exists(local, &e_addr, e_port))
{
- clib_warning ("in2out key del failed");
- return VNET_API_ERROR_UNSPECIFIED;
+ m_key.port = clib_host_to_net_u16 (local->port);
+ kv.key = m_key.as_u64;
+ if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
+ {
+ clib_warning ("in2out key del failed");
+ return VNET_API_ERROR_UNSPECIFIED;
+ }
}
/* Delete sessions */
u_key.addr = local->addr;
if (sm->out2in_dpo && !is_inside)
return VNET_API_ERROR_UNSUPPORTED;
+ pool_foreach (i, sm->output_feature_interfaces,
+ ({
+ if (i->sw_if_index == sw_if_index)
+ return VNET_API_ERROR_VALUE_EXIST;
+ }));
+
if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
feature_name = is_inside ? "nat44-in2out-fast" : "nat44-out2in-fast";
else
(sm->static_mapping_only && !(sm->static_mapping_connection_tracking)))
return VNET_API_ERROR_UNSUPPORTED;
+ pool_foreach (i, sm->interfaces,
+ ({
+ if (i->sw_if_index == sw_if_index)
+ return VNET_API_ERROR_VALUE_EXIST;
+ }));
+
if (is_inside)
{
vnet_feature_enable_disable ("ip4-unicast", "nat44-hairpin-dst",
dslite_init(vm);
+ nat66_init();
+
/* Init virtual fragmenentation reassembly */
return nat_reass_init(vm);
}
{
snat_main_t *sm = &snat_main;
snat_static_map_resolve_t *rp;
- u32 *indices_to_delete = 0;
ip4_address_t l_addr;
int i, j;
int rv;
if (rv)
clib_warning ("snat_add_static_mapping returned %d",
rv);
- vec_free (rp->tag);
- vec_add1 (indices_to_delete, j);
}
}
- /* If we resolved any of the outstanding static mappings */
- if (vec_len(indices_to_delete))
- {
- /* Delete them */
- for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
- vec_delete(sm->to_resolve, 1, j);
- vec_free(indices_to_delete);
- }
return;
}
else
snat_user_t *u;
ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
- if (sm->num_workers)
+ if (sm->num_workers > 1)
tsm =
vec_elt_at_index (sm->per_thread_data,
sm->worker_in2out_cb (&ip, fib_index));