NAT44: do not create session record for identity mapping (VPP-1439) 71/15171/2
authorMatus Fabian <matfabia@cisco.com>
Mon, 8 Oct 2018 04:28:23 +0000 (21:28 -0700)
committerOle Trøan <otroan@employees.org>
Mon, 8 Oct 2018 11:46:23 +0000 (11:46 +0000)
Change-Id: I39a3146a4e4ba8eadf50af7113b9ae6b1c1d688f
Signed-off-by: Matus Fabian <matfabia@cisco.com>
src/plugins/nat/in2out.c
src/plugins/nat/in2out_ed.c
src/plugins/nat/nat.c
src/plugins/nat/nat.h
src/plugins/nat/nat44_cli.c
src/plugins/nat/nat44_hairpinning.c
src/plugins/nat/nat_api.c
src/plugins/nat/nat_format.c
src/plugins/nat/out2in.c
src/plugins/nat/out2in_ed.c
test/test_nat.py

index b610650..b99aef3 100755 (executable)
@@ -135,7 +135,7 @@ snat_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
                              &value0))
     {
       /* or is static mappings */
-      if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+      if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0, 0))
        return 0;
     }
   else
@@ -236,13 +236,14 @@ slow_path (snat_main_t * sm, vlib_buffer_t * b0,
           vlib_node_runtime_t * node, u32 next0, u32 thread_index, f64 now)
 {
   snat_user_t *u;
-  snat_session_t *s;
+  snat_session_t *s = 0;
   clib_bihash_kv_8_8_t kv0;
   snat_session_key_t key1;
   udp_header_t *udp0 = ip4_next_header (ip0);
   u8 is_sm = 0;
   nat_outside_fib_t *outside_fib;
   fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
+  u8 identity_nat;
   fib_prefix_t pfx = {
     .fp_proto = FIB_PROTOCOL_IP4,
     .fp_len = 32,
@@ -263,7 +264,8 @@ slow_path (snat_main_t * sm, vlib_buffer_t * b0,
   key1.protocol = key0->protocol;
 
   /* First try to match static mapping by local address and port */
-  if (snat_static_mapping_match (sm, *key0, &key1, 0, 0, 0, 0, 0))
+  if (snat_static_mapping_match
+      (sm, *key0, &key1, 0, 0, 0, 0, 0, &identity_nat))
     {
       /* Try to create dynamic translation */
       if (snat_alloc_outside_address_and_port (sm->addresses, rx_fib_index0,
@@ -277,7 +279,15 @@ slow_path (snat_main_t * sm, vlib_buffer_t * b0,
        }
     }
   else
-    is_sm = 1;
+    {
+      if (PREDICT_FALSE (identity_nat))
+       {
+         *sessionp = s;
+         return next0;
+       }
+
+      is_sm = 1;
+    }
 
   u = nat_user_get_or_create (sm, &ip0->src_address, rx_fib_index0,
                              thread_index);
@@ -489,6 +499,12 @@ icmp_match_in2out_slow (snat_main_t * sm, vlib_node_runtime_t * node,
 
       if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
        goto out;
+
+      if (!s0)
+       {
+         dont_translate = 1;
+         goto out;
+       }
     }
   else
     {
@@ -558,7 +574,8 @@ icmp_match_in2out_fast (snat_main_t * sm, vlib_node_runtime_t * node,
     }
   key0.fib_index = rx_fib_index0;
 
-  if (snat_static_mapping_match (sm, key0, &sm0, 0, &is_addr_only, 0, 0, 0))
+  if (snat_static_mapping_match
+      (sm, key0, &sm0, 0, &is_addr_only, 0, 0, 0, 0))
     {
       if (PREDICT_FALSE (snat_not_translate_fast (sm, node, sw_if_index0, ip0,
                                                  IP_PROTOCOL_ICMP,
@@ -987,6 +1004,9 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                                     &s0, node, next0, thread_index, now);
                  if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
                    goto trace00;
+
+                 if (PREDICT_FALSE (!s0))
+                   goto trace00;
                }
              else
                {
@@ -1163,6 +1183,9 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                                     &s1, node, next1, thread_index, now);
                  if (PREDICT_FALSE (next1 == SNAT_IN2OUT_NEXT_DROP))
                    goto trace01;
+
+                 if (PREDICT_FALSE (!s1))
+                   goto trace01;
                }
              else
                {
@@ -1374,6 +1397,9 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
 
                  if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
                    goto trace0;
+
+                 if (PREDICT_FALSE (!s0))
+                   goto trace0;
                }
              else
                {
@@ -1717,6 +1743,9 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
                  if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
                    goto trace0;
 
+                 if (PREDICT_FALSE (!s0))
+                   goto trace0;
+
                  reass0->sess_index = s0 - per_thread_data->sessions;
                }
              else
@@ -1971,7 +2000,7 @@ snat_in2out_fast_static_map_fn (vlib_main_t * vm,
          key0.port = udp0->src_port;
          key0.fib_index = rx_fib_index0;
 
-         if (snat_static_mapping_match (sm, key0, &sm0, 0, 0, 0, 0, 0))
+         if (snat_static_mapping_match (sm, key0, &sm0, 0, 0, 0, 0, 0, 0))
            {
              b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
              next0 = SNAT_IN2OUT_NEXT_DROP;
index adf0ff3..8db53c0 100644 (file)
@@ -256,7 +256,7 @@ slow_path_ed (snat_main_t * sm,
              snat_session_t ** sessionp,
              vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now)
 {
-  snat_session_t *s;
+  snat_session_t *s = 0;
   snat_user_t *u;
   snat_session_key_t key0, key1;
   lb_nat_type_t lb = 0, is_sm = 0;
@@ -265,6 +265,7 @@ slow_path_ed (snat_main_t * sm,
   u32 proto = ip_proto_to_snat_proto (key->proto);
   nat_outside_fib_t *outside_fib;
   fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
+  u8 identity_nat;
   fib_prefix_t pfx = {
     .fp_proto = FIB_PROTOCOL_IP4,
     .fp_len = 32,
@@ -288,7 +289,8 @@ slow_path_ed (snat_main_t * sm,
   key0.fib_index = rx_fib_index;
   key1.fib_index = sm->outside_fib_index;
   /* First try to match static mapping by local address and port */
-  if (snat_static_mapping_match (sm, key0, &key1, 0, 0, 0, &lb, 0))
+  if (snat_static_mapping_match
+      (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
     {
       /* Try to create dynamic translation */
       if (snat_alloc_outside_address_and_port (sm->addresses, rx_fib_index,
@@ -302,7 +304,15 @@ slow_path_ed (snat_main_t * sm,
        }
     }
   else
-    is_sm = 1;
+    {
+      if (PREDICT_FALSE (identity_nat))
+       {
+         *sessionp = s;
+         return next;
+       }
+
+      is_sm = 1;
+    }
 
   u = nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index);
   if (!u)
@@ -413,7 +423,7 @@ nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
       key0.protocol = proto;
       key0.fib_index = sm->outside_fib_index;
       /* or is static mappings */
-      if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0))
+      if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0, 0))
        return 0;
     }
   else
@@ -607,6 +617,12 @@ icmp_match_in2out_ed (snat_main_t * sm, vlib_node_runtime_t * node,
 
       if (PREDICT_FALSE (next == NAT_IN2OUT_ED_NEXT_DROP))
        goto out;
+
+      if (!s)
+       {
+         dont_translate = 1;
+         goto out;
+       }
     }
   else
     {
@@ -1011,6 +1027,9 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
 
                  if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP))
                    goto trace00;
+
+                 if (PREDICT_FALSE (!s0))
+                   goto trace00;
                }
              else
                {
@@ -1212,6 +1231,9 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
 
                  if (PREDICT_FALSE (next1 == NAT_IN2OUT_ED_NEXT_DROP))
                    goto trace01;
+
+                 if (PREDICT_FALSE (!s1))
+                   goto trace01;
                }
              else
                {
@@ -1442,6 +1464,9 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
 
                  if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP))
                    goto trace0;
+
+                 if (PREDICT_FALSE (!s0))
+                   goto trace0;
                }
              else
                {
@@ -1839,6 +1864,12 @@ nat44_ed_in2out_reass_node_fn_inline (vlib_main_t * vm,
                  if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP))
                    goto trace0;
 
+                 if (PREDICT_FALSE (!s0))
+                   {
+                     reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
+                     goto trace0;
+                   }
+
                  reass0->sess_index = s0 - per_thread_data->sessions;
                }
              else
index 0818332..ae2e64e 100755 (executable)
@@ -583,7 +583,9 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm,
                                       u16 e_port,
                                       u32 vrf_id,
                                       snat_protocol_t proto,
-                                      int addr_only, int is_add, u8 * tag)
+                                      int addr_only, int is_add, u8 * tag,
+                                      int twice_nat, int out2in_only,
+                                      int identity_nat)
 {
   snat_static_map_resolve_t *rp;
 
@@ -596,6 +598,9 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm,
   rp->proto = proto;
   rp->addr_only = addr_only;
   rp->is_add = is_add;
+  rp->twice_nat = twice_nat;
+  rp->out2in_only = out2in_only;
+  rp->identity_nat = identity_nat;
   rp->tag = vec_dup (tag);
 }
 
@@ -613,34 +618,12 @@ get_thread_idx_by_port (u16 e_port)
   return thread_idx;
 }
 
-/**
- * @brief Add static mapping.
- *
- * Create static mapping between local addr+port and external addr+port.
- *
- * @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 vrf_id VRF ID.
- * @param addr_only If 0 address port and pair mapping, otherwise address only.
- * @param sw_if_index External port instead of specific IP address.
- * @param is_add If 0 delete static mapping, otherwise add.
- * @param twice_nat If value is TWICE_NAT then translate external host address
- *                  and port.
- *                  If value is TWICE_NAT_SELF then translate external host
- *                  address and port whenever external host address equals
- *                  local address of internal host.
- * @param out2in_only If 1 rule match only out2in direction
- * @param tag - opaque string tag
- *
- * @returns
- */
 int
 snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
                         u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
                         u32 sw_if_index, snat_protocol_t proto, int is_add,
-                        twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag)
+                        twice_nat_type_t twice_nat, u8 out2in_only, u8 * tag,
+                        u8 identity_nat)
 {
   snat_main_t *sm = &snat_main;
   snat_static_mapping_t *m;
@@ -702,7 +685,7 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
 
          snat_add_static_mapping_when_resolved
            (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
-            addr_only, is_add, tag);
+            addr_only, is_add, tag, twice_nat, out2in_only, identity_nat);
 
          /* DHCP resolution required? */
          if (first_int_addr == 0)
@@ -842,11 +825,15 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
       m->tag = vec_dup (tag);
       m->local_addr = l_addr;
       m->external_addr = e_addr;
-      m->addr_only = addr_only;
       m->vrf_id = vrf_id;
       m->fib_index = fib_index;
       m->twice_nat = twice_nat;
-      m->out2in_only = out2in_only;
+      if (out2in_only)
+       m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
+      if (addr_only)
+       m->flags |= NAT_STATIC_MAPPING_FLAG_ADDR_ONLY;
+      if (identity_nat)
+       m->flags |= NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT;
       if (!addr_only)
        {
          m->local_port = l_port;
@@ -1147,11 +1134,11 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       memset (m, 0, sizeof (*m));
       m->tag = vec_dup (tag);
       m->external_addr = e_addr;
-      m->addr_only = 0;
       m->external_port = e_port;
       m->proto = proto;
       m->twice_nat = twice_nat;
-      m->out2in_only = out2in_only;
+      if (out2in_only)
+       m->flags |= NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY;
       m->affinity = affinity;
 
       if (affinity)
@@ -1368,9 +1355,9 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm,
           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, m->addr_only, ~0,
+                                            m->vrf_id, is_addr_only_static_mapping(m), ~0,
                                             m->proto, 0, m->twice_nat,
-                                            m->out2in_only, m->tag);
+                                            is_out2in_only_static_mapping(m), m->tag, is_identity_static_mapping(m));
       }));
       /* *INDENT-ON* */
     }
