-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
3132 lines (3103 loc) · 564 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<meta name="author" content="Mike Pall" />
<meta name="author" content="Luke Gorrie" />
<meta name="author" content="Andy Wingo" />
<meta name="author" content="Max Rottenkolber" />
<meta name="author" content="Diego Pino Garcia" />
<meta name="author" content="Asumu Takikawa" />
<meta name="author" content="Jessica Tallon" />
<meta name="author" content="Diego Pino" />
<meta name="author" content="Alexander Gall" />
<meta name="author" content="Cosmin Apreutesei" />
<meta name="author" content="Nikolay Nikolaev" />
<meta name="author" content="Katerina Barone-Adesi" />
<meta name="author" content="Hans Huebner" />
<meta name="author" content="Javier Guerra" />
<meta name="author" content="Marcel Wiget" />
<meta name="author" content="Nicola Larosa" />
<meta name="author" content="Pete Bristow" />
<meta name="author" content="Adrian Perez de Castro" />
<meta name="author" content="Adrián Pérez de Castro" />
<meta name="author" content="Nicola tekNico Larosa" />
<meta name="author" content="Antonio Nikishaev" />
<meta name="author" content="Domen Kožar" />
<meta name="author" content="Peter Cawley" />
<meta name="author" content="Alexander Altshuler" />
<meta name="author" content="Rolf Sommerhalder" />
<meta name="author" content="Timo Buhrmester" />
<meta name="author" content="Pete Kazmier" />
<meta name="author" content="Dibyendu Majumdar" />
<meta name="author" content="Lesley De Cruz" />
<meta name="author" content="Mikhail Nazarov" />
<meta name="author" content="Kristian Larsson" />
<meta name="author" content="Justin Cormack" />
<meta name="author" content="Ben Agricola" />
<meta name="author" content="Felix Geißler" />
<meta name="author" content="R. Matthew Emerson" />
<meta name="author" content="Michael G" />
<meta name="author" content="Christian Graf" />
<meta name="author" content="Carlos Alberto Lopez Perez" />
<meta name="author" content="Jeff Loughridge" />
<meta name="author" content="Kacper Wysocki" />
<meta name="author" content="Adrian Perez" />
<meta name="author" content="William Adams" />
<meta name="author" content="Vladimir Fedin" />
<meta name="author" content="Vincenzo Maffione" />
<meta name="author" content="Tomas Korcak" />
<meta name="author" content="Tim Upthegrove" />
<meta name="author" content="Tim LaBerge" />
<meta name="author" content="Stevan Markovic" />
<meta name="author" content="Simon Leinen" />
<meta name="author" content="Ryan Hartlage" />
<meta name="author" content="Kristian Kielhofner" />
<meta name="author" content="Jon Olsson" />
<meta name="author" content="Jianbo Liu" />
<meta name="author" content="Jay Fenton" />
<meta name="author" content="James Cunningham" />
<meta name="author" content="Hui Xiang" />
<meta name="author" content="Gernot Nusshall" />
<meta name="author" content="Fabian Bonk" />
<meta name="author" content="Edward Hope-Morley" />
<meta name="author" content="Darius Bacon" />
<meta name="author" content="Anshul Makkar" />
<meta name="author" content="Andy Chong" />
<meta name="author" content="Alex Kordic" />
<meta name="author" content="Alexandr Kostrikov" />
<meta name="author" content="Alexander Spyridakis" />
<title>Snabb Reference Manual</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
<link href="data:text/css;charset=utf-8,%0A%23TOC%20%7B%0Aposition%3A%20fixed%3B%0Aoverflow%3A%20scroll%3B%0Atop%3A%200%3B%0Aleft%3A%200%3B%0Awidth%3A%2019%2E6em%3B%0Aheight%3A%20100%25%3B%0Amargin%3A%200%3B%0Apadding%3A%200%3B%0A%7D%0A%23TOC%20%3E%20header%20%7B%0Amargin%2Dtop%3A%201%2E4em%3B%0A%7D%0A%23TOC%20ul%2C%20%23TOC%20ol%20%7B%0Apadding%2Dleft%3A%201%2E4em%3B%0Amargin%3A%200%3B%0A%7D%0A%23TOC%20%3E%20ul%2C%20%23TOC%20%3E%20ol%20%7B%0Apadding%2Dtop%3A%200%2E7em%3B%0Awidth%3A%2025%2E2em%3B%0A%7D%0Abody%20%7B%0Amargin%3A%200%200%200%2021em%3B%0A%7D%0Abody%20%7B%0Amax%2Dwidth%3A%2040em%3B%0Afont%2Dfamily%3A%20sans%2Dserif%3B%0A%7D%0Acode%2C%20pre%20%7B%0Acolor%3A%20%23333%3B%0Abackground%3A%20%23f7f7f7%3B%0A%7D%0Apre%20%7B%0Apadding%3A%200%2E6em%3B%0A%7D%0Apre%20%3E%20code%20%7B%0Apadding%3A%200%3B%0Abackground%3A%20none%3B%0A%7D%0Acode%20%7B%0Apadding%3A%200%200%2E2em%200%2E1em%200%2E2em%3B%0A%7D%0Ap%2C%20li%20%7B%0Aline%2Dheight%3A%201%2E5%3B%0A%7D%0Ap%2Ecaption%20%7B%0Adisplay%3A%20none%3B%0A%7D%0Ah1%2Etitle%20%7B%0Afont%2Dsize%3A%202em%3B%0A%7D%0Ah2%2Eauthor%20%7B%0Adisplay%3A%20inline%3B%0Afont%2Dsize%3A%20small%3B%0Afont%2Dweight%3A%20normal%3B%0Awhite%2Dspace%3A%20nowrap%3B%0A%7D%0Ah2%2Eauthor%3Aafter%20%7B%0Acontent%3A%20%27%2C%20%27%3B%0Awhite%2Dspace%3A%20normal%3B%0A%7D%0Ah2%2Eauthor%3Anth%2Dlast%2Dchild%28%2Dn%2B2%29%3Aafter%20%7B%0Acontent%3A%20%27%27%3B%0A%7D%0Ah3%2Edate%20%7B%0Afont%2Dfamily%3A%20monospace%3B%0Afont%2Dsize%3A%20medium%3B%0Afont%2Dweight%3A%20normal%3B%0A%7D%0Adiv%23TOC%20a%20%7B%0Atext%2Ddecoration%3A%20none%3B%0A%7D%0Ah1%20a%2C%20h2%20a%2C%20h3%20a%2C%20h4%20a%2C%20h5%20a%2C%20h6%20a%20%7B%0Atext%2Ddecoration%3A%20none%3B%0Acolor%3A%20black%3B%0A%7D%0Ah1%20%7B%0Afont%2Dsize%3A%201%2E8em%3B%0A%7D%0Ah2%20%7B%0Afont%2Dsize%3A%201%2E6em%3B%0A%7D%0Ah3%20%7B%0Afont%2Dsize%3A%201%2E4em%3B%0A%7D%0Ah4%20%7B%0Afont%2Dsize%3A%201%2E2em%3B%0A%7D%0Ah5%20%7B%0Afont%2Dsize%3A%201%2E0em%3B%0A%7D%0Ah6%20%7B%0Afont%2Dweight%3A%20normal%3B%0Afont%2Dsize%3A%201%2E0em%3B%0Atext%2Ddecoration%3A%20underline%3B%0A%7D%0Adiv%2Efigure%20%3E%20img%20%7B%0Adisplay%3A%20block%3B%0Amargin%3A%20auto%3B%0A%7D%0A" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="header">
<h1 class="title">Snabb Reference Manual</h1>
<h2 class="author">Mike Pall</h2>
<h2 class="author">Luke Gorrie</h2>
<h2 class="author">Andy Wingo</h2>
<h2 class="author">Max Rottenkolber</h2>
<h2 class="author">Diego Pino Garcia</h2>
<h2 class="author">Asumu Takikawa</h2>
<h2 class="author">Jessica Tallon</h2>
<h2 class="author">Diego Pino</h2>
<h2 class="author">Alexander Gall</h2>
<h2 class="author">Cosmin Apreutesei</h2>
<h2 class="author">Nikolay Nikolaev</h2>
<h2 class="author">Katerina Barone-Adesi</h2>
<h2 class="author">Hans Huebner</h2>
<h2 class="author">Javier Guerra</h2>
<h2 class="author">Marcel Wiget</h2>
<h2 class="author">Nicola Larosa</h2>
<h2 class="author">Pete Bristow</h2>
<h2 class="author">Adrian Perez de Castro</h2>
<h2 class="author">Adrián Pérez de Castro</h2>
<h2 class="author">Nicola ‘tekNico’ Larosa</h2>
<h2 class="author">Antonio Nikishaev</h2>
<h2 class="author">Domen Kožar</h2>
<h2 class="author">Peter Cawley</h2>
<h2 class="author">Alexander Altshuler</h2>
<h2 class="author">Rolf Sommerhalder</h2>
<h2 class="author">Timo Buhrmester</h2>
<h2 class="author">Pete Kazmier</h2>
<h2 class="author">Dibyendu Majumdar</h2>
<h2 class="author">Lesley De Cruz</h2>
<h2 class="author">Mikhail Nazarov</h2>
<h2 class="author">Kristian Larsson</h2>
<h2 class="author">Justin Cormack</h2>
<h2 class="author">Ben Agricola</h2>
<h2 class="author">Felix Geißler</h2>
<h2 class="author">R. Matthew Emerson</h2>
<h2 class="author">Michael G</h2>
<h2 class="author">Christian Graf</h2>
<h2 class="author">Carlos Alberto Lopez Perez</h2>
<h2 class="author">Jeff Loughridge</h2>
<h2 class="author">Kacper Wysocki</h2>
<h2 class="author">Adrian Perez</h2>
<h2 class="author">William Adams</h2>
<h2 class="author">Vladimir Fedin</h2>
<h2 class="author">Vincenzo Maffione</h2>
<h2 class="author">Tomas Korcak</h2>
<h2 class="author">Tim Upthegrove</h2>
<h2 class="author">Tim LaBerge</h2>
<h2 class="author">Stevan Markovic</h2>
<h2 class="author">Simon Leinen</h2>
<h2 class="author">Ryan Hartlage</h2>
<h2 class="author">Kristian Kielhofner</h2>
<h2 class="author">Jon Olsson</h2>
<h2 class="author">Jianbo Liu</h2>
<h2 class="author">Jay Fenton</h2>
<h2 class="author">James Cunningham</h2>
<h2 class="author">Hui Xiang</h2>
<h2 class="author">Gernot Nusshall</h2>
<h2 class="author">Fabian Bonk</h2>
<h2 class="author">Edward Hope-Morley</h2>
<h2 class="author">Darius Bacon</h2>
<h2 class="author">Anshul Makkar</h2>
<h2 class="author">Andy Chong</h2>
<h2 class="author">Alex Kordic</h2>
<h2 class="author">Alexandr Kostrikov</h2>
<h2 class="author">Alexander Spyridakis</h2>
<h3 class="date">Version 4b0c18b, Fri Nov 8 08:53:57 2019 +0100</h3>
</div>
<div id="TOC">
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#snabb-api">Snabb API</a><ul>
<li><a href="#app">App</a></li>
<li><a href="#config-core.config">Config (core.config)</a></li>
<li><a href="#engine-core.app">Engine (core.app)</a></li>
<li><a href="#link-core.link">Link (core.link)</a></li>
<li><a href="#packet-core.packet">Packet (core.packet)</a></li>
<li><a href="#memory-core.memory">Memory (core.memory)</a></li>
<li><a href="#shared-memory-core.shm">Shared Memory (core.shm)</a><ul>
<li><a href="#counter-core.counter">Counter (core.counter)</a></li>
<li><a href="#histogram-core.histogram">Histogram (core.histogram)</a></li>
</ul></li>
<li><a href="#lib-core.lib">Lib (core.lib)</a></li>
<li><a href="#multiprocess-operation-core.worker">Multiprocess operation (core.worker)</a></li>
<li><a href="#main">Main</a></li>
</ul></li>
<li><a href="#basic-apps-apps.basic.basic_apps">Basic Apps (apps.basic.basic_apps)</a><ul>
<li><a href="#source">Source</a></li>
<li><a href="#join">Join</a></li>
<li><a href="#split">Split</a></li>
<li><a href="#sink">Sink</a></li>
<li><a href="#tee">Tee</a></li>
<li><a href="#repeater">Repeater</a></li>
<li><a href="#truncate">Truncate</a></li>
<li><a href="#sample">Sample</a></li>
</ul></li>
<li><a href="#intel-82599-ethernet-controller-apps">Intel 82599 Ethernet Controller Apps</a><ul>
<li><a href="#intel82599-apps.intel.intel_app">Intel82599 (apps.intel.intel_app)</a><ul>
<li><a href="#configuration">Configuration</a></li>
<li><a href="#performance">Performance</a></li>
<li><a href="#hardware-limits">Hardware limits</a></li>
</ul></li>
<li><a href="#loadgen-apps.intel.loadgen">LoadGen (apps.intel.loadgen)</a><ul>
<li><a href="#configuration-1">Configuration</a></li>
<li><a href="#performance-1">Performance</a></li>
</ul></li>
</ul></li>
<li><a href="#intel-i210-i350-82599-ethernet-controller-apps-apps.intel_mp.intel_mp">Intel i210 / i350 / 82599 Ethernet Controller apps (apps.intel_mp.intel_mp)</a><ul>
<li><a href="#caveats">Caveats</a></li>
<li><a href="#configuration-2">Configuration</a><ul>
<li><a href="#rss-hashing-methods">RSS hashing methods</a></li>
<li><a href="#default-rss-queue">Default RSS Queue</a></li>
<li><a href="#hardware-limits-1">Hardware limits</a></li>
</ul></li>
</ul></li>
<li><a href="#solarflare-ethernet-controller-apps">Solarflare Ethernet Controller Apps</a><ul>
<li><a href="#solarflare-apps.solarflare.solarflare">Solarflare (apps.solarflare.solarflare)</a><ul>
<li><a href="#configuration-3">Configuration</a></li>
</ul></li>
</ul></li>
<li><a href="#ratelimiter-app-apps.rate_limiter.rate_limiter">RateLimiter App (apps.rate_limiter.rate_limiter)</a><ul>
<li><a href="#configuration-4">Configuration</a></li>
<li><a href="#performance-2">Performance</a></li>
</ul></li>
<li><a href="#pcapfilter-app-apps.packet_filter.pcap_filter">PcapFilter App (apps.packet_filter.pcap_filter)</a><ul>
<li><a href="#configuration-5">Configuration</a></li>
<li><a href="#special-counters">Special Counters</a></li>
</ul></li>
<li><a href="#ipv4-apps">IPv4 Apps</a><ul>
<li><a href="#arp-apps.ipv4.arp">ARP (apps.ipv4.arp)</a><ul>
<li><a href="#configuration-6">Configuration</a></li>
</ul></li>
<li><a href="#reassembler-apps.ipv4.reassemble">Reassembler (apps.ipv4.reassemble)</a><ul>
<li><a href="#configuration-7">Configuration</a></li>
</ul></li>
<li><a href="#fragmenter-apps.ipv4.fragment">Fragmenter (apps.ipv4.fragment)</a><ul>
<li><a href="#configuration-8">Configuration</a></li>
</ul></li>
<li><a href="#icmp-echo-responder-apps.ipv4.echo">ICMP Echo responder (apps.ipv4.echo)</a><ul>
<li><a href="#configuration-9">Configuration</a></li>
</ul></li>
</ul></li>
<li><a href="#ipv6-apps">IPv6 Apps</a><ul>
<li><a href="#nd_light-apps.ipv6.nd_light">Nd_light (apps.ipv6.nd_light)</a><ul>
<li><a href="#configuration-10">Configuration</a></li>
<li><a href="#special-counters-1">Special Counters</a></li>
</ul></li>
<li><a href="#simplekeyedtunnel-apps.keyed_ipv6_tunnel.tunnel">SimpleKeyedTunnel (apps.keyed_ipv6_tunnel.tunnel)</a><ul>
<li><a href="#configuration-11">Configuration</a></li>
<li><a href="#special-counters-2">Special Counters</a></li>
</ul></li>
<li><a href="#fragmenter-apps.ipv6.fragment">Fragmenter (apps.ipv6.fragment)</a><ul>
<li><a href="#configuration-12">Configuration</a></li>
</ul></li>
<li><a href="#icmp-echo-responder-apps.ipv6.echo">ICMP Echo responder (apps.ipv6.echo)</a><ul>
<li><a href="#configuration-13">Configuration</a></li>
</ul></li>
</ul></li>
<li><a href="#vhostuser-app-apps.vhost.vhost_user">VhostUser App (apps.vhost.vhost_user)</a><ul>
<li><a href="#configuration-14">Configuration</a></li>
</ul></li>
<li><a href="#virtionet-app-apps.virtio_net.virtio_net">VirtioNet App (apps.virtio_net.virtio_net)</a><ul>
<li><a href="#configuration-15">Configuration</a></li>
</ul></li>
<li><a href="#pcap-savefile-apps">Pcap Savefile Apps</a><ul>
<li><a href="#pcapreader-and-pcapwriter-apps-apps.pcap.pcap">PcapReader and PcapWriter Apps (apps.pcap.pcap)</a><ul>
<li><a href="#configuration-16">Configuration</a></li>
</ul></li>
<li><a href="#tap-apps.pcap.tap">Tap (apps.pcap.tap)</a><ul>
<li><a href="#configuration-17">Configuration</a></li>
</ul></li>
</ul></li>
<li><a href="#rawsocket-app-apps.socket.raw">RawSocket App (apps.socket.raw)</a><ul>
<li><a href="#configuration-18">Configuration</a></li>
</ul></li>
<li><a href="#unixsocket-app-apps.socket.unix">UnixSocket App (apps.socket.unix)</a><ul>
<li><a href="#configuration-19">Configuration</a></li>
</ul></li>
<li><a href="#tap-app-apps.tap.tap">Tap app (apps.tap.tap)</a><ul>
<li><a href="#configuration-20">Configuration</a></li>
</ul></li>
<li><a href="#vlan-apps">VLAN Apps</a><ul>
<li><a href="#tagger-apps.vlan.vlan">Tagger (apps.vlan.vlan)</a><ul>
<li><a href="#configuration-21">Configuration</a></li>
</ul></li>
<li><a href="#untagger-apps.vlan.vlan">Untagger (apps.vlan.vlan)</a><ul>
<li><a href="#configuration-22">Configuration</a></li>
</ul></li>
<li><a href="#vlanmux-apps.vlan.vlan">VlanMux (apps.vlan.vlan)</a><ul>
<li><a href="#configuration-23">Configuration</a></li>
</ul></li>
</ul></li>
<li><a href="#bridge-apps">Bridge Apps</a><ul>
<li><a href="#configuration-24">Configuration</a></li>
<li><a href="#flooding-bridge-apps.bridge.flooding">Flooding bridge (apps.bridge.flooding)</a><ul>
<li><a href="#configuration-25">Configuration</a></li>
</ul></li>
<li><a href="#learning-bridge-apps.bridge.learning">Learning bridge (apps.bridge.learning)</a><ul>
<li><a href="#configuration-26">Configuration</a></li>
</ul></li>
</ul></li>
<li><a href="#ipfix-and-netflow-apps">IPFIX and NetFlow apps</a><ul>
<li><a href="#ipfix-apps.ipfix.ipfix">IPFIX (apps.ipfix.ipfix)</a><ul>
<li><a href="#configuration-27">Configuration</a></li>
<li><a href="#to-do-list">To-do list</a></li>
</ul></li>
</ul></li>
<li><a href="#ipsec-apps">IPsec Apps</a><ul>
<li><a href="#esp-transport6-and-tunnel6-apps.ipsec.esp">ESP Transport6 and Tunnel6 (apps.ipsec.esp)</a><ul>
<li><a href="#configuration-28">Configuration</a></li>
</ul></li>
</ul></li>
<li><a href="#test-apps">Test Apps</a><ul>
<li><a href="#match-apps.test.match">Match (apps.test.match)</a><ul>
<li><a href="#configuration-29">Configuration</a></li>
</ul></li>
<li><a href="#synth-apps.test.synth">Synth (apps.test.synth)</a><ul>
<li><a href="#configuration-30">Configuration</a></li>
</ul></li>
<li><a href="#npackets-apps.test.npackets">Npackets (apps.test.npackets)</a><ul>
<li><a href="#configuration-31">Configuration</a></li>
</ul></li>
</ul></li>
<li><a href="#snabbwall-apps">SnabbWall Apps</a><ul>
<li><a href="#l7spy-apps.wall.l7spy">L7Spy (apps.wall.l7spy)</a></li>
<li><a href="#filter-apps.wall.filter">Filter (apps.wall.filter)</a></li>
<li><a href="#scanner-apps.wall.scanner">Scanner (apps.wall.scanner)</a><ul>
<li><a href="#subclassing">Subclassing</a></li>
<li><a href="#ndpiscanner-apps.wall.scanner.ndpi">NdpiScanner (apps.wall.scanner.ndpi)</a></li>
</ul></li>
<li><a href="#utilities">Utilities</a><ul>
<li><a href="#southandnorth-apps.wall.util">SouthAndNorth (apps.wall.util)</a></li>
</ul></li>
</ul></li>
<li><a href="#rss-app-apps.rss.rss">RSS app (apps.rss.rss)</a><ul>
<li><a href="#flow-director">Flow-director</a></li>
<li><a href="#packet-replication">Packet replication</a></li>
<li><a href="#weighted-links">Weighted links</a></li>
<li><a href="#packet-meta-data">Packet meta-data</a></li>
<li><a href="#ipv6-extension-header-elimination">IPv6 extension header elimination</a></li>
<li><a href="#vlan-pseudo-tagging">VLAN pseudo-tagging</a></li>
<li><a href="#configuration-32">Configuration</a></li>
<li><a href="#meta-data-api">Meta-data API</a></li>
</ul></li>
<li><a href="#inter-process-links-apps.interlink.">Inter-process links (apps.interlink.*)</a><ul>
<li><a href="#configuration-33">Configuration</a></li>
</ul></li>
<li><a href="#libraries">Libraries</a><ul>
<li><a href="#ip-checksum-lib.checksum">IP checksum (lib.checksum)</a></li>
<li><a href="#ctable-lib.ctable">Ctable (lib.ctable)</a></li>
<li><a href="#poptrie-lib.poptrie">Poptrie (lib.poptrie)</a></li>
<li><a href="#pmu-lib.pmu">PMU (lib.pmu)</a></li>
<li><a href="#snabb-program-configuration-with-yang-lib.yang">Snabb program configuration with YANG (<code>lib.yang</code>)</a></li>
<li><a href="#hardware">Hardware</a><ul>
<li><a href="#pci-lib.hardware.pci">PCI (lib.hardware.pci)</a></li>
<li><a href="#register-lib.hardware.register">Register (lib.hardware.register)</a></li>
</ul></li>
<li><a href="#protocols">Protocols</a><ul>
<li><a href="#protocol-header-lib.protocol.header">Protocol Header (lib.protocol.header)</a></li>
<li><a href="#ethernet-lib.protocol.ethernet">Ethernet (lib.protocol.ethernet)</a></li>
<li><a href="#ipv4-lib.protocol.ipv4">IPv4 (lib.protocol.ipv4)</a></li>
<li><a href="#ipv6-lib.protocol.ipv6">IPv6 (lib.protocol.ipv6)</a></li>
<li><a href="#tcp-lib.protocol.tcp">TCP (lib.protocol.tcp)</a></li>
<li><a href="#udp-lib.protocol.udp">UDP (lib.protocol.udp)</a></li>
<li><a href="#gre-lib.protocol.gre">GRE (lib.protocol.gre)</a></li>
<li><a href="#icmp-lib.protocol.icmp.header">ICMP (lib.protocol.icmp.header)</a></li>
<li><a href="#datagram-lib.protocol.datagram">Datagram (lib.protocol.datagram)</a></li>
</ul></li>
<li><a href="#ipsec">IPsec</a><ul>
<li><a href="#encapsulating-security-payload-lib.ipsec.esp">Encapsulating Security Payload (lib.ipsec.esp)</a></li>
</ul></li>
<li><a href="#snabb-nfv">Snabb NFV</a><ul>
<li><a href="#nfv-config-program.snabbnfv.nfvconfig">NFV config (program.snabbnfv.nfvconfig)</a></li>
<li><a href="#snabbnfv-traffic">snabbnfv traffic</a></li>
<li><a href="#snabbnfv-neutron2snabb">snabbnfv neutron2snabb</a></li>
</ul></li>
<li><a href="#lisper">LISPER</a><ul>
<li><a href="#lisper-program.lisper">LISPER (program.lisper)</a></li>
</ul></li>
<li><a href="#ptree">Ptree</a><ul>
<li><a href="#ptree-program.ptree">Ptree (program.ptree)</a></li>
</ul></li>
<li><a href="#watchdog-lib.watchdog.watchdog">Watchdog (lib.watchdog.watchdog)</a></li>
</ul></li>
<li><a href="#snabblab">Snabblab</a><ul>
<li><a href="#guidelines">Guidelines</a></li>
<li><a href="#servers">Servers</a></li>
<li><a href="#get-started">Get started</a></li>
<li><a href="#using-the-lab">Using the lab</a></li>
<li><a href="#questions">Questions</a></li>
<li><a href="#thanks">Thanks</a></li>
</ul></li>
</ul>
</div>
<p><em><strong>Note:</strong> This reference manual is a draft. The API defined in this document is not guaranteed to be stable or complete and future versions of Snabb will introduce backwards incompatible changes. With that being said, discrepancies between this document and the actual Snabb Switch implementation are considered to be bugs. Please report them in order to help improve this document.</em></p>
<h1 id="introduction">Introduction</h1>
<p><em>Snabb</em> is an extensible, virtualized, Ethernet networking toolkit. With Snabb you can implement networking applications using the <em>Lua language</em>. Snabb includes all the tools you need to quickly realize your network designs and its really fast too! Furthermore, Snabb is extensible and encourages you to grow the ecosystem to match your requirements.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Architecture" />
<p class="caption">Architecture</p>
</div>
<p>The Snabb Core forms a runtime environment (<em>engine</em>) which executes your <em>design</em>. A design is simply a Lua script used to drive the Snabb stack, you can think of it as your top-level “main” routine.</p>
<p>In order to add functionality to the Snabb stack you can load modules into the Snabb engine. These can be Lua modules as well as native code objects. We differentiate between two classes of modules, namely libraries and <em>Apps</em>. Libraries are simple collections of program utilities to be used in your designs, apps or other libraries, just as you might expect. Apps, on the other hand, are code objects that implement a specific interface, which is used by the Snabb engine to organize an <em>App Network</em>.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Network" />
<p class="caption">Network</p>
</div>
<p>Usually, a Snabb design will create a series of apps, interconnect these in a desired way using <em>links</em> and finally pass the resulting app network on to the Snabb engine. The engine’s job is to:</p>
<ul>
<li>Pump traffic through the app network</li>
<li>Keep the app network running (e.g. restart failed apps)</li>
<li>Report on the network status</li>
</ul>
<h1 id="snabb-api">Snabb API</h1>
<p>The core modules defined below can be loaded using Lua’s <code>require</code>. For example:</p>
<pre><code>local config = require("core.config")
local c = config.new()
...</code></pre>
<h2 id="app">App</h2>
<p>An <em>app</em> is an isolated implementation of a specific networking function. For example, a switch, a router, or a packet filter.</p>
<p>Apps receive packets on <em>input ports</em>, perform some processing, and transmit packets on <em>output ports</em>. Each app has zero or more input and output ports. For example, a packet filter may have one input and one output port, while a packet recorder may have only an input port. Every app must implement the interface below. Methods which may be left unimplemented are marked as “optional”.</p>
<p>— Method <strong>myapp:new</strong> <em>arg</em></p>
<p><em>Required</em>. Create an instance of the app with a given argument <em>arg</em>. <code>Myapp:new</code> must return an instance of the app. The handling of <em>arg</em> is up to the app but it is encouraged to use <code>core.config</code>’s <code>parse_app_arg</code> to parse <em>arg</em>.</p>
<p>— Field <strong>myapp.input</strong></p>
<p>— Field <strong>myapp.output</strong></p>
<p>Tables of named input and output links. These tables are initialized by the engine for use in processing and are <em>read-only</em>.</p>
<p>— Field <strong>myapp.appname</strong></p>
<p>Name of the app. <em>Read-only</em>.</p>
<p>— Field <strong>myapp.shm</strong></p>
<p>Can be set to a specification for <code>core.shm.create_frame</code>. When set, this field will be initialized to a frame of shared memory objects by the engine.</p>
<p>— Field <strong>myapp.config</strong></p>
<p>Can be set to a specification for <code>core.lib.parse</code>. When set, the specification will be used to validate the app’s arg when it is configured using <code>config.app</code>.</p>
<p>— Method <strong>myapp:link</strong></p>
<p><em>Optional</em>. Called any time the app’s links may have been changed (including on start-up). Guaranteed to be called before <code>pull</code> and <code>push</code> are called with new links.</p>
<p>— Method <strong>myapp:pull</strong></p>
<p><em>Optional</em>. Pull packets into the network.</p>
<p>For example: Pull packets from a network adapter into the app network by transmitting them to output ports.</p>
<p>— Method <strong>myapp:push</strong></p>
<p><em>Optional</em>. Push packets through the system.</p>
<p>For example: Move packets from input ports to output ports or to a network adapter.</p>
<p>— Method <strong>myapp:reconfig</strong> <em>arg</em></p>
<p><em>Optional</em>. Reconfigure the app with a new <em>arg</em>. If this method is not implemented the app instance is discarded and a new instance is created.</p>
<p>— Method <strong>myapp:report</strong></p>
<p><em>Optional</em>. Print a report of the current app status.</p>
<p>— Method <strong>myapp:stop</strong></p>
<p><em>Optional</em>. Stop the app and release associated external resources.</p>
<p>— Field <strong>myapp.zone</strong></p>
<p><em>Optional</em>. Name of the LuaJIT <em>profiling zone</em> used for this app (descriptive string). The default is the module name.</p>
<h2 id="config-core.config">Config (core.config)</h2>
<p>A <em>config</em> is a description of a packet-processing network. The network is a directed graph. Nodes in the graph are <em>apps</em> that each process packets in a specific way. Each app has a set of named input and output <em>ports</em>—often called <em>rx</em> and <em>tx</em>. Edges of the graph are unidirectional <em>links</em> that carry packets from an output port to an input port.</p>
<p>The config is a purely passive data structure. Creating and manipulating a config object does not immediately affect operation. The config has to be activated using <code>engine.configure</code>.</p>
<p>— Function <strong>config.new</strong></p>
<p>Creates and returns a new empty configuration.</p>
<p>— Function <strong>config.app</strong> <em>config</em>, <em>name</em>, <em>class</em>, <em>arg</em></p>
<p>Adds an app of <em>class</em> with <em>arg</em> to the <em>config</em> where it will be assigned to <em>name</em>.</p>
<p>Example:</p>
<pre><code>config.app(c, "nic", Intel82599, {pciaddr = "0000:00:00.0"})</code></pre>
<p>— Function <strong>config.link</strong> <em>config</em>, <em>linkspec</em></p>
<p>Add a link defined by <em>linkspec</em> to the config <em>config</em>. <em>Linkspec</em> must be a string of the format</p>
<pre><code>app_name1.output_port->app_name2.input_port</code></pre>
<p>where <code>app_name1</code> and <code>app_name2</code> are names of apps in <em>config</em> and <code>output_port</code> and <code>input_port</code> are valid output and input ports of the referenced apps respectively.</p>
<p>Example:</p>
<pre><code>config.link(c, "nic1.tx->nic2.rx")</code></pre>
<h2 id="engine-core.app">Engine (core.app)</h2>
<p>The <em>engine</em> executes a config by initializing apps, creating links, and driving the flow of execution. The engine also performs profiling and reporting functions. It can be reconfigured during runtime. Within Snabb Switch scripts the <code>core.app</code> module is bound to the global <code>engine</code> variable.</p>
<p>— Function <strong>engine.configure</strong> <em>config</em></p>
<p>Configure the engine to use a new config <em>config</em>. You can safely call this method many times to incrementally update the running app network. The engine updates the app network as follows:</p>
<ul>
<li>Apps that did not exist in the old configuration are started.</li>
<li>Apps that do not exist in the new configuration are stopped. (The app <code>stop()</code> method is called if defined.)</li>
<li>Apps with unchanged configurations are preserved.</li>
<li>Apps with changed configurations are updated by calling their <code>reconfig()</code> method. If the <code>reconfig()</code> method is not implemented then the old instance is stopped a new one started.</li>
<li>Links with unchanged endpoints are preserved.</li>
</ul>
<p>— Function <strong>engine.main</strong> <em>options</em></p>
<p>Run the Snabb engine. <em>Options</em> is a table of key/value pairs. The following keys are recognized:</p>
<ul>
<li><code>duration</code> - Duration in seconds to run the engine for (as a floating point number). If this is set you cannot supply <code>done</code>.</li>
<li><code>done</code> - A function to be called repeatedly by <code>engine.main</code> until it returns <code>true</code>. Once it returns <code>true</code> the engine will be stopped and <code>engine.main</code> will return. If this is set you cannot supply <code>duration</code>.</li>
<li><code>report</code> - A table which configures the report printed before <code>engine.main()</code> returns. The keys <code>showlinks</code> and <code>showapps</code> can be set to boolean values to force or suppress link and app reporting individually. By default `engine.main()’ will report on links but not on apps.</li>
<li><code>measure_latency</code> - By default, the <code>breathe()</code> loop is instrumented to record the latency distribution of running the app graph. This information can be processed by the <code>snabb top</code> program. Passing <code>measure_latency=false</code> in the <em>options</em> will disable this instrumentation.</li>
<li><code>no_report</code> - A boolean value. If <code>true</code> no final report will be printed.</li>
</ul>
<p>— Function <strong>engine.stop</strong></p>
<p>Stop all apps in the engine by loading an empty configuration.</p>
<p>— Function <strong>engine.now</strong></p>
<p>Returns monotonic time in seconds as a floating point number. Suitable for timers.</p>
<p>— Variable <strong>engine.busywait</strong></p>
<p>If set to true then the engine polls continuously for new packets to process. This consumes 100% CPU and makes processing latency less vulnerable to kernel scheduling behavior which can cause pauses of more than one millisecond.</p>
<p>Default: false</p>
<p>— Variable <strong>engine.Hz</strong></p>
<p>Frequency at which to poll for new input packets. The default value is ‘false’ which means to adjust dynamically up to 100us during low traffic. The value can be overridden with a constant integer saying how many times per second to poll.</p>
<p>This setting is not used when engine.busywait is true.</p>
<h2 id="link-core.link">Link (core.link)</h2>
<p>A <em>link</em> is a <a href="http://en.wikipedia.org/wiki/Circular_buffer">ring buffer</a> used to store packets between apps. Links can be treated either like arrays—accessing their internal structure directly—or as streams of packets by using their API functions.</p>
<p>— Function <strong>link.empty</strong> <em>link</em></p>
<p>Predicate used to test if a link is empty. Returns true if <em>link</em> is empty and false otherwise.</p>
<p>— Function <strong>link.full</strong> <em>link</em></p>
<p>Predicate used to test if a link is full. Returns true if <em>link</em> is full and false otherwise.</p>
<p>— Function <strong>link.nreadable</strong> <em>link</em></p>
<p>Returns the number of packets on <em>link</em>.</p>
<p>— Function <strong>link.nwriteable</strong> <em>link</em></p>
<p>Returns the remaining number of packets that fit onto <em>link</em>.</p>
<p>— Function <strong>link.receive</strong> <em>link</em></p>
<p>Returns the next available packet (and advances the read cursor) on <em>link</em>. If the link is empty an error is signaled.</p>
<p>— Function <strong>link.front</strong> <em>link</em></p>
<p>Return the next available packet without advancing the read cursor on <em>link</em>. If the link is empty, <code>nil</code> is returned.</p>
<p>— Function <strong>link.transmit</strong> <em>link</em>, <em>packet</em></p>
<p>Transmits <em>packet</em> onto <em>link</em>. If the link is full <em>packet</em> is dropped (and the drop counter increased).</p>
<p>— Function <strong>link.stats</strong> <em>link</em></p>
<p>Returns a structure holding ring statistics for the <em>link</em>:</p>
<ul>
<li><code>txbytes</code>, <code>rxbytes</code>: Counts of transferred bytes.</li>
<li><code>txpackets</code>, <code>rxpackets</code>: Counts of transferred packets.</li>
<li><code>txdrop</code>: Count of packets dropped due to ring overflow.</li>
</ul>
<h2 id="packet-core.packet">Packet (core.packet)</h2>
<p>A <em>packet</em> is an FFI object of type <code>struct packet</code> representing a network packet that is currently being processed. The packet is used to explicitly manage the life cycle of the packet. Packets are explicitly allocated and freed by using <code>packet.allocate</code> and <code>packet.free</code>. When a packet is received using <code>link.receive</code> its ownership is acquired by the calling app. The app must then ensure to either transfer the packet ownership to another app by calling <code>link.transmit</code> on the packet or free the packet using <code>packet.free</code>. Apps may only use packets they own, e.g. packets that have not been transmitted or freed. The number of allocatable packets is limited by the size of the underlying “freelist”, e.g. a pool of unused packet objects from and to which packets are allocated and freed.</p>
<p>— Type <strong>struct packet</strong></p>
<pre><code>struct packet {
uint16_t length;
uint8_t data[packet.max_payload];
};</code></pre>
<p>— Constant <strong>packet.max_payload</strong></p>
<p>The maximum payload length of a packet.</p>
<p>— Function <strong>packet.allocate</strong></p>
<p>Returns a new empty packet. An an error is raised if there are no packets left on the freelist. Initially the <code>length</code> of the allocated is 0, and its <code>data</code> is uninitialized garbage.</p>
<p>— Function <strong>packet.free</strong> <em>packet</em></p>
<p>Frees <em>packet</em> and puts in back onto the freelist.</p>
<p>— Function <strong>packet.clone</strong> <em>packet</em></p>
<p>Returns an exact copy of <em>packet</em>.</p>
<p>— Function <strong>packet.resize</strong> <em>packet</em>, <em>length</em></p>
<p>Sets the payload length of <em>packet</em>, truncating or extending its payload. In the latter case the contents of the extended area at the end of the payload are filled with zeros.</p>
<p>— Function <strong>packet.append</strong> <em>packet</em>, <em>pointer</em>, <em>length</em></p>
<p>Appends <em>length</em> bytes starting at <em>pointer</em> to the end of <em>packet</em>. An error is raised if there is not enough space in <em>packet</em> to accomodate <em>length</em> additional bytes.</p>
<p>— Function <strong>packet.prepend</strong> <em>packet</em>, <em>pointer</em>, <em>length</em></p>
<p>Prepends <em>length</em> bytes starting at <em>pointer</em> to the front of <em>packet</em>, taking ownership of the packet and returning a new packet. An error is raised if there is not enough space in <em>packet</em> to accomodate <em>length</em> additional bytes.</p>
<p>— Function <strong>packet.shiftleft</strong> <em>packet</em>, <em>length</em></p>
<p>Take ownership of <em>packet</em>, truncate it by <em>length</em> bytes from the front, and return a new packet. <em>Length</em> must be less than or equal to <code>length</code> of <em>packet</em>.</p>
<p>— Function <strong>packet.shiftright</strong> <em>packet</em>, <em>length</em></p>
<p>Take ownership of <em>packet</em>, moves <em>packet</em> payload to the right by <em>length</em> bytes, growing <em>packet</em> by <em>length</em>. Returns a new packet. The sum of <em>length</em> and <code>length</code> of <em>packet</em> must be less than or equal to <code>packet.max_payload</code>.</p>
<p>— Function <strong>packet.from_pointer</strong> <em>pointer</em>, <em>length</em></p>
<p>Allocate packet and fill it with <em>length</em> bytes from <em>pointer</em>.</p>
<p>— Function <strong>packet.from_string</strong> <em>string</em></p>
<p>Allocate packet and fill it with the contents of <em>string</em>.</p>
<p>— Function **packet.clone_to_memory* <em>pointer</em> <em>packet</em></p>
<p>Creates an exact copy of at memory pointed to by <em>pointer</em>. <em>Pointer</em> must point to a <code>packet.packet_t</code>.</p>
<h2 id="memory-core.memory">Memory (core.memory)</h2>
<p>Snabb allocates special <a href="https://en.wikipedia.org/wiki/Direct_memory_access">DMA</a> memory that can be accessed directly by network cards. The important characteristic of DMA memory is being located in contiguous physical memory at a stable address.</p>
<p>— Function <strong>memory.dma_alloc</strong> <em>bytes</em>, [<em>alignment</em>]</p>
<p>Returns a pointer to <em>bytes</em> of new DMA memory.</p>
<p>Optionally a specific <em>alignment</em> requirement can be provided (in bytes). The default alignment is 128.</p>
<p>— Function <strong>memory.virtual_to_physical</strong> <em>pointer</em></p>
<p>Returns the physical address (<code>uint64_t</code>) the DMA memory at <em>pointer</em>.</p>
<p>— Variable <strong>memory.huge_page_size</strong></p>
<p>Size of a single huge page in bytes. Read-only.</p>
<h2 id="shared-memory-core.shm">Shared Memory (core.shm)</h2>
<p>This module facilitates creation and management of named shared memory objects. Objects can be created using <code>shm.create</code> similar to <code>ffi.new</code>, except that separate calls to <code>shm.open</code> for the same name will each return a new mapping of the same shared memory. Different processes can share memory by mapping an object with the same name (and type). Each process can map any object any number of times.</p>
<p>Mappings are deleted on process termination or with an explicit <code>shm.unmap</code>. Names are unlinked from objects that are no longer needed using <code>shm.unlink</code>. Object memory is freed when the name is unlinked and all mappings have been deleted.</p>
<p>Names can be fully qualified or abbreviated to be within the current process. Here are examples of names and how they are resolved where <code><pid></code> is the PID of this process:</p>
<ul>
<li>Local: <code>foo/bar</code> ⇒ <code>/var/run/snabb/<pid>/foo/bar</code></li>
<li>Fully qualified: <code>/1234/foo/bar</code> ⇒ <code>/var/run/snabb/1234/foo/bar</code></li>
</ul>
<p>Behind the scenes the objects are backed by files on ram disk (<code>/var/run/snabb/<pid></code>) and accessed with the equivalent of POSIX shared memory (<code>shm_overview(7)</code>). The files are automatically removed on shutdown unless the environment <code>SNABB_SHM_KEEP</code> is set. The location <code>/var/run/snabb</code> can be overridden by the environment variable <code>SNABB_SHM_ROOT</code>.</p>
<p>Shared memory objects are created world-readable for convenient access by diagnostic tools. You can lock this down by setting <code>SNABB_SHM_ROOT</code> to a path under a directory with appropriate permissions.</p>
<p>The practical limit on the number of objects that can be mapped will depend on the operating system limit for memory mappings. On Linux the default limit is 65,530 mappings:</p>
<pre><code>$ sysctl vm.max_map_count vm.max_map_count = 65530</code></pre>
<p>— Function <strong>shm.create</strong> <em>name</em>, <em>type</em></p>
<p>Creates and maps a shared object of <em>type</em> into memory via a hierarchical <em>name</em>. Returns a pointer to the mapped object.</p>
<p>— Function <strong>shm.open</strong> <em>name</em>, <em>type</em>, [<em>readonly</em>]</p>
<p>Maps an existing shared object of <em>type</em> into memory via a hierarchical <em>name</em>. If <em>readonly</em> is non-nil the shared object is mapped in read-only mode. <em>Readonly</em> defaults to nil. Fails if the shared object does not already exist. Returns a pointer to the mapped object.</p>
<p>— Function <strong>shm.alias</strong> <em>new-path</em> <em>existing-path</em></p>
<p>Create an alias (symbolic link) for an object.</p>
<p>— Function <strong>shm.path</strong> <em>name</em></p>
<p>Returns the fully-qualified path for an object called <em>name</em>.</p>
<p>— Function <strong>shm.exists</strong> <em>name</em></p>
<p>Returns a true value if shared object by <em>name</em> exists.</p>
<p>— Function <strong>shm.unmap</strong> <em>pointer</em></p>
<p>Deletes the memory mapping for <em>pointer</em>.</p>
<p>— Function <strong>shm.unlink</strong> <em>path</em></p>
<p>Unlinks the subtree of objects designated by <em>path</em> from the filesystem.</p>
<p>— Function <strong>shm.children</strong> <em>path</em></p>
<p>Returns an array of objects in the directory designated by <em>path</em>.</p>
<p>— Function <strong>shm.register</strong> <em>type</em>, <em>module</em></p>
<p>Registers an abstract shared memory object <em>type</em> implemented by <em>module</em> in <code>shm.types</code>. <em>Module</em> must provide the following functions:</p>
<ul>
<li><strong>create</strong> <em>name</em>, …</li>
<li><strong>open</strong>, <em>name</em></li>
</ul>
<p>and can optionally provide the function:</p>
<ul>
<li><strong>delete</strong>, <em>name</em></li>
</ul>
<p>The <em>module</em>’s <code>type</code> variable must be bound to <em>type</em>. To register a new type a module might invoke <code>shm.register</code> like so:</p>
<pre><code>type = shm.register('mytype', getfenv())
-- Now the following holds true:
-- shm.types[type] == getfenv()</code></pre>
<p>— Variable <strong>shm.types</strong></p>
<p>A table that maps types to modules. See <code>shm.register</code>.</p>
<p>— Function <strong>shm.create_frame</strong> <em>path</em>, <em>specification</em></p>
<p>Creates and returns a shared memory frame by <em>specification</em> under <em>path</em>. A frame is a table of mapped—possibly abstract‑shared memory objects. <em>Specification</em> must be of the form:</p>
<pre><code>{ <name> = {<module>, ...},
... }</code></pre>
<p><em>Module</em> must implement an abstract type registered with <code>shm.register</code>, and is followed by additional initialization arguments to its <code>create</code> function. Example usage:</p>
<pre><code>local counter = require("core.counter")
-- Create counters foo/bar/{dtime,rxpackets,txpackets}.counter
local f = shm.create_frame(
"foo/bar",
{dtime = {counter, C.get_unix_time()},
rxpackets = {counter},
txpackets = {counter}})
counter.add(f.rxpackets)
counter.read(f.dtime)</code></pre>
<p>— Function <strong>shm.open_frame</strong> <em>path</em></p>
<p>Opens and returns the shared memory frame under <em>path</em> for reading.</p>
<p>— Function <strong>shm.delete_frame</strong> <em>frame</em></p>
<p>Deletes/unmaps a shared memory <em>frame</em>. The <em>frame</em> directory is unlinked if <em>frame</em> was created by <code>shm.create_frame</code>.</p>
<h3 id="counter-core.counter">Counter (core.counter)</h3>
<p>Double-buffered shared memory counters. Counters are 64-bit unsigned values. Registered with <code>core.shm</code> as type <code>counter</code>.</p>
<p>— Function <strong>counter.create</strong> <em>name</em>, [<em>initval</em>]</p>
<p>Creates and returns a <code>counter</code> by <em>name</em>, initialized to <em>initval</em>. <em>Initval</em> defaults to 0.</p>
<p>— Function <strong>counter.open</strong> <em>name</em></p>
<p>Opens and returns the counter by <em>name</em> for reading.</p>
<p>— Function <strong>counter.delete</strong> <em>name</em></p>
<p>Deletes and unmaps the counter by <em>name</em>.</p>
<p>— Function <strong>counter.commit</strong></p>
<p>Commits buffered counter values to public shared memory.</p>
<p>— Function <strong>counter.set</strong> <em>counter</em>, <em>value</em></p>
<p>Sets <em>counter</em> to <em>value</em>.</p>
<p>— Function <strong>counter.add</strong> <em>counter</em>, [<em>value</em>]</p>
<p>Increments <em>counter</em> by <em>value</em>. <em>Value</em> defaults to 1.</p>
<p>— Function <strong>counter.read</strong> <em>counter</em></p>
<p>Returns the value of <em>counter</em>.</p>
<h3 id="histogram-core.histogram">Histogram (core.histogram)</h3>
<p>Shared memory histogram with logarithmic buckets. Registered with <code>core.shm</code> as type <code>histogram</code>.</p>
<p>— Function <strong>histogram.new</strong> <em>min</em>, <em>max</em></p>
<p>Returns a new <code>histogram</code>, with buckets covering the range from <em>min</em> to <em>max</em>. The range between <em>min</em> and <em>max</em> will be divided logarithmically.</p>
<p>— Function <strong>histogram.create</strong> <em>name</em>, <em>min</em>, <em>max</em></p>
<p>Creates and returns a <code>histogram</code> as in <code>histogram.new</code> by <em>name</em>. If the file exists already, it will be cleared.</p>
<p>— Function <strong>histogram.open</strong> <em>name</em></p>
<p>Opens and returns <code>histogram</code> by <em>name</em> for reading.</p>
<p>— Method <strong>histogram:add</strong> <em>measurement</em></p>
<p>Adds <em>measurement</em> to <em>histogram</em>.</p>
<p>— Method <strong>histogram:iterate</strong> <em>prev</em></p>
<p>When used as <code>for count, lo, hi in histogram:iterate()</code>, visits all buckets in <em>histogram</em> in order from lowest to highest. <em>Count</em> is the number of samples recorded in that bucket, and <em>lo</em> and <em>hi</em> are the lower and upper bounds of the bucket. Note that <em>count</em> is an unsigned 64-bit integer; to get it as a Lua number, use <code>tonumber</code>.</p>
<p>If <em>prev</em> is given, it should be a snapshot of the previous version of the histogram. In that case, the <em>count</em> values will be returned as a difference between their values in <em>histogram</em> and their values in <em>prev</em>.</p>
<p>— Method <strong>histogram:snapshot</strong> [<em>dest</em>]</p>
<p>Copies out the contents of <em>histogram</em> into the <code>histogram</code> <em>dest</em> and returns <em>dest</em>. If <em>dest</em> is not given, the result will be a fresh <code>histogram</code>.</p>
<p>— Method <strong>histogram:clear</strong></p>
<p>Clears the buckets of <em>histogram</em>.</p>
<p>— Method **histogram:wrap_thunk* <em>thunk</em>, <em>now</em></p>
<p>Returns a closure that wraps <em>thunk</em>, measuring and recording the difference between calls to <em>now</em> before and after <em>thunk</em> into <em>histogram</em>.</p>
<p>— Method **histogram:summarize* <em>prev</em></p>
<p>Returns the approximate minimum, average, and maximum values recorded in <em>histogram</em>.</p>
<p>If <em>prev</em> is given, it should be a snapshot of a previous version of the histogram. In that case, this method returns the approximate minimum, average and maximum values for the difference between <em>histogram</em> and <em>prev</em>.</p>
<h2 id="lib-core.lib">Lib (core.lib)</h2>
<p>The <code>core.lib</code> module contains miscellaneous utilities.</p>
<p>— Function <strong>lib.equal</strong> <em>x</em>, <em>y</em></p>
<p>Predicate to test if <em>x</em> and <em>y</em> are structurally similar (isomorphic).</p>
<p>— Function <strong>lib.can_open</strong> <em>filename</em>, <em>mode</em></p>
<p>Predicate to test if file at <em>filename</em> can be successfully opened with <em>mode</em>.</p>
<p>— Function <strong>lib.can_read</strong> <em>filename</em></p>
<p>Predicate to test if file at <em>filename</em> can be successfully opened for reading.</p>
<p>— Function <strong>lib.can_write</strong> <em>filename</em></p>
<p>Predicate to test if file at <em>filename</em> can be successfully opened for writing.</p>
<p>— Function <strong>lib.readcmd</strong> <em>command</em>, <em>what</em></p>
<p>Runs Unix shell <em>command</em> and returns <em>what</em> of its output. <em>What</em> must be a valid argument to <code>file:read</code>.</p>
<p>— Function <strong>lib.readfile</strong> <em>filename</em>, <em>what</em></p>
<p>Reads and returns <em>what</em> from file at <em>filename</em>. <em>What</em> must be a valid argument to <code>file:read</code>.</p>
<p>— Function <strong>lib.writefile</strong> <em>filename</em>, <em>value</em></p>
<p>Writes <em>value</em> to file at <em>filename</em> using <code>file:write</code>. Returns the value returned by <code>file:write</code>.</p>
<p>— Function <strong>lib.readlink</strong> <em>filename</em></p>
<p>Returns the true name of symbolic link at <em>filename</em>.</p>
<p>— Function <strong>lib.dirname</strong> <em>filename</em></p>
<p>Returns the <code>dirname(3)</code> of <em>filename</em>.</p>
<p>— Function <strong>lib.basename</strong> <em>filename</em></p>
<p>Returns the <code>basename(3)</code> of <em>filename</em>.</p>
<p>— Function <strong>lib.firstfile</strong> <em>directory</em></p>
<p>Returns the filename of the first file in <em>directory</em>.</p>
<p>— Function <strong>lib.firstline</strong> <em>filename</em></p>
<p>Returns the first line of file at <em>filename</em> as a string.</p>
<p>— Function <strong>lib.load_string</strong> <em>string</em></p>
<p>Evaluates and returns the value of the Lua expression in <em>string</em>.</p>
<p>— Function <strong>lib.load_conf</strong> <em>filename</em></p>
<p>Evaluates and returns the value of the Lua expression in file at <em>filename</em>.</p>
<p>— Function <strong>lib.store_conf</strong> <em>filename</em>, <em>value</em></p>
<p>Writes <em>value</em> to file at <em>filename</em> as a Lua expression. Supports tables, strings and everything that can be readably printed using <code>print</code>.</p>
<p>— Function <strong>lib.bits</strong> <em>bitset</em>, <em>basevalue</em></p>
<p>Returns a bitmask using the values of <em>bitset</em> as indexes. The keys of <em>bitset</em> are ignored (and can be used as comments).</p>
<p>Example:</p>
<pre><code>bits({RESET=0,ENABLE=4}, 123) => 1<<0 | 1<<4 | 123</code></pre>
<p>— Function <strong>lib.bitset</strong> <em>value</em>, <em>n</em></p>
<p>Predicate to test if bit number <em>n</em> of <em>value</em> is set.</p>
<p>— Function <strong>lib.bitfield</strong> <em>size</em>, <em>struct</em>, <em>member</em>, <em>offset</em>, <em>nbits</em>, <em>value</em></p>
<p>Combined accesor and setter function for bit ranges of integers in cdata structs. Sets <em>nbits</em> (number of bits) starting from <em>offset</em> to <em>value</em>. If <em>value</em> is not given the current value is returned.</p>
<p><em>Size</em> may be one of 8, 16 or 32 depending on the bit size of the integer being set or read.</p>
<p><em>Struct</em> must be a pointer to a cdata object and <em>member</em> must be the literal name of a member of <em>struct</em>.</p>
<p>Example:</p>
<pre><code>local struct_t = ffi.typeof[[struct { uint16_t flags; }]]
-- Assuming `s' is an instance of `struct_t', set bits 4-7 to 0xF:
lib.bitfield(16, s, 'flags', 4, 4, 0xf)
-- Get the value:
lib.bitfield(16, s, 'flags', 4, 4) -- => 0xF</code></pre>
<p>— Function <strong>string:split</strong> <em>pattern</em></p>
<p>Returns an iterator over the string split by <em>pattern</em>. <em>Pattern</em> must be a valid argument to <code>string:gmatch</code>.</p>
<p>Example:</p>
<pre><code>for word, sep in ("foo!bar!baz"):split("(!)") do
print(word, sep)
end
> foo !
> bar !
> baz nil</code></pre>
<p>— Function <strong>lib.hexdump</strong> <em>string</em></p>
<p>Returns hexadecimal string for bytes in <em>string</em>.</p>
<p>— Function <strong>lib.hexundump</strong> <em>hexstring</em>, <em>n</em>, <em>error</em></p>
<p>Returns string of <em>n</em> bytes for <em>hexstring</em>. Throws an error if less than <em>n</em> hex-encoded bytes could be parsed unless <em>error</em> is <code>false</code>.</p>
<p><em>Error</em> is optional and can be the error message to throw.</p>
<p>— Function <strong>lib.comma_value</strong> <em>n</em></p>
<p>Returns a string for decimal number <em>n</em> with magnitudes separated by commas. Example:</p>
<pre><code>comma_value(1000000) => "1,000,000"</code></pre>
<p>— Function <strong>lib.random_bytes_from_dev_urandom</strong> <em>length</em></p>
<p>Return <em>length</em> bytes of random data, as a byte array, taken from <code>/dev/urandom</code>. Suitable for cryptographic usage.</p>
<p>— Function <strong>lib.random_bytes_from_math_random</strong> <em>length</em></p>
<p>Return <em>length</em> bytes of random data, as a byte array, where each byte was taken from <code>math.random(0, 255)</code>. <em>Not</em> suitable for cryptographic usage.</p>
<p>— Function <strong>lib.random_bytes</strong> <em>length</em> — Function <strong>lib.randomseed</strong> <em>seed</em></p>
<p>Initialize Snabb’s random number generation facility. If <em>seed</em> is nil, then the Lua <code>math.random()</code> function will be seeded from <code>/dev/urandom</code>, and <code>lib.random_bytes</code> will be initialized to <code>lib.random_bytes_from_dev_urandom</code>. This is Snabb’s default mode of operation.</p>
<p>Sometimes it’s useful to make Snabb use deterministic random numbers. In that case, pass a seed to <strong>lib.randomseed</strong>; Snabb will set <code>lib.random_bytes</code> to <code>lib.random_bytes_from_math_random</code>, and also print out a message to stderr indicating that we are using lower-quality deterministic random numbers.</p>
<p>As part of its initialization process, Snabb will call <code>lib.randomseed</code> with the value of the <code>SNABB_RANDOM_SEED</code> environment variable (if any). Set this environment variable to enable deterministic random numbers.</p>
<p>— Function <strong>lib.bounds_checked</strong> <em>type</em>, <em>base</em>, <em>offset</em>, <em>size</em></p>
<p>Returns a table that acts as a bounds checked wrapper around a C array of <em>type</em> and <em>size</em> starting at <em>base</em> plus <em>offset</em>. <em>Type</em> must be a ctype and the caller must ensure that the allocated memory region at <em>base</em>/<em>offset</em> is at least <code>sizeof(type)*size</code> bytes long.</p>
<p>— Function <strong>lib.throttle</strong> <em>seconds</em></p>
<p>Return a closure that returns <code>true</code> at most once during any <em>seconds</em> (a floating point value) time interval, otherwise false.</p>
<p>— Function <strong>lib.timeout</strong> <em>seconds</em></p>
<p>Returns a closure that returns <code>true</code> if <em>seconds</em> (a floating point value) have elapsed since it was created, otherwise false.</p>
<p>— Function <strong>lib.waitfor</strong> <em>condition</em></p>
<p>Blocks until the function <em>condition</em> returns a true value.</p>
<p>— Function <strong>lib.waitfor2</strong> <em>name</em>, <em>condition</em>, <em>attempts</em>, <em>interval</em></p>
<p>Repeatedly calls the function <em>condition</em> in <em>interval</em> (milliseconds). If <em>condition</em> returns a true value <code>waitfor2</code> returns. If <em>condition</em> does not return a true value after <em>attempts</em> <code>waitfor2</code> raises an error identified by <em>name</em>.</p>
<p>— Function <strong>lib.yesno</strong> <em>flag</em></p>
<p>Returns the string <code>"yes"</code> if <em>flag</em> is a true value and <code>"no"</code> otherwise.</p>
<p>— Function <strong>lib.align</strong> <em>value</em>, <em>size</em></p>
<p>Return the next integer that is a multiple of <em>size</em> starting from <em>value</em>.</p>
<p>— Function <strong>lib.csum</strong> <em>pointer</em>, <em>length</em></p>
<p>Computes and returns the “IP checksum” <em>length</em> bytes starting at <em>pointer</em>.</p>
<p>— Function <strong>lib.update_csum</strong> <em>pointer</em>, <em>length</em>, <em>checksum</em></p>
<p>Returns <em>checksum</em> updated by <em>length</em> bytes starting at <em>pointer</em>. The default of <em>checksum</em> is <code>0LL</code>.</p>
<p>— Function <strong>lib.finish_csum</strong> <em>checksum</em></p>
<p>Returns the finalized <em>checksum</em>.</p>
<p>— Function <strong>lib.malloc</strong> <em>etype</em></p>
<p>Returns a pointer to newly allocated DMA memory for <em>etype</em>.</p>
<p>— Function <strong>lib.deepcopy</strong> <em>object</em></p>
<p>Returns a copy of <em>object</em>. Supports tables as well as ctypes.</p>
<p>— Function <strong>lib.array_copy</strong> <em>array</em></p>
<p>Returns a copy of <em>array</em>. <em>Array</em> must not be a “sparse array”.</p>
<p>— Function <strong>lib.htonl</strong> <em>n</em></p>
<p>— Function <strong>lib.htons</strong> <em>n</em></p>
<p>Host to network byte order conversion functions for 32 and 16 bit integers <em>n</em> respectively. Unsigned.</p>
<p>— Function <strong>lib.ntohl</strong> <em>n</em></p>
<p>— Function <strong>lib.ntohs</strong> <em>n</em></p>
<p>Network to host byte order conversion functions for 32 and 16 bit integers <em>n</em> respectively. Unsigned.</p>
<p>— Function <strong>lib.random_bytes</strong> <em>count</em></p>
<p>Return a fresh array of <em>count</em> random bytes. Suitable for cryptographic usage.</p>
<p>— Function <strong>lib.parse</strong> <em>arg</em>, <em>config</em></p>
<p>Validates <em>arg</em> against the specification in <em>config</em>, and returns a fresh table containing the parameters in <em>arg</em> and any omitted optional parameters with their default values. Given <em>arg</em>, a table of parameters or <code>nil</code>, assert that from <em>config</em> all of the required keys are present, fill in any missing values for optional keys, and error if any unknown keys are found. <em>Config</em> has the following format:</p>
<pre><code>config := { key = {[required=boolean], [default=value]}, ... }</code></pre>
<p>Each key is optional unless <code>required</code> is set to a true value, and its default value defaults to <code>nil</code>.</p>
<p>Example:</p>
<pre><code>lib.parse({foo=42, bar=43}, {foo={required=true}, bar={}, baz={default=44}})
=> {foo=42, bar=43, baz=44}</code></pre>
<ul>
<li>Function <strong>lib.set</strong> <em>vargs</em></li>
</ul>
<p>Reads a variable number of arguments and returns a table representing a set. The returned value can be used to query whether an element belongs or not to the set.</p>
<p>Example:</p>
<pre><code>local t = set('foo', 'bar')
t['foo'] -- yields true.
t['quax'] -- yields false.</code></pre>
<h2 id="multiprocess-operation-core.worker">Multiprocess operation (core.worker)</h2>
<p>Snabb can operate as a <em>group</em> of cooperating processes. The <em>main</em> process is the initial one that you start directly. The optional <em>worker</em> processes are children spawned when the main process calls the <code>core.worker</code> module.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Multiprocessing" />
<p class="caption">Multiprocessing</p>
</div>
<p>Each worker is a complete Snabb process. They can define app networks, run the engine, and do everything else that ordinary Snabb processes do. The exact behavior of each worker is determined by a Lua expression provided upon creation.</p>
<p>Groups of Snabb processes each have the following special properties:</p>
<ul>
<li><strong>Group termination</strong>: Terminating the main process automatically terminates all of the workers. This works for all process termination scenarios including <code>kill -9</code>.</li>
<li><strong>Shared DMA memory</strong>: DMA memory pointers obtained with <code>memory.dma_alloc()</code> are usable by all processes in the group. This means that you can share DMA memory pointers between processes, for example via <code>shm</code> shared memory objects, and reference them from any process. (The memory is automatically mapped at the expected address via a <code>SEGV</code> signal handler.)</li>
<li><strong>PCI device shutdown</strong>: For each PCI device opened by a process within the group, bus mastering (DMA) is disabled upon termination before any DMA memory is returned to the kernel. This prevents “dangling” DMA requests from corrupting memory that has been freed and reused. See <a href="#pci-lib.hardware.pci">lib.hardware.pci</a> for details.</li>
</ul>
<p>The <code>core.worker</code> API functions are available in the main process only:</p>
<p>— Function <strong>worker.start</strong> <em>name</em> <em>luacode</em></p>
<p>Start a named worker process. The worker starts with a completely fresh Snabb process image (<code>fork()+execve()</code>) and then executes the string <em>luacode</em> as a Lua source code expression.</p>
<p>Example:</p>
<pre><code>worker.start("myworker", [[
print("hello world, from a Snabb worker process!")
print("could configure and run the engine now...")
]])</code></pre>
<p>— Function <strong>worker.stop</strong> <em>name</em></p>
<p>Stop a named worker process. The worker is abruptly killed.</p>
<p>Example:</p>
<pre><code>worker.stop("myworker")</code></pre>
<p>— Function <strong>worker.status</strong></p>
<p>Return a table summarizing the status of all workers. The table key is the worker name and the value is a table with <code>pid</code> and <code>alive</code> attributes.</p>
<p>Example:</p>
<pre><code>for w, s in pairs(worker.status()) do
print((" worker %s: pid=%s alive=%s"):format(
w, s.pid, s.alive))
end</code></pre>
<p>Output:</p>
<pre><code>worker w3: pid=21949 alive=true
worker w1: pid=21947 alive=true
worker w2: pid=21948 alive=true</code></pre>
<h2 id="main">Main</h2>
<p>Snabb designs can be run either with:</p>
<pre><code>snabb <snabb-arg>* <design> <design-arg>*</code></pre>
<p>or</p>
<pre><code>#!/usr/bin/env snabb <snabb-arg>*
...</code></pre>
<p>The <em>main</em> module provides an interface for running Snabb scripts. It exposes various operating system functions to scripts.</p>
<p>— Field <strong>main.parameters</strong></p>
<p>A list of command-line arguments to the running script. Read-only.</p>
<p>— Function <strong>main.exit</strong> <em>status</em></p>
<p>Cleanly exits the process with <em>status</em>.</p>
<h1 id="basic-apps-apps.basic.basic_apps">Basic Apps (apps.basic.basic_apps)</h1>
<p>The module <em>apps.basic.basic_apps</em> provides apps with general functionality for use in you app networks.</p>
<h2 id="source">Source</h2>
<p>The <code>Source</code> app is a synthetic packet generator. On each breath it fills each attached output link with new packets. It accepts a number as its configuration argument which is the byte size of the generated packets. By default, each packet is 60 bytes long. The packet data is initialized with zero bytes.</p>
<div class="figure">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAC2CAIAAAAnTsNNAAALMElEQVR42u2deWxN3RqH2xqqaKmxRb+YElJDS8ScoIkhxqLE1IgpRBARTfwnhphFqyFCE0E/IpGgkZ6iNU81t46aa6ga69CWqune+8vdse++5dL6+jnd9zzPX11rr7P3OWuvZ79r7XO6X69/AoBt8aILABAYANwq8D8AwCYgMAACAwACAwACAyAwACAwACAwACAwAAIDAAIDAAIDIDACAyAwACAwACAwAAIDAAIDAAIDAAIDIDAAIDAAIDAAAiMwAAIDAAIDAAIDIDAAIDAAIDAAIDAAAgMAApcHrVu39oKvqDcY3whsJzRqydT+nzPq5VVQUPD27dv3799/+PDh8+fPDHcERmA7CZyTk/P8+XOXyyWN5TDDHYER2E4CX79+/d69e7m5uXK4qKiI4Y7ACGwngc+cOZORkSGHnz17VlhYyHBHYAS2k8AOh0MOO53OR48evXnzhuGOwAhsJ4F379596NChCxcu3L1799WrVwx3BEZgOwm8a9eulJSU8+fP37lzB4ERGIERGBAYgREYEBiBERgQGIEBgREYgQGBERiBAYEBgREYgREYEBiBERgQGIERGBAYgQGBERiBAYERGIEBgRH4/07g0aNHe3t7p6en/4Zj9evXr1KlSk6nE4ERGIHLgdOnT+udjx079vcc7urVq7pYDB48GIERGIHLgcjISONhQL/tiL169dIRs7KyEBiBKwR79uwZMGBAjRo1evbsuWXLFhsJ/PTp08qVKzdr1sxaKZkVkJs2bVqtWjVtmj59el5enrl1/PjxOu9z584NDw9XgxYtWqxevfrLly/G1kWLFmnrrFmzrIfQnLlmzZr5+flGzaZNm9QmJiYGgRHY/Wiwtm3bVg5fuXJlxIgRdevWdTgcdhF4586dOokTJkywVm7dulV2aTZx+PDhtWvXytL27dubj7k2BPb391eDR48eGQFcfxtbHz9+rCtCw4YNP336ZNTExcWpwdSpU839X7t2TTVhYWEIjMBuJjExUYGosLDQrJk5c6ZCll0Enjdvnk7i8uXLf9BGH0dtJLNV4BkzZhjFkydPqjho0KASc/JDhw4Zxe7du6t47tw5s4GuBVWrVvXx8Xn79i0CI7A7kb0awdaas2fPKiDbRWBNlXUSNe23VhYVFa1atapj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" alt="Source" />
<p class="caption">Source</p>
</div>
<h2 id="join">Join</h2>
<p>The <code>Join</code> app joins together packets from N input links onto one output link. On each breath it outputs as many packets as possible from the inputs onto the output.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Join" />
<p class="caption">Join</p>
</div>
<h2 id="split">Split</h2>
<p>The <code>Split</code> app splits packets from multiple inputs across multiple outputs. On each breath it transfers as many packets as possible from the input links to the output links.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Split" />
<p class="caption">Split</p>
</div>
<h2 id="sink">Sink</h2>
<p>The <code>Sink</code> app receives all packets from any number of input links and discards them. This can be handy in combination with a <code>Source</code>.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Sink" />
<p class="caption">Sink</p>
</div>
<h2 id="tee">Tee</h2>
<p>The <code>Tee</code> app receives all packets from any number of input links and transfers each received packet to all output links. It can be used to merge and/or duplicate packet streams</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Tee" />
<p class="caption">Tee</p>
</div>
<h2 id="repeater">Repeater</h2>
<p>The <code>Repeater</code> app collects all packets received from the <code>input</code> link and repeatedly transfers the accumulated packets to the <code>output</code> link. The packets are transmitted in the order they were received.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Repeater" />
<p class="caption">Repeater</p>
</div>
<h2 id="truncate">Truncate</h2>
<p>The <code>Truncate</code> app sends all packets received from the <code>input</code> to the <code>output</code> link and truncates or zero pads each packet to a given length. It accepts a number as its configuration argument which is the length of the truncated or padded packets.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Truncate" />
<p class="caption">Truncate</p>
</div>
<h2 id="sample">Sample</h2>
<p>The <code>Sample</code> app forwards packets every <em>n</em>th packet from the <code>input</code> link to the <code>output</code> link, and drops all others packets. It accepts a number as its configuration argument which is <em>n</em>.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Sample" />
<p class="caption">Sample</p>
</div>
<h1 id="intel-82599-ethernet-controller-apps">Intel 82599 Ethernet Controller Apps</h1>
<h2 id="intel82599-apps.intel.intel_app">Intel82599 (apps.intel.intel_app)</h2>
<p>The <code>Intel82599</code> drives one port of an Intel 82599 Ethernet controller. Packets taken from the <code>rx</code> port are transmitted onto the network. Packets received from the network are put on the <code>tx</code> port.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Intel82599" />
<p class="caption">Intel82599</p>
</div>
<p>— Method <strong>Intel82599.dev:get_rxstats</strong></p>
<p>Returns a table with the following keys:</p>
<ul>
<li><code>counter_id</code> - Counter id</li>
<li><code>packets</code> - Number of packets received</li>
<li><code>dropped</code> - Number of packets dropped</li>
<li><code>bytes</code> - Total bytes received</li>
</ul>
<p>— Method <strong>Intel82599.dev:get_txstats</strong></p>
<p>Returns a table with the following keys:</p>
<ul>
<li><code>counter_id</code> - Counter id</li>
<li><code>packets</code> - Number of packets sent</li>
<li><code>bytes</code> - Total bytes sent</li>
</ul>
<h3 id="configuration">Configuration</h3>
<p>The <code>Intel82599</code> app accepts a table as its configuration argument. The following keys are defined:</p>
<p>— Key <strong>pciaddr</strong></p>
<p><em>Required</em>. The PCI address of the NIC as a string.</p>
<p>— Key <strong>macaddr</strong></p>
<p><em>Optional</em>. The MAC address to use as a string. The default is a wild-card (e.g. accept all packets).</p>
<p>— Key <strong>vlan</strong></p>
<p><em>Optional</em>. A twelve bit integer (0-4095). If set, incoming packets from other VLANs are dropped and outgoing packets are tagged with a VLAN header.</p>
<p>— Key <strong>vmdq</strong></p>
<p><em>Optional</em>. Boolean, defaults to false. Enables interface virtualization. Allows to have multiple <code>Intel82599</code> apps per port. If enabled, <em>macaddr</em> must be specified.</p>
<p>— Key <strong>mirror</strong></p>
<p><em>Optional</em>. A table. If set, this app will receive copies of all selected packets on the physical port. The selection is configured by setting keys of the <em>mirror</em> table. Either <em>mirror.pool</em> or <em>mirror.port</em> may be set.</p>
<p>If <em>mirror.pool</em> is <code>true</code> all pools defined on this physical port are mirrored. If <em>mirror.pool</em> is an array of pool numbers then the specified pools are mirrored.</p>
<p>If <em>mirror.port</em> is one of “in”, “out” or “inout” all incoming and/or outgoing packets on the port are mirrored respectively. Note that this does not include internal traffic which does not enter or exit through the physical port.</p>
<p>— Key <strong>rxcounter</strong></p>
<p>— Key <strong>txcounter</strong></p>
<p><em>Optional</em>. Four bit integers (0-15). If set, incoming/outgoing packets will be counted in the selected statistics counter respectively. Multiple apps can share a counter. To retrieve counter statistics use <code>Intel82599.dev:get_rxstats()</code> and <code>Intel82599.dev:get_txstats()</code>.</p>
<p>— Key <strong>rate_limit</strong></p>
<p><em>Optional</em>. Number. Limits the maximum Mbit/s to transmit. Default is 0 which means no limit. Only applies to outgoing traffic.</p>
<p>— Key <strong>priority</strong></p>
<p><em>Optional</em>. Floating point number. Weight for the <em>round-robin</em> algorithm used to arbitrate transmission when <em>rate_limit</em> is not set or adds up to more than the line rate of the physical port. Default is 1.0 (scaled to the geometric middle of the scale which goes from 1/128 to 128). The absolute value is not relevant, instead only the ratio between competing apps controls their respective bandwidths. Only applies to outgoing traffic.</p>
<p>For example, if two apps without <em>rate_limit</em> set have the same <em>priority</em>, both get the same output bandwidth. If the priorities are 3.0/1.0, the output bandwidth is split 75%/25%. Likewise, 1.0/0.333 or 1.5/0.5 yield the same result.</p>
<p>Note that even a low-priority app can use the whole line rate unless other (higher priority) apps are using up the available bandwidth.</p>
<h3 id="performance">Performance</h3>
<p>The <code>Intel82599</code> app can transmit and receive at approximately 10 Mpps per processor core.</p>
<h3 id="hardware-limits">Hardware limits</h3>
<p>Each physical Intel 82599 port supports the use of up to:</p>
<ul>
<li>64 <em>pools</em> (virtualized <code>Intel82599</code> app instances)</li>
<li>127 MAC addresses (see the <code>macaddr</code> configuration option)</li>
<li>64 VLANs (see the <code>vlan</code> configuration option)</li>
<li>4 <em>mirror pools</em> (see the <code>mirror</code> configuration option)</li>
</ul>
<h2 id="loadgen-apps.intel.loadgen">LoadGen (apps.intel.loadgen)</h2>
<p><code>LoadGen</code> is a <em>load generator</em> app based on the Intel 82599 Ethernet controller. It reads up to 32,000 packets from the <code>input</code> port and transmits them repeatedly onto the network. All incoming packets are dropped.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="LoadGen" />
<p class="caption">LoadGen</p>
</div>
<h3 id="configuration-1">Configuration</h3>
<p>The <code>LoadGen</code> app accepts a string as its configuration argument. The given string denotes the PCI address of the NIC to use.</p>
<h3 id="performance-1">Performance</h3>
<p>The <code>LoadGen</code> app can transmit at line-rate (14 Mpps) without significant CPU usage.</p>
<h1 id="intel-i210-i350-82599-ethernet-controller-apps-apps.intel_mp.intel_mp">Intel i210 / i350 / 82599 Ethernet Controller apps (apps.intel_mp.intel_mp)</h1>
<p>The <code>intel_mp.Intel</code> app provides drivers for Intel i210/i250/82599 based network cards. The driver exposes multiple receive and transmit queues that can be attached to separate instances of the app on different processes.</p>
<p>The links are named <code>input</code> and <code>output</code>.</p>
<div class="figure">
<img src="data:image/png;base64,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" alt="Intel" />
<p class="caption">Intel</p>
</div>
<h2 id="caveats">Caveats</h2>
<p>If attaching multiple processes to a single NIC, performance appears better with <code>engine.busywait = false</code>.</p>
<p>The <code>intel_mp.Intel</code> app can drive an Intel 82599 NIC at 14 million pps.</p>
<p>— Method <strong>Intel:get_rxstats</strong></p>
<p>Returns a table with the following keys:</p>
<ul>
<li><code>counter_id</code> - Counter id</li>
<li><code>packets</code> - Number of packets received</li>
<li><code>dropped</code> - Number of packets dropped</li>
<li><code>bytes</code> - Total bytes received</li>
</ul>
<p>— Method <strong>Intel:get_txstats</strong></p>
<p>Returns a table with the following keys:</p>
<ul>
<li><code>counter_id</code> - Counter id</li>
<li><code>packets</code> - Number of packets sent</li>
<li><code>bytes</code> - Total bytes sent</li>
</ul>
<h2 id="configuration-2">Configuration</h2>
<p>— Key <strong>pciaddr</strong></p>
<p><em>Required</em>. The PCI address of the NIC as a string.</p>
<p>— Key <strong>ndesc</strong></p>
<p><em>Optional</em>. Number of DMA descriptors to use i.e. size of the DMA transmit and receive queues. Must be a multiple of 128. Default is not specified but assumed to be broadly applicable.</p>
<p>— Key <strong>rxq</strong></p>
<p><em>Optional</em>. The receive queue to attach to, numbered from 0. The default is 0. When VMDq is enabled, this number is used to index a queue (0 or 1) for the selected pool. Passing <code>false</code> will disable the receive queue.</p>
<p>— Key <strong>txq</strong></p>
<p><em>Optional</em>. The transmit queue to attach to, numbered from 0. The default is 0. Passing <code>false</code> will disable the transmit queue.</p>
<p>— Key <strong>vmdq</strong></p>
<p><em>Optional</em>. A boolean parameter that specifies whether VMDq (Virtual Machine Device Queues) is enabled. When VMDq is enabled, each instance of the driver is associated with a <em>pool</em> that can be assigned a MAC address or VLAN tag. Packets are delivered to pools that match the corresponding MACs or VLAN tags. Each pool may be associated with several receive and transmit queues.</p>
<p>For a given NIC, all driver instances should have this parameter either enabled or disabled uniformly. If this is enabled, <em>macaddr</em> must be specified.</p>
<p>— Key <strong>vmdq_queueing_mode</strong></p>
<p><em>Optional</em>. Sets the queueing mode to use in VMDq mode. Has no effect when VMDq is disabled. The available queueing modes for the 82599 are <code>"rss-64-2"</code> (the default with 64 pools, 2 queues each) and <code>"rss-32-4"</code> (32 pools, 4 queues each). The i350 provides only a single mode (8 pools, 2 queues each) and hence ignores this option.</p>
<p>— Key <strong>poolnum</strong></p>
<p><em>Optional</em>. The VMDq pool to associate with, numbered from 0. The default is to select a pool number automatically. The maximum pool number depends on the queueing mode.</p>
<p>— Key <strong>macaddr</strong></p>
<p><em>Optional</em>. The MAC address to use as a string. The default is a wild-card (i.e., accept all packets).</p>
<p>— Key <strong>vlan</strong> <em>Optional</em>. A twelve-bit integer (0-4095). If set, incoming packets from other VLANs are dropped and outgoing packets are tagged with a VLAN header.</p>