API refactoring : vhost_user
[vpp.git] / vnet / vnet / fib / fib_table.c
index 84c8708..76db42d 100644 (file)
@@ -323,6 +323,48 @@ fib_table_entry_special_dpo_add (u32 fib_index,
     return (fib_entry_index);
 }
 
+fib_node_index_t
+fib_table_entry_special_dpo_update (u32 fib_index,
+                                   const fib_prefix_t *prefix,
+                                   fib_source_t source,
+                                   fib_entry_flag_t flags,
+                                   const dpo_id_t *dpo)
+{
+    fib_node_index_t fib_entry_index;
+    fib_table_t *fib_table;
+
+    fib_table = fib_table_get(fib_index, prefix->fp_proto);
+    fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
+
+    if (FIB_NODE_INDEX_INVALID == fib_entry_index)
+    {
+       fib_entry_index = fib_entry_create_special(fib_index, prefix,
+                                                  source, flags,
+                                                  dpo);
+
+       fib_table_entry_insert(fib_table, prefix, fib_entry_index);
+        fib_table->ft_src_route_counts[source]++;
+    }
+    else
+    {
+        int was_sourced;
+
+        was_sourced = fib_entry_is_sourced(fib_entry_index, source);
+
+       if (was_sourced)
+           fib_entry_special_update(fib_entry_index, source, flags, dpo);
+       else
+           fib_entry_special_add(fib_entry_index, source, flags, dpo);
+
+        if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
+        {
+            fib_table->ft_src_route_counts[source]++;
+        }
+    }
+
+    return (fib_entry_index);
+}
+
 fib_node_index_t
 fib_table_entry_special_add (u32 fib_index,
                             const fib_prefix_t *prefix,
@@ -331,7 +373,7 @@ fib_table_entry_special_add (u32 fib_index,
                             adj_index_t adj_index)
 {
     fib_node_index_t fib_entry_index;
-    dpo_id_t tmp_dpo = DPO_NULL;
+    dpo_id_t tmp_dpo = DPO_INVALID;
 
     if (ADJ_INDEX_INVALID != adj_index)
     {
@@ -353,22 +395,6 @@ fib_table_entry_special_add (u32 fib_index,
     return (fib_entry_index);
 }
 
-void
-fib_table_entry_special_dpo_update (fib_node_index_t fib_entry_index,
-                                   fib_source_t source,
-                                   fib_entry_flag_t flags,
-                                   const dpo_id_t *dpo)
-{
-    fib_prefix_t prefix;
-    u32 fib_index;
-
-    fib_entry_get_prefix(fib_entry_index, &prefix);
-    fib_index = fib_entry_get_fib_index(fib_entry_index);
-
-    fib_table_entry_special_dpo_add(fib_index, &prefix, source, flags, dpo);
-    fib_table_entry_special_remove(fib_index, &prefix, source);
-}
-
 void
 fib_table_entry_special_remove (u32 fib_index,
                                const fib_prefix_t *prefix,
@@ -467,7 +493,7 @@ fib_table_entry_path_add (u32 fib_index,
                          u32 next_hop_sw_if_index,
                          u32 next_hop_fib_index,
                          u32 next_hop_weight,
-                         mpls_label_t next_hop_label,
+                         mpls_label_t *next_hop_labels,
                          fib_route_path_flags_t path_flags)
 {
     fib_route_path_t path = {
@@ -477,12 +503,11 @@ fib_table_entry_path_add (u32 fib_index,
        .frp_fib_index = next_hop_fib_index,
        .frp_weight = next_hop_weight,
        .frp_flags = path_flags,
-       .frp_label = next_hop_label,
+       .frp_label_stack = next_hop_labels,
     };
     fib_node_index_t fib_entry_index;
     fib_route_path_t *paths = NULL;
 
-    fib_table_route_path_fixup(prefix, &path);
     vec_add1(paths, path);
 
     fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
@@ -497,14 +522,20 @@ fib_table_entry_path_add2 (u32 fib_index,
                           const fib_prefix_t *prefix,
                           fib_source_t source,
                           fib_entry_flag_t flags,
-                          const fib_route_path_t *rpath)
+                          fib_route_path_t *rpath)
 {
     fib_node_index_t fib_entry_index;
     fib_table_t *fib_table;
+    u32 ii;
 
     fib_table = fib_table_get(fib_index, prefix->fp_proto);
     fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
 
+    for (ii = 0; ii < vec_len(rpath); ii++)
+    {
+       fib_table_route_path_fixup(prefix, &rpath[ii]);
+    }
+
     if (FIB_NODE_INDEX_INVALID == fib_entry_index)
     {
        fib_entry_index = fib_entry_create(fib_index, prefix,
@@ -532,9 +563,9 @@ fib_table_entry_path_add2 (u32 fib_index,
 
 void
 fib_table_entry_path_remove2 (u32 fib_index,
-                            const fib_prefix_t *prefix,
-                            fib_source_t source,
-                             const fib_route_path_t *rpath)
+                             const fib_prefix_t *prefix,
+                             fib_source_t source,
+                             fib_route_path_t *rpath)
 {
     /*
      * 1 is it present
@@ -544,10 +575,16 @@ fib_table_entry_path_remove2 (u32 fib_index,
      */
     fib_node_index_t fib_entry_index;
     fib_table_t *fib_table;
+    u32 ii;
 
     fib_table = fib_table_get(fib_index, prefix->fp_proto);
     fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
 
+    for (ii = 0; ii < vec_len(rpath); ii++)
+    {
+       fib_table_route_path_fixup(prefix, &rpath[ii]);
+    }
+
     if (FIB_NODE_INDEX_INVALID == fib_entry_index)
     {
        /*
@@ -641,20 +678,24 @@ fib_table_entry_update (u32 fib_index,
                        const fib_prefix_t *prefix,
                        fib_source_t source,
                        fib_entry_flag_t flags,
-                       const fib_route_path_t *paths)
+                       fib_route_path_t *paths)
 {
     fib_node_index_t fib_entry_index;
     fib_table_t *fib_table;
+    u32 ii;
 
     fib_table = fib_table_get(fib_index, prefix->fp_proto);
     fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
 
+    for (ii = 0; ii < vec_len(paths); ii++)
+    {
+       fib_table_route_path_fixup(prefix, &paths[ii]);
+    }
     /*
      * sort the paths provided by the control plane. this means
      * the paths and the extension on the entry will be sorted.
      */
-    vec_sort_with_function(((fib_route_path_t*)paths), // const cast
-                          fib_route_path_cmp_for_sort);
+    vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
 
     if (FIB_NODE_INDEX_INVALID == fib_entry_index)
     {
@@ -691,7 +732,7 @@ fib_table_entry_update_one_path (u32 fib_index,
                                 u32 next_hop_sw_if_index,
                                 u32 next_hop_fib_index,
                                 u32 next_hop_weight,
-                                mpls_label_t next_hop_label,
+                                mpls_label_t *next_hop_labels,
                                 fib_route_path_flags_t path_flags)
 {
     fib_node_index_t fib_entry_index;
@@ -702,7 +743,7 @@ fib_table_entry_update_one_path (u32 fib_index,
        .frp_fib_index = next_hop_fib_index,
        .frp_weight = next_hop_weight,
        .frp_flags = path_flags,
-       .frp_label = next_hop_label,
+       .frp_label_stack = next_hop_labels,
     };
     fib_route_path_t *paths = NULL;
 
@@ -805,10 +846,21 @@ fib_table_entry_local_label_add (u32 fib_index,
 {
     fib_node_index_t fib_entry_index;
  
-    fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, 
-                                                      FIB_SOURCE_MPLS,
-                                                      FIB_ENTRY_FLAG_NONE,
-                                                      NULL);
+    fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
+
+    if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
+       !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
+    {
+       /*
+        * only source the prefix once. this allows the label change
+        * operation to work
+        */
+       fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
+                                                         FIB_SOURCE_MPLS,
+                                                         FIB_ENTRY_FLAG_NONE,
+                                                         NULL);
+    }
+
     fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
 
     return (fib_entry_index);