Acquire SNAT pool addresses from specific interfaces 49/4649/1
authorDave Barach <dave@barachs.net>
Wed, 11 Jan 2017 18:01:14 +0000 (13:01 -0500)
committerDave Barach <dave@barachs.net>
Wed, 11 Jan 2017 18:01:44 +0000 (13:01 -0500)
Pick up addresses added by DHCP client, or by static configuration
Needs to have binary API support added

Change-Id: I962ef89e6e5f36cdc5457b92e165c498b08b25a9
Signed-off-by: Dave Barach <dave@barachs.net>
src/plugins/snat/snat.c
src/plugins/snat/snat.h
src/vnet/ip/ip4.h

index bc99568..94e0507 100644 (file)
@@ -16,6 +16,8 @@
  */
 
 #include <vnet/vnet.h>
+#include <vnet/ip/ip.h>
+#include <vnet/ip/ip4.h>
 #include <vnet/plugin/plugin.h>
 #include <vlibapi/api.h>
 #include <snat/snat.h>
@@ -1146,6 +1148,15 @@ static void plugin_custom_dump_configure (snat_main_t * sm)
 #undef _
 }
 
+static void
+snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
+                                       uword opaque,
+                                       u32 sw_if_index,
+                                       ip4_address_t * address,
+                                       u32 address_length,
+                                       u32 if_address_index,
+                                       u32 is_delete);
+
 static clib_error_t * snat_init (vlib_main_t * vm)
 {
   snat_main_t * sm = &snat_main;
@@ -1158,6 +1169,7 @@ static clib_error_t * snat_init (vlib_main_t * vm)
   vlib_thread_main_t *tm = vlib_get_thread_main ();
   uword *bitmap = 0;
   u32 i;
+  ip4_add_del_interface_address_callback_t cb4;
 
   name = format (0, "snat_%08x%c", api_version, 0);
 
@@ -1205,6 +1217,12 @@ static clib_error_t * snat_init (vlib_main_t * vm)
   plugin_custom_dump_configure (sm);
   vec_free(name);
 
+  /* Set up the interface address add/del callback */
+  cb4.function = snat_ip4_add_del_interface_address_cb;
+  cb4.function_opaque = 0;
+
+  vec_add1 (im->add_del_interface_address_callbacks, cb4);
+
   return error;
 }
 
@@ -1955,3 +1973,109 @@ VLIB_CLI_COMMAND (show_snat_command, static) = {
     .short_help = "show snat",
     .function = show_snat_command_fn,
 };
+
+
+static void
+snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
+                                       uword opaque,
+                                       u32 sw_if_index,
+                                       ip4_address_t * address,
+                                       u32 address_length,
+                                       u32 if_address_index,
+                                       u32 is_delete)
+{
+  snat_main_t *sm = &snat_main;
+  int i, j;
+
+  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
+    {
+      if (sw_if_index == sm->auto_add_sw_if_indices[i])
+        {
+          if (!is_delete)
+            {
+              /* Don't trip over lease renewal, static config */
+              for (j = 0; j < vec_len(sm->addresses); j++)
+                if (sm->addresses[j].addr.as_u32 == address->as_u32)
+                  return;
+
+              snat_add_address (sm, address);
+              return;
+            }
+          else
+            {
+              (void) snat_del_address(sm, address[0]);
+              return;
+            }
+        }
+    }
+}
+
+
+static int snat_add_interface_address (snat_main_t *sm, u32 sw_if_index)
+{
+  ip4_main_t * ip4_main = sm->ip4_main;
+  ip4_address_t * first_int_addr;
+  int i;
+
+  first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index,
+                                                0 /* just want the address*/);
+
+  for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
+    {
+      if (sm->auto_add_sw_if_indices[i] == sw_if_index)
+        return 0;
+    }
+  
+  /* add to the auto-address list */
+  vec_add1(sm->auto_add_sw_if_indices, sw_if_index);
+
+  /* If the address is already bound - or static - add it now */
+  if (first_int_addr)
+      snat_add_address (sm, first_int_addr);
+
+  return 0;
+}
+
+static clib_error_t *
+snat_add_interface_address_command_fn (vlib_main_t * vm,
+                                       unformat_input_t * input,
+                                       vlib_cli_command_t * cmd)
+{
+  snat_main_t *sm = &snat_main;
+  unformat_input_t _line_input, *line_input = &_line_input;
+  u32 sw_if_index;
+  int rv;
+
+  /* Get a line of input. */
+  if (!unformat_user (input, unformat_line_input, line_input))
+    return 0;
+
+  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (line_input, "%U", unformat_vnet_sw_interface,
+                    sm->vnet_main, &sw_if_index))
+        ;
+      else
+        return clib_error_return (0, "unknown input '%U'",
+                                 format_unformat_error, line_input);
+    }
+
+  rv = snat_add_interface_address (sm, sw_if_index);
+
+  switch (rv)
+    {
+    case 0:
+      break;
+
+    default:
+      return clib_error_return (0, "snat_add_interface_address returned %d",
+                                rv);
+    }
+  return 0;
+}
+
+VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
+    .path = "snat add interface address",
+    .short_help = "snat add interface address <interface>",
+    .function = snat_add_interface_address_command_fn,
+};
index cb31dc5..71f254f 100644 (file)
@@ -179,6 +179,9 @@ typedef struct {
   /* Vector of outside addresses */
   snat_address_t * addresses;
 
+  /* sw_if_indices whose intfc addresses should be auto-added */
+  u32 * auto_add_sw_if_indices;
+
   /* Randomize port allocation order */
   u32 random_seed;
 
index 0331c44..cc33dff 100644 (file)
@@ -190,7 +190,6 @@ ip4_src_address_for_packet (ip_lookup_main_t * lm,
     }
   else
     {
-      ASSERT (0);
       src->as_u32 = 0;
     }
   return (!0);