forked from openvswitch/ovs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathovn.at
6132 lines (5140 loc) · 211 KB
/
ovn.at
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
# OVN_CHECK_PACKETS([PCAP], [EXPECTED])
#
# This compares packets read from PCAP, in pcap format, to those read
# from EXPECTED, which is a text file containing packets as hex
# strings, one per line. If PCAP contains fewer packets than
# EXPECTED, it waits up to 10 seconds for more packets to appear.
#
# The implementation is an m4 macro that is mostly implemented in
# terms of a shell function. This reduces the size of the generated
# testsuite file since the shell function is only emitted once even
# when this macro is invoked many times.
m4_divert_text([PREPARE_TESTS],
[ovn_check_packets__ () {
echo
echo "checking packets in $1 against $2:"
rcv_pcap=$1
rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
exp_text=$2
exp_n=`wc -l < "$exp_text"`
ovs_wait_cond () {
$PYTHON "$top_srcdir/utilities/ovs-pcap.in" $rcv_pcap > $rcv_text
rcv_n=`wc -l < "$rcv_text"`
test $rcv_n -ge $exp_n
}
ovs_wait || echo "expected $exp_n packets, only received $rcv_n"
sort $exp_text > expout
}
])
m4_define([OVN_CHECK_PACKETS],
[ovn_check_packets__ "$1" "$2"
AT_CHECK([sort $rcv_text], [0], [expout])])
AT_BANNER([OVN components])
AT_SETUP([ovn -- lexer])
dnl For lines without =>, input and expected output are identical.
dnl For lines with =>, input precedes => and expected output follows =>.
AT_DATA([test-cases.txt], [dnl
foo bar baz quuxquuxquux _abcd_ a.b.c.d a123_.456
"abc\u0020def" => "abc def"
" => error("Input ends inside quoted string.")dnl "
$foo $bar $baz $quuxquuxquux $_abcd_ $a.b.c.d $a123_.456
$1 => error("`$' must be followed by a valid identifier.") 1
a/*b*/c => a c
a//b c => a
a/**/b => a b
a/*/b => a error("`/*' without matching `*/'.")
a/*/**/b => a b
a/b => a error("`/' is only valid as part of `//' or `/*'.") b
0 1 12345 18446744073709551615
18446744073709551616 => error("Decimal constants must be less than 2**64.")
9999999999999999999999 => error("Decimal constants must be less than 2**64.")
01 => error("Decimal constants must not have leading zeros.")
0/0
0/1
1/0 => error("Value contains unmasked 1-bits.")
1/1
128/384
1/3
1/ => error("Integer constant expected.")
1/0x123 => error("Value and mask have incompatible formats.")
0x1234
0x01234 => 0x1234
0x0 => 0
0x000 => 0
0xfedcba9876543210
0XFEDCBA9876543210 => 0xfedcba9876543210
0xfedcba9876543210fedcba9876543210
0x0000fedcba9876543210fedcba9876543210 => 0xfedcba9876543210fedcba9876543210
0x => error("Hex digits expected following 0x.")
0X => error("Hex digits expected following 0X.")
0x0/0x0 => 0/0
0x0/0x1 => 0/0x1
0x1/0x0 => error("Value contains unmasked 1-bits.")
0xffff/0x1ffff
0x. => error("Invalid syntax in hexadecimal constant.")
192.168.128.1 1.2.3.4 255.255.255.255 0.0.0.0
256.1.2.3 => error("Invalid numeric constant.")
192.168.0.0/16
192.168.0.0/255.255.0.0 => 192.168.0.0/16
192.168.0.0/255.255.255.0 => 192.168.0.0/24
192.168.0.0/255.255.0.255
192.168.0.0/255.0.0.0 => error("Value contains unmasked 1-bits.")
192.168.0.0/32
192.168.0.0/255.255.255.255 => 192.168.0.0/32
1.2.3.4:5 => 1.2.3.4 : 5
::
::1
ff00::1234 => ff00::1234
2001:db8:85a3::8a2e:370:7334
2001:db8:85a3:0:0:8a2e:370:7334 => 2001:db8:85a3::8a2e:370:7334
2001:0db8:85a3:0000:0000:8a2e:0370:7334 => 2001:db8:85a3::8a2e:370:7334
::ffff:192.0.2.128
::ffff:c000:0280 => ::ffff:192.0.2.128
::1/::1
::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff => ::1/128
::1/128
ff00::/8
ff00::/ff00:: => ff00::/8
01:23:45:67:ab:cd
01:23:45:67:AB:CD => 01:23:45:67:ab:cd
fe:dc:ba:98:76:54
FE:DC:ba:98:76:54 => fe:dc:ba:98:76:54
01:00:00:00:00:00/01:00:00:00:00:00
ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
fe:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains unmasked 1-bits.")
fe:x => error("Invalid numeric constant.")
00:01:02:03:04:x => error("Invalid numeric constant.")
# Test that operators are tokenized as expected, even without white space.
(){}[[]]==!=<<=>>=!&&||..,;=<->--: => ( ) { } [[ ]] == != < <= > >= ! && || .. , ; = <-> -- :
& => error("`&' is only valid as part of `&&'.")
| => error("`|' is only valid as part of `||'.")
- => error("`-' is only valid as part of `--'.")
^ => error("Invalid character `^' in input.")
])
AT_CAPTURE_FILE([input.txt])
sed 's/ =>.*//' test-cases.txt > input.txt
sed 's/.* => //' test-cases.txt > expout
AT_CHECK([ovstest test-ovn lex < input.txt], [0], [expout])
AT_CLEANUP
dnl The OVN expression parser needs to know what fields overlap with one
dnl another. This test therefore verifies that all the smaller registers
dnl are defined as terms of subfields of the larger ones.
dnl
dnl When we add or remove registers this test needs to be updated, of course.
AT_SETUP([ovn -- registers])
AT_CHECK([ovstest test-ovn dump-symtab | grep reg | sort], [0],
[[reg0 = xxreg0[96..127]
reg1 = xxreg0[64..95]
reg2 = xxreg0[32..63]
reg3 = xxreg0[0..31]
reg4 = xxreg1[96..127]
reg5 = xxreg1[64..95]
reg6 = xxreg1[32..63]
reg7 = xxreg1[0..31]
reg8 = xreg4[32..63]
reg9 = xreg4[0..31]
xreg0 = xxreg0[64..127]
xreg1 = xxreg0[0..63]
xreg2 = xxreg1[64..127]
xreg3 = xxreg1[0..63]
xreg4 = OXM_OF_PKT_REG4
xxreg0 = NXM_NX_XXREG0
xxreg1 = NXM_NX_XXREG1
]])
AT_CLEANUP
dnl Check that the OVN conntrack field definitions are correct.
AT_SETUP([ovn -- conntrack fields])
AT_CHECK([ovstest test-ovn dump-symtab | grep ^ct | sort], [0],
[[ct.dnat = ct_state[7]
ct.est = ct_state[1]
ct.inv = ct_state[4]
ct.new = ct_state[0]
ct.rel = ct_state[2]
ct.rpl = ct_state[3]
ct.snat = ct_state[6]
ct.trk = ct_state[5]
ct_label = NXM_NX_CT_LABEL
ct_label.blocked = ct_label[0]
ct_mark = NXM_NX_CT_MARK
ct_state = NXM_NX_CT_STATE
]])
AT_CLEANUP
AT_SETUP([ovn -- compsition])
AT_CHECK([ovstest test-ovn composition 2], [0], [ignore])
AT_CLEANUP
AT_SETUP([ovn -- expression parser])
dnl For lines without =>, input and expected output are identical.
dnl For lines with =>, input precedes => and expected output follows =>.
AT_DATA([test-cases.txt], [[
eth.type == 0x800
eth.type==0x800 => eth.type == 0x800
eth.type[0..15] == 0x800 => eth.type == 0x800
vlan.present
vlan.present == 1 => vlan.present
!(vlan.present == 0) => vlan.present
!(vlan.present != 1) => vlan.present
!vlan.present
vlan.present == 0 => !vlan.present
vlan.present != 1 => !vlan.present
!(vlan.present == 1) => !vlan.present
!(vlan.present != 0) => !vlan.present
eth.dst[0]
eth.dst[0] == 1 => eth.dst[0]
eth.dst[0] != 0 => eth.dst[0]
!(eth.dst[0] == 0) => eth.dst[0]
!(eth.dst[0] != 1) => eth.dst[0]
!eth.dst[0]
eth.dst[0] == 0 => !eth.dst[0]
eth.dst[0] != 1 => !eth.dst[0]
!(eth.dst[0] == 1) => !eth.dst[0]
!(eth.dst[0] != 0) => !eth.dst[0]
vlan.tci[12..15] == 0x3
vlan.tci == 0x3000/0xf000 => vlan.tci[12..15] == 0x3
vlan.tci[12..15] != 0x3
vlan.tci != 0x3000/0xf000 => vlan.tci[12..15] != 0x3
!vlan.pcp => vlan.pcp == 0
!(vlan.pcp) => vlan.pcp == 0
vlan.pcp == 0x4
vlan.pcp != 0x4
vlan.pcp > 0x4
vlan.pcp >= 0x4
vlan.pcp < 0x4
vlan.pcp <= 0x4
!(vlan.pcp != 0x4) => vlan.pcp == 0x4
!(vlan.pcp == 0x4) => vlan.pcp != 0x4
!(vlan.pcp <= 0x4) => vlan.pcp > 0x4
!(vlan.pcp < 0x4) => vlan.pcp >= 0x4
!(vlan.pcp >= 0x4) => vlan.pcp < 0x4
!(vlan.pcp > 0x4) => vlan.pcp <= 0x4
0x4 == vlan.pcp => vlan.pcp == 0x4
0x4 != vlan.pcp => vlan.pcp != 0x4
0x4 < vlan.pcp => vlan.pcp > 0x4
0x4 <= vlan.pcp => vlan.pcp >= 0x4
0x4 > vlan.pcp => vlan.pcp < 0x4
0x4 >= vlan.pcp => vlan.pcp <= 0x4
!(0x4 != vlan.pcp) => vlan.pcp == 0x4
!(0x4 == vlan.pcp) => vlan.pcp != 0x4
!(0x4 >= vlan.pcp) => vlan.pcp > 0x4
!(0x4 > vlan.pcp) => vlan.pcp >= 0x4
!(0x4 <= vlan.pcp) => vlan.pcp < 0x4
!(0x4 < vlan.pcp) => vlan.pcp <= 0x4
1 < vlan.pcp < 4 => vlan.pcp > 0x1 && vlan.pcp < 0x4
1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
1 < vlan.pcp <= 4 => vlan.pcp > 0x1 && vlan.pcp <= 0x4
1 <= vlan.pcp < 4 => vlan.pcp >= 0x1 && vlan.pcp < 0x4
1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
4 > vlan.pcp > 1 => vlan.pcp < 0x4 && vlan.pcp > 0x1
4 >= vlan.pcp > 1 => vlan.pcp <= 0x4 && vlan.pcp > 0x1
4 > vlan.pcp >= 1 => vlan.pcp < 0x4 && vlan.pcp >= 0x1
4 >= vlan.pcp >= 1 => vlan.pcp <= 0x4 && vlan.pcp >= 0x1
!(1 < vlan.pcp < 4) => vlan.pcp <= 0x1 || vlan.pcp >= 0x4
!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
!(1 < vlan.pcp <= 4) => vlan.pcp <= 0x1 || vlan.pcp > 0x4
!(1 <= vlan.pcp < 4) => vlan.pcp < 0x1 || vlan.pcp >= 0x4
!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
!(4 > vlan.pcp > 1) => vlan.pcp >= 0x4 || vlan.pcp <= 0x1
!(4 >= vlan.pcp > 1) => vlan.pcp > 0x4 || vlan.pcp <= 0x1
!(4 > vlan.pcp >= 1) => vlan.pcp >= 0x4 || vlan.pcp < 0x1
!(4 >= vlan.pcp >= 1) => vlan.pcp > 0x4 || vlan.pcp < 0x1
vlan.pcp == {1, 2, 3, 4} => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 || vlan.pcp == 0x4
vlan.pcp == 1 || ((vlan.pcp == 2 || vlan.pcp == 3) || vlan.pcp == 4) => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 || vlan.pcp == 0x4
vlan.pcp != {1, 2, 3, 4} => vlan.pcp != 0x1 && vlan.pcp != 0x2 && vlan.pcp != 0x3 && vlan.pcp != 0x4
vlan.pcp == 1 && ((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && vlan.pcp == 0x2 && vlan.pcp == 0x3 && vlan.pcp == 0x4
vlan.pcp == 1 && !((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3 || vlan.pcp != 0x4)
vlan.pcp == 1 && (!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3) && vlan.pcp == 0x4
vlan.pcp == 1 && !(!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && ((vlan.pcp == 0x2 && vlan.pcp == 0x3) || vlan.pcp != 0x4)
ip4.src == {10.0.0.0/8, 192.168.0.0/16, 172.16.20.0/24, 8.8.8.8} => ip4.src[24..31] == 0xa || ip4.src[16..31] == 0xc0a8 || ip4.src[8..31] == 0xac1014 || ip4.src == 0x8080808
ip6.src == ::1 => ip6.src == 0x1
ip4.src == 1.2.3.4 => ip4.src == 0x1020304
ip4.src == ::1.2.3.4/::ffff:ffff => ip4.src == 0x1020304
ip6.src == ::1 => ip6.src == 0x1
1
0
!1 => 0
!0 => 1
inport == "eth0"
!(inport != "eth0") => inport == "eth0"
ip4.src == "eth0" => Integer field ip4.src is not compatible with string constant.
inport == 1 => String field inport is not compatible with integer constant.
ip4.src = 1.2.3.4 => Syntax error at `=' expecting relational operator.
ip4.src > {1, 2, 3} => Only == and != operators may be used with value sets.
eth.type > 0x800 => Only == and != operators may be used with nominal field eth.type.
vlan.present > 0 => Only == and != operators may be used with Boolean field vlan.present.
inport != "eth0" => Nominal field inport may only be tested for equality (taking enclosing `!' operators into account).
!(inport == "eth0") => Nominal field inport may only be tested for equality (taking enclosing `!' operators into account).
eth.type != 0x800 => Nominal field eth.type may only be tested for equality (taking enclosing `!' operators into account).
!(eth.type == 0x800) => Nominal field eth.type may only be tested for equality (taking enclosing `!' operators into account).
inport = "eth0" => Syntax error at `=' expecting relational operator.
123 == 123 => Syntax error at `123' expecting field name.
$name => Syntax error at `$name' expecting address set name.
123 == xyzzy => Syntax error at `xyzzy' expecting field name.
xyzzy == 1 => Syntax error at `xyzzy' expecting field name.
inport[1] == 1 => Cannot select subfield of string field inport.
eth.type[] == 1 => Syntax error at `@:>@' expecting small integer.
eth.type[::1] == 1 => Syntax error at `::1' expecting small integer.
eth.type[18446744073709551615] == 1 => Syntax error at `18446744073709551615' expecting small integer.
eth.type[5!] => Syntax error at `!' expecting `@:>@'.
eth.type[5..1] => Invalid bit range 5 to 1.
eth.type[12..16] => Cannot select bits 12 to 16 of 16-bit field eth.type.
eth.type[10] == 1 => Cannot select subfield of nominal field eth.type.
eth.type => Explicit `!= 0' is required for inequality test of multibit field against 0.
!(!(vlan.pcp)) => Explicit `!= 0' is required for inequality test of multibit field against 0.
123 => Syntax error at end of input expecting relational operator.
123 x => Syntax error at `x' expecting relational operator.
{1, "eth0"} => Syntax error at `"eth0"' expecting integer.
eth.type == xyzzy => Syntax error at `xyzzy' expecting constant.
(1 x) => Syntax error at `x' expecting `)'.
!0x800 != eth.type => Missing parentheses around operand of !.
eth.type == 0x800 || eth.type == 0x86dd && ip.proto == 17 => && and || must be parenthesized when used together.
eth.dst == {} => Syntax error at `}' expecting constant.
eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and != operators may be used with masked constants. Consider using subfields instead (e.g. eth.src[0..15] > 0x1111 in place of eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff).
ip4.src == ::1 => 128-bit constant is not compatible with 32-bit field ip4.src.
1 == eth.type == 2 => Range expressions must have the form `x < field < y' or `x > field > y', with each `<' optionally replaced by `<=' or `>' by `>=').
eth.dst[40] x => Syntax error at `x' expecting end of input.
ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at `$unknownset' expecting address set name.
eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at `badmac' expecting constant.
]])
sed 's/ =>.*//' test-cases.txt > input.txt
sed 's/.* => //' test-cases.txt > expout
AT_CHECK([ovstest test-ovn parse-expr < input.txt], [0], [expout])
AT_CLEANUP
AT_SETUP([ovn -- expression annotation])
dnl Input precedes =>, expected output follows =>.
AT_DATA([test-cases.txt], [[
ip4.src == 1.2.3.4 => ip4.src == 0x1020304 && eth.type == 0x800
ip4.src != 1.2.3.4 => ip4.src != 0x1020304 && eth.type == 0x800
ip.proto == 123 => ip.proto == 0x7b && (eth.type == 0x800 || eth.type == 0x86dd)
ip.proto == {123, 234} => (ip.proto == 0x7b && (eth.type == 0x800 || eth.type == 0x86dd)) || (ip.proto == 0xea && (eth.type == 0x800 || eth.type == 0x86dd))
ip4.src == 1.2.3.4 && ip4.dst == 5.6.7.8 => ip4.src == 0x1020304 && eth.type == 0x800 && ip4.dst == 0x5060708 && eth.type == 0x800
ip => eth.type == 0x800 || eth.type == 0x86dd
ip == 1 => eth.type == 0x800 || eth.type == 0x86dd
ip[0] == 1 => eth.type == 0x800 || eth.type == 0x86dd
ip > 0 => Only == and != operators may be used with nominal field ip.
!ip => Nominal predicate ip may only be tested positively, e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
ip == 0 => Nominal predicate ip may only be tested positively, e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
vlan.present => vlan.tci[12]
!vlan.present => !vlan.tci[12]
!vlan.pcp => vlan.tci[13..15] == 0 && vlan.tci[12]
vlan.pcp == 1 && vlan.vid == 2 => vlan.tci[13..15] == 0x1 && vlan.tci[12] && vlan.tci[0..11] == 0x2 && vlan.tci[12]
!reg0 && !reg1 && !reg2 && !reg3 => xxreg0[96..127] == 0 && xxreg0[64..95] == 0 && xxreg0[32..63] == 0 && xxreg0[0..31] == 0
ip.first_frag => ip.frag[0] && (eth.type == 0x800 || eth.type == 0x86dd) && (!ip.frag[1] || (eth.type != 0x800 && eth.type != 0x86dd))
!ip.first_frag => !ip.frag[0] || (eth.type != 0x800 && eth.type != 0x86dd) || (ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd))
ip.later_frag => ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd)
bad_prereq != 0 => Error parsing expression `xyzzy' encountered as prerequisite or predicate of initial expression: Syntax error at `xyzzy' expecting field name.
self_recurse != 0 => Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `self_recurse'.
mutual_recurse_1 != 0 => Error parsing expression `mutual_recurse_2 != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `mutual_recurse_1 != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `mutual_recurse_1'.
mutual_recurse_2 != 0 => Error parsing expression `mutual_recurse_1 != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `mutual_recurse_2 != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `mutual_recurse_2'.
]])
sed 's/ =>.*//' test-cases.txt > input.txt
sed 's/.* => //' test-cases.txt > expout
AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], [expout])
AT_CLEANUP
AT_SETUP([ovn -- 1-term expression conversion])
AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], [0],
[Tested converting all 1-terminal expressions with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 2 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 2-term expression conversion])
AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], [0],
[Tested converting 578 expressions of 2 terminals with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 2 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 3-term expression conversion])
AT_CHECK([ovstest test-ovn exhaustive --operation=convert --bits=2 3], [0],
[Tested converting 67410 expressions of 3 terminals with 2 numeric vars (each 2 bits) in terms of operators == != < <= > >= and 2 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 3-term numeric expression simplification])
AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=2 --svars=0 3], [0],
[Tested simplifying 490770 expressions of 3 terminals with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >=.
])
AT_CLEANUP
AT_SETUP([ovn -- 4-term string expression simplification])
AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=0 --svars=4 4], [0],
[Tested simplifying 21978 expressions of 4 terminals with 4 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 3-term mixed expression simplification])
AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=1 --svars=1 3], [0],
[Tested simplifying 127890 expressions of 3 terminals with 1 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 1 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- simplification special cases])
simplify() {
echo "$1" | ovstest test-ovn simplify-expr
}
AT_CHECK([simplify 'eth.dst == 0/0'], [0], [1
])
AT_CHECK([simplify 'eth.dst != 0/0'], [0], [0
])
AT_CHECK([simplify 'tcp.dst >= 0'], [0],
[ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
])
AT_CHECK([simplify 'tcp.dst <= 65535'], [0],
[ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
])
AT_CHECK([simplify 'tcp.dst > 0'], [0],
[[(tcp.dst[0] || tcp.dst[1] || tcp.dst[2] || tcp.dst[3] || tcp.dst[4] || tcp.dst[5] || tcp.dst[6] || tcp.dst[7] || tcp.dst[8] || tcp.dst[9] || tcp.dst[10] || tcp.dst[11] || tcp.dst[12] || tcp.dst[13] || tcp.dst[14] || tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
]])
AT_CHECK([simplify 'tcp.dst < 65535'], [0],
[[(!tcp.dst[0] || !tcp.dst[1] || !tcp.dst[2] || !tcp.dst[3] || !tcp.dst[4] || !tcp.dst[5] || !tcp.dst[6] || !tcp.dst[7] || !tcp.dst[8] || !tcp.dst[9] || !tcp.dst[10] || !tcp.dst[11] || !tcp.dst[12] || !tcp.dst[13] || !tcp.dst[14] || !tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
]])
AT_CLEANUP
AT_SETUP([ovn -- 4-term numeric expression normalization])
AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3 --svars=0 --bits=1 4], [0],
[Tested normalizing 1874026 expressions of 4 terminals with 3 numeric vars (each 1 bits) in terms of operators == != < <= > >=.
])
AT_CLEANUP
AT_SETUP([ovn -- 4-term string expression normalization])
AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0 --svars=3 --bits=1 4], [0],
[Tested normalizing 11242 expressions of 4 terminals with 3 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 4-term mixed expression normalization])
AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1 --bits=1 --svars=2 4], [0],
[Tested normalizing 175978 expressions of 4 terminals with 1 numeric vars (each 1 bits) in terms of operators == != < <= > >= and 2 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 5-term numeric expression normalization])
AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3 --svars=0 --bits=1 --relops='==' 5], [0],
[Tested normalizing 1317600 expressions of 5 terminals with 3 numeric vars (each 1 bits) in terms of operators ==.
])
AT_CLEANUP
AT_SETUP([ovn -- 5-term string expression normalization])
AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0 --svars=3 --bits=1 --relops='==' 5], [0],
[Tested normalizing 368550 expressions of 5 terminals with 3 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 5-term mixed expression normalization])
AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1 --svars=1 --bits=1 --relops='==' 5], [0],
[Tested normalizing 216000 expressions of 5 terminals with 1 numeric vars (each 1 bits) in terms of operators == and 1 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 4-term numeric expressions to flows])
AT_KEYWORDS([expression])
AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=2 --svars=0 --bits=2 --relops='==' 4], [0],
[Tested converting to flows 175978 expressions of 4 terminals with 2 numeric vars (each 2 bits) in terms of operators ==.
])
AT_CLEANUP
AT_SETUP([ovn -- 4-term string expressions to flows])
AT_KEYWORDS([expression])
AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=0 --svars=4 4], [0],
[Tested converting to flows 21978 expressions of 4 terminals with 4 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 4-term mixed expressions to flows])
AT_KEYWORDS([expression])
AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=1 --bits=2 --svars=1 --relops='==' 4], [0],
[Tested converting to flows 48312 expressions of 4 terminals with 1 numeric vars (each 2 bits) in terms of operators == and 1 string vars.
])
AT_CLEANUP
AT_SETUP([ovn -- 3-term numeric expressions to flows])
AT_KEYWORDS([expression])
AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=3 --svars=0 --bits=3 --relops='==' 3], [0],
[Tested converting to flows 41328 expressions of 3 terminals with 3 numeric vars (each 3 bits) in terms of operators ==.
])
AT_CLEANUP
AT_SETUP([ovn -- converting expressions to flows -- string fields])
AT_KEYWORDS([expression])
expr_to_flow () {
echo "$1" | ovstest test-ovn expr-to-flows | sort
}
AT_CHECK([expr_to_flow 'inport == "eth0"'], [0], [reg14=0x5
])
AT_CHECK([expr_to_flow 'inport == "eth1"'], [0], [reg14=0x6
])
AT_CHECK([expr_to_flow 'inport == "eth2"'], [0], [(no flows)
])
AT_CHECK([expr_to_flow 'inport == "eth0" && ip'], [0], [dnl
ip,reg14=0x5
ipv6,reg14=0x5
])
AT_CHECK([expr_to_flow 'inport == "eth1" && ip'], [0], [dnl
ip,reg14=0x6
ipv6,reg14=0x6
])
AT_CHECK([expr_to_flow 'inport == "eth2" && ip'], [0], [(no flows)
])
AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2", "LOCAL"}'], [0],
[reg14=0x5
reg14=0x6
reg14=0xfffe
])
AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2"} && ip'], [0], [dnl
ip,reg14=0x5
ip,reg14=0x6
ipv6,reg14=0x5
ipv6,reg14=0x6
])
AT_CHECK([expr_to_flow 'inport == "eth0" && inport == "eth1"'], [0], [dnl
(no flows)
])
AT_CLEANUP
AT_SETUP([ovn -- converting expressions to flows -- address sets])
AT_KEYWORDS([expression])
expr_to_flow () {
echo "$1" | ovstest test-ovn expr-to-flows | sort
}
AT_CHECK([expr_to_flow 'ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3}'], [0], [dnl
ip,nw_src=10.0.0.1
ip,nw_src=10.0.0.2
ip,nw_src=10.0.0.3
])
AT_CHECK([expr_to_flow 'ip4.src == $set1'], [0], [dnl
ip,nw_src=10.0.0.1
ip,nw_src=10.0.0.2
ip,nw_src=10.0.0.3
])
AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set1}'], [0], [dnl
ip,nw_src=1.2.3.4
ip,nw_src=10.0.0.1
ip,nw_src=10.0.0.2
ip,nw_src=10.0.0.3
])
AT_CHECK([expr_to_flow 'ip4.src == {1.2.0.0/20, 5.5.5.0/24, $set1}'], [0], [dnl
ip,nw_src=1.2.0.0/20
ip,nw_src=10.0.0.1
ip,nw_src=10.0.0.2
ip,nw_src=10.0.0.3
ip,nw_src=5.5.5.0/24
])
AT_CHECK([expr_to_flow 'ip6.src == {::1, ::2, ::3}'], [0], [dnl
ipv6,ipv6_src=::1
ipv6,ipv6_src=::2
ipv6,ipv6_src=::3
])
AT_CHECK([expr_to_flow 'ip6.src == {::1, $set2, ::4}'], [0], [dnl
ipv6,ipv6_src=::1
ipv6,ipv6_src=::2
ipv6,ipv6_src=::3
ipv6,ipv6_src=::4
])
AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, 00:00:00:00:00:02, 00:00:00:00:00:03}'], [0], [dnl
dl_src=00:00:00:00:00:01
dl_src=00:00:00:00:00:02
dl_src=00:00:00:00:00:03
])
AT_CHECK([expr_to_flow 'eth.src == {$set3}'], [0], [dnl
dl_src=00:00:00:00:00:01
dl_src=00:00:00:00:00:02
dl_src=00:00:00:00:00:03
])
AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, $set3, ba:be:be:ef:de:ad, $set3}'], [0], [dnl
dl_src=00:00:00:00:00:01
dl_src=00:00:00:00:00:02
dl_src=00:00:00:00:00:03
dl_src=ba:be:be:ef:de:ad
])
AT_CLEANUP
AT_SETUP([ovn -- action parsing])
dnl Unindented text is input (a set of OVN logical actions).
dnl Indented text is expected output.
AT_DATA([test-cases.txt],
[[# drop
drop;
encodes as drop
drop; next;
Syntax error at `next' expecting end of input.
next; drop;
Syntax error at `drop' expecting action.
# output
output;
encodes as resubmit(,64)
# next
next;
formats as next(11);
encodes as resubmit(,27)
next(11);
encodes as resubmit(,27)
next(0);
encodes as resubmit(,16)
next(15);
encodes as resubmit(,31)
next();
Syntax error at `)' expecting small integer.
next(10;
Syntax error at `;' expecting `)'.
next(16);
"next" argument must be in range 0 to 15.
# Loading a constant value.
tcp.dst=80;
formats as tcp.dst = 80;
encodes as set_field:80->tcp_dst
has prereqs ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
eth.dst[40] = 1;
encodes as set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst
vlan.pcp = 2;
encodes as set_field:0x4000/0xe000->vlan_tci
has prereqs vlan.tci[12]
vlan.tci[13..15] = 2;
encodes as set_field:0x4000/0xe000->vlan_tci
inport = "";
encodes as set_field:0->reg14
ip.ttl=4;
formats as ip.ttl = 4;
encodes as set_field:4->nw_ttl
has prereqs eth.type == 0x800 || eth.type == 0x86dd
outport="eth0"; next; outport="LOCAL"; next;
formats as outport = "eth0"; next(11); outport = "LOCAL"; next(11);
encodes as set_field:0x5->reg15,resubmit(,27),set_field:0xfffe->reg15,resubmit(,27)
inport[1] = 1;
Cannot select subfield of string field inport.
ip.proto[1] = 1;
Cannot select subfield of nominal field ip.proto.
eth.dst[40] == 1;
Syntax error at `==' expecting `=' or `<->'.
ip = 1;
Predicate symbol ip used where lvalue required.
ip.proto = 6;
Field ip.proto is not modifiable.
inport = {"a", "b"};
Syntax error at `{' expecting constant.
inport = {};
Syntax error at `{' expecting constant.
bad_prereq = 123;
Error parsing expression `xyzzy' encountered as prerequisite or predicate of initial expression: Syntax error at `xyzzy' expecting field name.
self_recurse = 123;
Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `self_recurse'.
vlan.present = 0;
Predicate symbol vlan.present used where lvalue required.
# Moving one field into another.
reg0=reg1;
formats as reg0 = reg1;
encodes as move:NXM_NX_XXREG0[64..95]->NXM_NX_XXREG0[96..127]
vlan.pcp = reg0[0..2];
encodes as move:NXM_NX_XXREG0[96..98]->NXM_OF_VLAN_TCI[13..15]
has prereqs vlan.tci[12]
reg0[10] = vlan.pcp[1];
encodes as move:NXM_OF_VLAN_TCI[14]->NXM_NX_XXREG0[106]
has prereqs vlan.tci[12]
outport = inport;
encodes as move:NXM_NX_REG14[]->NXM_NX_REG15[]
reg0[0] = vlan.present;
Predicate symbol vlan.present used where lvalue required.
reg0 = reg1[0..10];
Can't assign 11-bit value to 32-bit destination.
inport = reg0;
Can't assign integer field (reg0) to string field (inport).
inport = big_string;
String fields inport and big_string are incompatible for assignment.
ip.proto = reg0[0..7];
Field ip.proto is not modifiable.
# Exchanging fields.
reg0 <-> reg1;
encodes as push:NXM_NX_XXREG0[64..95],push:NXM_NX_XXREG0[96..127],pop:NXM_NX_XXREG0[64..95],pop:NXM_NX_XXREG0[96..127]
vlan.pcp <-> reg0[0..2];
encodes as push:NXM_NX_XXREG0[96..98],push:NXM_OF_VLAN_TCI[13..15],pop:NXM_NX_XXREG0[96..98],pop:NXM_OF_VLAN_TCI[13..15]
has prereqs vlan.tci[12]
reg0[10] <-> vlan.pcp[1];
encodes as push:NXM_OF_VLAN_TCI[14],push:NXM_NX_XXREG0[106],pop:NXM_OF_VLAN_TCI[14],pop:NXM_NX_XXREG0[106]
has prereqs vlan.tci[12]
outport <-> inport;
encodes as push:NXM_NX_REG14[],push:NXM_NX_REG15[],pop:NXM_NX_REG14[],pop:NXM_NX_REG15[]
reg0[0] <-> vlan.present;
Predicate symbol vlan.present used where lvalue required.
reg0 <-> reg1[0..10];
Can't exchange 32-bit field with 11-bit field.
inport <-> reg0;
Can't exchange string field (inport) with integer field (reg0).
inport <-> big_string;
String fields inport and big_string are incompatible for exchange.
ip.proto <-> reg0[0..7];
Field ip.proto is not modifiable.
reg0[0..7] <-> ip.proto;
Field ip.proto is not modifiable.
# TTL decrement.
ip.ttl--;
encodes as dec_ttl
has prereqs ip
ip.ttl
Syntax error at end of input expecting `--'.
# load balancing.
ct_lb;
encodes as ct(table=27,zone=NXM_NX_REG13[0..15],nat)
has prereqs ip
ct_lb();
formats as ct_lb;
encodes as ct(table=27,zone=NXM_NX_REG13[0..15],nat)
has prereqs ip
ct_lb(192.168.1.2:80, 192.168.1.3:80);
encodes as group:1
has prereqs ip
ct_lb(192.168.1.2, 192.168.1.3, );
formats as ct_lb(192.168.1.2, 192.168.1.3);
encodes as group:2
has prereqs ip
ct_lb(192.168.1.2:);
Syntax error at `)' expecting port number.
ct_lb(192.168.1.2:123456);
Syntax error at `123456' expecting port number.
ct_lb(foo);
Syntax error at `foo' expecting IPv4 address.
# ct_next
ct_next;
encodes as ct(table=27,zone=NXM_NX_REG13[0..15])
has prereqs ip
# ct_commit
ct_commit;
encodes as ct(commit,zone=NXM_NX_REG13[0..15])
has prereqs ip
ct_commit();
formats as ct_commit;
encodes as ct(commit,zone=NXM_NX_REG13[0..15])
has prereqs ip
ct_commit(ct_mark=1);
formats as ct_commit(ct_mark=0x1);
encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
has prereqs ip
ct_commit(ct_mark=1/1);
formats as ct_commit(ct_mark=0x1/0x1);
encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark))
has prereqs ip
ct_commit(ct_label=1);
formats as ct_commit(ct_label=0x1);
encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_label))
has prereqs ip
ct_commit(ct_label=1/1);
formats as ct_commit(ct_label=0x1/0x1);
encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_label))
has prereqs ip
ct_commit(ct_mark=1, ct_label=2);
formats as ct_commit(ct_mark=0x1, ct_label=0x2);
encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark,set_field:0x2->ct_label))
has prereqs ip
ct_commit(ct_label=0x01020304050607080910111213141516);
formats as ct_commit(ct_label=0x1020304050607080910111213141516);
encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1020304050607080910111213141516->ct_label))
has prereqs ip
ct_commit(ct_label=0x181716151413121110090807060504030201);
formats as ct_commit(ct_label=0x16151413121110090807060504030201);
encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x16151413121110090807060504030201->ct_label))
has prereqs ip
ct_commit(ct_label=0x1000000000000000000000000000000/0x1000000000000000000000000000000);
encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1000000000000000000000000000000/0x1000000000000000000000000000000->ct_label))
has prereqs ip
ct_commit(ct_label=18446744073709551615);
formats as ct_commit(ct_label=0xffffffffffffffff);
encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0xffffffffffffffff->ct_label))
has prereqs ip
ct_commit(ct_label=18446744073709551616);
Decimal constants must be less than 2**64.
# ct_dnat
ct_dnat;
encodes as ct(table=27,zone=NXM_NX_REG11[0..15],nat)
has prereqs ip
ct_dnat(192.168.1.2);
encodes as ct(commit,table=27,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
has prereqs ip
ct_dnat(192.168.1.2, 192.168.1.3);
Syntax error at `,' expecting `)'.
ct_dnat(foo);
Syntax error at `foo' expecting IPv4 address.
ct_dnat(foo, bar);
Syntax error at `foo' expecting IPv4 address.
ct_dnat();
Syntax error at `)' expecting IPv4 address.
# ct_snat
ct_snat;
encodes as ct(zone=NXM_NX_REG12[0..15],nat)
has prereqs ip
ct_snat(192.168.1.2);
encodes as ct(commit,table=27,zone=NXM_NX_REG12[0..15],nat(src=192.168.1.2))
has prereqs ip
ct_snat(192.168.1.2, 192.168.1.3);
Syntax error at `,' expecting `)'.
ct_snat(foo);
Syntax error at `foo' expecting IPv4 address.
ct_snat(foo, bar);
Syntax error at `foo' expecting IPv4 address.
ct_snat();
Syntax error at `)' expecting IPv4 address.
# arp
arp { eth.dst = ff:ff:ff:ff:ff:ff; output; };
encodes as controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
has prereqs ip4
# get_arp
get_arp(outport, ip4.dst);
encodes as push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[]
has prereqs eth.type == 0x800
get_arp(inport, reg0);
encodes as push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_NX_XXREG0[96..127],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[],pop:NXM_NX_REG15[]
get_arp;
Syntax error at `;' expecting `('.
get_arp();
Syntax error at `)' expecting field name.
get_arp(inport);
Syntax error at `)' expecting `,'.
get_arp(inport ip4.dst);
Syntax error at `ip4.dst' expecting `,'.
get_arp(inport, ip4.dst;
Syntax error at `;' expecting `)'.
get_arp(inport, eth.dst);
Cannot use 48-bit field eth.dst[0..47] where 32-bit field is required.
get_arp(inport, outport);
Cannot use string field outport where numeric field is required.
get_arp(reg0, ip4.dst);
Cannot use numeric field reg0 where string field is required.
# put_arp
put_arp(inport, arp.spa, arp.sha);
encodes as push:NXM_NX_REG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ARP_SHA[],push:NXM_OF_ARP_SPA[],pop:NXM_NX_REG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.01.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_REG0[]
has prereqs eth.type == 0x806 && eth.type == 0x806
# put_dhcp_opts
reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause)
reg2[5] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain="ovn.org");
formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain = "ovn.org");
encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67,pause)
reg0[15] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1},ethernet_encap=1,router_discovery=0);
formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.255.0, mtu = 1400, ip_forward_enable = 1, default_ttl = 121, dns_server = {8.8.8.8, 7.7.7.7}, classless_static_route = {30.0.0.0/24, 10.0.0.4, 40.0.0.0/16, 10.0.0.6, 0.0.0.0/0, 10.0.0.1}, ethernet_encap = 1, router_discovery = 0);
encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00,pause)
reg1[0..1] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
Cannot use 2-bit field reg1[0..1] where 1-bit field is required.
reg1[0] = put_dhcp_opts();
put_dhcp_opts requires offerip to be specified.
reg1[0] = put_dhcp_opts(x = 1.2.3.4, router = 10.0.0.1);
Syntax error at `x' expecting DHCPv4 option name.
reg1[0] = put_dhcp_opts(router = 10.0.0.1);
put_dhcp_opts requires offerip to be specified.
reg1[0] = put_dhcp_opts(offerip=1.2.3.4, "hi");
Syntax error at `"hi"'.
reg1[0] = put_dhcp_opts(offerip=1.2.3.4, xyzzy);
Syntax error at `xyzzy' expecting DHCPv4 option name.
reg1[0] = put_dhcp_opts(offerip="xyzzy");
DHCPv4 option offerip requires numeric value.
reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain=1.2.3.4);
DHCPv4 option domain requires string value.
# nd_na
nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending out inport. */ output; };
formats as nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
encodes as controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
has prereqs nd_ns
# get_nd
get_nd(outport, ip6.dst);
encodes as push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],pop:NXM_NX_XXREG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_XXREG0[]
has prereqs eth.type == 0x86dd
get_nd(inport, xxreg0);
encodes as push:NXM_NX_REG15[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG15[]
get_nd;
Syntax error at `;' expecting `('.
get_nd();
Syntax error at `)' expecting field name.
get_nd(inport);
Syntax error at `)' expecting `,'.
get_nd(inport ip6.dst);
Syntax error at `ip6.dst' expecting `,'.
get_nd(inport, ip6.dst;
Syntax error at `;' expecting `)'.
get_nd(inport, eth.dst);
Cannot use 48-bit field eth.dst[0..47] where 128-bit field is required.
get_nd(inport, outport);
Cannot use string field outport where numeric field is required.
get_nd(xxreg0, ip6.dst);
Cannot use numeric field xxreg0 where string field is required.
# put_nd
put_nd(inport, nd.target, nd.sll);
encodes as push:NXM_NX_XXREG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ND_SLL[],push:NXM_NX_ND_TARGET[],pop:NXM_NX_XXREG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.04.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_XXREG0[]
has prereqs ((icmp6.type == 0x87 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd)) || (icmp6.type == 0x88 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd))) && icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.type == 0x87 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd)
# put_dhcpv6_opts
reg1[0] = put_dhcpv6_opts(ia_addr = ae70::4, server_id = 00:00:00:00:10:02);
encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.02.00.06.00.00.00.00.10.02,pause)
reg1[0] = put_dhcpv6_opts();
encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40,pause)
reg1[0] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
formats as reg1[0] = put_dhcpv6_opts(dns_server = {ae70::1, ae70::2});
encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
reg1[0] = put_dhcpv6_opts(server_id=12:34:56:78:9a:bc, dns_server={ae70::1,ae89::2});
formats as reg1[0] = put_dhcpv6_opts(server_id = 12:34:56:78:9a:bc, dns_server = {ae70::1, ae89::2});
encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.02.00.06.12.34.56.78.9a.bc.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.89.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
reg1[0] = put_dhcpv6_opts(domain_search = "ovn.org");
encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.18.00.07.6f.76.6e.2e.6f.72.67,pause)
reg1[0] = put_dhcpv6_opts(x = 1.2.3.4);
Syntax error at `x' expecting DHCPv6 option name.
reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, "hi");
Syntax error at `"hi"'.
reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, xyzzy);
Syntax error at `xyzzy' expecting DHCPv6 option name.
reg1[0] = put_dhcpv6_opts(ia_addr="ae70::4");
DHCPv6 option ia_addr requires numeric value.
reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, domain_search=ae70::1);
DHCPv6 option domain_search requires string value.
# set_queue
set_queue(0);
encodes as set_queue:0
set_queue(61440);
encodes as set_queue:61440
set_queue(65535);
Queue ID 65535 for set_queue is not in valid range 0 to 61440.
# Contradictionary prerequisites (allowed but not useful):
ip4.src = ip6.src[0..31];
encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]
has prereqs eth.type == 0x800 && eth.type == 0x86dd
ip4.src <-> ip6.src[0..31];
encodes as push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[]
has prereqs eth.type == 0x800 && eth.type == 0x86dd
# Miscellaneous negative tests.
;
Syntax error at `;'.
xyzzy;
Syntax error at `xyzzy' expecting action.
next; 123;
Syntax error at `123'.
next; xyzzy;
Syntax error at `xyzzy' expecting action.
next