2 VNET (VPP Network Stack)
3 ========================
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.
11 In terms of building a packet processing application, vnet provides a
12 platform-independent subgraph to which one connects a couple of
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
20 Effective graph dispatch function coding
21 ----------------------------------------
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.
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
36 Here is an quad/single loop which can leverage up-to-avx512 SIMD vector
37 units to convert buffer indices to buffer pointers:
41 simulated_ethernet_interface_tx (vlib_main_t * vm,
43 node, vlib_frame_t * frame)
45 u32 n_left_from, *from;
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;
54 n_left_from = frame->n_vectors;
55 from = vlib_frame_args (frame);
58 * Convert up to VLIB_FRAME_SIZE indices in "from" to
59 * buffer pointers in bufs[]
61 vlib_get_buffers (vm, from, bufs, n_left_from);
66 * While we have at least 4 vector elements (pkts) to process..
68 while (n_left_from >= 4)
70 /* Prefetch next quad-loop iteration. */
71 if (PREDICT_TRUE (n_left_from >= 8))
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);
80 * $$$ Process 4x packets right here...
81 * set next[0..3] to send the packets where they need to go
84 do_something_to (b[0]);
85 do_something_to (b[1]);
86 do_something_to (b[2]);
87 do_something_to (b[3]);
89 /* Process the next 0..4 packets */
95 * Clean up 0...3 remaining packets at the end of the incoming frame
97 while (n_left_from > 0)
100 * $$$ Process one packet right here...
101 * set next[0..3] to send the packets where they need to go
103 do_something_to (b[0]);
105 /* Process the next packet */
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
117 vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
119 return frame->n_vectors;
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.
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".
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"
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.
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.
147 Set the VLIB node registration ".format\_trace" member to the name of
148 the per-graph node format function.
150 Here's a simple example:
153 u8 * my_node_format_trace (u8 * s, va_list * args)
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 *);
159 s = format (s, "My trace data was: %d", t-><whatever>);
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