Adding Multipath support for exclusive DPO based fib path entries via rpath
[vpp.git] / src / vnet / fib / fib_path.c
index 2912c6a..4c93f73 100644 (file)
@@ -874,14 +874,14 @@ fib_path_unresolve (fib_path_t *path)
     case FIB_PATH_TYPE_RECURSIVE:
        if (FIB_NODE_INDEX_INVALID != path->fp_via_fib)
        {
-           fib_prefix_t pfx;
-
-           fib_entry_get_prefix(path->fp_via_fib, &pfx);
            fib_entry_child_remove(path->fp_via_fib,
                                   path->fp_sibling);
            fib_table_entry_special_remove(path->recursive.fp_tbl_id,
-                                          &pfx,
+                                          fib_entry_get_prefix(path->fp_via_fib),
                                           FIB_SOURCE_RR);
+            fib_table_unlock(path->recursive.fp_tbl_id,
+                             dpo_proto_to_fib(path->fp_nh_proto),
+                             FIB_SOURCE_RR);
            path->fp_via_fib = FIB_NODE_INDEX_INVALID;
        }
        break;
@@ -906,7 +906,7 @@ fib_path_unresolve (fib_path_t *path)
         adj_unlock(path->fp_dpo.dpoi_index);
         break;
     case FIB_PATH_TYPE_UDP_ENCAP:
-       udp_encap_unlock_w_index(path->fp_dpo.dpoi_index);
+       udp_encap_unlock(path->fp_dpo.dpoi_index);
         break;
     case FIB_PATH_TYPE_EXCLUSIVE:
        dpo_reset(&path->exclusive.fp_ex_dpo);
@@ -1323,6 +1323,11 @@ fib_path_create (fib_node_index_t pl_index,
        path->fp_type = FIB_PATH_TYPE_DVR;
        path->dvr.fp_interface = rpath->frp_sw_if_index;
     }
+    else if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE)
+    {
+       path->fp_type = FIB_PATH_TYPE_EXCLUSIVE;
+       dpo_copy(&path->exclusive.fp_ex_dpo, &rpath->dpo);
+    }
     else if (~0 != rpath->frp_sw_if_index)
     {
         if (ip46_address_is_zero(&rpath->frp_addr))
@@ -1574,9 +1579,11 @@ fib_path_cmp_i (const fib_path_t *path1,
        case FIB_PATH_TYPE_DVR:
            res = (path1->dvr.fp_interface - path2->dvr.fp_interface);
            break;
+       case FIB_PATH_TYPE_EXCLUSIVE:
+           res = dpo_cmp(&path1->exclusive.fp_ex_dpo, &path2->exclusive.fp_ex_dpo);
+           break;
        case FIB_PATH_TYPE_SPECIAL:
        case FIB_PATH_TYPE_RECEIVE:
-       case FIB_PATH_TYPE_EXCLUSIVE:
            res = 0;
            break;
        }
@@ -1711,9 +1718,11 @@ fib_path_cmp_w_route_path (fib_node_index_t path_index,
        case FIB_PATH_TYPE_DVR:
            res = (path->dvr.fp_interface - rpath->frp_sw_if_index);
            break;
+       case FIB_PATH_TYPE_EXCLUSIVE:
+           res = dpo_cmp(&path->exclusive.fp_ex_dpo, &rpath->dpo);
+           break;
        case FIB_PATH_TYPE_SPECIAL:
        case FIB_PATH_TYPE_RECEIVE:
-       case FIB_PATH_TYPE_EXCLUSIVE:
            res = 0;
            break;
        }
@@ -1900,6 +1909,9 @@ fib_path_resolve (fib_node_index_t path_index)
            fib_prefix_from_ip46_addr(&path->recursive.fp_nh.fp_ip, &pfx);
        }
 
+        fib_table_lock(path->recursive.fp_tbl_id,
+                       dpo_proto_to_fib(path->fp_nh_proto),
+                       FIB_SOURCE_RR);
        fei = fib_table_entry_special_add(path->recursive.fp_tbl_id,
                                          &pfx,
                                          FIB_SOURCE_RR,