@@ -1682,7 +1669,7 @@ fib:
 
   pool_foreach (m, sm->static_mappings,
   ({
-    if (!(m->addr_only) || (m->local_addr.as_u32 == m->external_addr.as_u32))
+    if (!(is_addr_only_static_mapping(m)) || (m->local_addr.as_u32 == m->external_addr.as_u32))
       continue;
 
     snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
@@ -1810,7 +1797,7 @@ fib:
 
   pool_foreach (m, sm->static_mappings,
   ({
-    if (!(m->addr_only)  || (m->local_addr.as_u32 == m->external_addr.as_u32))
+    if (!((is_addr_only_static_mapping(m)))  || (m->local_addr.as_u32 == m->external_addr.as_u32))
       continue;
 
     snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
@@ -2017,7 +2004,8 @@ snat_static_mapping_match (snat_main_t * sm,
                           u8 by_external,
                           u8 * is_addr_only,
                           twice_nat_type_t * twice_nat,
-                          lb_nat_type_t * lb, ip4_address_t * ext_host_addr)
+                          lb_nat_type_t * lb, ip4_address_t * ext_host_addr,
+                          u8 * is_identity_nat)
 {
   clib_bihash_kv_8_8_t kv, value;
   snat_static_mapping_t *m;
@@ -2108,7 +2096,7 @@ snat_static_mapping_match (snat_main_t * sm,
          mapping->fib_index = m->fib_index;
          mapping->addr = m->local_addr;
          /* Address only mapping doesn't change port */
-         mapping->port = m->addr_only ? match.port
+         mapping->port = is_addr_only_static_mapping (m) ? match.port
            : clib_host_to_net_u16 (m->local_port);
        }
       mapping->protocol = m->proto;
@@ -2117,18 +2105,21 @@ snat_static_mapping_match (snat_main_t * sm,
     {
       mapping->addr = m->external_addr;
       /* Address only mapping doesn't change port */
-      mapping->port = m->addr_only ? match.port
+      mapping->port = is_addr_only_static_mapping (m) ? match.port
        : clib_host_to_net_u16 (m->external_port);
       mapping->fib_index = sm->outside_fib_index;
     }
 
 end:
   if (PREDICT_FALSE (is_addr_only != 0))
-    *is_addr_only = m->addr_only;
+    *is_addr_only = is_addr_only_static_mapping (m);
 
   if (PREDICT_FALSE (twice_nat != 0))
     *twice_nat = m->twice_nat;
 
+  if (PREDICT_FALSE (is_identity_nat != 0))
+    *is_identity_nat = is_identity_static_mapping (m);
+
   return 0;
 }
 
@@ -2919,7 +2910,8 @@ match:
                                rp->e_port,
                                rp->vrf_id,
                                rp->addr_only, ~0 /* sw_if_index */ ,
-                               rp->proto, !is_delete, 0, 0, rp->tag);
+                               rp->proto, !is_delete, rp->twice_nat,
+                               rp->out2in_only, rp->tag, rp->identity_nat);
   if (rv)
     nat_log_notice ("snat_add_static_mapping returned %d", rv);
 }
@@ -2988,7 +2980,9 @@ match:
                                            rp->addr_only,
                                            ~0 /* sw_if_index */ ,
                                            rp->proto,
-                                           rp->is_add, 0, 0, rp->tag);
+                                           rp->is_add, rp->twice_nat,
+                                           rp->out2in_only, rp->tag,
+                                           rp->identity_nat);
              if (rv)
                nat_log_notice ("snat_add_static_mapping returned %d", rv);
            }
