NAT44: LB NAT - local backends in multiple VRFs (VPP-1345)
[vpp.git] / src / plugins / nat / nat_api.c
index 417d298..5887efe 100644 (file)
@@ -24,6 +24,7 @@
 #include <nat/nat66.h>
 #include <nat/dslite.h>
 #include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
 #include <vlibapi/api.h>
 #include <vlibmemory/api.h>
 
@@ -444,7 +445,7 @@ static void
   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
 
   if (count > 1024)
-    clib_warning ("%U - %U, %d addresses...",
+    nat_log_info ("%U - %U, %d addresses...",
                  format_ip4_address, mp->first_ip_address,
                  format_ip4_address, mp->last_ip_address, count);
 
@@ -453,7 +454,7 @@ static void
   for (i = 0; i < count; i++)
     {
       if (mp->is_add)
-       snat_add_address (sm, &this_addr, vrf_id, mp->twice_nat);
+       rv = snat_add_address (sm, &this_addr, vrf_id, mp->twice_nat);
       else
        rv = snat_del_address (sm, this_addr, 0, mp->twice_nat);
 
@@ -876,7 +877,9 @@ 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_addr.as_u32 != m->external_addr.as_u32))
+      if (!vec_len (m->locals) &&
+          ((m->local_port != m->external_port)
+           || (m->local_addr.as_u32 != m->external_addr.as_u32)))
         send_nat44_static_mapping_details (m, reg, mp->context);
   }));
   /* *INDENT-ON* */
@@ -1034,7 +1037,8 @@ static void
   /* *INDENT-OFF* */
   pool_foreach (m, sm->static_mappings,
   ({
-      if (!vec_len(m->locals) && (m->local_addr.as_u32 == m->external_addr.as_u32))
+      if (!vec_len (m->locals) && (m->local_port == m->external_port)
+          && (m->local_addr.as_u32 == m->external_addr.as_u32))
         send_nat44_identity_mapping_details (m, reg, mp->context);
   }));
   /* *INDENT-ON* */
