Improve Load-Balance MAPs
[vpp.git] / src / vnet / fib / fib_walk.c
index 938f7b8..c570476 100644 (file)
@@ -95,11 +95,6 @@ typedef struct fib_walk_t_
  */
 static fib_walk_t *fib_walk_pool;
 
-/**
- * @brief There's only one event type sent to the walk process
- */
-#define FIB_WALK_EVENT 0
-
 /**
  * Statistics maintained per-walk queue
  */
@@ -240,10 +235,13 @@ fib_walk_queue_get_front (fib_walk_priority_t prio)
 }
 
 static void
-fib_walk_destroy (fib_walk_t *fwalk)
+fib_walk_destroy (index_t fwi)
 {
+    fib_walk_t *fwalk;
     u32 bucket, ii;
 
+    fwalk = fib_walk_get(fwi);
+
     if (FIB_NODE_INDEX_INVALID != fwalk->fw_prio_sibling)
     {
        fib_node_list_elt_remove(fwalk->fw_prio_sibling);
@@ -252,6 +250,12 @@ fib_walk_destroy (fib_walk_t *fwalk)
                          fwalk->fw_parent.fnp_index,
                          fwalk->fw_dep_sibling);
 
+    /*
+     * refetch the walk object. More walks could have been spawned as a result
+     * of releasing the lock on the parent.
+     */
+    fwalk = fib_walk_get(fwi);
+
     /*
      * add the stats to the continuous histogram collection.
      */
@@ -466,8 +470,7 @@ fib_walk_process_queues (vlib_main_t * vm,
             */
            if (FIB_WALK_ADVANCE_MORE != rc)
            {
-               fwalk = fib_walk_get(fwi);
-               fib_walk_destroy(fwalk);
+                fib_walk_destroy(fwi);
                fib_walk_queues.fwqs_queues[prio].fwq_stats[FIB_WALK_COMPLETED]++;
            }
            else
@@ -510,6 +513,16 @@ that_will_do_for_now:
     return (fib_walk_sleep_duration[sleep]);
 }
 
+/**
+ * Events sent to the FIB walk process
+ */
+typedef enum fib_walk_process_event_t_
+{
+    FIB_WALK_PROCESS_EVENT_DATA,
+    FIB_WALK_PROCESS_EVENT_ENABLE,
+    FIB_WALK_PROCESS_EVENT_DISABLE,
+} fib_walk_process_event;
+
 /**
  * @brief The 'fib-walk' process's main loop.
  */
@@ -518,22 +531,47 @@ fib_walk_process (vlib_main_t * vm,
                  vlib_node_runtime_t * node,
                  vlib_frame_t * f)
 {
+    uword event_type, *event_data = 0;
     f64 sleep_time;
+    int enabled;
 
+    enabled = 1;
     sleep_time = fib_walk_sleep_duration[FIB_WALK_SHORT_SLEEP];
 
     while (1)
     {
-       vlib_process_wait_for_event_or_clock(vm, sleep_time);
+        /*
+         * the feature to disable/enable this walk process is only
+         * for testing purposes
+         */
+        if (enabled)
+        {
+            vlib_process_wait_for_event_or_clock(vm, sleep_time);
+        }
+        else
+        {
+            vlib_process_wait_for_event(vm);
+        }
 
-       /*
-        * there may be lots of event queued between the processes,
-        * but the walks we want to schedule are in the priority queues,
-        * so we ignore the process events.
-        */
-       vlib_process_get_events(vm, NULL);
+        event_type = vlib_process_get_events(vm, &event_data);
+        vec_reset_length(event_data);
+
+        switch (event_type)
+       {
+       case FIB_WALK_PROCESS_EVENT_ENABLE:
+            enabled = 1;
+            break;
+       case FIB_WALK_PROCESS_EVENT_DISABLE:
+            enabled = 0;
+            break;
+       default:
+            break;
+       }
 
-       sleep_time = fib_walk_process_queues(vm, quota);
+        if (enabled)
+        {
+            sleep_time = fib_walk_process_queues(vm, quota);
+        }
     }
 
     /*
@@ -610,8 +648,8 @@ fib_walk_prio_queue_enquue (fib_walk_priority_t prio,
      */
     vlib_process_signal_event(vlib_get_main(),
                              fib_walk_process_node.index,
-                             FIB_WALK_EVENT,
-                             FIB_WALK_EVENT);
+                             FIB_WALK_PROCESS_EVENT_DATA,
+                             0);
 
     return (sibling);
 }
@@ -742,7 +780,7 @@ fib_walk_sync (fib_node_type_t parent_type,
            ASSERT(FIB_NODE_INDEX_INVALID != merged_walk.fnp_index);
            ASSERT(FIB_NODE_TYPE_WALK == merged_walk.fnp_type);
 
-           fib_walk_destroy(fwalk);
+           fib_walk_destroy(fwi);
 
            fwi = merged_walk.fnp_index;
            fwalk = fib_walk_get(fwi);
@@ -774,7 +812,7 @@ fib_walk_sync (fib_node_type_t parent_type,
 
     if (NULL != fwalk)
     {
-       fib_walk_destroy(fwalk);
+       fib_walk_destroy(fwi);
     }
 }
 
@@ -1106,3 +1144,47 @@ VLIB_CLI_COMMAND (fib_walk_clear_command, static) = {
     .short_help = "clear fib walk",
     .function = fib_walk_clear,
 };
+
+void
+fib_walk_process_enable (void)
+{
+    vlib_process_signal_event(vlib_get_main(),
+                              fib_walk_process_node.index,
+                              FIB_WALK_PROCESS_EVENT_ENABLE,
+                              0);
+}
+
+void
+fib_walk_process_disable (void)
+{
+    vlib_process_signal_event(vlib_get_main(),
+                              fib_walk_process_node.index,
+                              FIB_WALK_PROCESS_EVENT_DISABLE,
+                              0);
+}
+
+static clib_error_t *
+fib_walk_process_enable_disable (vlib_main_t * vm,
+                                 unformat_input_t * input,
+                                 vlib_cli_command_t * cmd)
+{
+    if (unformat (input, "enable"))
+    {
+        fib_walk_process_enable();
+    }
+    else if (unformat (input, "disable"))
+    {
+        fib_walk_process_disable();
+    }
+    else
+    {
+        return clib_error_return(0, "choose enable or disable");
+    }
+    return (NULL);
+}
+
+VLIB_CLI_COMMAND (fib_walk_process_command, static) = {
+    .path = "test fib-walk-process",
+    .short_help = "test fib-walk-process [enable|disable]",
+    .function = fib_walk_process_enable_disable,
+};