index 1baf10f..0549acd 100644 (file)
@@ -179,6 +179,11 @@ typedef enum
 #define NAT_INTERFACE_FLAG_IS_INSIDE 1
 #define NAT_INTERFACE_FLAG_IS_OUTSIDE 2
 
+/* Static mapping flags */
+#define NAT_STATIC_MAPPING_FLAG_ADDR_ONLY    1
+#define NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY  2
+#define NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT 4
+
 /* *INDENT-OFF* */
 typedef CLIB_PACKED(struct
 {
@@ -321,12 +326,8 @@ typedef struct
   u16 local_port;
   /* external port */
   u16 external_port;
-  /* 1 = 1:1NAT, 0 = 1:1NAPT */
-  u8 addr_only;
   /* is twice-nat */
   twice_nat_type_t twice_nat;
-  /* 1 = rule match only out2in direction */
-  u8 out2in_only;
   /* local FIB table */
   u32 vrf_id;
   u32 fib_index;
@@ -342,6 +343,8 @@ typedef struct
   nat44_lb_addr_port_t *locals;
   /* affinity per service lis */
   u32 affinity_per_service_list_head_index;
+  /* flags */
+  u32 flags;
 } snat_static_mapping_t;
 
 typedef struct
@@ -358,9 +361,12 @@ typedef struct
   u32 sw_if_index;
   u32 vrf_id;
   snat_protocol_t proto;
+  u32 flags;
   int addr_only;
   int twice_nat;
   int is_add;
+  int out2in_only;
+  int identity_nat;
   u8 *tag;
 } snat_static_map_resolve_t;
 
