nat: twice-nat static mapping pool address
Let twice-nat static mapping pick specific
address from the twice-nat pool.
Type: improvement
Change-Id: Iadaa036af2fa3b0e6e9a68ff6e68b4bbe1650eb1
Signed-off-by: Filip Varga <fivarga@cisco.com>
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index 796d9d0..61a36ec 100644
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -692,7 +692,8 @@
nat_protocol_t proto,
int addr_only, int is_add, u8 * tag,
int twice_nat, int out2in_only,
- int identity_nat)
+ int identity_nat,
+ ip4_address_t pool_addr, int exact)
{
snat_static_map_resolve_t *rp;
@@ -709,6 +710,8 @@
rp->out2in_only = out2in_only;
rp->identity_nat = identity_nat;
rp->tag = vec_dup (tag);
+ rp->pool_addr = pool_addr;
+ rp->exact = exact;
}
static u32
@@ -829,7 +832,7 @@
u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
u32 sw_if_index, nat_protocol_t proto, int is_add,
twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag,
- u8 identity_nat)
+ u8 identity_nat, ip4_address_t pool_addr, int exact)
{
snat_main_t *sm = &snat_main;
snat_static_mapping_t *m;
@@ -891,7 +894,8 @@
snat_add_static_mapping_when_resolved
(sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
- addr_only, is_add, tag, twice_nat, out2in_only, identity_nat);
+ addr_only, is_add, tag, twice_nat, out2in_only,
+ identity_nat, pool_addr, exact);
/* DHCP resolution required? */
if (first_int_addr == 0)
@@ -1046,6 +1050,13 @@
m->local_addr = l_addr;
m->external_addr = e_addr;
m->twice_nat = twice_nat;
+
+ if (twice_nat == TWICE_NAT && exact)
+ {
+ m->flags |= NAT_STATIC_MAPPING_FLAG_EXACT_ADDRESS;
+ m->pool_addr = pool_addr;
+ }
+
if (out2in_only)
m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
if (addr_only)
@@ -1673,15 +1684,21 @@
if (delete_sm)
{
+ ip4_address_t pool_addr = { 0 };
/* *INDENT-OFF* */
pool_foreach (m, sm->static_mappings,
({
if (m->external_addr.as_u32 == addr.as_u32)
(void) snat_add_static_mapping (m->local_addr, m->external_addr,
m->local_port, m->external_port,
- m->vrf_id, is_addr_only_static_mapping(m), ~0,
- m->proto, 0, m->twice_nat,
- is_out2in_only_static_mapping(m), m->tag, is_identity_static_mapping(m));
+ m->vrf_id,
+ is_addr_only_static_mapping(m), ~0,
+ m->proto, 0 /* is_add */,
+ m->twice_nat,
+ is_out2in_only_static_mapping(m),
+ m->tag,
+ is_identity_static_mapping(m),
+ pool_addr, 0);
}));
/* *INDENT-ON* */
}
@@ -2801,16 +2818,29 @@
u8 * is_addr_only,
twice_nat_type_t * twice_nat,
lb_nat_type_t * lb, ip4_address_t * ext_host_addr,
- u8 * is_identity_nat)
+ u8 * is_identity_nat, snat_static_mapping_t ** out)
{
clib_bihash_kv_8_8_t kv, value;
+ clib_bihash_8_8_t *mapping_hash;
snat_static_mapping_t *m;
- clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
u32 rand, lo = 0, hi, mid, *tmp = 0, i;
- u8 backend_index;
nat44_lb_addr_port_t *local;
+ u8 backend_index;
- if (by_external)
+ if (!by_external)
+ {
+ mapping_hash = &sm->static_mapping_by_local;
+ init_nat_k (&kv, match_addr, match_port, match_fib_index,
+ match_protocol);
+ if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
+ {
+ /* Try address only mapping */
+ init_nat_k (&kv, match_addr, 0, match_fib_index, 0);
+ if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
+ return 1;
+ }
+ }
+ else
{
mapping_hash = &sm->static_mapping_by_external;
init_nat_k (&kv, match_addr, match_port, 0, match_protocol);
@@ -2821,20 +2851,6 @@
if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
return 1;
}
-
- }
- else
- {
- init_nat_k (&kv, match_addr, match_port, match_fib_index,
- match_protocol);
- if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
- {
- /* Try address only mapping */
- init_nat_k (&kv, match_addr, 0, match_fib_index, 0);
- if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
- return 1;
- }
-
}
m = pool_elt_at_index (sm->static_mappings, value.value);
@@ -2943,6 +2959,9 @@
if (PREDICT_FALSE (is_identity_nat != 0))
*is_identity_nat = is_identity_static_mapping (m);
+ if (out != 0)
+ *out = m;
+
return 0;
}
@@ -4358,7 +4377,8 @@
rp->vrf_id,
rp->addr_only, ~0 /* sw_if_index */ ,
rp->proto, !is_delete, rp->twice_nat,
- rp->out2in_only, rp->tag, rp->identity_nat);
+ rp->out2in_only, rp->tag, rp->identity_nat,
+ rp->pool_addr, rp->exact);
if (rv)
nat_elog_notice_X1 ("snat_add_static_mapping returned %d", "i4", rv);
}
@@ -4429,7 +4449,8 @@
rp->proto,
rp->is_add, rp->twice_nat,
rp->out2in_only, rp->tag,
- rp->identity_nat);
+ rp->identity_nat,
+ rp->pool_addr, rp->exact);
if (rv)
nat_elog_notice_X1 ("snat_add_static_mapping returned %d",
"i4", rv);