docs: convert plugins doc md->rst
[vpp.git] / docs / gettingstarted / developers / vlib.md
index f25b0ba..3a35978 100644 (file)
@@ -15,10 +15,11 @@ Init function discovery
 vlib applications register for various \[initialization\] events by
 placing structures and \_\_attribute\_\_((constructor)) functions into
 the image. At appropriate times, the vlib framework walks
-constructor-generated singly-linked structure lists, calling the
-indicated functions. vlib applications create graph nodes, add CLI
-functions, start cooperative multi-tasking threads, etc. etc. using this
-mechanism.
+constructor-generated singly-linked structure lists, performs a
+topological sort based on specified constraints, and calls the
+indicated functions. Vlib applications create graph nodes, add CLI
+functions, start cooperative multi-tasking threads, etc. etc. using
+this mechanism.
 
 vlib applications invariably include a number of VLIB\_INIT\_FUNCTION
 (my\_init\_function) macros.
@@ -32,6 +33,50 @@ other libraries such as VNET. In the latter case, it may be necessary to
 explicitly reference symbol(s) otherwise large portions of the library
 may be AWOL at runtime.
 
+### Init function construction and constraint specification
+
+It's easy to add an init function:
+
+```
+   static clib_error_t *my_init_function (vlib_main_t *vm)
+   {
+      /* ... initialize things ... */
+
+      return 0; // or return clib_error_return (0, "BROKEN!");
+   }
+   VLIB_INIT_FUNCTION(my_init_function);
+```
+
+As given, my_init_function will be executed "at some point," but with
+no ordering guarantees.
+
+Specifying ordering constraints is easy:
+
+```
+   VLIB_INIT_FUNCTION(my_init_function) =
+   {
+      .runs_before = VLIB_INITS("we_run_before_function_1",
+                                "we_run_before_function_2"),
+      .runs_after = VLIB_INITS("we_run_after_function_1",
+                               "we_run_after_function_2),
+    };
+```
+
+It's also easy to specify bulk ordering constraints of the form "a
+then b then c then d":
+
+```
+   VLIB_INIT_FUNCTION(my_init_function) =
+   {
+      .init_order = VLIB_INITS("a", "b", "c", "d"),
+   };
+```
+
+It's OK to specify all three sorts of ordering constraints for a
+single init function, although it's hard to imagine why it would be
+necessary.
+
+
 Node Graph Initialization
 -------------------------
 
@@ -482,7 +527,7 @@ Here is a complete example:
 
 This example implements the "show ip tuple match" debug cli
 command. In ordinary usage, the vlib cli is available via the "vppctl"
-applicationn, which sends traffic to a named pipe. One can configure
+application, which sends traffic to a named pipe. One can configure
 debug CLI telnet access on a configurable port.
 
 The cli implementation has an output redirection facility which makes it
@@ -495,6 +540,54 @@ certain cli command has the potential to hurt packet processing
 performance by running for too long, do the work incrementally in a
 process node. The client can wait.
 
+### Macro expansion
+
+The vpp debug CLI engine includes a recursive macro expander. This
+is quite useful for factoring out address and/or interface name
+specifics:
+
+```
+   define ip1 192.168.1.1/24
+   define ip2 192.168.2.1/24
+   define iface1 GigabitEthernet3/0/0
+   define iface2 loop1
+
+   set int ip address $iface1 $ip1
+   set int ip address $iface2 $(ip2)
+
+   undefine ip1
+   undefine ip2
+   undefine iface1
+   undefine iface2
+```
+
+Each socket (or telnet) debug CLI session has its own macro
+tables. All debug CLI sessions which use CLI_INBAND binary API
+messages share a single table.
+
+The macro expander recognizes circular defintions:
+
+```
+    define foo \$(bar)
+    define bar \$(mumble)
+    define mumble \$(foo)
+```
+
+At 8 levels of recursion, the macro expander throws up its hands and
+replies "CIRCULAR."
+
+### Macro-related debug CLI commands
+
+In addition to the "define" and "undefine" debug CLI commands, use
+"show macro [noevaluate]" to dump the macro table. The "echo" debug
+CLI command will evaluate and print its argument:
+
+```
+    vpp# define foo This\ Is\ Foo
+    vpp# echo $foo
+    This Is Foo
+```
+
 Handing off buffers between threads
 -----------------------------------
 