@@ -642,6 +648,24 @@ unformat_function_t unformat_snat_protocol;
 */
 #define nat44_is_ses_closed(s) s->state == 0xf
 
+/** \brief Check if NAT static mapping is address only (1:1NAT).
+    @param sm NAT static mapping
+    @return 1 if 1:1NAT, 0 if 1:1NAPT
+*/
+#define is_addr_only_static_mapping(sm) (sm->flags & NAT_STATIC_MAPPING_FLAG_ADDR_ONLY)
+
+/** \brief Check if NAT static mapping match only out2in direction.
+    @param sm NAT static mapping
+    @return 1 if rule match only out2in direction
+*/
+#define is_out2in_only_static_mapping(sm) (sm->flags & NAT_STATIC_MAPPING_FLAG_OUT2IN_ONLY)
+
+/** \brief Check if NAT static mapping is identity NAT.
+    @param sm NAT static mapping
+    @return 1 if identity NAT
+*/
+#define is_identity_static_mapping(sm) (sm->flags & NAT_STATIC_MAPPING_FLAG_IDENTITY_NAT)
+
 /* logging */
 #define nat_log_err(...) \
   vlib_log(VLIB_LOG_LEVEL_ERR, snat_main.log_class, __VA_ARGS__)
@@ -773,18 +797,19 @@ void nat44_add_del_address_dpo (ip4_address_t addr, u8 is_add);
 /**
  * @brief Add/delete NAT44 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 vrf_id      local VRF ID
- * @param addr_only   1 = 1:1NAT, 0 = 1:1NAPT
- * @param sw_if_index use interface address as external IPv4 address
- * @param proto       L4 protocol
- * @param is_add      1 = add, 0 = delete
- * @param twice_nat   twice-nat mode
- * @param out2in_only if 1 rule match only out2in direction
- * @param tagi        opaque string tag
+ * @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 vrf_id       local VRF ID
+ * @param addr_only    1 = 1:1NAT, 0 = 1:1NAPT
+ * @param sw_if_index  use interface address as external IPv4 address
+ * @param proto        L4 protocol
+ * @param is_add       1 = add, 0 = delete
+ * @param twice_nat    twice-nat mode
+ * @param out2in_only  if 1 rule match only out2in direction
+ * @param tag          opaque string tag
+ * @param identity_nat identity NAT
  *
  * @return 0 on success, non-zero value otherwise
  */
@@ -793,7 +818,7 @@ int snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
                             int addr_only, u32 sw_if_index,
                             snat_protocol_t proto, int is_add,
                             twice_nat_type_t twice_nat, u8 out2in_only,
