Initial commit of Sphinx docs
[vpp.git] / docs / gettingstarted / developers / infrastructure.md
1 VPPINFRA (Infrastructure)
2 =========================
3
4 The files associated with the VPP Infrastructure layer are located in
5 the ./src/vppinfra folder.
6
7 VPPinfra is a collection of basic c-library services, quite
8 sufficient to build standalone programs to run directly on bare metal.
9 It also provides high-performance dynamic arrays, hashes, bitmaps,
10 high-precision real-time clock support, fine-grained event-logging, and
11 data structure serialization.
12
13 One fair comment / fair warning about vppinfra: you can\'t always tell a
14 macro from an inline function from an ordinary function simply by name.
15 Macros are used to avoid function calls in the typical case, and to
16 cause (intentional) side-effects.
17
18 Vppinfra has been around for almost 20 years and tends not to change
19 frequently. The VPP Infrastructure layer contains the following
20 functions:
21
22 Vectors
23 -------
24
25 Vppinfra vectors are ubiquitous dynamically resized arrays with by user
26 defined \"headers\". Many vpppinfra data structures (e.g. hash, heap,
27 pool) are vectors with various different headers.
28
29 The memory layout looks like this:
30
31 ```
32                    User header (optional, uword aligned)
33                    Alignment padding (if needed)
34                    Vector length in elements
35  User's pointer -> Vector element 0
36                    Vector element 1
37                    ...
38                    Vector element N-1
39 ```
40
41 As shown above, the vector APIs deal with pointers to the 0th element of
42 a vector. Null pointers are valid vectors of length zero.
43
44 To avoid thrashing the memory allocator, one often resets the length of
45 a vector to zero while retaining the memory allocation. Set the vector
46 length field to zero via the vec\_reset\_length(v) macro. \[Use the
47 macro! It's smart about NULL pointers.\]
48
49 Typically, the user header is not present. User headers allow for other
50 data structures to be built atop vppinfra vectors. Users may specify the
51 alignment for data elements via the [vec]()\*\_aligned macros.
52
53 Vectors elements can be any C type e.g. (int, double, struct bar). This
54 is also true for data types built atop vectors (e.g. heap, pool, etc.).
55 Many macros have \_a variants supporting alignment of vector data and
56 \_h variants supporting non-zero-length vector headers. The \_ha
57 variants support both.
58
59 Inconsistent usage of header and/or alignment related macro variants
60 will cause delayed, confusing failures.
61
62 Standard programming error: memorize a pointer to the ith element of a
63 vector, and then expand the vector. Vectors expand by 3/2, so such code
64 may appear to work for a period of time. Correct code almost always
65 memorizes vector **indices** which are invariant across reallocations.
66
67 In typical application images, one supplies a set of global functions
68 designed to be called from gdb. Here are a few examples:
69
70 -   vl(v) - prints vec\_len(v)
71 -   pe(p) - prints pool\_elts(p)
72 -   pifi(p, index) - prints pool\_is\_free\_index(p, index)
73 -   debug\_hex\_bytes (p, nbytes) - hex memory dump nbytes starting at p
74
75 Use the "show gdb" debug CLI command to print the current set.
76
77 Bitmaps
78 -------
79
80 Vppinfra bitmaps are dynamic, built using the vppinfra vector APIs.
81 Quite handy for a variety jobs.
82
83 Pools
84 -----
85
86 Vppinfra pools combine vectors and bitmaps to rapidly allocate and free
87 fixed-size data structures with independent lifetimes. Pools are perfect
88 for allocating per-session structures.
89
90 Hashes
91 ------
92
93 Vppinfra provides several hash flavors. Data plane problems involving
94 packet classification / session lookup often use
95 ./src/vppinfra/bihash\_template.\[ch\] bounded-index extensible
96 hashes. These templates are instantiated multiple times, to efficiently
97 service different fixed-key sizes.
98
99 Bihashes are thread-safe. Read-locking is not required. A simple
100 spin-lock ensures that only one thread writes an entry at a time.
101
102 The original vppinfra hash implementation in
103 ./src/vppinfra/hash.\[ch\] are simple to use, and are often used in
104 control-plane code which needs exact-string-matching.
105
106 In either case, one almost always looks up a key in a hash table to
107 obtain an index in a related vector or pool. The APIs are simple enough,
108 but one must take care when using the unmanaged arbitrary-sized key
109 variant. Hash\_set\_mem (hash\_table, key\_pointer, value) memorizes
110 key\_pointer. It is usually a bad mistake to pass the address of a
111 vector element as the second argument to hash\_set\_mem. It is perfectly
112 fine to memorize constant string addresses in the text segment.
113
114 Format
115 ------
116
117 Vppinfra format is roughly equivalent to printf.
118
119 Format has a few properties worth mentioning. Format's first argument is
120 a (u8 \*) vector to which it appends the result of the current format
121 operation. Chaining calls is very easy:
122
123 ```c
124     u8 * result;
125
126     result = format (0, "junk = %d, ", junk);
127     result = format (result, "more junk = %d\n", more_junk);
128 ```
129
130 As previously noted, NULL pointers are perfectly proper 0-length
131 vectors. Format returns a (u8 \*) vector, **not** a C-string. If you
132 wish to print a (u8 \*) vector, use the "%v" format string. If you need
133 a (u8 \*) vector which is also a proper C-string, either of these
134 schemes may be used:
135
136 ```c
137     vec_add1 (result, 0)
138     or 
139     result = format (result, "<whatever>%c", 0); 
140 ```
141
142 Remember to vec\_free() the result if appropriate. Be careful not to
143 pass format an uninitialized (u8 \*).
144
145 Format implements a particularly handy user-format scheme via the "%U"
146 format specification. For example:
147
148 ```c
149     u8 * format_junk (u8 * s, va_list *va)
150     {
151       junk = va_arg (va, u32);
152       s = format (s, "%s", junk);
153       return s;
154     }
155
156     result = format (0, "junk = %U, format_junk, "This is some junk");
157 ```
158
159 format\_junk() can invoke other user-format functions if desired. The
160 programmer shoulders responsibility for argument type-checking. It is
161 typical for user format functions to blow up if the va\_arg(va,
162 type) macros don't match the caller's idea of reality.
163
164 Unformat
165 --------
166
167 Vppinfra unformat is vaguely related to scanf, but considerably more
168 general.
169
170 A typical use case involves initializing an unformat\_input\_t from
171 either a C-string or a (u8 \*) vector, then parsing via unformat() as
172 follows:
173
174 ```c
175     unformat_input_t input;
176
177     unformat_init_string (&input, "<some-C-string>");
178     /* or */
179     unformat_init_vector (&input, <u8-vector>);
180 ```
181
182 Then loop parsing individual elements:
183
184 ```c
185     while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT) 
186     {
187       if (unformat (&input, "value1 %d", &value1))
188         ;/* unformat sets value1 */
189       else if (unformat (&input, "value2 %d", &value2)
190         ;/* unformat sets value2 */
191       else
192         return clib_error_return (0, "unknown input '%U'", 
193                                   format_unformat_error, input);
194     }
195 ```
196
197 As with format, unformat implements a user-unformat function capability
198 via a "%U" user unformat function scheme.
199
200 Vppinfra errors and warnings
201 ----------------------------
202
203 Many functions within the vpp dataplane have return-values of type
204 clib\_error\_t \*. Clib\_error\_t's are arbitrary strings with a bit of
205 metadata \[fatal, warning\] and are easy to announce. Returning a NULL
206 clib\_error\_t \* indicates "A-OK, no error."
207
208 Clib\_warning(format-args) is a handy way to add debugging
209 output; clib warnings prepend function:line info to unambiguously locate
210 the message source. Clib\_unix\_warning() adds perror()-style Linux
211 system-call information. In production images, clib\_warnings result in
212 syslog entries.
213
214 Serialization
215 -------------
216
217 Vppinfra serialization support allows the programmer to easily serialize
218 and unserialize complex data structures.
219
220 The underlying primitive serialize/unserialize functions use network
221 byte-order, so there are no structural issues serializing on a
222 little-endian host and unserializing on a big-endian host.
223
224 Event-logger, graphical event log viewer
225 ----------------------------------------
226
227 The vppinfra event logger provides very lightweight (sub-100ns)
228 precisely time-stamped event-logging services. See
229 ./src/vppinfra/{elog.c, elog.h}
230
231 Serialization support makes it easy to save and ultimately to combine a
232 set of event logs. In a distributed system running NTP over a local LAN,
233 we find that event logs collected from multiple system elements can be
234 combined with a temporal uncertainty no worse than 50us.
235
236 A typical event definition and logging call looks like this:
237
238 ```c
239     ELOG_TYPE_DECLARE (e) = 
240     {
241       .format = "tx-msg: stream %d local seq %d attempt %d",
242       .format_args = "i4i4i4",
243     };
244     struct { u32 stream_id, local_sequence, retry_count; } * ed;
245     ed = ELOG_DATA (m->elog_main, e);
246     ed->stream_id = stream_id;
247     ed->local_sequence = local_sequence;
248     ed->retry_count = retry_count;
249 ```
250
251 The ELOG\_DATA macro returns a pointer to 20 bytes worth of arbitrary
252 event data, to be formatted (offline, not at runtime) as described by
253 format\_args. Aside from obvious integer formats, the CLIB event logger
254 provides a couple of interesting additions. The "t4" format
255 pretty-prints enumerated values:
256
257 ```c
258     ELOG_TYPE_DECLARE (e) = 
259     {
260       .format = "get_or_create: %s",
261       .format_args = "t4",
262       .n_enum_strings = 2,
263       .enum_strings = { "old", "new", },
264     };
265 ```
266
267 The "t" format specifier indicates that the corresponding datum is an
268 index in the event's set of enumerated strings, as shown in the previous
269 event type definition.
270
271 The “T” format specifier indicates that the corresponding datum is an
272 index in the event log’s string heap. This allows the programmer to emit
273 arbitrary formatted strings. One often combines this facility with a
274 hash table to keep the event-log string heap from growing arbitrarily
275 large.
276
277 Noting the 20-octet limit per-log-entry data field, the event log
278 formatter supports arbitrary combinations of these data types. As in:
279 the ".format" field may contain one or more instances of the following:
280
281 -   i1 - 8-bit unsigned integer
282 -   i2 - 16-bit unsigned integer
283 -   i4 - 32-bit unsigned integer
284 -   i8 - 64-bit unsigned integer
285 -   f4 - float
286 -   f8 - double
287 -   s - NULL-terminated string - be careful
288 -   sN - N-byte character array
289 -   t1,2,4 - per-event enumeration ID
290 -   T4 - Event-log string table offset
291
292 The vpp engine event log is thread-safe, and is shared by all threads.
293 Take care not to serialize the computation. Although the event-logger is
294 about as fast as practicable, it's not appropriate for per-packet use in
295 hard-core data plane code. It's most appropriate for capturing rare
296 events - link up-down events, specific control-plane events and so
297 forth.
298
299 The vpp engine has several debug CLI commands for manipulating its event
300 log:
301
302 ```
303     vpp# event-logger clear
304     vpp# event-logger save <filename> # for security, writes into /tmp/<filename>.
305                                       # <filename> must not contain '.' or '/' characters
306     vpp# show event-logger [all] [<nnn>] # display the event log
307                                        # by default, the last 250 entries
308 ```
309
310 The event log defaults to 128K entries. The command-line argument "...
311 vlib { elog-events nnn } ..." configures the size of the event log.
312
313 As described above, the vpp engine event log is thread-safe and shared.
314 To avoid confusing non-appearance of events logged by worker threads,
315 make sure to code vlib\_global\_main.elog\_main - instead of
316 vm->elog\_main. The latter form is correct in the main thread, but
317 will almost certainly produce bad results in worker threads.
318
319 G2 graphical event viewer
320 -------------------------
321
322 The g2 graphical event viewer can display serialized vppinfra event logs
323 directly, or via the c2cpel tool.
324
325 <div class="admonition note">
326
327 Todo: please convert wiki page and figures
328
329 </div>
330