@@ -575,7 +668,7 @@ a typical graph-node dispatch function:
 
        /* Enqueue buffers to threads */
        n_enq =
-        vlib_buffer_enqueue_to_thread (vm, hmp->frame_queue_index,
+        vlib_buffer_enqueue_to_thread (vm, node, hmp->frame_queue_index,
                                        from, thread_indices, frame->n_vectors,
                                        1 /* drop on congestion */);
        /* Typical counters,
@@ -600,3 +693,199 @@ enqueue node by freeing dropped packets, or by pushing them to
 "error-drop." Either of those actions would be a severe error.
 
 * It's perfectly OK to enqueue packets to the current thread.
+
+Handoff Demo Plugin
+-------------------
+
+Check out the sample (plugin) example in
+.../src/examples/handoffdemo. If you want to build the handoff demo plugin:
+
+```
+$ cd .../src/plugins
+$ ln -s ../examples/handoffdemo
+```
+
+This plugin provides a simple example of how to hand off packets
+between threads. We used it to debug packet-tracer handoff tracing
+support.
+
+# Packet generator input script
+
+```
+ packet-generator new {
+    name x
+    limit 5
+    size 128-128
+    interface local0
+    node handoffdemo-1
+    data {
+        incrementing 30
+    }
+ }
+```
+# Start vpp with 2 worker threads
+
+The demo plugin hands packets from worker 1 to worker 2.
+
+# Enable tracing, and start the packet generator
+
+```
+  trace add pg-input 100
+  packet-generator enable
+```
+
+# Sample Run
+
+```
+  DBGvpp# ex /tmp/pg_input_script
+  DBGvpp# pa en
+  DBGvpp# sh err
+   Count                    Node                  Reason
+         5              handoffdemo-1             packets handed off processed
+         5              handoffdemo-2             completed packets
+  DBGvpp# show run
+  Thread 1 vpp_wk_0 (lcore 0)
+  Time 133.9, average vectors/node 5.00, last 128 main loops 0.00 per node 0.00
+    vector rates in 3.7331e-2, out 0.0000e0, drop 0.0000e0, punt 0.0000e0
+               Name                 State         Calls          Vectors        Suspends         Clocks       Vectors/Call
+  handoffdemo-1                    active                  1               5               0          4.76e3            5.00
+  pg-input                        disabled                 2               5               0          5.58e4            2.50
+  unix-epoll-input                 polling             22760               0               0          2.14e7            0.00
+  ---------------
+  Thread 2 vpp_wk_1 (lcore 2)
+  Time 133.9, average vectors/node 5.00, last 128 main loops 0.00 per node 0.00
+    vector rates in 0.0000e0, out 0.0000e0, drop 3.7331e-2, punt 0.0000e0
+               Name                 State         Calls          Vectors        Suspends         Clocks       Vectors/Call
+  drop                             active                  1               5               0          1.35e4            5.00
+  error-drop                       active                  1               5               0          2.52e4            5.00
+  handoffdemo-2                    active                  1               5               0          2.56e4            5.00
+  unix-epoll-input                 polling             22406               0               0          2.18e7            0.00
+```
+
+Enable the packet tracer and run it again...
+
+```
+  DBGvpp# trace add pg-input 100
+  DBGvpp# pa en
+  DBGvpp# sh trace
+  sh trace
+  ------------------- Start of thread 0 vpp_main -------------------
+  No packets in trace buffer
+  ------------------- Start of thread 1 vpp_wk_0 -------------------
+  Packet 1
+
+  00:06:50:520688: pg-input
+    stream x, 128 bytes, 0 sw_if_index
+    current data 0, length 128, buffer-pool 0, ref-count 1, trace handle 0x1000000
+    00000000: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d0000
+    00000020: 0000000000000000000000000000000000000000000000000000000000000000
+    00000040: 0000000000000000000000000000000000000000000000000000000000000000
+    00000060: 0000000000000000000000000000000000000000000000000000000000000000
+  00:06:50:520762: handoffdemo-1
+    HANDOFFDEMO: current thread 1
+
+  Packet 2
+
+  00:06:50:520688: pg-input
+    stream x, 128 bytes, 0 sw_if_index
+    current data 0, length 128, buffer-pool 0, ref-count 1, trace handle 0x1000001
+    00000000: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d0000
+    00000020: 0000000000000000000000000000000000000000000000000000000000000000
+    00000040: 0000000000000000000000000000000000000000000000000000000000000000
+    00000060: 0000000000000000000000000000000000000000000000000000000000000000
+  00:06:50:520762: handoffdemo-1
+    HANDOFFDEMO: current thread 1
+
+  Packet 3
+
+  00:06:50:520688: pg-input
+    stream x, 128 bytes, 0 sw_if_index
+    current data 0, length 128, buffer-pool 0, ref-count 1, trace handle 0x1000002
+    00000000: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d0000
+    00000020: 0000000000000000000000000000000000000000000000000000000000000000
+    00000040: 0000000000000000000000000000000000000000000000000000000000000000
+    00000060: 0000000000000000000000000000000000000000000000000000000000000000
+  00:06:50:520762: handoffdemo-1
+    HANDOFFDEMO: current thread 1
+
+  Packet 4
+
+  00:06:50:520688: pg-input
+    stream x, 128 bytes, 0 sw_if_index
+    current data 0, length 128, buffer-pool 0, ref-count 1, trace handle 0x1000003
+    00000000: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d0000
+    00000020: 0000000000000000000000000000000000000000000000000000000000000000
+    00000040: 0000000000000000000000000000000000000000000000000000000000000000
+    00000060: 0000000000000000000000000000000000000000000000000000000000000000
+  00:06:50:520762: handoffdemo-1
+    HANDOFFDEMO: current thread 1
+
+  Packet 5
+
+  00:06:50:520688: pg-input
+    stream x, 128 bytes, 0 sw_if_index
+    current data 0, length 128, buffer-pool 0, ref-count 1, trace handle 0x1000004
+    00000000: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d0000
+    00000020: 0000000000000000000000000000000000000000000000000000000000000000
+    00000040: 0000000000000000000000000000000000000000000000000000000000000000
+    00000060: 0000000000000000000000000000000000000000000000000000000000000000
+  00:06:50:520762: handoffdemo-1
+    HANDOFFDEMO: current thread 1
+
+  ------------------- Start of thread 2 vpp_wk_1 -------------------
+  Packet 1
+
+  00:06:50:520796: handoff_trace
+    HANDED-OFF: from thread 1 trace index 0
+  00:06:50:520796: handoffdemo-2
+    HANDOFFDEMO: current thread 2
+  00:06:50:520867: error-drop
+    rx:local0
+  00:06:50:520914: drop
+    handoffdemo-2: completed packets
+
+  Packet 2
+
+  00:06:50:520796: handoff_trace
+    HANDED-OFF: from thread 1 trace index 1
+  00:06:50:520796: handoffdemo-2
+    HANDOFFDEMO: current thread 2
+  00:06:50:520867: error-drop
+    rx:local0
+  00:06:50:520914: drop
+    handoffdemo-2: completed packets
+
+  Packet 3
+
+  00:06:50:520796: handoff_trace
+    HANDED-OFF: from thread 1 trace index 2
+  00:06:50:520796: handoffdemo-2
+    HANDOFFDEMO: current thread 2
+  00:06:50:520867: error-drop
+    rx:local0
+  00:06:50:520914: drop
+    handoffdemo-2: completed packets
+
+  Packet 4
+
+  00:06:50:520796: handoff_trace
+    HANDED-OFF: from thread 1 trace index 3
+  00:06:50:520796: handoffdemo-2
+    HANDOFFDEMO: current thread 2
+  00:06:50:520867: error-drop
+    rx:local0
+  00:06:50:520914: drop
+    handoffdemo-2: completed packets
+
+  Packet 5
+
+  00:06:50:520796: handoff_trace
+    HANDED-OFF: from thread 1 trace index 4
+  00:06:50:520796: handoffdemo-2
+    HANDOFFDEMO: current thread 2
+  00:06:50:520867: error-drop
+    rx:local0
+  00:06:50:520914: drop
+    handoffdemo-2: completed packets
+ DBGvpp#
+```