-                            u8 * tag);
+                            u8 * tag, u8 identity_nat);
 
 /**
  * @brief Add/delete static mapping with load-balancing (multiple backends)
@@ -1009,7 +1034,8 @@ int snat_static_mapping_match (snat_main_t * sm,
                               u8 * is_addr_only,
                               twice_nat_type_t * twice_nat,
                               lb_nat_type_t * lb,
-                              ip4_address_t * ext_host_addr);
+                              ip4_address_t * ext_host_addr,
+                              u8 * is_identity_nat);
 
 /**
  * @brief Add/del NAT address to FIB.
index bebc6a0..0a3379a 100644 (file)
@@ -718,7 +718,7 @@ add_static_mapping_command_fn (vlib_main_t * vm,
 
   rv = snat_add_static_mapping (l_addr, e_addr, (u16) l_port, (u16) e_port,
                                vrf_id, addr_only, sw_if_index, proto, is_add,
-                               twice_nat, out2in_only, 0);
+                               twice_nat, out2in_only, 0, 0);
 
   switch (rv)
     {
@@ -802,7 +802,7 @@ add_identity_mapping_command_fn (vlib_main_t * vm,
 
   rv = snat_add_static_mapping (addr, addr, (u16) port, (u16) port,
                                vrf_id, addr_only, sw_if_index, proto, is_add,
-                               0, 0, 0);
+                               0, 0, 0, 1);
 
   switch (rv)
     {
index 9d49dc2..c07427d 100644 (file)
@@ -114,7 +114,7 @@ snat_hairpinning (snat_main_t * sm,
   kv0.key = key0.as_u64;
 
   /* Check if destination is static mappings */
