NAT44: asymmetrical load balancing static mapping rule (VPP-1132)
[vpp.git] / src / plugins / nat / nat.c
index 90515ac..99c5f63 100644 (file)
@@ -973,7 +973,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
 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,
-                                     u8 twice_nat)
+                                     u8 twice_nat, u8 out2in_only)
 {
   snat_main_t * sm = &snat_main;
   snat_static_mapping_t *m;
@@ -1014,7 +1014,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
 
       /* Find external address in allocated addresses and reserve port for
          address and port pair mapping when dynamic translations enabled */
-      if (!sm->static_mapping_only)
+      if (!(sm->static_mapping_only || out2in_only))
         {
           for (i = 0; i < vec_len (sm->addresses); i++)
             {
@@ -1058,6 +1058,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       m->external_port = e_port;
       m->proto = proto;
       m->twice_nat = twice_nat;
+      m->out2in_only = out2in_only;
 
       m_key.addr = m->external_addr;
       m_key.port = m->external_port;
@@ -1095,10 +1096,13 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       for (i = 0; i < vec_len (locals); i++)
         {
           m_key.addr = locals[i].addr;
-          m_key.port = locals[i].port;
-          kv.key = m_key.as_u64;
-          kv.value = m - sm->static_mappings;
-          clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
+          if (!out2in_only)
+            {
+              m_key.port = locals[i].port;
+              kv.key = m_key.as_u64;
+              kv.value = m - sm->static_mappings;
+              clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
+            }
           locals[i].prefix = (i == 0) ? locals[i].probability :\
             (locals[i - 1].prefix + locals[i].probability);
           vec_add1 (m->locals, locals[i]);
@@ -1121,7 +1125,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       fib_table_unlock (m->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_HI);
 
       /* Free external address port */
-      if (!sm->static_mapping_only)
+      if (!(sm->static_mapping_only || out2in_only))
         {
           for (i = 0; i < vec_len (sm->addresses); i++)
             {
@@ -1173,13 +1177,16 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       vec_foreach (local, m->locals)
         {
           m_key.addr = local->addr;
-          m_key.port = local->port;
-          m_key.fib_index = m->fib_index;
-          kv.key = m_key.as_u64;
-          if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
+          if (!out2in_only)
             {
-              clib_warning ("static_mapping_by_local key del failed");
-              return VNET_API_ERROR_UNSPECIFIED;
+              m_key.port = local->port;
+              m_key.fib_index = m->fib_index;
+              kv.key = m_key.as_u64;
+              if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
+                {
+                  clib_warning ("static_mapping_by_local key del failed");
+                  return VNET_API_ERROR_UNSPECIFIED;
+                }
             }
 
           m_key.port = clib_host_to_net_u16 (local->port);
@@ -2509,6 +2516,7 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm,
   u8 proto_set = 0;
   nat44_lb_addr_port_t *locals = 0, local;
   u8 twice_nat = 0;
+  u8 out2in_only = 0;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -2535,6 +2543,8 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm,
         proto_set = 1;
       else if (unformat (line_input, "twice-nat"))
         twice_nat = 1;
+      else if (unformat (line_input, "out2in-only"))
+        out2in_only = 1;
       else if (unformat (line_input, "del"))
         is_add = 0;
       else
@@ -2558,7 +2568,7 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm,
     }
 
   rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, vrf_id,
-                                        locals, is_add, twice_nat);
+                                        locals, is_add, twice_nat, out2in_only);
 
   switch (rv)
     {
@@ -2591,7 +2601,7 @@ VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
   .short_help =
     "nat44 add load-balancing static mapping protocol tcp|udp "
     "external <addr>:<port> local <addr>:<port> probability <n> [twice-nat] "
-    "[vrf <table-id>] [del]",
+    "[vrf <table-id>] [out2in-only] [del]",
 };
 
 static clib_error_t *