ab081b0830258b81d2534b8d024e70381b1f7191
[vpp.git] / docs / gettingstarted / developers / vnet.md
1
2 VNET (VPP Network Stack)
3 ========================
4
5 The files associated with the VPP network stack layer are located in the
6 *./src/vnet* folder. The Network Stack Layer is basically an
7 instantiation of the code in the other layers. This layer has a vnet
8 library that provides vectorized layer-2 and 3 networking graph nodes, a
9 packet generator, and a packet tracer.
10
11 In terms of building a packet processing application, vnet provides a
12 platform-independent subgraph to which one connects a couple of
13 device-driver nodes.
14
15 Typical RX connections include "ethernet-input" \[full software
16 classification, feeds ipv4-input, ipv6-input, arp-input etc.\] and
17 "ipv4-input-no-checksum" \[if hardware can classify, perform ipv4 header
18 checksum\].
19
20 Effective graph dispatch function coding
21 ----------------------------------------
22
23 Over the 15 years, multiple coding styles have emerged: a
24 single/dual/quad loop coding model (with variations) and a
25 fully-pipelined coding model.
26
27 Single/dual loops
28 -----------------
29
30 The single/dual/quad loop model variations conveniently solve problems
31 where the number of items to process is not known in advance: typical
32 hardware RX-ring processing. This coding style is also very effective
33 when a given node will not need to cover a complex set of dependent
34 reads.
35
36 Here is an quad/single loop which can leverage up-to-avx512 SIMD vector
37 units to convert buffer indices to buffer pointers:
38
39 ```c
40    static uword
41    simulated_ethernet_interface_tx (vlib_main_t * vm,
42                                  vlib_node_runtime_t *
43                                  node, vlib_frame_t * frame)
44    {
45      u32 n_left_from, *from;
46      u32 next_index = 0;
47      u32 n_bytes;
48      u32 thread_index = vm->thread_index;
49      vnet_main_t *vnm = vnet_get_main ();
50      vnet_interface_main_t *im = &vnm->interface_main;
51      vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
52      u16 nexts[VLIB_FRAME_SIZE], *next;
53
54      n_left_from = frame->n_vectors;
55      from = vlib_frame_args (frame);
56
57      /* 
58       * Convert up to VLIB_FRAME_SIZE indices in "from" to 
59       * buffer pointers in bufs[]
60       */
61      vlib_get_buffers (vm, from, bufs, n_left_from);
62      b = bufs;
63      next = nexts;
64
65      /* 
66       * While we have at least 4 vector elements (pkts) to process.. 
67       */
68      while (n_left_from >= 4)
69        {
70          /* Prefetch next quad-loop iteration. */
71          if (PREDICT_TRUE (n_left_from >= 8))
72            {
73              vlib_prefetch_buffer_header (b[4], STORE);
74              vlib_prefetch_buffer_header (b[5], STORE);
75              vlib_prefetch_buffer_header (b[6], STORE);
76              vlib_prefetch_buffer_header (b[7], STORE);
77            }
78
79          /* 
80           * $$$ Process 4x packets right here...
81           * set next[0..3] to send the packets where they need to go
82           */
83
84           do_something_to (b[0]);
85           do_something_to (b[1]);
86           do_something_to (b[2]);
87           do_something_to (b[3]);
88
89          /* Process the next 0..4 packets */
90          b += 4;
91          next += 4;
92          n_left_from -= 4;
93         }
94      /* 
95       * Clean up 0...3 remaining packets at the end of the incoming frame
96       */
97      while (n_left_from > 0)
98        {
99          /* 
100           * $$$ Process one packet right here...
101           * set next[0..3] to send the packets where they need to go
102           */
103           do_something_to (b[0]);
104
105          /* Process the next packet */
106          b += 1;
107          next += 1;
108          n_left_from -= 1;
109        }
110
111      /*
112       * Send the packets along their respective next-node graph arcs
113       * Considerable locality of reference is expected, most if not all
114       * packets in the inbound vector will traverse the same next-node
115       * arc
116       */
117      vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
118
119      return frame->n_vectors;
120    }  
121 ```
122
123 Given a packet processing task to implement, it pays to scout around
124 looking for similar tasks, and think about using the same coding
125 pattern. It is not uncommon to recode a given graph node dispatch function
126 several times during performance optimization.
127
128 Packet tracer
129 -------------
130
131 Vlib includes a frame element \[packet\] trace facility, with a simple
132 vlib cli interface. The cli is straightforward: "trace add
133 input-node-name count".
134
135 To trace 100 packets on a typical x86\_64 system running the dpdk
136 plugin: "trace add dpdk-input 100". When using the packet generator:
137 "trace add pg-input 100"
138
139 Each graph node has the opportunity to capture its own trace data. It is
140 almost always a good idea to do so. The trace capture APIs are simple.
141
142 The packet capture APIs snapshoot binary data, to minimize processing at
143 capture time. Each participating graph node initialization provides a
144 vppinfra format-style user function to pretty-print data when required
145 by the VLIB "show trace" command.
146
147 Set the VLIB node registration ".format\_trace" member to the name of
148 the per-graph node format function.
149
150 Here's a simple example:
151
152 ```c
153     u8 * my_node_format_trace (u8 * s, va_list * args)
154     {
155         vlib_main_t * vm = va_arg (*args, vlib_main_t *);
156         vlib_node_t * node = va_arg (*args, vlib_node_t *);
157         my_node_trace_t * t = va_arg (*args, my_trace_t *);
158
159         s = format (s, "My trace data was: %d", t-><whatever>);
160
161         return s;
162     } 
163 ```
164
165 The trace framework hands the per-node format function the data it
166 captured as the packet whizzed by. The format function pretty-prints the
167 data as desired.