-  if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+  if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0, 0))
     {
       new_dst_addr0 = sm0.addr.as_u32;
       new_dst_port0 = sm0.port;
@@ -444,7 +444,7 @@ nat44_reass_hairpinning (snat_main_t * sm,
   udp0 = ip4_next_header (ip0);
 
   /* Check if destination is static mappings */
-  if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+  if (!snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0, 0))
     {
       new_dst_addr0 = sm0.addr.as_u32;
       new_dst_port0 = sm0.port;
index e642edd..8ad5c66 100644 (file)
@@ -980,7 +980,7 @@ static void
   rv = snat_add_static_mapping (local_addr, external_addr, local_port,
                                external_port, vrf_id, mp->addr_only,
                                external_sw_if_index, proto, mp->is_add,
-                               twice_nat, mp->out2in_only, tag);
+                               twice_nat, mp->out2in_only, tag, 0);
 
   vec_free (tag);
 
@@ -1027,7 +1027,7 @@ send_nat44_static_mapping_details (snat_static_mapping_t * m,
   memset (rmp, 0, sizeof (*rmp));
   rmp->_vl_msg_id =
     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
-  rmp->addr_only = m->addr_only;
+  rmp->addr_only = is_addr_only_static_mapping (m);
   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
   rmp->external_sw_if_index = ~0;
@@ -1037,8 +1037,8 @@ send_nat44_static_mapping_details (snat_static_mapping_t * m,
     rmp->twice_nat = 1;
   else if (m->twice_nat == TWICE_NAT_SELF)
     rmp->self_twice_nat = 1;
-  rmp->out2in_only = m->out2in_only;
-  if (m->addr_only == 0)
+  rmp->out2in_only = is_out2in_only_static_mapping (m);
+  if (rmp->addr_only == 0)
     {
       rmp->protocol = snat_proto_to_ip_proto (m->proto);
       rmp->external_port = htons (m->external_port);
@@ -1100,9 +1100,7 @@ vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
   /* *INDENT-OFF* */
   pool_foreach (m, sm->static_mappings,
   ({
-      if (!vec_len (m->locals) &&
-          ((m->local_port != m->external_port)
-           || (m->local_addr.as_u32 != m->external_addr.as_u32)))
+      if (!is_identity_static_mapping(m) && !vec_len (m->locals))
         send_nat44_static_mapping_details (m, reg, mp->context);
   }));
   /* *INDENT-ON* */
@@ -1110,7 +1108,7 @@ vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
   for (j = 0; j < vec_len (sm->to_resolve); j++)
     {
       rp = sm->to_resolve + j;
-      if (rp->l_addr.as_u32 != 0)
+      if (!rp->identity_nat)
        send_nat44_static_map_resolve_details (rp, reg, mp->context);
     }
 }
@@ -1162,7 +1160,7 @@ static void
 
   rv =
     snat_add_static_mapping (addr, addr, port, port, vrf_id, mp->addr_only,
-                            sw_if_index, proto, mp->is_add, 0, 0, tag);
+                            sw_if_index, proto, mp->is_add, 0, 0, tag, 1);
 
   vec_free (tag);
 
@@ -1203,7 +1201,7 @@ send_nat44_identity_mapping_details (snat_static_mapping_t * m,
   memset (rmp, 0, sizeof (*rmp));
   rmp->_vl_msg_id =
     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
-  rmp->addr_only = m->addr_only;
+  rmp->addr_only = is_addr_only_static_mapping (m);
   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
   rmp->port = htons (m->local_port);
   rmp->sw_if_index = ~0;
@@ -1260,8 +1258,7 @@ static void
   /* *INDENT-OFF* */
   pool_foreach (m, sm->static_mappings,
   ({
-      if (!vec_len (m->locals) && (m->local_port == m->external_port)
-          && (m->local_addr.as_u32 == m->external_addr.as_u32))
+      if (is_identity_static_mapping(m) && !vec_len (m->locals))
         send_nat44_identity_mapping_details (m, reg, mp->context);
   }));
   /* *INDENT-ON* */
@@ -1269,7 +1266,7 @@ static void
   for (j = 0; j < vec_len (sm->to_resolve); j++)
     {
       rp = sm->to_resolve + j;
-      if (rp->l_addr.as_u32 == 0)
+      if (rp->identity_nat)
        send_nat44_identity_map_resolve_details (rp, reg, mp->context);
     }
 }
@@ -1656,7 +1653,7 @@ send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
     rmp->twice_nat = 1;
   else if (m->twice_nat == TWICE_NAT_SELF)
     rmp->self_twice_nat = 1;
-  rmp->out2in_only = m->out2in_only;
+  rmp->out2in_only = is_out2in_only_static_mapping (m);
   if (m->tag)
     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
 
index 279d666..a4b62b6 100644 (file)
@@ -220,14 +220,14 @@ format_snat_static_mapping (u8 * s, va_list * args)
   snat_static_mapping_t *m = va_arg (*args, snat_static_mapping_t *);
   nat44_lb_addr_port_t *local;
 
-  if (m->addr_only)
+  if (is_addr_only_static_mapping (m))
     s = format (s, "local %U external %U vrf %d %s %s",
                format_ip4_address, &m->local_addr,
                format_ip4_address, &m->external_addr,
                m->vrf_id,
                m->twice_nat == TWICE_NAT ? "twice-nat" :
                m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
-               m->out2in_only ? "out2in-only" : "");
+               is_out2in_only_static_mapping (m) ? "out2in-only" : "");
   else
     {
       if (vec_len (m->locals))
@@ -237,7 +237,7 @@ format_snat_static_mapping (u8 * s, va_list * args)
                      format_ip4_address, &m->external_addr, m->external_port,
                      m->twice_nat == TWICE_NAT ? "twice-nat" :
                      m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
-                     m->out2in_only ? "out2in-only" : "");
+                     is_out2in_only_static_mapping (m) ? "out2in-only" : "");
          vec_foreach (local, m->locals)
            s = format (s, "\n  local %U:%d vrf %d probability %d\%",
                        format_ip4_address, &local->addr, local->port,
@@ -251,7 +251,7 @@ format_snat_static_mapping (u8 * s, va_list * args)
                    m->vrf_id,
                    m->twice_nat == TWICE_NAT ? "twice-nat" :
                    m->twice_nat == TWICE_NAT_SELF ? "self-twice-nat" : "",
-                   m->out2in_only ? "out2in-only" : "");
+                   is_out2in_only_static_mapping (m) ? "out2in-only" : "");
     }
   return s;
 }
