Fix issues with order of NAT commands before set VRF table on an interface 61/16961/15
authorDmitry Vakhrushev <dmitry@netgate.com>
Tue, 22 Jan 2019 10:28:53 +0000 (05:28 -0500)
committerFlorin Coras <florin.coras@gmail.com>
Mon, 28 Jan 2019 15:23:03 +0000 (15:23 +0000)
Outside FIB index doesn't change in this case. We register
callback for changing of outside FIB if table binding is changed
on an interface.

Change-Id: I1ebbd7c3c547fc999089db07abd2019734395a6e
Signed-off-by: Dmitry Vakhrushev <dmitry@netgate.com>
src/plugins/nat/nat.c

index 8d02e56..dabb812 100755 (executable)
@@ -1769,7 +1769,7 @@ snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
             {
               if (is_del)
                 {
-                  outside_fib->refcount--;
+                 outside_fib->refcount--;
                   if (!outside_fib->refcount)
                     vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
                 }
@@ -1995,7 +1995,7 @@ snat_interface_add_del_output_feature (u32 sw_if_index,
             {
               if (is_del)
                 {
-                  outside_fib->refcount--;
+                 outside_fib->refcount--;
                   if (!outside_fib->refcount)
                     vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
                 }
@@ -2144,6 +2144,65 @@ snat_set_workers (uword * bitmap)
   return 0;
 }
 
+static void
+snat_update_outside_fib (u32 sw_if_index, u32 new_fib_index,
+                        u32 old_fib_index)
+{
+  snat_main_t *sm = &snat_main;
+  nat_outside_fib_t *outside_fib;
+  snat_interface_t *i;
+  u8 is_add = 1;
+
+  if (new_fib_index == old_fib_index)
+    return;
+
+  if (!vec_len (sm->outside_fibs))
+    return;
+
+  pool_foreach (i, sm->interfaces, (
+                                    {
+                                    if (i->sw_if_index == sw_if_index)
+                                    {
+                                    if (!(nat_interface_is_outside (i)))
+                                    return;}
+                                    }
+               ));
+  vec_foreach (outside_fib, sm->outside_fibs)
+  {
+    if (outside_fib->fib_index == old_fib_index)
+      {
+       outside_fib->refcount--;
+       if (!outside_fib->refcount)
+         vec_del1 (sm->outside_fibs, outside_fib - sm->outside_fibs);
+       break;
+      }
+  }
+
+  vec_foreach (outside_fib, sm->outside_fibs)
+  {
+    if (outside_fib->fib_index == new_fib_index)
+      {
+       outside_fib->refcount++;
+       is_add = 0;
+       break;
+      }
+  }
+
+  if (is_add)
+    {
+      vec_add2 (sm->outside_fibs, outside_fib, 1);
+      outside_fib->refcount = 1;
+      outside_fib->fib_index = new_fib_index;
+    }
+}
+
+static void
+snat_ip4_table_bind (ip4_main_t * im,
+                    uword opaque,
+                    u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
+{
+  snat_update_outside_fib (sw_if_index, new_fib_index, old_fib_index);
+}
 
 static void
 snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
@@ -2272,6 +2331,11 @@ snat_init (vlib_main_t * vm)
 
   nat66_init ();
 
+  ip4_table_bind_callback_t cbt4 = {
+    .function = snat_ip4_table_bind,
+  };
+  vec_add1 (ip4_main.table_bind_callbacks, cbt4);
+
   /* Init virtual fragmenentation reassembly */
   return nat_reass_init (vm);
 }