@@ -1154,13 +1158,17 @@ send_nat44_user_details (snat_user_t * u, vl_api_registration_t * reg,
 {
   vl_api_nat44_user_details_t *rmp;
   snat_main_t *sm = &snat_main;
-  fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
+  ip4_main_t *im = &ip4_main;
 
   rmp = vl_msg_api_alloc (sizeof (*rmp));
   memset (rmp, 0, sizeof (*rmp));
   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
 
-  rmp->vrf_id = ntohl (fib->ft_table_id);
+  if (!pool_is_free_index (im->fibs, u->fib_index))
+    {
+      fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
+      rmp->vrf_id = ntohl (fib->ft_table_id);
+    }
 
   clib_memcpy (rmp->ip_address, &(u->addr), 4);
   rmp->nsessions = ntohl (u->nsessions);
@@ -1215,7 +1223,10 @@ send_nat44_user_session_details (snat_session_t * s,
     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
-  rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
+  rmp->is_static = snat_is_session_static (s) ? 1 : 0;
+  rmp->is_twicenat = is_twice_nat_session (s) ? 1 : 0;
+  rmp->ext_host_valid = is_ed_session (s)
+    || is_fwd_bypass_session (s) ? 1 : 0;
   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
   rmp->total_pkts = ntohl (s->total_pkts);
@@ -1232,6 +1243,16 @@ send_nat44_user_session_details (snat_session_t * s,
       rmp->inside_port = s->in2out.port;
       rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
     }
+  if (is_ed_session (s) || is_fwd_bypass_session (s))
+    {
+      clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
+      rmp->ext_host_port = s->ext_host_port;
+      if (is_twice_nat_session (s))
+       {
+         clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
+         rmp->ext_host_nat_port = s->ext_host_nat_port;
+       }
+    }
 
   vl_api_send_msg (reg, (u8 *) rmp);
 }
@@ -1320,6 +1341,7 @@ unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t * addr_port_pairs,
       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
       lb_addr_port.port = clib_net_to_host_u16 (ap->port);
       lb_addr_port.probability = ap->probability;
+      lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
       vec_add1 (lb_addr_port_pairs, lb_addr_port);
     }
 
@@ -1339,7 +1361,7 @@ static void
   snat_protocol_t proto;
   u8 *tag = 0;
 
-  if (sm->deterministic)
+  if (!sm->endpoint_dependent)
     {
       rv = VNET_API_ERROR_UNSUPPORTED;
       goto send_reply;
@@ -1359,8 +1381,7 @@ static void
   rv =
     nat44_add_del_lb_static_mapping (e_addr,
                                     clib_net_to_host_u16 (mp->external_port),
-                                    proto, clib_net_to_host_u32 (mp->vrf_id),
-                                    locals, mp->is_add, twice_nat,
+                                    proto, locals, mp->is_add, twice_nat,
                                     mp->out2in_only, tag);
 
   vec_free (locals);
@@ -1402,7 +1423,6 @@ send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
   rmp->external_port = ntohs (m->external_port);
   rmp->protocol = snat_proto_to_ip_proto (m->proto);
-  rmp->vrf_id = ntohl (m->vrf_id);
   rmp->context = context;
   if (m->twice_nat == TWICE_NAT)
     rmp->twice_nat = 1;
@@ -1418,6 +1438,7 @@ send_nat44_lb_static_mapping_details (snat_static_mapping_t * m,
     clib_memcpy (locals->addr, &(ap->addr), 4);
     locals->port = htons (ap->port);
     locals->probability = ap->probability;
+    locals->vrf_id = ntohl (ap->vrf_id);
     locals++;
     rmp->local_num++;
   }
@@ -1433,7 +1454,7 @@ static void
   snat_main_t *sm = &snat_main;
   snat_static_mapping_t *m;
 
-  if (sm->deterministic)
+  if (!sm->endpoint_dependent)
     return;
 
   reg = vl_api_client_index_to_registration (mp->client_index);
@@ -1464,8 +1485,8 @@ vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
 {
   snat_main_t *sm = &snat_main;
   vl_api_nat44_del_session_reply_t *rmp;
-  ip4_address_t addr;
-  u16 port;
+  ip4_address_t addr, eh_addr;
+  u16 port, eh_port;
   u32 vrf_id;
   int rv = 0;
   snat_protocol_t proto;
@@ -1480,8 +1501,15 @@ vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t * mp)
   port = clib_net_to_host_u16 (mp->port);
   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
   proto = ip_proto_to_snat_proto (mp->protocol);
+  memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
+  eh_port = clib_net_to_host_u16 (mp->ext_host_port);
 
-  rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in);
+  if (mp->ext_host_valid)
+    rv =
+      nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
+                           vrf_id, mp->is_in);
+  else
+    rv = nat44_del_session (sm, &addr, port, proto, vrf_id, mp->is_in);
 
 send_reply:
   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
@@ -1498,6 +1526,10 @@ vl_api_nat44_del_session_t_print (vl_api_nat44_del_session_t * mp,
              format_ip4_address, mp->address,
              clib_net_to_host_u16 (mp->port),
              mp->protocol, clib_net_to_host_u32 (mp->vrf_id), mp->is_in);
+  if (mp->ext_host_valid)
+    s = format (s, "ext_host_address %U ext_host_port %d",
+               format_ip4_address, mp->ext_host_address,
+               clib_net_to_host_u16 (mp->ext_host_port));
 
   FINISH;
 }
@@ -1509,9 +1541,35 @@ static void
   snat_main_t *sm = &snat_main;
   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
   int rv = 0;
+  u32 *ses_to_be_removed = 0, *ses_index;
+  snat_main_per_thread_data_t *tsm;
+  snat_session_t *s;
 
   sm->forwarding_enabled = mp->enable != 0;
 
+  if (mp->enable == 0)
+    {
+      /* *INDENT-OFF* */
+      vec_foreach (tsm, sm->per_thread_data)
+      {
+        pool_foreach (s, tsm->sessions,
+        ({
+          if (is_fwd_bypass_session(s))
+            {
+              vec_add1 (ses_to_be_removed, s - tsm->sessions);
+            }
+        }));
+        vec_foreach (ses_index, ses_to_be_removed)
+        {
+          s = pool_elt_at_index(tsm->sessions, ses_index[0]);
+          nat_free_session_data (sm, s, tsm - sm->per_thread_data);
+          nat44_delete_session (sm, s, tsm - sm->per_thread_data);
+        }
+        vec_free (ses_to_be_removed);
+      }
+      /* *INDENT-ON* */
+    }
+
   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
 }