index 67d831a..eeecf16 100755 (executable)
@@ -309,6 +309,7 @@ icmp_match_out2in_slow (snat_main_t * sm, vlib_node_runtime_t * node,
   u8 is_addr_only;
   u32 next0 = ~0;
   int err;
+  u8 identity_nat;
 
   icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
   sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
@@ -333,7 +334,7 @@ icmp_match_out2in_slow (snat_main_t * sm, vlib_node_runtime_t * node,
       /* Try to match static mapping by external address and port,
          destination address and port in packet */
       if (snat_static_mapping_match
-         (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0))
+         (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0, &identity_nat))
        {
          if (!sm->forwarding_enabled)
            {
@@ -364,6 +365,11 @@ icmp_match_out2in_slow (snat_main_t * sm, vlib_node_runtime_t * node,
          goto out;
        }
 
+      if (PREDICT_FALSE (identity_nat))
+       {
+         dont_translate = 1;
+         goto out;
+       }
       /* Create session initiated by host from external network */
       s0 = create_session_for_static_mapping (sm, b0, sm0, key0,
                                              node, thread_index,
@@ -443,7 +449,8 @@ icmp_match_out2in_fast (snat_main_t * sm, vlib_node_runtime_t * node,
     }
   key0.fib_index = rx_fib_index0;
 
-  if (snat_static_mapping_match (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0))
+  if (snat_static_mapping_match
+      (sm, key0, &sm0, 1, &is_addr_only, 0, 0, 0, 0))
     {
       /* Don't NAT packet aimed at the intfc address */
       if (is_interface_addr (sm, node, sw_if_index0, ip0->dst_address.as_u32))
@@ -703,6 +710,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
          u32 proto0, proto1;
          snat_session_t *s0 = 0, *s1 = 0;
          clib_bihash_kv_8_8_t kv0, kv1, value0, value1;
+         u8 identity_nat0, identity_nat1;
 
          /* Prefetch next iteration. */
          {
@@ -793,7 +801,8 @@ snat_out2in_node_fn (vlib_main_t * vm,
            {
              /* Try to match static mapping by external address and port,
                 destination address and port in packet */
-             if (snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+             if (snat_static_mapping_match
+                 (sm, key0, &sm0, 1, 0, 0, 0, 0, &identity_nat0))
                {
                  /*
                   * Send DHCP packets to the ipv4 stack, or we won't
@@ -817,6 +826,9 @@ snat_out2in_node_fn (vlib_main_t * vm,
                  goto trace0;
                }
 
+             if (PREDICT_FALSE (identity_nat0))
+               goto trace0;
+
              /* Create session initiated by host from external network */
              s0 = create_session_for_static_mapping (sm, b0, sm0, key0, node,
                                                      thread_index, now);
@@ -950,7 +962,8 @@ snat_out2in_node_fn (vlib_main_t * vm,
            {
              /* Try to match static mapping by external address and port,
                 destination address and port in packet */
-             if (snat_static_mapping_match (sm, key1, &sm1, 1, 0, 0, 0, 0))
+             if (snat_static_mapping_match
+                 (sm, key1, &sm1, 1, 0, 0, 0, 0, &identity_nat1))
                {
                  /*
                   * Send DHCP packets to the ipv4 stack, or we won't
@@ -974,6 +987,9 @@ snat_out2in_node_fn (vlib_main_t * vm,
                  goto trace1;
                }
 
+             if (PREDICT_FALSE (identity_nat1))
+               goto trace1;
+
              /* Create session initiated by host from external network */
              s1 = create_session_for_static_mapping (sm, b1, sm1, key1, node,
                                                      thread_index, now);
@@ -1069,6 +1085,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
          u32 proto0;
          snat_session_t *s0 = 0;
          clib_bihash_kv_8_8_t kv0, value0;
+         u8 identity_nat0;
 
          /* speculatively enqueue b0 to the current next frame */
          bi0 = from[0];
@@ -1143,7 +1160,8 @@ snat_out2in_node_fn (vlib_main_t * vm,
            {
              /* Try to match static mapping by external address and port,
                 destination address and port in packet */
-             if (snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+             if (snat_static_mapping_match
+                 (sm, key0, &sm0, 1, 0, 0, 0, 0, &identity_nat0))
                {
                  /*
                   * Send DHCP packets to the ipv4 stack, or we won't
@@ -1167,6 +1185,9 @@ snat_out2in_node_fn (vlib_main_t * vm,
                  goto trace00;
                }
 
+             if (PREDICT_FALSE (identity_nat0))
+               goto trace00;
+
              /* Create session initiated by host from external network */
              s0 = create_session_for_static_mapping (sm, b0, sm0, key0, node,
                                                      thread_index, now);
@@ -1320,6 +1341,7 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
          snat_session_t *s0 = 0;
          u16 old_port0, new_port0;
          ip_csum_t sum0;
+         u8 identity_nat0;
 
          /* speculatively enqueue b0 to the current next frame */
          bi0 = from[0];
@@ -1377,7 +1399,7 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
                  /* Try to match static mapping by external address and port,
                     destination address and port in packet */
                  if (snat_static_mapping_match
-                     (sm, key0, &sm0, 1, 0, 0, 0, 0))
+                     (sm, key0, &sm0, 1, 0, 0, 0, 0, &identity_nat0))
                    {
                      /*
                       * Send DHCP packets to the ipv4 stack, or we won't
@@ -1402,6 +1424,9 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
                      goto trace0;
                    }
 
+                 if (PREDICT_FALSE (identity_nat0))
+                   goto trace0;
+
                  /* Create session initiated by host from external network */
                  s0 =
                    create_session_for_static_mapping (sm, b0, sm0, key0,
@@ -1663,7 +1688,7 @@ snat_out2in_fast_node_fn (vlib_main_t * vm,
          key0.port = udp0->dst_port;
          key0.fib_index = rx_fib_index0;
 
-         if (snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0))
+         if (snat_static_mapping_match (sm, key0, &sm0, 1, 0, 0, 0, 0, 0))
            {
              b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
              goto trace00;
index dce6c56..b2dbc51 100644 (file)
@@ -471,7 +471,7 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
   clib_bihash_kv_16_8_t kv, value;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
   snat_session_t *s = 0;
-  u8 dont_translate = 0, is_addr_only;
+  u8 dont_translate = 0, is_addr_only, identity_nat;
   snat_session_key_t e_key, l_key;
 
   icmp = (icmp46_header_t *) ip4_next_header (ip);
@@ -496,7 +496,7 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
       e_key.protocol = ip_proto_to_snat_proto (key.proto);
       e_key.fib_index = rx_fib_index;
       if (snat_static_mapping_match
-         (sm, e_key, &l_key, 1, &is_addr_only, 0, 0, 0))
+         (sm, e_key, &l_key, 1, &is_addr_only, 0, 0, 0, &identity_nat))
        {
          if (!sm->forwarding_enabled)
            {
@@ -533,6 +533,12 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
          goto out;
        }
 
+      if (PREDICT_FALSE (identity_nat))
+       {
+         dont_translate = 1;
+         goto out;
+       }
+
       /* Create session initiated by host from external network */
       s = create_session_for_static_mapping_ed (sm, b, l_key, e_key, node,
                                                thread_index, 0, 0,
@@ -717,6 +723,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
          snat_session_key_t e_key0, l_key0, e_key1, l_key1;
          lb_nat_type_t lb_nat0, lb_nat1;
          twice_nat_type_t twice_nat0, twice_nat1;
+         u8 identity_nat0, identity_nat1;
 
          /* Prefetch next iteration. */
          {
@@ -828,7 +835,8 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  e_key0.fib_index = rx_fib_index0;
                  if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
                                                 &twice_nat0, &lb_nat0,
-                                                &ip0->src_address))
+                                                &ip0->src_address,
+                                                &identity_nat0))
                    {
                      /*
                       * Send DHCP packets to the ipv4 stack, or we won't
@@ -864,6 +872,9 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                      goto trace00;
                    }
 
+                 if (PREDICT_FALSE (identity_nat0))
+                   goto trace00;
+
                  /* Create session initiated by host from external network */
                  s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
                                                             e_key0, node,
@@ -1046,7 +1057,8 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  e_key1.fib_index = rx_fib_index1;
                  if (snat_static_mapping_match (sm, e_key1, &l_key1, 1, 0,
                                                 &twice_nat1, &lb_nat1,
-                                                &ip1->src_address))
+                                                &ip1->src_address,
+                                                &identity_nat1))
                    {
                      /*
                       * Send DHCP packets to the ipv4 stack, or we won't
@@ -1082,6 +1094,9 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                      goto trace01;
                    }
 
+                 if (PREDICT_FALSE (identity_nat1))
+                   goto trace01;
+
                  /* Create session initiated by host from external network */
                  s1 = create_session_for_static_mapping_ed (sm, b1, l_key1,
                                                             e_key1, node,
@@ -1202,6 +1217,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
          snat_session_key_t e_key0, l_key0;
          lb_nat_type_t lb_nat0;
          twice_nat_type_t twice_nat0;
+         u8 identity_nat0;
 
          /* speculatively enqueue b0 to the current next frame */
          bi0 = from[0];
@@ -1297,7 +1313,8 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  e_key0.fib_index = rx_fib_index0;
                  if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
                                                 &twice_nat0, &lb_nat0,
-                                                &ip0->src_address))
+                                                &ip0->src_address,
+                                                &identity_nat0))
                    {
                      /*
                       * Send DHCP packets to the ipv4 stack, or we won't
@@ -1333,6 +1350,9 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                      goto trace0;
                    }
 
+                 if (PREDICT_FALSE (identity_nat0))
+                   goto trace0;
+
                  /* Create session initiated by host from external network */
                  s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
                                                             e_key0, node,
@@ -1554,6 +1574,7 @@ nat44_ed_out2in_reass_node_fn (vlib_main_t * vm,
          snat_session_key_t e_key0, l_key0;
          lb_nat_type_t lb0;
          twice_nat_type_t twice_nat0;
+         u8 identity_nat0;
 
          /* speculatively enqueue b0 to the current next frame */
          bi0 = from[0];
@@ -1634,7 +1655,8 @@ nat44_ed_out2in_reass_node_fn (vlib_main_t * vm,
                  e_key0.protocol = proto0;
                  e_key0.fib_index = rx_fib_index0;
                  if (snat_static_mapping_match (sm, e_key0, &l_key0, 1, 0,
-                                                &twice_nat0, &lb0, 0))
+                                                &twice_nat0, &lb0, 0,
+                                                &identity_nat0))
                    {
                      /*
                       * Send DHCP packets to the ipv4 stack, or we won't
@@ -1674,6 +1696,12 @@ nat44_ed_out2in_reass_node_fn (vlib_main_t * vm,
                      goto trace0;
                    }
 
+                 if (PREDICT_FALSE (identity_nat0))
+                   {
+                     reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE;
+                     goto trace0;
+                   }
+
                  /* Create session initiated by host from external network */
                  s0 = create_session_for_static_mapping_ed (sm, b0, l_key0,
                                                             e_key0, node,
index 9092b47..3b9007f 100644 (file)
@@ -1935,6 +1935,9 @@ class TestNAT44(MethodHolder):
             self.logger.error(ppp("Unexpected or invalid packet:", p))
             raise
 
+        sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
+        self.assertEqual(len(sessions), 0)
+
     def test_multiple_inside_interfaces(self):
         """ NAT44 multiple non-overlapping address space inside interfaces """