(VPP-455) arp doesn't work when ip4 classifier configured with fib 2.0 28/3228/1
authorNeale Ranns <nranns@cisco.com>
Sun, 2 Oct 2016 15:39:06 +0000 (16:39 +0100)
committerNeale Ranns <nranns@cisco.com>
Mon, 3 Oct 2016 08:56:14 +0000 (09:56 +0100)
Change-Id: I046de0c00db75d25ed90e33e9910c9dd0ff95580
Signed-off-by: Neale Ranns <nranns@cisco.com>
vnet/vnet/ethernet/arp.c
vnet/vnet/fib/fib_entry.c
vnet/vnet/fib/fib_entry.h
vnet/vnet/fib/fib_entry_src.c
vnet/vnet/ip/ip4_forward.c
vnet/vnet/ip/ip6_forward.c
vnet/vnet/ip/ip6_neighbor.c

index 7d61843..90d193e 100644 (file)
@@ -923,9 +923,12 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
          dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
                                          &arp0->ip4_over_ethernet[1].ip4,
                                          32);
-         dst_flags = fib_entry_get_flags (dst_fei);
+         dst_flags = fib_entry_get_flags_for_source (dst_fei,
+                                                     FIB_SOURCE_INTERFACE);
 
-         conn_sw_if_index0 = fib_entry_get_resolving_interface (dst_fei);
+         conn_sw_if_index0 =
+           fib_entry_get_resolving_interface_for_source (dst_fei,
+                                                         FIB_SOURCE_INTERFACE);
 
          if (!(FIB_ENTRY_FLAG_CONNECTED & dst_flags))
            {
index 8b63f0d..8b275c6 100644 (file)
@@ -1299,7 +1299,7 @@ fib_entry_recursive_loop_detect (fib_node_index_t entry_index,
 u32
 fib_entry_get_resolving_interface (fib_node_index_t entry_index)
 {
-   fib_entry_t *fib_entry;
+    fib_entry_t *fib_entry;
 
     fib_entry = fib_entry_get(entry_index);
 
index ac22c17..1ed9d61 100644 (file)
@@ -480,6 +480,9 @@ extern u32 fib_entry_child_add(fib_node_index_t fib_entry_index,
 extern void fib_entry_child_remove(fib_node_index_t fib_entry_index,
                                   u32 sibling_index);
 extern u32 fib_entry_get_resolving_interface(fib_node_index_t fib_entry_index);
+extern u32 fib_entry_get_resolving_interface_for_source(
+    fib_node_index_t fib_entry_index,
+    fib_source_t source);
 
 extern void fib_entry_get_prefix(fib_node_index_t fib_entry_index,
                                 fib_prefix_t *pfx);
@@ -491,6 +494,9 @@ extern const void* fib_entry_get_source_data(fib_node_index_t fib_entry_index,
                                              fib_source_t source);
 
 extern fib_entry_flag_t fib_entry_get_flags(fib_node_index_t fib_entry_index);
+extern fib_entry_flag_t fib_entry_get_flags_for_source(
+    fib_node_index_t fib_entry_index,
+    fib_source_t source);
 extern fib_source_t fib_entry_get_best_source(fib_node_index_t fib_entry_index);
 extern int fib_entry_is_sourced(fib_node_index_t fib_entry_index,
                                 fib_source_t source);
index f7d84e5..7055006 100644 (file)
@@ -1038,8 +1038,8 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry,
 
     ASSERT(NULL != fib_entry_src_vft[source].fesv_path_swap);
 
-    pl_flags = fib_entry_src_flags_2_path_list_flags(
-                  fib_entry_get_flags_i(fib_entry));
+    pl_flags = fib_entry_src_flags_2_path_list_flags(flags);
+
     vec_foreach(rpath, rpaths)
     {
        fib_entry_flags_update(fib_entry, rpath, &pl_flags, esrc);
@@ -1205,6 +1205,46 @@ fib_entry_get_dpo_for_source (fib_node_index_t fib_entry_index,
     return (0);
 }
 
+u32
+fib_entry_get_resolving_interface_for_source (fib_node_index_t entry_index,
+                                             fib_source_t source)
+{
+    fib_entry_t *fib_entry;
+    fib_entry_src_t *esrc;
+
+    fib_entry = fib_entry_get(entry_index);
+
+    esrc = fib_entry_src_find(fib_entry, source, NULL);
+
+    if (NULL != esrc)
+    {
+       if (FIB_NODE_INDEX_INVALID != esrc->fes_pl)
+       {
+           return (fib_path_list_get_resolving_interface(esrc->fes_pl));
+       }
+    }
+    return (~0);
+}
+
+fib_entry_flag_t
+fib_entry_get_flags_for_source (fib_node_index_t entry_index,
+                               fib_source_t source)
+{
+    fib_entry_t *fib_entry;
+    fib_entry_src_t *esrc;
+
+    fib_entry = fib_entry_get(entry_index);
+
+    esrc = fib_entry_src_find(fib_entry, source, NULL);
+
+    if (NULL != esrc)
+    {
+       return (esrc->fes_entry_flags);
+    }
+
+    return (FIB_ENTRY_FLAG_NONE);
+}
+
 fib_entry_flag_t
 fib_entry_get_flags_i (const fib_entry_t *fib_entry)
 {
index 8105d74..08fe816 100644 (file)
@@ -3058,6 +3058,7 @@ int vnet_set_ip4_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
   ip4_main_t * ipm = &ip4_main;
   ip_lookup_main_t * lm = &ipm->lookup_main;
   vnet_classify_main_t * cm = &vnet_classify_main;
+  ip4_address_t *if_addr;
 
   if (pool_is_free_index (im->sw_interfaces, sw_if_index))
     return VNET_API_ERROR_NO_MATCHING_INTERFACE;
@@ -3068,6 +3069,46 @@ int vnet_set_ip4_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
   vec_validate (lm->classify_table_index_by_sw_if_index, sw_if_index);
   lm->classify_table_index_by_sw_if_index [sw_if_index] = table_index;
 
+  if_addr = ip4_interface_first_address (ipm, sw_if_index, NULL);
+
+  if (NULL != if_addr)
+  {
+      fib_prefix_t pfx = {
+         .fp_len = 32,
+         .fp_proto = FIB_PROTOCOL_IP4,
+         .fp_addr.ip4 = *if_addr,
+      };
+      u32 fib_index;
+
+      fib_index = fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP4,
+                                                     sw_if_index);
+
+
+      if (table_index != (u32) ~0)
+      {
+          dpo_id_t dpo = DPO_NULL;
+
+          dpo_set(&dpo,
+                  DPO_CLASSIFY,
+                  DPO_PROTO_IP4,
+                  classify_dpo_create(FIB_PROTOCOL_IP4,
+                                      table_index));
+
+         fib_table_entry_special_dpo_add(fib_index,
+                                         &pfx,
+                                         FIB_SOURCE_CLASSIFY,
+                                         FIB_ENTRY_FLAG_NONE,
+                                         &dpo);
+          dpo_reset(&dpo);
+      }
+      else
+      {
+         fib_table_entry_special_remove(fib_index,
+                                        &pfx,
+                                        FIB_SOURCE_CLASSIFY);
+      }
+  }
+
   return 0;
 }
 
index 56892d4..65e8759 100644 (file)
@@ -457,6 +457,28 @@ ip6_sw_interface_enable_disable (u32 sw_if_index,
     }
 }
 
+/* get first interface address */
+ip6_address_t *
+ip6_interface_first_address (ip6_main_t * im,
+                            u32 sw_if_index,
+                             ip_interface_address_t ** result_ia)
+{
+  ip_lookup_main_t * lm = &im->lookup_main;
+  ip_interface_address_t * ia = 0;
+  ip6_address_t * result = 0;
+
+  foreach_ip_interface_address (lm, ia, sw_if_index,
+                                1 /* honor unnumbered */,
+  ({
+    ip6_address_t * a = ip_interface_address_get_address (lm, ia);
+    result = a;
+    break;
+  }));
+  if (result_ia)
+    *result_ia = result ? ia : 0;
+  return result;
+}
+
 clib_error_t *
 ip6_add_del_interface_address (vlib_main_t * vm,
                               u32 sw_if_index,
@@ -2866,6 +2888,7 @@ int vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
   ip6_main_t * ipm = &ip6_main;
   ip_lookup_main_t * lm = &ipm->lookup_main;
   vnet_classify_main_t * cm = &vnet_classify_main;
+  ip6_address_t *if_addr;
 
   if (pool_is_free_index (im->sw_interfaces, sw_if_index))
     return VNET_API_ERROR_NO_MATCHING_INTERFACE;
@@ -2876,6 +2899,46 @@ int vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
   vec_validate (lm->classify_table_index_by_sw_if_index, sw_if_index);
   lm->classify_table_index_by_sw_if_index [sw_if_index] = table_index;
 
+  if_addr = ip6_interface_first_address (ipm, sw_if_index, NULL);
+
+  if (NULL != if_addr)
+  {
+      fib_prefix_t pfx = {
+         .fp_len = 128,
+         .fp_proto = FIB_PROTOCOL_IP6,
+         .fp_addr.ip6 = *if_addr,
+      };
+      u32 fib_index;
+
+      fib_index = fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP4,
+                                                     sw_if_index);
+
+
+      if (table_index != (u32) ~0)
+      {
+          dpo_id_t dpo = DPO_NULL;
+
+          dpo_set(&dpo,
+                  DPO_CLASSIFY,
+                  DPO_PROTO_IP4,
+                  classify_dpo_create(FIB_PROTOCOL_IP4,
+                                      table_index));
+
+         fib_table_entry_special_dpo_add(fib_index,
+                                         &pfx,
+                                         FIB_SOURCE_CLASSIFY,
+                                         FIB_ENTRY_FLAG_NONE,
+                                         &dpo);
+          dpo_reset(&dpo);
+      }
+      else
+      {
+         fib_table_entry_special_remove(fib_index,
+                                        &pfx,
+                                        FIB_SOURCE_CLASSIFY);
+      }
+  }
+
   return 0;
 }
 
index 5d059e9..a03701b 100644 (file)
@@ -812,7 +812,8 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm,
                                                         128);
 
                  if (FIB_NODE_INDEX_INVALID == fei || 
-                     !(FIB_ENTRY_FLAG_LOCAL & fib_entry_get_flags(fei)))
+                     !(FIB_ENTRY_FLAG_LOCAL &
+                       fib_entry_get_flags_for_source(fei, FIB_SOURCE_INTERFACE)))
                    {
                      error0 = ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_UNKNOWN;
                    }