summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-05-08 13:08:45 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-05-11 12:17:45 +0200
commitd196dccf1853039656f15c8da94ad349a3b7d07c (patch)
treeada3c2446bd764efd12fed37ea7a9bc16ab4b328 /tests
parent875232bc3e6bf55cc31f3763449503a80a7c2382 (diff)
tests/py: Support testing JSON input and output as well
This extends nft-test.py by optional JSON testing capabilities, activated via '-j'/'--enable-json' parameter). JSON testing happens for all rules which are supposed to work: After a rule has been added and the existing tests (payload, ruleset listing output) have been performed, basically the same test is done again using a recorded JSON equivalent and (if necessary) a recorded listing output. The code tries to ease new test case creation overhead by auto-generating JSON equivalent input via listing the (non-JSON) rule in JSON format. Also, differing netlink debug and listing output are stored in *.got files to assist in analyzing/fixing failing test cases. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/py/any/ct.t.json1352
-rw-r--r--tests/py/any/ct.t.json.output575
-rw-r--r--tests/py/any/dup.t.json30
-rw-r--r--tests/py/any/fwd.t.json32
-rw-r--r--tests/py/any/fwd.t.json.output25
-rw-r--r--tests/py/any/limit.t.json374
-rw-r--r--tests/py/any/log.t.json169
-rw-r--r--tests/py/any/log.t.json.output16
-rw-r--r--tests/py/any/meta.t.json2418
-rw-r--r--tests/py/any/meta.t.json.output577
-rw-r--r--tests/py/any/queue.t.json86
-rw-r--r--tests/py/any/queue.t.json.output9
-rw-r--r--tests/py/any/quota.t.json136
-rw-r--r--tests/py/any/rawpayload.t.json157
-rw-r--r--tests/py/any/rawpayload.t.json.output104
-rw-r--r--tests/py/any/rt.t.json14
-rw-r--r--tests/py/arp/arp.t.json877
-rw-r--r--tests/py/arp/arp.t.json.output148
-rw-r--r--tests/py/bridge/ether.t.json180
-rw-r--r--tests/py/bridge/ether.t.json.output77
-rw-r--r--tests/py/bridge/icmpX.t.json82
-rw-r--r--tests/py/bridge/icmpX.t.json.output52
-rw-r--r--tests/py/bridge/meta.t.json23
-rw-r--r--tests/py/bridge/reject.t.json221
-rw-r--r--tests/py/bridge/reject.t.json.output260
-rw-r--r--tests/py/bridge/vlan.t.json468
-rw-r--r--tests/py/inet/ah.t.json557
-rw-r--r--tests/py/inet/comp.t.json316
-rw-r--r--tests/py/inet/comp.t.json.output166
-rw-r--r--tests/py/inet/ct.t.json39
-rw-r--r--tests/py/inet/ct.t.json.output16
-rw-r--r--tests/py/inet/dccp.t.json340
-rw-r--r--tests/py/inet/dccp.t.json.output17
-rw-r--r--tests/py/inet/esp.t.json256
-rw-r--r--tests/py/inet/ether-ip.t.json85
-rw-r--r--tests/py/inet/ether-ip.t.json.output40
-rw-r--r--tests/py/inet/ether.t.json84
-rw-r--r--tests/py/inet/ether.t.json.output29
-rw-r--r--tests/py/inet/fib.t.json128
-rw-r--r--tests/py/inet/fib.t.json.output39
-rw-r--r--tests/py/inet/icmpX.t.json116
-rw-r--r--tests/py/inet/icmpX.t.json.output86
-rw-r--r--tests/py/inet/ip.t.json41
-rw-r--r--tests/py/inet/ip_tcp.t.json158
-rw-r--r--tests/py/inet/ip_tcp.t.json.output121
-rw-r--r--tests/py/inet/map.t.json66
-rw-r--r--tests/py/inet/map.t.json.output66
-rw-r--r--tests/py/inet/meta.t.json198
-rw-r--r--tests/py/inet/meta.t.json.output35
-rw-r--r--tests/py/inet/reject.t.json240
-rw-r--r--tests/py/inet/reject.t.json.output224
-rw-r--r--tests/py/inet/rt.t.json56
-rw-r--r--tests/py/inet/rt.t.json.output23
-rw-r--r--tests/py/inet/sctp.t.json594
-rw-r--r--tests/py/inet/tcp.t.json1552
-rw-r--r--tests/py/inet/tcp.t.json.output134
-rw-r--r--tests/py/inet/tcpopt.t.json418
-rw-r--r--tests/py/inet/tcpopt.t.json.output30
-rw-r--r--tests/py/inet/udp.t.json730
-rw-r--r--tests/py/inet/udplite.t.json526
-rw-r--r--tests/py/ip/ct.t.json213
-rw-r--r--tests/py/ip/ct.t.json.output25
-rw-r--r--tests/py/ip/dnat.t.json255
-rw-r--r--tests/py/ip/dnat.t.json.output65
-rw-r--r--tests/py/ip/dup.t.json46
-rw-r--r--tests/py/ip/ether.t.json151
-rw-r--r--tests/py/ip/ether.t.json.output40
-rw-r--r--tests/py/ip/flowtable.t.json23
-rw-r--r--tests/py/ip/hash.t.json230
-rw-r--r--tests/py/ip/icmp.t.json1382
-rw-r--r--tests/py/ip/icmp.t.json.output85
-rw-r--r--tests/py/ip/ip.t.json1781
-rw-r--r--tests/py/ip/ip.t.json.output226
-rw-r--r--tests/py/ip/ip_tcp.t.json60
-rw-r--r--tests/py/ip/ip_tcp.t.json.output49
-rw-r--r--tests/py/ip/masquerade.t.json411
-rw-r--r--tests/py/ip/masquerade.t.json.output118
-rw-r--r--tests/py/ip/meta.t.json99
-rw-r--r--tests/py/ip/meta.t.json.output45
-rw-r--r--tests/py/ip/numgen.t.json99
-rw-r--r--tests/py/ip/numgen.t.json.output82
-rw-r--r--tests/py/ip/objects.t.json185
-rw-r--r--tests/py/ip/objects.t.json.output64
-rw-r--r--tests/py/ip/redirect.t.json610
-rw-r--r--tests/py/ip/redirect.t.json.output140
-rw-r--r--tests/py/ip/reject.t.json94
-rw-r--r--tests/py/ip/reject.t.json.output24
-rw-r--r--tests/py/ip/rt.t.json15
-rw-r--r--tests/py/ip/sets.t.json185
-rw-r--r--tests/py/ip/snat.t.json161
-rw-r--r--tests/py/ip/snat.t.json.output69
-rw-r--r--tests/py/ip/tcp.t.json59
-rw-r--r--tests/py/ip/tcp.t.json.output48
-rw-r--r--tests/py/ip/tcpopt.t.json390
-rw-r--r--tests/py/ip/tcpopt.t.json.output15
-rw-r--r--tests/py/ip6/dnat.t.json75
-rw-r--r--tests/py/ip6/dst.t.json386
-rw-r--r--tests/py/ip6/dst.t.json.output86
-rw-r--r--tests/py/ip6/dup.t.json46
-rw-r--r--tests/py/ip6/ether.t.json151
-rw-r--r--tests/py/ip6/ether.t.json.output40
-rw-r--r--tests/py/ip6/exthdr.t.json172
-rw-r--r--tests/py/ip6/exthdr.t.json.output56
-rw-r--r--tests/py/ip6/flowtable.t.json60
-rw-r--r--tests/py/ip6/frag.t.json624
-rw-r--r--tests/py/ip6/frag.t.json.output114
-rw-r--r--tests/py/ip6/hbh.t.json386
-rw-r--r--tests/py/ip6/hbh.t.json.output66
-rw-r--r--tests/py/ip6/icmpv6.t.json1257
-rw-r--r--tests/py/ip6/icmpv6.t.json.output92
-rw-r--r--tests/py/ip6/ip6.t.json1613
-rw-r--r--tests/py/ip6/ip6.t.json.output361
-rw-r--r--tests/py/ip6/map.t.json38
-rw-r--r--tests/py/ip6/map.t.json.output38
-rw-r--r--tests/py/ip6/masquerade.t.json405
-rw-r--r--tests/py/ip6/masquerade.t.json.output94
-rw-r--r--tests/py/ip6/meta.t.json99
-rw-r--r--tests/py/ip6/meta.t.json.output45
-rw-r--r--tests/py/ip6/mh.t.json781
-rw-r--r--tests/py/ip6/mh.t.json.output86
-rw-r--r--tests/py/ip6/redirect.t.json576
-rw-r--r--tests/py/ip6/redirect.t.json.output140
-rw-r--r--tests/py/ip6/reject.t.json84
-rw-r--r--tests/py/ip6/reject.t.json.output24
-rw-r--r--tests/py/ip6/rt.t.json717
-rw-r--r--tests/py/ip6/rt.t.json.output86
-rw-r--r--tests/py/ip6/rt0.t.json15
-rw-r--r--tests/py/ip6/sets.t.json91
-rw-r--r--tests/py/ip6/snat.t.json52
-rw-r--r--tests/py/ip6/srh.t.json183
-rw-r--r--tests/py/ip6/srh.t.json.output21
-rw-r--r--tests/py/ip6/tcpopt.t.json390
-rw-r--r--tests/py/ip6/tcpopt.t.json.output15
-rw-r--r--tests/py/ip6/vmap.t.json1037
-rw-r--r--tests/py/ip6/vmap.t.json.output336
-rwxr-xr-xtests/py/nft-test.py186
136 files changed, 34651 insertions, 5 deletions
diff --git a/tests/py/any/ct.t.json b/tests/py/any/ct.t.json
new file mode 100644
index 00000000..83f1bbbd
--- /dev/null
+++ b/tests/py/any/ct.t.json
@@ -0,0 +1,1352 @@
+# ct state new,established, related, untracked
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": [
+ "new",
+ "established",
+ "related",
+ "untracked"
+ ]
+ }
+ }
+]
+
+# ct state != related
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "!=",
+ "right": "related"
+ }
+ }
+]
+
+# ct state {new,established, related, untracked}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": {
+ "set": [
+ "new",
+ "established",
+ "related",
+ "untracked"
+ ]
+ }
+ }
+ }
+]
+
+# ct state != {new,established, related, untracked}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "new",
+ "established",
+ "related",
+ "untracked"
+ ]
+ }
+ }
+ }
+]
+
+# ct state invalid drop
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": "invalid"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ct state established accept
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": "established"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ct state 8
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": 8
+ }
+ }
+]
+
+# ct direction original
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "right": "original"
+ }
+ }
+]
+
+# ct direction != original
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "!=",
+ "right": "original"
+ }
+ }
+]
+
+# ct direction reply
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "right": "reply"
+ }
+ }
+]
+
+# ct direction != reply
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "!=",
+ "right": "reply"
+ }
+ }
+]
+
+# ct direction {reply, original}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "right": {
+ "set": [
+ "reply",
+ "original"
+ ]
+ }
+ }
+ }
+]
+
+# ct direction != {reply, original}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "reply",
+ "original"
+ ]
+ }
+ }
+ }
+]
+
+# ct status expected
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "right": "expected"
+ }
+ }
+]
+
+# ct status != expected
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "!=",
+ "right": "expected"
+ }
+ }
+]
+
+# ct status seen-reply
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "right": "seen-reply"
+ }
+ }
+]
+
+# ct status != seen-reply
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "!=",
+ "right": "seen-reply"
+ }
+ }
+]
+
+# ct status {expected, seen-reply, assured, confirmed, dying}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "right": {
+ "set": [
+ "expected",
+ "seen-reply",
+ "assured",
+ "confirmed",
+ "dying"
+ ]
+ }
+ }
+ }
+]
+
+# ct status expected,seen-reply,assured,confirmed,snat,dnat,dying
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "right": [
+ "expected",
+ "seen-reply",
+ "assured",
+ "confirmed",
+ "snat",
+ "dnat",
+ "dying"
+ ]
+ }
+ }
+]
+
+# ct status snat
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "right": "snat"
+ }
+ }
+]
+
+# ct status dnat
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "right": "dnat"
+ }
+ }
+]
+
+# ct mark 0
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# ct mark or 0x23 == 0x11
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "0x23"
+ ]
+ },
+ "op": "==",
+ "right": "0x11"
+ }
+ }
+]
+
+# ct mark or 0x3 != 0x1
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "0x3"
+ ]
+ },
+ "op": "!=",
+ "right": "0x1"
+ }
+ }
+]
+
+# ct mark and 0x23 == 0x11
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "0x23"
+ ]
+ },
+ "op": "==",
+ "right": "0x11"
+ }
+ }
+]
+
+# ct mark and 0x3 != 0x1
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "0x3"
+ ]
+ },
+ "op": "!=",
+ "right": "0x1"
+ }
+ }
+]
+
+# ct mark xor 0x23 == 0x11
+[
+ {
+ "match": {
+ "left": {
+ "^": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "0x23"
+ ]
+ },
+ "right": "0x11"
+ }
+ }
+]
+
+# ct mark xor 0x3 != 0x1
+[
+ {
+ "match": {
+ "left": {
+ "^": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "0x3"
+ ]
+ },
+ "op": "!=",
+ "right": "0x1"
+ }
+ }
+]
+
+# ct mark 0x00000032
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": "0x00000032"
+ }
+ }
+]
+
+# ct mark != 0x00000032
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": "0x00000032"
+ }
+ }
+]
+
+# ct mark 0x00000032-0x00000045
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "range": [ "0x00000032", "0x00000045" ]
+ }
+ }
+ }
+]
+
+# ct mark != 0x00000032-0x00000045
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "0x00000032", "0x00000045" ]
+ }
+ }
+ }
+]
+
+# ct mark {0x32, 0x2222, 0x42de3}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "set": [
+ "0x32",
+ "0x2222",
+ "0x42de3"
+ ]
+ }
+ }
+ }
+]
+
+# ct mark {0x32-0x2222, 0x4444-0x42de3}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "set": [
+ {
+ "range": [ "0x32", "0x2222" ]
+ },
+ {
+ "range": [ "0x4444", "0x42de3" ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct mark != {0x32, 0x2222, 0x42de3}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "0x32",
+ "0x2222",
+ "0x42de3"
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set 0x11 xor 0x1331
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": { "^": [ "0x11", "0x1331" ] }
+ }
+ }
+]
+
+# ct mark set 0x11333 and 0x11
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": { "&": [ "0x11333", "0x11" ] }
+ }
+ }
+]
+
+# ct mark set 0x12 or 0x11
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": { "|": [ "0x12", "0x11" ] }
+ }
+ }
+]
+
+# ct mark set 0x11
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": "0x11"
+ }
+ }
+]
+
+# ct mark set mark
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "meta": "mark"
+ }
+ }
+ }
+]
+
+# ct mark set mark map { 1 : 10, 2 : 20, 3 : 30 }
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "map": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": {
+ "set": [
+ [ 1, 10 ],
+ [ 2, 20 ],
+ [ 3, 30 ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# ct expiration 30
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "right": 30
+ }
+ }
+]
+
+# ct expiration 22
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ct expiration != 233
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ct expiration 33-45
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ct expiration != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ct expiration {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ct expiration != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ct expiration {33-55}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "right": {
+ "set": [
+ {
+ "range": [ 33, 55 ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct expiration != {33-55}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ {
+ "range": [ 33, 55 ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct helper "ftp"
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "helper"
+ }
+ },
+ "right": "ftp"
+ }
+ }
+]
+
+# ct state . ct mark { new . 0x12345678}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "new",
+ "0x12345678"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct state . ct mark { new . 0x12345678, new . 0x34127856, established . 0x12785634}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ { "concat": [ "new", "0x12345678" ] },
+ { "concat": [ "new", "0x34127856" ] },
+ { "concat": [ "established", "0x12785634" ] }
+ ]
+ }
+ }
+ }
+]
+
+# ct direction . ct mark { original . 0x12345678}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "original",
+ "0x12345678"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct state . ct mark vmap { new . 0x12345678 : drop}
+[
+ {
+ "map": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ [
+ {
+ "concat": [
+ "new",
+ "0x12345678"
+ ]
+ },
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ct original bytes > 100000
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "bytes"
+ }
+ },
+ "op": ">",
+ "right": 100000
+ }
+ }
+]
+
+# ct reply packets < 100
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "packets"
+ }
+ },
+ "op": "<",
+ "right": 100
+ }
+ }
+]
+
+# ct bytes > 100000
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "bytes"
+ }
+ },
+ "op": ">",
+ "right": 100000
+ }
+ }
+]
+
+# ct avgpkt > 200
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "avgpkt"
+ }
+ },
+ "op": ">",
+ "right": 200
+ }
+ }
+]
+
+# ct original avgpkt < 500
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "avgpkt"
+ }
+ },
+ "op": "<",
+ "right": 500
+ }
+ }
+]
+
+# ct event set new
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "right": "new"
+ }
+ }
+]
+
+# ct event set new | related | destroy | label
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "right": [
+ "new",
+ "related",
+ "destroy",
+ "label"
+ ]
+ }
+ }
+]
+
+# ct event set new,related,destroy,label
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "right": [
+ "new",
+ "related",
+ "destroy",
+ "label"
+ ]
+ }
+ }
+]
+
+# ct event set new,destroy
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "right": [
+ "new",
+ "destroy"
+ ]
+ }
+ }
+]
+
+# ct event set 1
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# ct event set 0x0
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "right": "0x0"
+ }
+ }
+]
+
+# ct label 127
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "label"
+ }
+ },
+ "right": 127
+ }
+ }
+]
+
+# ct label set 127
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "label"
+ }
+ },
+ "right": 127
+ }
+ }
+]
+
+# ct zone 0
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "zone"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# ct zone 23
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "zone"
+ }
+ },
+ "right": 23
+ }
+ }
+]
+
+# ct original zone 1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "zone"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# ct reply zone 1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "zone"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# ct zone set 1
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "zone"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# ct original zone set 1
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "zone"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# ct reply zone set 1
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "zone"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# ct zone set mark map { 1 : 1, 2 : 2 }
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "zone"
+ }
+ },
+ "right": {
+ "map": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": {
+ "set": [
+ [ 1, 1 ],
+ [ 2, 2 ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# notrack
+[
+ {
+ "notrack": null
+ }
+]
+
diff --git a/tests/py/any/ct.t.json.output b/tests/py/any/ct.t.json.output
new file mode 100644
index 00000000..01dbb486
--- /dev/null
+++ b/tests/py/any/ct.t.json.output
@@ -0,0 +1,575 @@
+# ct state new,established, related, untracked
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": [
+ "established",
+ "related",
+ "new",
+ "untracked"
+ ]
+ }
+ }
+]
+
+# ct state {new,established, related, untracked}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": {
+ "set": [
+ "established",
+ "related",
+ "new",
+ "untracked"
+ ]
+ }
+ }
+ }
+]
+
+# ct state != {new,established, related, untracked}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "established",
+ "related",
+ "new",
+ "untracked"
+ ]
+ }
+ }
+ }
+]
+
+# ct state 8
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": "new"
+ }
+ }
+]
+
+# ct direction {reply, original}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "right": {
+ "set": [
+ "original",
+ "reply"
+ ]
+ }
+ }
+ }
+]
+
+# ct direction != {reply, original}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "original",
+ "reply"
+ ]
+ }
+ }
+ }
+]
+
+# ct mark or 0x23 == 0x11
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ 35
+ ]
+ },
+ "op": "==",
+ "right": 17
+ }
+ }
+]
+
+# ct mark or 0x3 != 0x1
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ 3
+ ]
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# ct mark and 0x23 == 0x11
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ 35
+ ]
+ },
+ "op": "==",
+ "right": 17
+ }
+ }
+]
+
+# ct mark and 0x3 != 0x1
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ 3
+ ]
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# ct mark xor 0x23 == 0x11
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": 50
+ }
+ }
+]
+
+# ct mark xor 0x3 != 0x1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": 2
+ }
+ }
+]
+
+# ct mark 0x00000032
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": 50
+ }
+ }
+]
+
+# ct mark != 0x00000032
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": 50
+ }
+ }
+]
+
+# ct mark 0x00000032-0x00000045
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "range": [ 50, 69 ]
+ }
+ }
+ }
+]
+
+# ct mark != 0x00000032-0x00000045
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 69 ]
+ }
+ }
+ }
+]
+
+# ct mark {0x32, 0x2222, 0x42de3}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "set": [
+ 50,
+ 8738,
+ 273891
+ ]
+ }
+ }
+ }
+]
+
+# ct mark {0x32-0x2222, 0x4444-0x42de3}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 50, 8738 ] },
+ { "range": [ 17476, 273891 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ct mark != {0x32, 0x2222, 0x42de3}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 50,
+ 8738,
+ 273891
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set 0x11 xor 0x1331
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": 4896
+ }
+ }
+]
+
+# ct mark set 0x11333 and 0x11
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": 17
+ }
+ }
+]
+
+# ct mark set 0x12 or 0x11
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": 19
+ }
+ }
+]
+
+# ct mark set 0x11
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": 17
+ }
+ }
+]
+
+# ct state . ct mark { new . 0x12345678}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "new",
+ 305419896
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct state . ct mark { new . 0x12345678, new . 0x34127856, established . 0x12785634}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "established",
+ 309876276
+ ]
+ },
+ {
+ "concat": [
+ "new",
+ 305419896
+ ]
+ },
+ {
+ "concat": [
+ "new",
+ 873625686
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct direction . ct mark { original . 0x12345678}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "original",
+ 305419896
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct state . ct mark vmap { new . 0x12345678 : drop}
+[
+ {
+ "map": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ [
+ {
+ "concat": [
+ "new",
+ 305419896
+ ]
+ },
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ct event set 1
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "right": "new"
+ }
+ }
+]
+
+# ct event set 0x0
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
diff --git a/tests/py/any/dup.t.json b/tests/py/any/dup.t.json
new file mode 100644
index 00000000..5927f7ea
--- /dev/null
+++ b/tests/py/any/dup.t.json
@@ -0,0 +1,30 @@
+# dup to "lo"
+[
+ {
+ "dup": {
+ "addr": "lo"
+ }
+ }
+]
+
+# dup to mark map { 0x00000001 : "lo", 0x00000002 : "lo"}
+[
+ {
+ "dup": {
+ "addr": {
+ "map": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": {
+ "set": [
+ [ 1, "lo" ],
+ [ 2, "lo" ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/any/fwd.t.json b/tests/py/any/fwd.t.json
new file mode 100644
index 00000000..644d6d48
--- /dev/null
+++ b/tests/py/any/fwd.t.json
@@ -0,0 +1,32 @@
+# fwd to "lo"
+[
+ {
+ "fwd": "lo"
+ }
+]
+
+# fwd to mark map { 0x00000001 : "lo", 0x00000002 : "lo"}
+[
+ {
+ "fwd": {
+ "map": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": {
+ "set": [
+ [
+ "0x00000001",
+ "lo"
+ ],
+ [
+ "0x00000002",
+ "lo"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/any/fwd.t.json.output b/tests/py/any/fwd.t.json.output
new file mode 100644
index 00000000..5a943567
--- /dev/null
+++ b/tests/py/any/fwd.t.json.output
@@ -0,0 +1,25 @@
+# fwd to mark map { 0x00000001 : "lo", 0x00000002 : "lo"}
+[
+ {
+ "fwd": {
+ "map": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": {
+ "set": [
+ [
+ 1,
+ "lo"
+ ],
+ [
+ 2,
+ "lo"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/any/limit.t.json b/tests/py/any/limit.t.json
new file mode 100644
index 00000000..8bab7e3d
--- /dev/null
+++ b/tests/py/any/limit.t.json
@@ -0,0 +1,374 @@
+# limit rate 400/minute
+[
+ {
+ "limit": {
+ "per": "minute",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate 20/second
+[
+ {
+ "limit": {
+ "per": "second",
+ "rate": 20
+ }
+ }
+]
+
+# limit rate 400/hour
+[
+ {
+ "limit": {
+ "per": "hour",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate 40/day
+[
+ {
+ "limit": {
+ "per": "day",
+ "rate": 40
+ }
+ }
+]
+
+# limit rate 400/week
+[
+ {
+ "limit": {
+ "per": "week",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate 1023/second burst 10 packets
+[
+ {
+ "limit": {
+ "burst": 10,
+ "per": "second",
+ "rate": 1023
+ }
+ }
+]
+
+# limit rate 1 kbytes/second
+[
+ {
+ "limit": {
+ "per": "second",
+ "rate": 1,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 2 kbytes/second
+[
+ {
+ "limit": {
+ "per": "second",
+ "rate": 2,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 1025 kbytes/second
+[
+ {
+ "limit": {
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 1023 mbytes/second
+[
+ {
+ "limit": {
+ "per": "second",
+ "rate": 1023,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate 10230 mbytes/second
+[
+ {
+ "limit": {
+ "per": "second",
+ "rate": 10230,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate 1023000 mbytes/second
+[
+ {
+ "limit": {
+ "per": "second",
+ "rate": 1023000,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate 1025 bytes/second burst 512 bytes
+[
+ {
+ "limit": {
+ "burst": 512,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "bytes"
+ }
+ }
+]
+
+# limit rate 1025 kbytes/second burst 1023 kbytes
+[
+ {
+ "limit": {
+ "burst": 1023,
+ "burst_unit": "kbytes",
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 1025 mbytes/second burst 1025 kbytes
+[
+ {
+ "limit": {
+ "burst": 1025,
+ "burst_unit": "kbytes",
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate 1025000 mbytes/second burst 1023 mbytes
+[
+ {
+ "limit": {
+ "burst": 1023,
+ "burst_unit": "mbytes",
+ "per": "second",
+ "rate": 1025000,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 400/minute
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "minute",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate over 20/second
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "second",
+ "rate": 20
+ }
+ }
+]
+
+# limit rate over 400/hour
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "hour",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate over 40/day
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "day",
+ "rate": 40
+ }
+ }
+]
+
+# limit rate over 400/week
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "week",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate over 1023/second burst 10 packets
+[
+ {
+ "limit": {
+ "burst": 10,
+ "inv": true,
+ "per": "second",
+ "rate": 1023
+ }
+ }
+]
+
+# limit rate over 1 kbytes/second
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "second",
+ "rate": 1,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 2 kbytes/second
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "second",
+ "rate": 2,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 1025 kbytes/second
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 1023 mbytes/second
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "second",
+ "rate": 1023,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 10230 mbytes/second
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "second",
+ "rate": 10230,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 1023000 mbytes/second
+[
+ {
+ "limit": {
+ "inv": true,
+ "per": "second",
+ "rate": 1023000,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 1025 bytes/second burst 512 bytes
+[
+ {
+ "limit": {
+ "burst": 512,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "bytes"
+ }
+ }
+]
+
+# limit rate over 1025 kbytes/second burst 1023 kbytes
+[
+ {
+ "limit": {
+ "burst": 1023,
+ "burst_unit": "kbytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 1025 mbytes/second burst 1025 kbytes
+[
+ {
+ "limit": {
+ "burst": 1025,
+ "burst_unit": "kbytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 1025000 mbytes/second burst 1023 mbytes
+[
+ {
+ "limit": {
+ "burst": 1023,
+ "burst_unit": "mbytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025000,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
diff --git a/tests/py/any/log.t.json b/tests/py/any/log.t.json
new file mode 100644
index 00000000..9c89dff8
--- /dev/null
+++ b/tests/py/any/log.t.json
@@ -0,0 +1,169 @@
+# log
+[
+ {
+ "log": null
+ }
+]
+
+# log level emerg
+[
+ {
+ "log": {
+ "level": "emerg"
+ }
+ }
+]
+
+# log level alert
+[
+ {
+ "log": {
+ "level": "alert"
+ }
+ }
+]
+
+# log level crit
+[
+ {
+ "log": {
+ "level": "crit"
+ }
+ }
+]
+
+# log level err
+[
+ {
+ "log": {
+ "level": "err"
+ }
+ }
+]
+
+# log level warn
+[
+ {
+ "log": {
+ "level": "warn"
+ }
+ }
+]
+
+# log level notice
+[
+ {
+ "log": {
+ "level": "notice"
+ }
+ }
+]
+
+# log level info
+[
+ {
+ "log": {
+ "level": "info"
+ }
+ }
+]
+
+# log level debug
+[
+ {
+ "log": {
+ "level": "debug"
+ }
+ }
+]
+
+# log prefix aaaaa-aaaaaa group 2 snaplen 33
+[
+ {
+ "log": {
+ "group": 2,
+ "prefix": "aaaaa-aaaaaa",
+ "snaplen": 33
+ }
+ }
+]
+
+# log group 2 queue-threshold 2
+[
+ {
+ "log": {
+ "group": 2,
+ "queue-threshold": 2
+ }
+ }
+]
+
+# log group 2 snaplen 33
+[
+ {
+ "log": {
+ "group": 2,
+ "snaplen": 33
+ }
+ }
+]
+
+# log group 2 prefix "nft-test: "
+[
+ {
+ "log": {
+ "group": 2,
+ "prefix": "nft-test: "
+ }
+ }
+]
+
+# log flags all
+[
+ {
+ "log": {
+ "flags": "all"
+ }
+ }
+]
+
+# log level debug flags ip options flags skuid
+[
+ {
+ "log": {
+ "flags": [
+ "ip options",
+ "skuid"
+ ],
+ "level": "debug"
+ }
+ }
+]
+
+# log flags tcp sequence,options
+[
+ {
+ "log": {
+ "flags": [
+ "tcp sequence",
+ "tcp options"
+ ]
+ }
+ }
+]
+
+# log flags ip options flags ether flags skuid flags tcp sequence,options
+[
+ {
+ "log": {
+ "flags": [
+ "ip options",
+ "ether",
+ "skuid",
+ "tcp sequence",
+ "tcp options"
+ ]
+ }
+ }
+]
+
diff --git a/tests/py/any/log.t.json.output b/tests/py/any/log.t.json.output
new file mode 100644
index 00000000..051c448b
--- /dev/null
+++ b/tests/py/any/log.t.json.output
@@ -0,0 +1,16 @@
+# log level warn
+[
+ {
+ "log": null
+ }
+]
+
+# log flags ip options flags ether flags skuid flags tcp sequence,options
+[
+ {
+ "log": {
+ "flags": "all"
+ }
+ }
+]
+
diff --git a/tests/py/any/meta.t.json b/tests/py/any/meta.t.json
new file mode 100644
index 00000000..ae745078
--- /dev/null
+++ b/tests/py/any/meta.t.json
@@ -0,0 +1,2418 @@
+# meta length 1000
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "right": 1000
+ }
+ }
+]
+
+# meta length 22
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "right": 22
+ }
+ }
+]
+
+# meta length != 233
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# meta length 33-45
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# meta length != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# meta length { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# meta length { 33-55, 67-88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] },
+ { "range": [ 67, 88 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta length { 33-55, 56-88, 100-120}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 88 ] },
+ { "range": [ 100, 120 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta length != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# meta length { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta length != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "length"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta protocol { ip, arp, ip6, vlan }
+[
+ {
+ "match": {
+ "left": {
+ "meta": "protocol"
+ },
+ "right": {
+ "set": [
+ "ip",
+ "arp",
+ "ip6",
+ "vlan"
+ ]
+ }
+ }
+ }
+]
+
+# meta protocol != {ip, arp, ip6, vlan}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "protocol"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ip",
+ "arp",
+ "ip6",
+ "vlan"
+ ]
+ }
+ }
+ }
+]
+
+# meta protocol ip
+[
+ {
+ "match": {
+ "left": {
+ "meta": "protocol"
+ },
+ "right": "ip"
+ }
+ }
+]
+
+# meta protocol != ip
+[
+ {
+ "match": {
+ "left": {
+ "meta": "protocol"
+ },
+ "op": "!=",
+ "right": "ip"
+ }
+ }
+]
+
+# meta l4proto 22
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": 22
+ }
+ }
+]
+
+# meta l4proto != 233
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# meta l4proto 33-45
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# meta l4proto != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# meta l4proto { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta priority root
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": "root"
+ }
+ }
+]
+
+# meta priority none
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": "none"
+ }
+ }
+]
+
+# meta priority 0x87654321
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": "0x87654321"
+ }
+ }
+]
+
+# meta priority 2271560481
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": 2271560481
+ }
+ }
+]
+
+# meta priority 1:1234
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": "1:1234"
+ }
+ }
+]
+
+# meta priority bcad:dadc
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": "bcad:dadc"
+ }
+ }
+]
+
+# meta priority aabb:0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": "aabb:0"
+ }
+ }
+]
+
+# meta priority != bcad:dadc
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "op": "!=",
+ "right": "bcad:dadc"
+ }
+ }
+]
+
+# meta priority != aabb:0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "op": "!=",
+ "right": "aabb:0"
+ }
+ }
+]
+
+# meta priority bcad:dada-bcad:dadc
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": {
+ "range": [ "bcad:dada", "bcad:dadc" ]
+ }
+ }
+ }
+]
+
+# meta priority != bcad:dada-bcad:dadc
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "bcad:dada", "bcad:dadc" ]
+ }
+ }
+ }
+]
+
+# meta priority {bcad:dada, bcad:dadc, aaaa:bbbb}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": {
+ "set": [
+ "bcad:dada",
+ "bcad:dadc",
+ "aaaa:bbbb"
+ ]
+ }
+ }
+ }
+]
+
+# meta priority set cafe:beef
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": "cafe:beef"
+ }
+ }
+]
+
+# meta priority != {bcad:dada, bcad:dadc, aaaa:bbbb}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "aaaa:bbbb",
+ "bcad:dada",
+ "bcad:dadc"
+ ]
+ }
+ }
+ }
+]
+
+# meta mark 0x4
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": "0x4"
+ }
+ }
+]
+
+# meta mark 0x32
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": "0x32"
+ }
+ }
+]
+
+# meta mark and 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "meta": "mark"
+ },
+ "0x03"
+ ]
+ },
+ "op": "==",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark and 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "meta": "mark"
+ },
+ "0x03"
+ ]
+ },
+ "op": "!=",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark 0x10
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": "0x10"
+ }
+ }
+]
+
+# meta mark != 0x10
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "op": "!=",
+ "right": "0x10"
+ }
+ }
+]
+
+# meta mark or 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "meta": "mark"
+ },
+ "0x03"
+ ]
+ },
+ "op": "==",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark or 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "meta": "mark"
+ },
+ "0x03"
+ ]
+ },
+ "op": "!=",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark xor 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "^": [
+ {
+ "meta": "mark"
+ },
+ "0x03"
+ ]
+ },
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark xor 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "^": [
+ {
+ "meta": "mark"
+ },
+ "0x03"
+ ]
+ },
+ "op": "!=",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta iif "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta iif != "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "op": "!=",
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta iifname "dummy0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "dummy0"
+ }
+ }
+]
+
+# meta iifname != "dummy0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "op": "!=",
+ "right": "dummy0"
+ }
+ }
+]
+
+# meta iifname {"dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": {
+ "set": [
+ "dummy0",
+ "lo"
+ ]
+ }
+ }
+ }
+]
+
+# meta iifname != {"dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "dummy0",
+ "lo"
+ ]
+ }
+ }
+ }
+]
+
+# meta iifname "dummy*"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "dummy*"
+ }
+ }
+]
+
+# meta iifname "dummy\*"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "dummy\\*"
+ }
+ }
+]
+
+# meta iiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "right": {
+ "set": [
+ "ether",
+ "ppp",
+ "ipip",
+ "ipip6",
+ "loopback",
+ "sit",
+ "ipgre"
+ ]
+ }
+ }
+ }
+]
+
+# meta iiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ether",
+ "ppp",
+ "ipip",
+ "ipip6",
+ "loopback",
+ "sit",
+ "ipgre"
+ ]
+ }
+ }
+ }
+]
+
+# meta iiftype != ether
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "op": "!=",
+ "right": "ether"
+ }
+ }
+]
+
+# meta iiftype ether
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "right": "ether"
+ }
+ }
+]
+
+# meta iiftype != ppp
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "op": "!=",
+ "right": "ppp"
+ }
+ }
+]
+
+# meta iiftype ppp
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "right": "ppp"
+ }
+ }
+]
+
+# meta oif "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta oif != "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oif"
+ },
+ "op": "!=",
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta oif {"lo"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oif"
+ },
+ "right": {
+ "set": [
+ "lo"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta oif != {"lo"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oif"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "lo"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta oifname "dummy0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifname"
+ },
+ "right": "dummy0"
+ }
+ }
+]
+
+# meta oifname != "dummy0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifname"
+ },
+ "op": "!=",
+ "right": "dummy0"
+ }
+ }
+]
+
+# meta oifname { "dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifname"
+ },
+ "right": {
+ "set": [
+ "dummy0",
+ "lo"
+ ]
+ }
+ }
+ }
+]
+
+# meta oifname "dummy*"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifname"
+ },
+ "right": "dummy*"
+ }
+ }
+]
+
+# meta oifname "dummy\*"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifname"
+ },
+ "right": "dummy\\*"
+ }
+ }
+]
+
+# meta oiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oiftype"
+ },
+ "right": {
+ "set": [
+ "ether",
+ "ppp",
+ "ipip",
+ "ipip6",
+ "loopback",
+ "sit",
+ "ipgre"
+ ]
+ }
+ }
+ }
+]
+
+# meta oiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oiftype"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ether",
+ "ppp",
+ "ipip",
+ "ipip6",
+ "loopback",
+ "sit",
+ "ipgre"
+ ]
+ }
+ }
+ }
+]
+
+# meta oiftype != ether
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oiftype"
+ },
+ "op": "!=",
+ "right": "ether"
+ }
+ }
+]
+
+# meta oiftype ether
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oiftype"
+ },
+ "right": "ether"
+ }
+ }
+]
+
+# meta skuid {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "right": {
+ "set": [
+ "bin",
+ "root",
+ "daemon"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid != {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "bin",
+ "root",
+ "daemon"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "right": "root"
+ }
+ }
+]
+
+# meta skuid != "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "op": "!=",
+ "right": "root"
+ }
+ }
+]
+
+# meta skuid lt 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "op": "<",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid gt 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "op": ">",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid eq 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid 3001-3005 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "right": {
+ "range": [ 3001, 3005 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid != 2001-2005 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 2001, 2005 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid { 2001-2005} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "right": {
+ "set": [
+ { "range": [ 2001, 2005 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid != { 2001-2005} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 2001, 2005 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "right": {
+ "set": [
+ "bin",
+ "root",
+ "daemon"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid != {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "bin",
+ "root",
+ "daemon"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "right": "root"
+ }
+ }
+]
+
+# meta skgid != "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "op": "!=",
+ "right": "root"
+ }
+ }
+]
+
+# meta skgid lt 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "op": "<",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid gt 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "op": ">",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid eq 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid 2001-2005 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "right": {
+ "range": [ 2001, 2005 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid != 2001-2005 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 2001, 2005 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid { 2001-2005} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "right": {
+ "set": [
+ { "range": [ 2001, 2005 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid != { 2001-2005} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 2001, 2005 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta mark set 0xffffffc8 xor 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": { "^": [ "0xffffffc8", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0x16 and 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": { "&": [ "0x16", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0xffffffe9 or 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": { "|": [ "0xffffffe9", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0xffffffde and 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": { "&": [ "0xffffffde", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0xf045ffde or 0x10
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": { "|": [ "0xf045ffde", "0x10" ] }
+ }
+ }
+]
+
+# meta mark set 0xffffffde or 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": { "|": [ "0xffffffde", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0x32 or 0xfffff
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": { "|": [ "0x32", "0xfffff" ] }
+ }
+ }
+]
+
+# meta mark set 0xfffe xor 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": { "^": [ "0xfffe", "0x16" ] }
+ }
+ }
+]
+
+# meta iif "lo"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ }
+]
+
+# meta oif "lo"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oif"
+ },
+ "right": "lo"
+ }
+ }
+]
+
+# meta oifname "dummy2" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifname"
+ },
+ "right": "dummy2"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid 3000
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "right": 3000
+ }
+ }
+]
+
+# meta skgid 3000
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "right": 3000
+ }
+ }
+]
+
+# meta rtclassid "cosmos"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "rtclassid"
+ },
+ "right": "cosmos"
+ }
+ }
+]
+
+# meta pkttype broadcast
+[
+ {
+ "match": {
+ "left": {
+ "meta": "pkttype"
+ },
+ "right": "broadcast"
+ }
+ }
+]
+
+# meta pkttype host
+[
+ {
+ "match": {
+ "left": {
+ "meta": "pkttype"
+ },
+ "right": "host"
+ }
+ }
+]
+
+# meta pkttype multicast
+[
+ {
+ "match": {
+ "left": {
+ "meta": "pkttype"
+ },
+ "right": "multicast"
+ }
+ }
+]
+
+# meta pkttype != broadcast
+[
+ {
+ "match": {
+ "left": {
+ "meta": "pkttype"
+ },
+ "op": "!=",
+ "right": "broadcast"
+ }
+ }
+]
+
+# meta pkttype != host
+[
+ {
+ "match": {
+ "left": {
+ "meta": "pkttype"
+ },
+ "op": "!=",
+ "right": "host"
+ }
+ }
+]
+
+# meta pkttype != multicast
+[
+ {
+ "match": {
+ "left": {
+ "meta": "pkttype"
+ },
+ "op": "!=",
+ "right": "multicast"
+ }
+ }
+]
+
+# pkttype { broadcast, multicast} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "pkttype"
+ },
+ "right": {
+ "set": [
+ "broadcast",
+ "multicast"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta cpu 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cpu"
+ },
+ "right": 1
+ }
+ }
+]
+
+# meta cpu != 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cpu"
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# meta cpu 1-3
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cpu"
+ },
+ "right": {
+ "range": [ 1, 3 ]
+ }
+ }
+ }
+]
+
+# meta cpu != 1-2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cpu"
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 1, 2 ]
+ }
+ }
+ }
+]
+
+# meta cpu { 2,3}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cpu"
+ },
+ "right": {
+ "set": [
+ 2,
+ 3
+ ]
+ }
+ }
+ }
+]
+
+# meta cpu { 2-3, 5-7}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cpu"
+ },
+ "right": {
+ "set": [
+ { "range": [ 2, 3 ] },
+ { "range": [ 5, 7 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta cpu != { 2,3}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cpu"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 2,
+ 3
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "right": 0
+ }
+ }
+]
+
+# meta iifgroup != 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# meta iifgroup "default"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "right": "default"
+ }
+ }
+]
+
+# meta iifgroup != "default"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "op": "!=",
+ "right": "default"
+ }
+ }
+]
+
+# meta iifgroup {"default"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "right": {
+ "set": [
+ "default"
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup != {"default"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "default"
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup { 11,33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "right": {
+ "set": [
+ 11,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup {11-33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "right": {
+ "set": [
+ { "range": [ 11, 33 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup != { 11,33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 11,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup != {11-33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 11, 33 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "right": 0
+ }
+ }
+]
+
+# meta oifgroup != 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# meta oifgroup "default"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "right": "default"
+ }
+ }
+]
+
+# meta oifgroup != "default"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "op": "!=",
+ "right": "default"
+ }
+ }
+]
+
+# meta oifgroup {"default"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "right": {
+ "set": [
+ "default"
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup != {"default"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "default"
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup { 11,33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "right": {
+ "set": [
+ 11,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup {11-33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "right": {
+ "set": [
+ { "range": [ 11, 33 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup != { 11,33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 11,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup != {11-33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 11, 33 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta cgroup 1048577
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cgroup"
+ },
+ "right": 1048577
+ }
+ }
+]
+
+# meta cgroup != 1048577
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cgroup"
+ },
+ "op": "!=",
+ "right": 1048577
+ }
+ }
+]
+
+# meta cgroup { 1048577, 1048578 }
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cgroup"
+ },
+ "right": {
+ "set": [
+ 1048577,
+ 1048578
+ ]
+ }
+ }
+ }
+]
+
+# meta cgroup != { 1048577, 1048578}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cgroup"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 1048577,
+ 1048578
+ ]
+ }
+ }
+ }
+]
+
+# meta cgroup 1048577-1048578
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cgroup"
+ },
+ "right": {
+ "range": [ 1048577, 1048578 ]
+ }
+ }
+ }
+]
+
+# meta cgroup != 1048577-1048578
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cgroup"
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 1048577, 1048578 ]
+ }
+ }
+ }
+]
+
+# meta cgroup {1048577-1048578}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cgroup"
+ },
+ "right": {
+ "set": [
+ {
+ "range": [ 1048577, 1048578 ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta cgroup != { 1048577-1048578}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "cgroup"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ {
+ "range": [ 1048577, 1048578 ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta iif . meta oif { "lo" . "lo" }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "meta": "iif"
+ },
+ {
+ "meta": "oif"
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "lo",
+ "lo"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta iif . meta oif . meta mark { "lo" . "lo" . 0x0000000a }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "meta": "iif"
+ },
+ {
+ "meta": "oif"
+ },
+ {
+ "meta": "mark"
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "lo",
+ "lo",
+ "0x0000000a"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta iif . meta oif vmap { "lo" . "lo" : drop }
+[
+ {
+ "map": {
+ "left": {
+ "concat": [
+ {
+ "meta": "iif"
+ },
+ {
+ "meta": "oif"
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ [
+ {
+ "concat": [
+ "lo",
+ "lo"
+ ]
+ },
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# meta random eq 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": "random"
+ },
+ "right": 1
+ }
+ }
+]
+
+# meta random gt 1000000
+[
+ {
+ "match": {
+ "left": {
+ "meta": "random"
+ },
+ "op": ">",
+ "right": 1000000
+ }
+ }
+]
+
diff --git a/tests/py/any/meta.t.json.output b/tests/py/any/meta.t.json.output
new file mode 100644
index 00000000..a4b9633a
--- /dev/null
+++ b/tests/py/any/meta.t.json.output
@@ -0,0 +1,577 @@
+# meta protocol { ip, arp, ip6, vlan }
+[
+ {
+ "match": {
+ "left": {
+ "meta": "protocol"
+ },
+ "right": {
+ "set": [
+ "ip",
+ "arp",
+ "vlan",
+ "ip6"
+ ]
+ }
+ }
+ }
+]
+
+# meta protocol != {ip, arp, ip6, vlan}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "protocol"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ip",
+ "arp",
+ "vlan",
+ "ip6"
+ ]
+ }
+ }
+ }
+]
+
+# meta priority 0x87654321
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": "8765:4321"
+ }
+ }
+]
+
+# meta priority 2271560481
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": "8765:4321"
+ }
+ }
+]
+
+# meta priority {bcad:dada, bcad:dadc, aaaa:bbbb}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "priority"
+ },
+ "right": {
+ "set": [
+ "aaaa:bbbb",
+ "bcad:dada",
+ "bcad:dadc"
+ ]
+ }
+ }
+ }
+]
+
+# meta mark 0x4
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 4
+ }
+ }
+]
+
+# meta mark 0x32
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 50
+ }
+ }
+]
+
+# meta mark and 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "meta": "mark"
+ },
+ 3
+ ]
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# meta mark and 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "meta": "mark"
+ },
+ 3
+ ]
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# meta mark 0x10
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 16
+ }
+ }
+]
+
+# meta mark != 0x10
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "op": "!=",
+ "right": 16
+ }
+ }
+]
+
+# meta mark or 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "meta": "mark"
+ },
+ 3
+ ]
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# meta mark or 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "meta": "mark"
+ },
+ 3
+ ]
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# meta mark xor 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 2
+ }
+ }
+]
+
+# meta mark xor 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "op": "!=",
+ "right": 2
+ }
+ }
+]
+
+# meta iifname {"dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": {
+ "set": [
+ "lo",
+ "dummy0"
+ ]
+ }
+ }
+ }
+]
+
+# meta iifname != {"dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "lo",
+ "dummy0"
+ ]
+ }
+ }
+ }
+]
+
+# meta oifname { "dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifname"
+ },
+ "right": {
+ "set": [
+ "lo",
+ "dummy0"
+ ]
+ }
+ }
+ }
+]
+
+# meta skuid {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "right": {
+ "set": [ 0, 1, 2 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid != {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "op": "!=",
+ "right": {
+ "set": [ 0, 1, 2 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "right": 0
+ }
+ }
+]
+
+# meta skuid != "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skuid"
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# meta skgid {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "right": {
+ "set": [ 0, 1, 2 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid != {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "op": "!=",
+ "right": {
+ "set": [ 0, 1, 2 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "right": 0
+ }
+ }
+]
+
+# meta skgid != "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "skgid"
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# meta mark set 0xffffffc8 xor 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 4294967262
+ }
+ }
+]
+
+# meta mark set 0x16 and 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 22
+ }
+ }
+]
+
+# meta mark set 0xffffffe9 or 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 4294967295
+ }
+ }
+]
+
+# meta mark set 0xffffffde and 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 22
+ }
+ }
+]
+
+# meta mark set 0xf045ffde or 0x10
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 4031119326
+ }
+ }
+]
+
+# meta mark set 0xffffffde or 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 4294967262
+ }
+ }
+]
+
+# meta mark set 0x32 or 0xfffff
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 1048575
+ }
+ }
+]
+
+# meta mark set 0xfffe xor 0x16
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 65512
+ }
+ }
+]
+
+# meta iifgroup 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "right": "default"
+ }
+ }
+]
+
+# meta iifgroup != 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifgroup"
+ },
+ "op": "!=",
+ "right": "default"
+ }
+ }
+]
+
+# meta oifgroup 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "right": "default"
+ }
+ }
+]
+
+# meta oifgroup != 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "oifgroup"
+ },
+ "op": "!=",
+ "right": "default"
+ }
+ }
+]
+
+# meta iif . meta oif . meta mark { "lo" . "lo" . 0x0000000a }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "meta": "iif"
+ },
+ {
+ "meta": "oif"
+ },
+ {
+ "meta": "mark"
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "lo",
+ "lo",
+ 10
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/any/queue.t.json b/tests/py/any/queue.t.json
new file mode 100644
index 00000000..48e86727
--- /dev/null
+++ b/tests/py/any/queue.t.json
@@ -0,0 +1,86 @@
+# queue
+[
+ {
+ "queue": null
+ }
+]
+
+# queue num 2
+[
+ {
+ "queue": {
+ "num": 2
+ }
+ }
+]
+
+# queue num 65535
+[
+ {
+ "queue": {
+ "num": 65535
+ }
+ }
+]
+
+# queue num 2-3
+[
+ {
+ "queue": {
+ "num": {
+ "range": [ 2, 3 ]
+ }
+ }
+ }
+]
+
+# queue num 1-65535
+[
+ {
+ "queue": {
+ "num": {
+ "range": [ 1, 65535 ]
+ }
+ }
+ }
+]
+
+# queue num 4-5 fanout bypass
+[
+ {
+ "queue": {
+ "flags": [
+ "bypass",
+ "fanout"
+ ],
+ "num": {
+ "range": [ 4, 5 ]
+ }
+ }
+ }
+]
+
+# queue num 4-5 fanout
+[
+ {
+ "queue": {
+ "flags": "fanout",
+ "num": {
+ "range": [ 4, 5 ]
+ }
+ }
+ }
+]
+
+# queue num 4-5 bypass
+[
+ {
+ "queue": {
+ "flags": "bypass",
+ "num": {
+ "range": [ 4, 5 ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/any/queue.t.json.output b/tests/py/any/queue.t.json.output
new file mode 100644
index 00000000..1104d760
--- /dev/null
+++ b/tests/py/any/queue.t.json.output
@@ -0,0 +1,9 @@
+# queue
+[
+ {
+ "queue": {
+ "num": 0
+ }
+ }
+]
+
diff --git a/tests/py/any/quota.t.json b/tests/py/any/quota.t.json
new file mode 100644
index 00000000..59ccc72c
--- /dev/null
+++ b/tests/py/any/quota.t.json
@@ -0,0 +1,136 @@
+# quota 1025 bytes
+[
+ {
+ "quota": {
+ "val": 1025,
+ "val_unit": "bytes"
+ }
+ }
+]
+
+# quota 1 kbytes
+[
+ {
+ "quota": {
+ "val": 1,
+ "val_unit": "kbytes"
+ }
+ }
+]
+
+# quota 2 kbytes
+[
+ {
+ "quota": {
+ "val": 2,
+ "val_unit": "kbytes"
+ }
+ }
+]
+
+# quota 1025 kbytes
+[
+ {
+ "quota": {
+ "val": 1025,
+ "val_unit": "kbytes"
+ }
+ }
+]
+
+# quota 1023 mbytes
+[
+ {
+ "quota": {
+ "val": 1023,
+ "val_unit": "mbytes"
+ }
+ }
+]
+
+# quota 10230 mbytes
+[
+ {
+ "quota": {
+ "val": 10230,
+ "val_unit": "mbytes"
+ }
+ }
+]
+
+# quota 1023000 mbytes
+[
+ {
+ "quota": {
+ "val": 1023000,
+ "val_unit": "mbytes"
+ }
+ }
+]
+
+# quota over 1 kbytes
+[
+ {
+ "quota": {
+ "inv": true,
+ "val": 1,
+ "val_unit": "kbytes"
+ }
+ }
+]
+
+# quota over 2 kbytes
+[
+ {
+ "quota": {
+ "inv": true,
+ "val": 2,
+ "val_unit": "kbytes"
+ }
+ }
+]
+
+# quota over 1025 kbytes
+[
+ {
+ "quota": {
+ "inv": true,
+ "val": 1025,
+ "val_unit": "kbytes"
+ }
+ }
+]
+
+# quota over 1023 mbytes
+[
+ {
+ "quota": {
+ "inv": true,
+ "val": 1023,
+ "val_unit": "mbytes"
+ }
+ }
+]
+
+# quota over 10230 mbytes
+[
+ {
+ "quota": {
+ "inv": true,
+ "val": 10230,
+ "val_unit": "mbytes"
+ }
+ }
+]
+
+# quota over 1023000 mbytes
+[
+ {
+ "quota": {
+ "inv": true,
+ "val": 1023000,
+ "val_unit": "mbytes"
+ }
+ }
+]
+
diff --git a/tests/py/any/rawpayload.t.json b/tests/py/any/rawpayload.t.json
new file mode 100644
index 00000000..b4ce0bd8
--- /dev/null
+++ b/tests/py/any/rawpayload.t.json
@@ -0,0 +1,157 @@
+# meta l4proto { tcp, udp, sctp} @th,16,16 { 22, 23, 80 }
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": {
+ "set": [
+ "tcp",
+ "udp",
+ "sctp"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "th",
+ "len": 16,
+ "name": "raw",
+ "offset": 16
+ }
+ },
+ "right": {
+ "set": [
+ 22,
+ 23,
+ 80
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto tcp @th,16,16 { 22, 23, 80}
+[
+ {
+ "match": {
+ "left": { "meta": "l4proto" },
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "th",
+ "len": 16,
+ "offset": 16,
+ "name": "raw"
+ }
+ },
+ "right": {
+ "set": [
+ 22,
+ 23,
+ 80
+ ]
+ }
+ }
+ }
+]
+
+# @nh,8,8 255
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 8,
+ "name": "raw",
+ "offset": 8
+ }
+ },
+ "right": 255
+ }
+ }
+]
+
+# @nh,8,16 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 16,
+ "name": "raw",
+ "offset": 8
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# @ll,0,1 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "ll",
+ "len": 1,
+ "name": "raw",
+ "offset": 0
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# @ll,0,8 and 0x80 eq 0x80
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "base": "ll",
+ "len": 8,
+ "name": "raw",
+ "offset": 0
+ }
+ },
+ "0x80"
+ ]
+ },
+ "op": "==",
+ "right": "0x80"
+ }
+ }
+]
+
+# @ll,0,128 0xfedcba987654321001234567890abcde
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "ll",
+ "len": 128,
+ "name": "raw",
+ "offset": 0
+ }
+ },
+ "right": "0xfedcba987654321001234567890abcde"
+ }
+ }
+]
+
diff --git a/tests/py/any/rawpayload.t.json.output b/tests/py/any/rawpayload.t.json.output
new file mode 100644
index 00000000..fd70341c
--- /dev/null
+++ b/tests/py/any/rawpayload.t.json.output
@@ -0,0 +1,104 @@
+# meta l4proto { tcp, udp, sctp} @th,16,16 { 22, 23, 80 }
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 132
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "th",
+ "len": 16,
+ "name": "raw",
+ "offset": 16
+ }
+ },
+ "right": {
+ "set": [
+ 22,
+ 23,
+ 80
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto tcp @th,16,16 { 22, 23, 80}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 22,
+ 23,
+ 80
+ ]
+ }
+ }
+ }
+]
+
+# @ll,0,1 1
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "base": "ll",
+ "len": 8,
+ "name": "raw",
+ "offset": 0
+ }
+ },
+ 128
+ ]
+ },
+ "op": "==",
+ "right": 128
+ }
+ }
+]
+
+# @ll,0,8 and 0x80 eq 0x80
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "base": "ll",
+ "len": 8,
+ "name": "raw",
+ "offset": 0
+ }
+ },
+ 128
+ ]
+ },
+ "op": "==",
+ "right": 128
+ }
+ }
+]
+
diff --git a/tests/py/any/rt.t.json b/tests/py/any/rt.t.json
new file mode 100644
index 00000000..146a8a01
--- /dev/null
+++ b/tests/py/any/rt.t.json
@@ -0,0 +1,14 @@
+# rt classid "cosmos"
+[
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "key": "classid"
+ }
+ },
+ "right": "cosmos"
+ }
+ }
+]
+
diff --git a/tests/py/arp/arp.t.json b/tests/py/arp/arp.t.json
new file mode 100644
index 00000000..005fcf64
--- /dev/null
+++ b/tests/py/arp/arp.t.json
@@ -0,0 +1,877 @@
+# arp htype 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# arp htype != 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# arp htype 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# arp htype != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# arp htype 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp htype != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp htype { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp htype != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp htype { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# arp htype != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# arp ptype 0x0800
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ptype",
+ "name": "arp"
+ }
+ },
+ "right": "0x0800"
+ }
+ }
+]
+
+# arp hlen 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# arp hlen != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# arp hlen 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp hlen != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp hlen { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp hlen != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp hlen { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# arp hlen != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# arp plen 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# arp plen != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# arp plen 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp plen != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp plen { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp plen != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp plen { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# arp plen != {33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "set": [
+ "nak",
+ "inreply",
+ "inrequest",
+ "rreply",
+ "rrequest",
+ "reply",
+ "request"
+ ]
+ }
+ }
+ }
+]
+
+# arp operation != {nak, inreply, inrequest, rreply, rrequest, reply, request}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "nak",
+ "inreply",
+ "inrequest",
+ "rreply",
+ "rrequest",
+ "reply",
+ "request"
+ ]
+ }
+ }
+ }
+]
+
+# arp operation request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": "request"
+ }
+ }
+]
+
+# arp operation reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": "reply"
+ }
+ }
+]
+
+# arp operation rrequest
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": "rrequest"
+ }
+ }
+]
+
+# arp operation rreply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": "rreply"
+ }
+ }
+]
+
+# arp operation inrequest
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": "inrequest"
+ }
+ }
+]
+
+# arp operation inreply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": "inreply"
+ }
+ }
+]
+
+# arp operation nak
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": "nak"
+ }
+ }
+]
+
+# arp operation reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": "reply"
+ }
+ }
+]
+
+# arp operation != request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "request"
+ }
+ }
+]
+
+# arp operation != reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "reply"
+ }
+ }
+]
+
+# arp operation != rrequest
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "rrequest"
+ }
+ }
+]
+
+# arp operation != rreply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "rreply"
+ }
+ }
+]
+
+# arp operation != inrequest
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "inrequest"
+ }
+ }
+]
+
+# arp operation != inreply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "inreply"
+ }
+ }
+]
+
+# arp operation != nak
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "nak"
+ }
+ }
+]
+
+# arp operation != reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "reply"
+ }
+ }
+]
+
+# meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "invalid"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ptype",
+ "name": "arp"
+ }
+ },
+ "right": "0x0800"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "right": 4
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 32,
+ "name": "raw",
+ "offset": 192
+ }
+ },
+ "right": "0xc0a88f10"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 48,
+ "name": "raw",
+ "offset": 144
+ }
+ },
+ "right": "0x112233445566"
+ }
+ }
+]
+
diff --git a/tests/py/arp/arp.t.json.output b/tests/py/arp/arp.t.json.output
new file mode 100644
index 00000000..0120025b
--- /dev/null
+++ b/tests/py/arp/arp.t.json.output
@@ -0,0 +1,148 @@
+# arp ptype 0x0800
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ptype",
+ "name": "arp"
+ }
+ },
+ "right": "ip"
+ }
+ }
+]
+
+# arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "right": {
+ "set": [
+ "request",
+ "reply",
+ "rrequest",
+ "rreply",
+ "inrequest",
+ "inreply",
+ "nak"
+ ]
+ }
+ }
+ }
+]
+
+# arp operation != {nak, inreply, inrequest, rreply, rrequest, reply, request}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "name": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "request",
+ "reply",
+ "rrequest",
+ "rreply",
+ "inrequest",
+ "inreply",
+ "nak"
+ ]
+ }
+ }
+ }
+]
+
+# meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "invalid"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "name": "arp"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ptype",
+ "name": "arp"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "name": "arp"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "name": "arp"
+ }
+ },
+ "right": 4
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 32,
+ "name": "raw",
+ "offset": 192
+ }
+ },
+ "right": 3232272144
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 48,
+ "name": "raw",
+ "offset": 144
+ }
+ },
+ "right": 18838586676582
+ }
+ }
+]
+
diff --git a/tests/py/bridge/ether.t.json b/tests/py/bridge/ether.t.json
new file mode 100644
index 00000000..89cd128c
--- /dev/null
+++ b/tests/py/bridge/ether.t.json
@@ -0,0 +1,180 @@
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "right": "ether"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ }
+]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ether daddr 00:01:02:03:04:05 ether saddr set ff:fe:dc:ba:98:76 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:01:02:03:04:05"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "ff:fe:dc:ba:98:76"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
diff --git a/tests/py/bridge/ether.t.json.output b/tests/py/bridge/ether.t.json.output
new file mode 100644
index 00000000..f68748cb
--- /dev/null
+++ b/tests/py/bridge/ether.t.json.output
@@ -0,0 +1,77 @@
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ }
+]
+
diff --git a/tests/py/bridge/icmpX.t.json b/tests/py/bridge/icmpX.t.json
new file mode 100644
index 00000000..77638825
--- /dev/null
+++ b/tests/py/bridge/icmpX.t.json
@@ -0,0 +1,82 @@
+# ip protocol icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "name": "ip6"
+ }
+ },
+ "right": "icmpv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
diff --git a/tests/py/bridge/icmpX.t.json.output b/tests/py/bridge/icmpX.t.json.output
new file mode 100644
index 00000000..e2695750
--- /dev/null
+++ b/tests/py/bridge/icmpX.t.json.output
@@ -0,0 +1,52 @@
+# ip protocol icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "name": "ip6"
+ }
+ },
+ "right": 58
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
diff --git a/tests/py/bridge/meta.t.json b/tests/py/bridge/meta.t.json
new file mode 100644
index 00000000..dad5c6e1
--- /dev/null
+++ b/tests/py/bridge/meta.t.json
@@ -0,0 +1,23 @@
+# meta obrname "br0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "obrname"
+ },
+ "right": "br0"
+ }
+ }
+]
+
+# meta ibrname "br0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": "ibrname"
+ },
+ "right": "br0"
+ }
+ }
+]
diff --git a/tests/py/bridge/reject.t.json b/tests/py/bridge/reject.t.json
new file mode 100644
index 00000000..aa716f80
--- /dev/null
+++ b/tests/py/bridge/reject.t.json
@@ -0,0 +1,221 @@
+# reject with icmp type host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-unreachable
+[
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type prot-unreachable
+[
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-prohibited
+[
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type host-prohibited
+[
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmpv6 type no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type addr-unreachable
+[
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# mark 12345 ip protocol tcp reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 12345
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject
+[
+ {
+ "reject": null
+ }
+]
+
+# ether type ip reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# ether type ip6 reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# reject with icmpx type host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx type no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
diff --git a/tests/py/bridge/reject.t.json.output b/tests/py/bridge/reject.t.json.output
new file mode 100644
index 00000000..6effd179
--- /dev/null
+++ b/tests/py/bridge/reject.t.json.output
@@ -0,0 +1,260 @@
+# reject with icmp type host-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type prot-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type port-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# reject with icmp type net-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type host-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmpv6 type no-route
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type addr-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type port-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# mark 12345 ip protocol tcp reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 12345
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject with icmpx type port-unreachable
+[
+ {
+ "reject": null
+ }
+]
+
diff --git a/tests/py/bridge/vlan.t.json b/tests/py/bridge/vlan.t.json
new file mode 100644
index 00000000..b57deca7
--- /dev/null
+++ b/tests/py/bridge/vlan.t.json
@@ -0,0 +1,468 @@
+# vlan id 4094
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ }
+]
+
+# vlan id 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# vlan id 4094 vlan cfi 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cfi",
+ "name": "vlan"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# vlan id 4094 vlan cfi != 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cfi",
+ "name": "vlan"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# vlan id 4094 vlan cfi 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cfi",
+ "name": "vlan"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# vlan id 4094 vlan cfi 1 vlan pcp 7
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cfi",
+ "name": "vlan"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "pcp",
+ "name": "vlan"
+ }
+ },
+ "right": 7
+ }
+ }
+]
+
+# vlan id 4094 vlan cfi 1 vlan pcp 3
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cfi",
+ "name": "vlan"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "pcp",
+ "name": "vlan"
+ }
+ },
+ "right": 3
+ }
+ }
+]
+
+# ether type vlan vlan id 4094
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ }
+]
+
+# ether type vlan vlan id 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# ether type vlan vlan id 4094 vlan cfi 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cfi",
+ "name": "vlan"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# ether type vlan vlan id 4094 vlan cfi 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cfi",
+ "name": "vlan"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# vlan id 4094 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# vlan id 1 ip saddr 10.0.0.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "10.0.0.1"
+ }
+ }
+]
+
+# vlan id 1 ip saddr 10.0.0.0/23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "prefix": {
+ "addr": "10.0.0.0",
+ "len": 23
+ }
+ }
+ }
+ }
+]
+
+# vlan id 1 ip saddr 10.0.0.0/23 udp dport 53
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "prefix": {
+ "addr": "10.0.0.0",
+ "len": 23
+ }
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ }
+]
+
+# ether type vlan vlan id 1 ip saddr 10.0.0.0/23 udp dport 53
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "prefix": {
+ "addr": "10.0.0.0",
+ "len": 23
+ }
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ }
+]
+
+# vlan id { 1, 2, 4, 100, 4095 } vlan pcp 1-3
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "vlan"
+ }
+ },
+ "right": {
+ "set": [
+ 1,
+ 2,
+ 4,
+ 100,
+ 4095
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "pcp",
+ "name": "vlan"
+ }
+ },
+ "right": {
+ "range": [ 1, 3 ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/ah.t.json b/tests/py/inet/ah.t.json
new file mode 100644
index 00000000..4489f2d3
--- /dev/null
+++ b/tests/py/inet/ah.t.json
@@ -0,0 +1,557 @@
+# ah hdrlength 11-23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "range": [ 11, 23 ]
+ }
+ }
+ }
+]
+
+# ah hdrlength != 11-23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 11, 23 ]
+ }
+ }
+ }
+]
+
+# ah hdrlength { 11-23}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 11, 23 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ah hdrlength != { 11-23}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 11, 23 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ah hdrlength {11, 23, 44 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "set": [
+ 11,
+ 23,
+ 44
+ ]
+ }
+ }
+ }
+]
+
+# ah hdrlength != {11, 23, 44 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 11,
+ 23,
+ 44
+ ]
+ }
+ }
+ }
+]
+
+# ah reserved 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "name": "ah"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ah reserved != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ah reserved 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ah reserved != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ah reserved {23, 100}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "set": [
+ 23,
+ 100
+ ]
+ }
+ }
+ }
+]
+
+# ah reserved != {23, 100}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 100
+ ]
+ }
+ }
+ }
+]
+
+# ah reserved { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ah reserved != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ah spi 111
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "ah"
+ }
+ },
+ "right": 111
+ }
+ }
+]
+
+# ah spi != 111
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": 111
+ }
+ }
+]
+
+# ah spi 111-222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "range": [ 111, 222 ]
+ }
+ }
+ }
+]
+
+# ah spi != 111-222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 111, 222 ]
+ }
+ }
+ }
+]
+
+# ah spi {111, 122}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "set": [
+ 111,
+ 122
+ ]
+ }
+ }
+ }
+]
+
+# ah spi != {111, 122}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 111,
+ 122
+ ]
+ }
+ }
+ }
+]
+
+# ah spi { 111-122}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 111, 122 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ah spi != { 111-122}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 111, 122 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ah sequence 123
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "ah"
+ }
+ },
+ "right": 123
+ }
+ }
+]
+
+# ah sequence != 123
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": 123
+ }
+ }
+]
+
+# ah sequence {23, 25, 33}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "set": [
+ 23,
+ 25,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# ah sequence != {23, 25, 33}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 25,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# ah sequence { 23-33}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 23, 33 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ah sequence != { 23-33}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 23, 33 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ah sequence 23-33
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "ah"
+ }
+ },
+ "right": {
+ "range": [ 23, 33 ]
+ }
+ }
+ }
+]
+
+# ah sequence != 23-33
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 23, 33 ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/comp.t.json b/tests/py/inet/comp.t.json
new file mode 100644
index 00000000..d76d6ed8
--- /dev/null
+++ b/tests/py/inet/comp.t.json
@@ -0,0 +1,316 @@
+# comp nexthdr != esp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": "esp"
+ }
+ }
+]
+
+# comp flags 0x0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "right": "0x0"
+ }
+ }
+]
+
+# comp flags != 0x23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": "0x23"
+ }
+ }
+]
+
+# comp flags 0x33-0x45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "right": {
+ "range": [ "0x33", "0x45" ]
+ }
+ }
+ }
+]
+
+# comp flags != 0x33-0x45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "0x33", "0x45" ]
+ }
+ }
+ }
+]
+
+# comp flags {0x33, 0x55, 0x67, 0x88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "right": {
+ "set": [
+ "0x33",
+ "0x55",
+ "0x67",
+ "0x88"
+ ]
+ }
+ }
+ }
+]
+
+# comp flags != {0x33, 0x55, 0x67, 0x88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "0x33",
+ "0x55",
+ "0x67",
+ "0x88"
+ ]
+ }
+ }
+ }
+]
+
+# comp flags { 0x33-0x55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ "0x33", "0x55" ] }
+ ]
+ }
+ }
+ }
+]
+
+# comp flags != { 0x33-0x55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ "0x33", "0x55" ] }
+ ]
+ }
+ }
+ }
+]
+
+# comp cpi 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "name": "comp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# comp cpi != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# comp cpi 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "name": "comp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# comp cpi != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# comp cpi {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "name": "comp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# comp cpi != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# comp cpi { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "name": "comp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# comp cpi != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/comp.t.json.output b/tests/py/inet/comp.t.json.output
new file mode 100644
index 00000000..79e286b7
--- /dev/null
+++ b/tests/py/inet/comp.t.json.output
@@ -0,0 +1,166 @@
+# comp nexthdr != esp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": 50
+ }
+ }
+]
+
+# comp flags 0x0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# comp flags != 0x23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": 35
+ }
+ }
+]
+
+# comp flags 0x33-0x45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "right": {
+ "range": [ 51, 69 ]
+ }
+ }
+ }
+]
+
+# comp flags != 0x33-0x45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 51, 69 ]
+ }
+ }
+ }
+]
+
+# comp flags {0x33, 0x55, 0x67, 0x88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "right": {
+ "set": [
+ 51,
+ 85,
+ 103,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# comp flags != {0x33, 0x55, 0x67, 0x88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 51,
+ 85,
+ 103,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# comp flags { 0x33-0x55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 51, 85 ] }
+ ]
+ }
+ }
+ }
+]
+
+# comp flags != { 0x33-0x55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 51, 85 ] }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/ct.t.json b/tests/py/inet/ct.t.json
new file mode 100644
index 00000000..686c43f4
--- /dev/null
+++ b/tests/py/inet/ct.t.json
@@ -0,0 +1,39 @@
+# meta nfproto ipv4 ct original saddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "saddr"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# ct original ip6 saddr ::1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "family": "ip6",
+ "key": "saddr"
+ }
+ },
+ "right": "::1"
+ }
+ }
+]
+
diff --git a/tests/py/inet/ct.t.json.output b/tests/py/inet/ct.t.json.output
new file mode 100644
index 00000000..5605ebcf
--- /dev/null
+++ b/tests/py/inet/ct.t.json.output
@@ -0,0 +1,16 @@
+# meta nfproto ipv4 ct original saddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "family": "ip",
+ "key": "saddr"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ }
+]
+
diff --git a/tests/py/inet/dccp.t.json b/tests/py/inet/dccp.t.json
new file mode 100644
index 00000000..7f925047
--- /dev/null
+++ b/tests/py/inet/dccp.t.json
@@ -0,0 +1,340 @@
+# dccp sport 21-35
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "range": [ 21, 35 ]
+ }
+ }
+ }
+]
+
+# dccp sport != 21-35
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 21, 35 ]
+ }
+ }
+ }
+]
+
+# dccp sport {23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# dccp sport != {23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# dccp sport { 20-50 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 20, 50 ] }
+ ]
+ }
+ }
+ }
+]
+
+# dccp sport ftp-data - re-mail-ck
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "range": [ "ftp-data", "re-mail-ck" ]
+ }
+ }
+ }
+]
+
+# dccp sport 20-50
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "range": [ 20, 50 ]
+ }
+ }
+ }
+]
+
+# dccp sport { 20-50}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 20, 50 ] }
+ ]
+ }
+ }
+ }
+]
+
+# dccp sport != { 20-50}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 20, 50 ] }
+ ]
+ }
+ }
+ }
+]
+
+# dccp dport {23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# dccp dport != {23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# dccp dport { 20-50}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 20, 50 ] }
+ ]
+ }
+ }
+ }
+]
+
+# dccp dport != { 20-50}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 20, 50 ] }
+ ]
+ }
+ }
+ }
+]
+
+# dccp type {request, response, data, ack, dataack, closereq, close, reset, sync, syncack}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "set": [
+ "request",
+ "response",
+ "data",
+ "ack",
+ "dataack",
+ "closereq",
+ "close",
+ "reset",
+ "sync",
+ "syncack"
+ ]
+ }
+ }
+ }
+]
+
+# dccp type != {request, response, data, ack, dataack, closereq, close, reset, sync, syncack}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "request",
+ "response",
+ "data",
+ "ack",
+ "dataack",
+ "closereq",
+ "close",
+ "reset",
+ "sync",
+ "syncack"
+ ]
+ }
+ }
+ }
+]
+
+# dccp type request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "dccp"
+ }
+ },
+ "right": "request"
+ }
+ }
+]
+
+# dccp type != request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": "request"
+ }
+ }
+]
+
diff --git a/tests/py/inet/dccp.t.json.output b/tests/py/inet/dccp.t.json.output
new file mode 100644
index 00000000..9e3a57a7
--- /dev/null
+++ b/tests/py/inet/dccp.t.json.output
@@ -0,0 +1,17 @@
+# dccp sport ftp-data - re-mail-ck
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "dccp"
+ }
+ },
+ "right": {
+ "range": [ 20, 50 ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/esp.t.json b/tests/py/inet/esp.t.json
new file mode 100644
index 00000000..39c446c7
--- /dev/null
+++ b/tests/py/inet/esp.t.json
@@ -0,0 +1,256 @@
+# esp spi 100
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "esp"
+ }
+ },
+ "right": 100
+ }
+ }
+]
+
+# esp spi != 100
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "esp"
+ }
+ },
+ "op": "!=",
+ "right": 100
+ }
+ }
+]
+
+# esp spi 111-222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "esp"
+ }
+ },
+ "right": {
+ "range": [ 111, 222 ]
+ }
+ }
+ }
+]
+
+# esp spi != 111-222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 111, 222 ]
+ }
+ }
+ }
+]
+
+# esp spi { 100, 102}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "esp"
+ }
+ },
+ "right": {
+ "set": [
+ 100,
+ 102
+ ]
+ }
+ }
+ }
+]
+
+# esp spi != { 100, 102}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 100,
+ 102
+ ]
+ }
+ }
+ }
+]
+
+# esp spi { 100-102}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "name": "esp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 100, 102 ] }
+ ]
+ }
+ }
+ }
+]
+
+# esp sequence 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "esp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# esp sequence 22-24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "esp"
+ }
+ },
+ "right": {
+ "range": [ 22, 24 ]
+ }
+ }
+ }
+]
+
+# esp sequence != 22-24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 22, 24 ]
+ }
+ }
+ }
+]
+
+# esp sequence { 22, 24}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "esp"
+ }
+ },
+ "right": {
+ "set": [
+ 22,
+ 24
+ ]
+ }
+ }
+ }
+]
+
+# esp sequence != { 22, 24}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 22,
+ 24
+ ]
+ }
+ }
+ }
+]
+
+# esp sequence { 22-25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "esp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 22, 25 ] }
+ ]
+ }
+ }
+ }
+]
+
+# esp sequence != { 22-25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 22, 25 ] }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/ether-ip.t.json b/tests/py/inet/ether-ip.t.json
new file mode 100644
index 00000000..0c0964e6
--- /dev/null
+++ b/tests/py/inet/ether-ip.t.json
@@ -0,0 +1,85 @@
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "right": "ether"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ }
+]
+
diff --git a/tests/py/inet/ether-ip.t.json.output b/tests/py/inet/ether-ip.t.json.output
new file mode 100644
index 00000000..80f8a4c3
--- /dev/null
+++ b/tests/py/inet/ether-ip.t.json.output
@@ -0,0 +1,40 @@
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/inet/ether.t.json b/tests/py/inet/ether.t.json
new file mode 100644
index 00000000..0daf46e9
--- /dev/null
+++ b/tests/py/inet/ether.t.json
@@ -0,0 +1,84 @@
+# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "right": "ether"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ether saddr 00:0f:54:0c:11:04 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/inet/ether.t.json.output b/tests/py/inet/ether.t.json.output
new file mode 100644
index 00000000..bd7bd67e
--- /dev/null
+++ b/tests/py/inet/ether.t.json.output
@@ -0,0 +1,29 @@
+# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/inet/fib.t.json b/tests/py/inet/fib.t.json
new file mode 100644
index 00000000..cb15e397
--- /dev/null
+++ b/tests/py/inet/fib.t.json
@@ -0,0 +1,128 @@
+# fib saddr . iif oif ne 0
+[
+ {
+ "match": {
+ "left": {
+ "fib": {
+ "flags": [
+ "saddr",
+ "iif"
+ ],
+ "result": "oif"
+ }
+ },
+ "op": "!=",
+ "right": "0"
+ }
+ }
+]
+
+# fib saddr . iif oifname "lo"
+[
+ {
+ "match": {
+ "left": {
+ "fib": {
+ "flags": [
+ "saddr",
+ "iif"
+ ],
+ "result": "oifname"
+ }
+ },
+ "right": "lo"
+ }
+ }
+]
+
+# fib daddr . iif type local
+[
+ {
+ "match": {
+ "left": {
+ "fib": {
+ "flags": [
+ "daddr",
+ "iif"
+ ],
+ "result": "type"
+ }
+ },
+ "right": "local"
+ }
+ }
+]
+
+# fib daddr . iif type vmap { blackhole : drop, prohibit : drop, unicast : accept }
+[
+ {
+ "map": {
+ "left": {
+ "fib": {
+ "flags": [
+ "daddr",
+ "iif"
+ ],
+ "result": "type"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ "blackhole",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "prohibit",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "unicast",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# fib daddr oif exists
+[
+ {
+ "match": {
+ "left": {
+ "fib": {
+ "flags": [
+ "daddr"
+ ],
+ "result": "oif"
+ }
+ },
+ "right": true
+ }
+ }
+]
+
+# fib daddr oif missing
+[
+ {
+ "match": {
+ "left": {
+ "fib": {
+ "flags": [
+ "daddr"
+ ],
+ "result": "oif"
+ }
+ },
+ "right": false
+ }
+ }
+]
+
diff --git a/tests/py/inet/fib.t.json.output b/tests/py/inet/fib.t.json.output
new file mode 100644
index 00000000..c473b2af
--- /dev/null
+++ b/tests/py/inet/fib.t.json.output
@@ -0,0 +1,39 @@
+# fib daddr . iif type vmap { blackhole : drop, prohibit : drop, unicast : accept }
+[
+ {
+ "map": {
+ "left": {
+ "fib": {
+ "flags": [
+ "daddr",
+ "iif"
+ ],
+ "result": "type"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ "unicast",
+ {
+ "accept": null
+ }
+ ],
+ [
+ "blackhole",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "prohibit",
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/icmpX.t.json b/tests/py/inet/icmpX.t.json
new file mode 100644
index 00000000..006419e3
--- /dev/null
+++ b/tests/py/inet/icmpX.t.json
@@ -0,0 +1,116 @@
+# ip protocol icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "name": "ip6"
+ }
+ },
+ "right": "icmpv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip protocol ipv6-icmp meta l4proto ipv6-icmp icmpv6 type 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "ipv6-icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": "ipv6-icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
diff --git a/tests/py/inet/icmpX.t.json.output b/tests/py/inet/icmpX.t.json.output
new file mode 100644
index 00000000..94034388
--- /dev/null
+++ b/tests/py/inet/icmpX.t.json.output
@@ -0,0 +1,86 @@
+# ip protocol icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "name": "ip6"
+ }
+ },
+ "right": 58
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip protocol ipv6-icmp meta l4proto ipv6-icmp icmpv6 type 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 58
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": 58
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "destination-unreachable"
+ }
+ }
+]
+
diff --git a/tests/py/inet/ip.t.json b/tests/py/inet/ip.t.json
new file mode 100644
index 00000000..b2327377
--- /dev/null
+++ b/tests/py/inet/ip.t.json
@@ -0,0 +1,41 @@
+# ip saddr . ip daddr . ether saddr { 1.1.1.1 . 2.2.2.2 . ca:fe:ca:fe:ca:fe }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.1.1.1",
+ "2.2.2.2",
+ "ca:fe:ca:fe:ca:fe"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/ip_tcp.t.json b/tests/py/inet/ip_tcp.t.json
new file mode 100644
index 00000000..f9c8b5c6
--- /dev/null
+++ b/tests/py/inet/ip_tcp.t.json
@@ -0,0 +1,158 @@
+# ip protocol tcp tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp ip saddr 1.2.3.4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp counter ip saddr 1.2.3.4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp counter tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ether type ip tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "ether"
+ }
+ },
+ "right": "ip"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
diff --git a/tests/py/inet/ip_tcp.t.json.output b/tests/py/inet/ip_tcp.t.json.output
new file mode 100644
index 00000000..1581f30e
--- /dev/null
+++ b/tests/py/inet/ip_tcp.t.json.output
@@ -0,0 +1,121 @@
+# ip protocol tcp tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp ip saddr 1.2.3.4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp counter ip saddr 1.2.3.4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp counter tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
diff --git a/tests/py/inet/map.t.json b/tests/py/inet/map.t.json
new file mode 100644
index 00000000..b7bb10a9
--- /dev/null
+++ b/tests/py/inet/map.t.json
@@ -0,0 +1,66 @@
+# mark set ip saddr map { 10.2.3.2 : 0x0000002a, 10.2.3.1 : 0x00000017}
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ "10.2.3.2",
+ "0x0000002a"
+ ],
+ [
+ "10.2.3.1",
+ "0x00000017"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# mark set ip hdrlength map { 5 : 0x00000017, 4 : 0x00000001}
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 5,
+ "0x00000017"
+ ],
+ [
+ 4,
+ "0x00000001"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/map.t.json.output b/tests/py/inet/map.t.json.output
new file mode 100644
index 00000000..5a410b3b
--- /dev/null
+++ b/tests/py/inet/map.t.json.output
@@ -0,0 +1,66 @@
+# mark set ip saddr map { 10.2.3.2 : 0x0000002a, 10.2.3.1 : 0x00000017}
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ "10.2.3.1",
+ 23
+ ],
+ [
+ "10.2.3.2",
+ 42
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# mark set ip hdrlength map { 5 : 0x00000017, 4 : 0x00000001}
+[
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 4,
+ 1
+ ],
+ [
+ 5,
+ 23
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/meta.t.json b/tests/py/inet/meta.t.json
new file mode 100644
index 00000000..2687f69e
--- /dev/null
+++ b/tests/py/inet/meta.t.json
@@ -0,0 +1,198 @@
+# meta nfproto ipv4
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ }
+]
+
+# meta nfproto ipv6
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ }
+]
+
+# meta nfproto {ipv4, ipv6}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": {
+ "set": [
+ "ipv4",
+ "ipv6"
+ ]
+ }
+ }
+ }
+]
+
+# meta nfproto != {ipv4, ipv6}
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ipv4",
+ "ipv6"
+ ]
+ }
+ }
+ }
+]
+
+# meta nfproto ipv6 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# meta nfproto ipv4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# meta nfproto ipv4 ip saddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# meta nfproto ipv6 meta l4proto tcp
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": "tcp"
+ }
+ }
+]
+
+# meta nfproto ipv4 counter ip saddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# meta secpath exists
+[
+ {
+ "match": {
+ "left": {
+ "meta": "secpath"
+ },
+ "right": true
+ }
+ }
+]
+
+# meta secpath missing
+[
+ {
+ "match": {
+ "left": {
+ "meta": "secpath"
+ },
+ "right": false
+ }
+ }
+]
+
diff --git a/tests/py/inet/meta.t.json.output b/tests/py/inet/meta.t.json.output
new file mode 100644
index 00000000..19b2d262
--- /dev/null
+++ b/tests/py/inet/meta.t.json.output
@@ -0,0 +1,35 @@
+# meta nfproto ipv4 ip saddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# meta nfproto ipv6 meta l4proto tcp
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": 6
+ }
+ }
+]
+
diff --git a/tests/py/inet/reject.t.json b/tests/py/inet/reject.t.json
new file mode 100644
index 00000000..0939f445
--- /dev/null
+++ b/tests/py/inet/reject.t.json
@@ -0,0 +1,240 @@
+# reject with icmp type host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-unreachable
+[
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type prot-unreachable
+[
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-prohibited
+[
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type host-prohibited
+[
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmpv6 type no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type addr-unreachable
+[
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# mark 12345 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 12345
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject
+[
+ {
+ "reject": null
+ }
+]
+
+# meta nfproto ipv4 reject
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# meta nfproto ipv6 reject
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# reject with icmpx type host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx type no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# meta nfproto ipv4 reject with icmp type host-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# meta nfproto ipv6 reject with icmpv6 type no-route
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
diff --git a/tests/py/inet/reject.t.json.output b/tests/py/inet/reject.t.json.output
new file mode 100644
index 00000000..b1e77990
--- /dev/null
+++ b/tests/py/inet/reject.t.json.output
@@ -0,0 +1,224 @@
+# reject with icmp type host-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type prot-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type port-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# reject with icmp type net-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type host-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmpv6 type no-route
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type addr-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type port-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv6"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# mark 12345 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 12345
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject with icmpx type port-unreachable
+[
+ {
+ "reject": null
+ }
+]
+
diff --git a/tests/py/inet/rt.t.json b/tests/py/inet/rt.t.json
new file mode 100644
index 00000000..32e1d437
--- /dev/null
+++ b/tests/py/inet/rt.t.json
@@ -0,0 +1,56 @@
+# meta nfproto ipv4 rt nexthop 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "key": "nexthop"
+ }
+ },
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# rt ip6 nexthop fd00::1
+[
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "family": "ip6",
+ "key": "nexthop"
+ }
+ },
+ "right": "fd00::1"
+ }
+ }
+]
+
+# tcp option maxseg size set rt mtu
+[
+ {
+ "mangle": {
+ "left": {
+ "tcp option": {
+ "field": "size",
+ "name": "maxseg"
+ }
+ },
+ "right": {
+ "rt": {
+ "key": "mtu"
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/rt.t.json.output b/tests/py/inet/rt.t.json.output
new file mode 100644
index 00000000..1d3ecac1
--- /dev/null
+++ b/tests/py/inet/rt.t.json.output
@@ -0,0 +1,23 @@
+# meta nfproto ipv4 rt nexthop 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "meta": "nfproto"
+ },
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "family": "ip",
+ "key": "nexthop"
+ }
+ },
+ "right": "192.168.0.1"
+ }
+ }
+]
+
diff --git a/tests/py/inet/sctp.t.json b/tests/py/inet/sctp.t.json
new file mode 100644
index 00000000..86193080
--- /dev/null
+++ b/tests/py/inet/sctp.t.json
@@ -0,0 +1,594 @@
+# sctp sport 23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "sctp"
+ }
+ },
+ "right": 23
+ }
+ }
+]
+
+# sctp sport != 23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": 23
+ }
+ }
+]
+
+# sctp sport 23-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "range": [ 23, 44 ]
+ }
+ }
+ }
+]
+
+# sctp sport != 23-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 23, 44 ]
+ }
+ }
+ }
+]
+
+# sctp sport { 23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# sctp sport != { 23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# sctp sport { 23-44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 23, 44 ] }
+ ]
+ }
+ }
+ }
+]
+
+# sctp sport != { 23-44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 23, 44 ] }
+ ]
+ }
+ }
+ }
+]
+
+# sctp dport 23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "sctp"
+ }
+ },
+ "right": 23
+ }
+ }
+]
+
+# sctp dport != 23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": 23
+ }
+ }
+]
+
+# sctp dport 23-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "range": [ 23, 44 ]
+ }
+ }
+ }
+]
+
+# sctp dport != 23-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 23, 44 ]
+ }
+ }
+ }
+]
+
+# sctp dport { 23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# sctp dport != { 23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# sctp dport { 23-44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 23, 44 ] }
+ ]
+ }
+ }
+ }
+]
+
+# sctp dport != { 23-44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 23, 44 ] }
+ ]
+ }
+ }
+ }
+]
+
+# sctp checksum 1111
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "sctp"
+ }
+ },
+ "right": 1111
+ }
+ }
+]
+
+# sctp checksum != 11
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": 11
+ }
+ }
+]
+
+# sctp checksum 21-333
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "range": [ 21, 333 ]
+ }
+ }
+ }
+]
+
+# sctp checksum != 32-111
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 32, 111 ]
+ }
+ }
+ }
+]
+
+# sctp checksum { 22, 33, 44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "set": [
+ 22,
+ 33,
+ 44
+ ]
+ }
+ }
+ }
+]
+
+# sctp checksum != { 22, 33, 44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 22,
+ 33,
+ 44
+ ]
+ }
+ }
+ }
+]
+
+# sctp checksum { 22-44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 22, 44 ] }
+ ]
+ }
+ }
+ }
+]
+
+# sctp checksum != { 22-44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 22, 44 ] }
+ ]
+ }
+ }
+ }
+]
+
+# sctp vtag 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "name": "sctp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# sctp vtag != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# sctp vtag 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# sctp vtag != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# sctp vtag {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# sctp vtag != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# sctp vtag { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "name": "sctp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# sctp vtag != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "name": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/tcp.t.json b/tests/py/inet/tcp.t.json
new file mode 100644
index 00000000..559206df
--- /dev/null
+++ b/tests/py/inet/tcp.t.json
@@ -0,0 +1,1552 @@
+# tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp dport != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp dport 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp dport != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp dport { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport {telnet, http, https} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ "telnet",
+ "http",
+ "https"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp dport vmap { 22 : accept, 23 : drop }
+[
+ {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 22,
+ {
+ "accept": null
+ }
+ ],
+ [
+ 23,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport vmap { 25:accept, 28:drop }
+[
+ {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 25,
+ {
+ "accept": null
+ }
+ ],
+ [
+ 28,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport { 22, 53, 80, 110 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 22,
+ 53,
+ 80,
+ 110
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport != { 22, 53, 80, 110 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 22,
+ 53,
+ 80,
+ 110
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp sport != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp sport 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp sport != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp sport { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport vmap { 25:accept, 28:drop }
+[
+ {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 25,
+ {
+ "accept": null
+ }
+ ],
+ [
+ 28,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport 8080 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": 8080
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# tcp sport 1024 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": 1024
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp sport 1024 tcp dport 22 tcp sequence 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": 1024
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# tcp sequence 0 tcp sport 1024 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "right": 0
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": 1024
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp sequence 0 tcp sport { 1024, 1022} tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "right": 0
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 1024,
+ 1022
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp sequence 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp sequence != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp sequence 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp sequence != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp sequence { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp sequence != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp sequence { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp sequence != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp ackseq 42949672 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "name": "tcp"
+ }
+ },
+ "right": 42949672
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# tcp ackseq 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp ackseq != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp ackseq 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp ackseq != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp ackseq { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp ackseq != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp ackseq { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp ackseq != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp flags { fin, syn, rst, psh, ack, urg, ecn, cwr} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ "fin",
+ "syn",
+ "rst",
+ "psh",
+ "ack",
+ "urg",
+ "ecn",
+ "cwr"
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# tcp flags != { fin, urg, ecn, cwr} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "fin",
+ "urg",
+ "ecn",
+ "cwr"
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# tcp flags cwr
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "tcp"
+ }
+ },
+ "right": "cwr"
+ }
+ }
+]
+
+# tcp flags != cwr
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": "cwr"
+ }
+ }
+]
+
+# tcp flags & (syn|fin) == (syn|fin)
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "name": "tcp"
+ }
+ },
+ {
+ "|": [
+ "syn",
+ "fin"
+ ]
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "|": [
+ "syn",
+ "fin"
+ ]
+ }
+ }
+ }
+]
+
+# tcp window 22222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "name": "tcp"
+ }
+ },
+ "right": 22222
+ }
+ }
+]
+
+# tcp window 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp window != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp window 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp window != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp window { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp window != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp window { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp window != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp checksum 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp checksum != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp checksum 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp checksum != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp checksum { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp checksum != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp checksum { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp checksum != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp urgptr 1234 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "name": "tcp"
+ }
+ },
+ "right": 1234
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp urgptr 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# tcp urgptr != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp urgptr 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp urgptr != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp urgptr { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp urgptr != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp urgptr { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp urgptr != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# tcp doff 8
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "doff",
+ "name": "tcp"
+ }
+ },
+ "right": 8
+ }
+ }
+]
+
diff --git a/tests/py/inet/tcp.t.json.output b/tests/py/inet/tcp.t.json.output
new file mode 100644
index 00000000..d099d6fe
--- /dev/null
+++ b/tests/py/inet/tcp.t.json.output
@@ -0,0 +1,134 @@
+# tcp dport {telnet, http, https} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 23,
+ 80,
+ 443
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp sequence 0 tcp sport 1024 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": 1024
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# tcp sequence 0 tcp sport { 1024, 1022} tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 1022,
+ 1024
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "tcp"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# tcp flags & (syn|fin) == (syn|fin)
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "name": "tcp"
+ }
+ },
+ {
+ "|": [
+ "fin",
+ "syn"
+ ]
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "|": [
+ "fin",
+ "syn"
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/tcpopt.t.json b/tests/py/inet/tcpopt.t.json
new file mode 100644
index 00000000..d4632187
--- /dev/null
+++ b/tests/py/inet/tcpopt.t.json
@@ -0,0 +1,418 @@
+# tcp option eol kind 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "kind",
+ "name": "eol"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option noop kind 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "kind",
+ "name": "noop"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option maxseg kind 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "kind",
+ "name": "maxseg"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option maxseg length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "maxseg"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option maxseg size 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "size",
+ "name": "maxseg"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option window kind 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "kind",
+ "name": "window"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option window length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "window"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option window count 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "count",
+ "name": "window"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack-permitted kind 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "kind",
+ "name": "sack-permitted"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack-permitted length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "sack-permitted"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack kind 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "kind",
+ "name": "sack"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "sack"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack0 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack0"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack1 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack1"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack2 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack2"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack3 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack3"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack0 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack0"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack1 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack1"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack2 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack2"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack3 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack3"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option timestamp kind 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "kind",
+ "name": "timestamp"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option timestamp length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "timestamp"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option timestamp tsval 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "tsval",
+ "name": "timestamp"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option timestamp tsecr 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "tsecr",
+ "name": "timestamp"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option window exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "window"
+ }
+ },
+ "right": true
+ }
+ }
+]
+
+# tcp option window missing
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "window"
+ }
+ },
+ "right": false
+ }
+ }
+]
+
+# tcp option maxseg size set 1360
+[
+ {
+ "mangle": {
+ "left": {
+ "tcp option": {
+ "field": "size",
+ "name": "maxseg"
+ }
+ },
+ "right": 1360
+ }
+ }
+]
+
diff --git a/tests/py/inet/tcpopt.t.json.output b/tests/py/inet/tcpopt.t.json.output
new file mode 100644
index 00000000..302108c2
--- /dev/null
+++ b/tests/py/inet/tcpopt.t.json.output
@@ -0,0 +1,30 @@
+# tcp option sack0 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack0 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
diff --git a/tests/py/inet/udp.t.json b/tests/py/inet/udp.t.json
new file mode 100644
index 00000000..d760fb75
--- /dev/null
+++ b/tests/py/inet/udp.t.json
@@ -0,0 +1,730 @@
+# udp sport 80 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udp"
+ }
+ },
+ "right": 80
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp sport != 60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": 60
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp sport 50-70 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "range": [ 50, 70 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp sport != 50-60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 60 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp sport { 49, 50} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udp sport != { 50, 60} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 50,
+ 60
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp sport { 12-40}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 12, 40 ] }
+ ]
+ }
+ }
+ }
+]
+
+# udp sport != { 13-24}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 13, 24 ] }
+ ]
+ }
+ }
+ }
+]
+
+# udp dport 80 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 80
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport != 60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": 60
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport 70-75 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "range": [ 70, 75 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport != 50-60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 60 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport { 49, 50} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udp dport != { 50, 60} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 50,
+ 60
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport { 70-75} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 70, 75 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport != { 50-60} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 50, 60 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp length 6666
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "udp"
+ }
+ },
+ "right": 6666
+ }
+ }
+]
+
+# udp length != 6666
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": 6666
+ }
+ }
+]
+
+# udp length 50-65 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "range": [ 50, 65 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp length != 50-65 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 65 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp length { 50, 65} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "set": [
+ 50,
+ 65
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp length != { 50, 65} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 50,
+ 65
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp length { 35-50}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 35, 50 ] }
+ ]
+ }
+ }
+ }
+]
+
+# udp length != { 35-50}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 35, 50 ] }
+ ]
+ }
+ }
+ }
+]
+
+# udp checksum 6666 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "right": 6666
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udp checksum != { 444, 555} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 444,
+ 555
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp checksum 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# udp checksum != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# udp checksum 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# udp checksum != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# udp checksum { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# udp checksum != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# udp checksum { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# udp checksum != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# iif "lo" udp checksum set 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udp"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# iif "lo" udp dport set 65535
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 65535
+ }
+ }
+]
+
diff --git a/tests/py/inet/udplite.t.json b/tests/py/inet/udplite.t.json
new file mode 100644
index 00000000..5173a68c
--- /dev/null
+++ b/tests/py/inet/udplite.t.json
@@ -0,0 +1,526 @@
+# udplite sport 80 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udplite"
+ }
+ },
+ "right": 80
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite sport != 60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": 60
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite sport 50-70 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udplite"
+ }
+ },
+ "right": {
+ "range": [ 50, 70 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite sport != 50-60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 60 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite sport { 49, 50} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udplite"
+ }
+ },
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udplite sport != { 49, 50} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite sport { 12-40}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udplite"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 12, 40 ] }
+ ]
+ }
+ }
+ }
+]
+
+# udplite sport != { 12-40}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 12, 40 ] }
+ ]
+ }
+ }
+ }
+]
+
+# udplite dport 80 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udplite"
+ }
+ },
+ "right": 80
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport != 60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": 60
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport 70-75 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udplite"
+ }
+ },
+ "right": {
+ "range": [ 70, 75 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport != 50-60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 60 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport { 49, 50} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udplite"
+ }
+ },
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udplite dport != { 49, 50} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport { 70-75} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udplite"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 70, 75 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport != { 70-75} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 70, 75 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite checksum 6666 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "right": 6666
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udplite checksum != { 444, 555} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 444,
+ 555
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite checksum 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# udplite checksum != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# udplite checksum 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# udplite checksum != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# udplite checksum { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# udplite checksum != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# udplite checksum { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# udplite checksum != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/ct.t.json b/tests/py/ip/ct.t.json
new file mode 100644
index 00000000..6314d5b2
--- /dev/null
+++ b/tests/py/ip/ct.t.json
@@ -0,0 +1,213 @@
+# ct original ip saddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "family": "ip",
+ "key": "saddr"
+ }
+ },
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ct reply ip saddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "family": "ip",
+ "key": "saddr"
+ }
+ },
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ct original ip daddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "family": "ip",
+ "key": "daddr"
+ }
+ },
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ct reply ip daddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "family": "ip",
+ "key": "daddr"
+ }
+ },
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ct original ip saddr 192.168.1.0/24
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "family": "ip",
+ "key": "saddr"
+ }
+ },
+ "right": {
+ "prefix": {
+ "addr": "192.168.1.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ct reply ip saddr 192.168.1.0/24
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "family": "ip",
+ "key": "saddr"
+ }
+ },
+ "right": {
+ "prefix": {
+ "addr": "192.168.1.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ct original ip daddr 192.168.1.0/24
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "family": "ip",
+ "key": "daddr"
+ }
+ },
+ "right": {
+ "prefix": {
+ "addr": "192.168.1.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ct reply ip daddr 192.168.1.0/24
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "family": "ip",
+ "key": "daddr"
+ }
+ },
+ "right": {
+ "prefix": {
+ "addr": "192.168.1.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ct l3proto ipv4
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "l3proto"
+ }
+ },
+ "right": "ipv4"
+ }
+ }
+]
+
+# ct protocol 6 ct original proto-dst 22
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "protocol"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "proto-dst"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ct original protocol 17 ct reply proto-src 53
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "protocol"
+ }
+ },
+ "right": 17
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "proto-src"
+ }
+ },
+ "right": 53
+ }
+ }
+]
+
diff --git a/tests/py/ip/ct.t.json.output b/tests/py/ip/ct.t.json.output
new file mode 100644
index 00000000..2429ec69
--- /dev/null
+++ b/tests/py/ip/ct.t.json.output
@@ -0,0 +1,25 @@
+# ct original protocol 17 ct reply proto-src 53
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "protocol"
+ }
+ },
+ "right": 17
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "proto-src"
+ }
+ },
+ "right": 53
+ }
+ }
+]
+
diff --git a/tests/py/ip/dnat.t.json b/tests/py/ip/dnat.t.json
new file mode 100644
index 00000000..56f8272f
--- /dev/null
+++ b/tests/py/ip/dnat.t.json
@@ -0,0 +1,255 @@
+# iifname "eth0" tcp dport 80-90 dnat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "range": [ 80, 90 ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport != 80-90 dnat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 80, 90 ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport {80, 90, 23} dnat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 23,
+ 80,
+ 90
+ ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport != {80, 90, 23} dnat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 80,
+ 90
+ ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport != 23-34 dnat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 23, 34 ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 81 dnat to 192.168.3.2:8080
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 81
+ }
+ },
+ {
+ "dnat": {
+ "addr": "192.168.3.2",
+ "port": 8080
+ }
+ }
+]
+
+# dnat to ct mark map { 0x00000014 : 1.2.3.4}
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ "0x00000014",
+ "1.2.3.4"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# dnat to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4}
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ [
+ {
+ "concat": [
+ "0x00000014",
+ "1.1.1.1"
+ ]
+ },
+ "1.2.3.4"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/dnat.t.json.output b/tests/py/ip/dnat.t.json.output
new file mode 100644
index 00000000..73b6b204
--- /dev/null
+++ b/tests/py/ip/dnat.t.json.output
@@ -0,0 +1,65 @@
+# dnat to ct mark map { 0x00000014 : 1.2.3.4}
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 20,
+ "1.2.3.4"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# dnat to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4}
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ }
+ ]
+ },
+ "right": {
+ "set": [
+ [
+ {
+ "concat": [
+ 20,
+ "1.1.1.1"
+ ]
+ },
+ "1.2.3.4"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/dup.t.json b/tests/py/ip/dup.t.json
new file mode 100644
index 00000000..abc5be47
--- /dev/null
+++ b/tests/py/ip/dup.t.json
@@ -0,0 +1,46 @@
+# dup to 192.168.2.1
+[
+ {
+ "dup": {
+ "addr": "192.168.2.1"
+ }
+ }
+]
+
+# dup to 192.168.2.1 device "lo"
+[
+ {
+ "dup": {
+ "addr": "192.168.2.1",
+ "dev": "lo"
+ }
+ }
+]
+
+# dup to ip saddr map { 192.168.2.120 : 192.168.2.1 } device "lo"
+[
+ {
+ "dup": {
+ "addr": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ "192.168.2.120",
+ "192.168.2.1"
+ ]
+ ]
+ }
+ }
+ },
+ "dev": "lo"
+ }
+ }
+]
+
diff --git a/tests/py/ip/ether.t.json b/tests/py/ip/ether.t.json
new file mode 100644
index 00000000..022ae0b5
--- /dev/null
+++ b/tests/py/ip/ether.t.json
@@ -0,0 +1,151 @@
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": "iiftype"
+ },
+ "right": "ether"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ }
+]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/ip/ether.t.json.output b/tests/py/ip/ether.t.json.output
new file mode 100644
index 00000000..d3127161
--- /dev/null
+++ b/tests/py/ip/ether.t.json.output
@@ -0,0 +1,40 @@
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ether"
+ }
+ },
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/ip/flowtable.t.json b/tests/py/ip/flowtable.t.json
new file mode 100644
index 00000000..e6fc09f4
--- /dev/null
+++ b/tests/py/ip/flowtable.t.json
@@ -0,0 +1,23 @@
+# meter xyz { ip saddr timeout 30s counter}
+[
+ {
+ "meter": {
+ "key": {
+ "elem": {
+ "elem_timeout": 30,
+ "val": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ }
+ }
+ },
+ "name": "xyz",
+ "stmt": {
+ "counter": null
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/hash.t.json b/tests/py/ip/hash.t.json
new file mode 100644
index 00000000..a463f94d
--- /dev/null
+++ b/tests/py/ip/hash.t.json
@@ -0,0 +1,230 @@
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ }
+ ]
+ },
+ "mod": 2,
+ "seed": 3735928559
+ }
+ }
+ }
+ }
+]
+
+# ct mark set jhash ip saddr . ip daddr mod 2
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ }
+ ]
+ },
+ "mod": 2
+ }
+ }
+ }
+ }
+]
+
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0x0
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ }
+ ]
+ },
+ "mod": 2,
+ "seed": 0
+ }
+ }
+ }
+ }
+]
+
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef offset 100
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ }
+ ]
+ },
+ "mod": 2,
+ "offset": 100,
+ "seed": 3735928559
+ }
+ }
+ }
+ }
+]
+
+# ct mark set jhash ip saddr . ip daddr mod 2 offset 100
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ }
+ ]
+ },
+ "mod": 2,
+ "offset": 100
+ }
+ }
+ }
+ }
+]
+
+# dnat to jhash ip saddr mod 2 seed 0xdeadbeef map { 0 : 192.168.20.100, 1 : 192.168.30.100 }
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "left": {
+ "jhash": {
+ "expr": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "mod": 2,
+ "seed": 3735928559
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 0,
+ "192.168.20.100"
+ ],
+ [
+ 1,
+ "192.168.30.100"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# ct mark set symhash mod 2 offset 100
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "symhash": {
+ "mod": 2,
+ "offset": 100
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/icmp.t.json b/tests/py/ip/icmp.t.json
new file mode 100644
index 00000000..4d51ad2f
--- /dev/null
+++ b/tests/py/ip/icmp.t.json
@@ -0,0 +1,1382 @@
+# icmp type echo-reply accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-reply"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type destination-unreachable accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "destination-unreachable"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type source-quench accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "source-quench"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type redirect accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "redirect"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type echo-request accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type time-exceeded accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "time-exceeded"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type parameter-problem accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "parameter-problem"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type timestamp-request accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "timestamp-request"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type timestamp-reply accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "timestamp-reply"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type info-request accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "info-request"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type info-reply accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "info-reply"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type address-mask-request accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "address-mask-request"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type address-mask-reply accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "address-mask-reply"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type router-advertisement accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "router-advertisement"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type router-solicitation accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "router-solicitation"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type {echo-reply, destination-unreachable, source-quench, redirect, echo-request, time-exceeded, parameter-problem, timestamp-request, timestamp-reply, info-request, info-reply, address-mask-request, address-mask-reply, router-advertisement, router-solicitation} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ "echo-reply",
+ "destination-unreachable",
+ "source-quench",
+ "redirect",
+ "echo-request",
+ "time-exceeded",
+ "parameter-problem",
+ "timestamp-request",
+ "timestamp-reply",
+ "info-request",
+ "info-reply",
+ "address-mask-request",
+ "address-mask-reply",
+ "router-advertisement",
+ "router-solicitation"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type != {echo-reply, destination-unreachable, source-quench}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "echo-reply",
+ "destination-unreachable",
+ "source-quench"
+ ]
+ }
+ }
+ }
+]
+
+# icmp code 111 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "name": "icmp"
+ }
+ },
+ "right": 111
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp code != 111 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 111
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp code 33-55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "range": [ 33, 55 ]
+ }
+ }
+ }
+]
+
+# icmp code != 33-55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 55 ]
+ }
+ }
+ }
+]
+
+# icmp code { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp code != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp code { 2, 4, 54, 33, 56}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ 2,
+ 4,
+ 33,
+ 54,
+ 56
+ ]
+ }
+ }
+ }
+]
+
+# icmp code != { 2, 4, 54, 33, 56}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 2,
+ 4,
+ 33,
+ 54,
+ 56
+ ]
+ }
+ }
+ }
+]
+
+# icmp checksum 12343 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "right": 12343
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum != 12343 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 12343
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum 11-343 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "range": [ 11, 343 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum != 11-343 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 11, 343 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum { 11-343} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 11, 343 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum != { 11-343} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 11, 343 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum { 1111, 222, 343} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ 1111,
+ 222,
+ 343
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum != { 1111, 222, 343} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 1111,
+ 222,
+ 343
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp id 1245 log
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "icmp"
+ }
+ },
+ "right": 1245
+ }
+ },
+ {
+ "log": null
+ }
+]
+
+# icmp id 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "icmp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# icmp id != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmp id 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmp id != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmp id { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp id != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp id { 22, 34, 333}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ 22,
+ 34,
+ 333
+ ]
+ }
+ }
+ }
+]
+
+# icmp id != { 22, 34, 333}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 22,
+ 34,
+ 333
+ ]
+ }
+ }
+ }
+]
+
+# icmp sequence 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "icmp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# icmp sequence != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmp sequence 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmp sequence != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmp sequence { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp sequence != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp sequence { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp sequence != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu 33
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "right": 33
+ }
+ }
+]
+
+# icmp mtu 22-33
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "range": [ 22, 33 ]
+ }
+ }
+ }
+]
+
+# icmp mtu { 22-33}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 22, 33 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu != { 22-33}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 22, 33 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# icmp mtu != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmp mtu 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmp mtu != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmp mtu { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# icmp gateway != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmp gateway 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmp gateway != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmp gateway { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway != 34
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 34
+ }
+ }
+]
+
+# icmp gateway != { 333, 334}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 333,
+ 334
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/icmp.t.json.output b/tests/py/ip/icmp.t.json.output
new file mode 100644
index 00000000..488048f7
--- /dev/null
+++ b/tests/py/ip/icmp.t.json.output
@@ -0,0 +1,85 @@
+# icmp type {echo-reply, destination-unreachable, source-quench, redirect, echo-request, time-exceeded, parameter-problem, timestamp-request, timestamp-reply, info-request, info-reply, address-mask-request, address-mask-reply, router-advertisement, router-solicitation} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ "echo-reply",
+ "destination-unreachable",
+ "source-quench",
+ "redirect",
+ "echo-request",
+ "router-advertisement",
+ "router-solicitation",
+ "time-exceeded",
+ "parameter-problem",
+ "timestamp-request",
+ "timestamp-reply",
+ "info-request",
+ "info-reply",
+ "address-mask-request",
+ "address-mask-reply"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum { 1111, 222, 343} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "right": {
+ "set": [
+ 222,
+ 343,
+ 1111
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum != { 1111, 222, 343} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 222,
+ 343,
+ 1111
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/ip/ip.t.json b/tests/py/ip/ip.t.json
new file mode 100644
index 00000000..abd45ce7
--- /dev/null
+++ b/tests/py/ip/ip.t.json
@@ -0,0 +1,1781 @@
+# ip dscp cs1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "right": "cs1"
+ }
+ }
+]
+
+# ip dscp != cs1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "cs1"
+ }
+ }
+]
+
+# ip dscp 0x38
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "right": "0x38"
+ }
+ }
+]
+
+# ip dscp != 0x20
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "0x20"
+ }
+ }
+]
+
+# ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ "cs0",
+ "cs1",
+ "cs2",
+ "cs3",
+ "cs4",
+ "cs5",
+ "cs6",
+ "cs7",
+ "af11",
+ "af12",
+ "af13",
+ "af21",
+ "af22",
+ "af23",
+ "af31",
+ "af32",
+ "af33",
+ "af41",
+ "af42",
+ "af43",
+ "ef"
+ ]
+ }
+ }
+ }
+]
+
+# ip dscp != {cs0, cs3}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "cs0",
+ "cs3"
+ ]
+ }
+ }
+ }
+]
+
+# ip dscp vmap { cs1 : continue , cs4 : accept } counter
+[
+ {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ "cs1",
+ {
+ "continue": null
+ }
+ ],
+ [
+ "cs4",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "counter": null
+ }
+]
+
+# ip length 232
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "ip"
+ }
+ },
+ "right": 232
+ }
+ }
+]
+
+# ip length != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip length 333-435
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ 333, 435 ]
+ }
+ }
+ }
+]
+
+# ip length != 333-453
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 333, 453 ]
+ }
+ }
+ }
+]
+
+# ip length { 333, 553, 673, 838}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ 333,
+ 553,
+ 673,
+ 838
+ ]
+ }
+ }
+ }
+]
+
+# ip length != { 333, 553, 673, 838}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 333,
+ 553,
+ 673,
+ 838
+ ]
+ }
+ }
+ }
+]
+
+# ip length { 333-535}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 333, 535 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip length != { 333-535}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 333, 535 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip id 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "ip"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip id != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip id 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip id != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip id { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip id != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip id { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip id != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip frag-off 222 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "name": "ip"
+ }
+ },
+ "right": 222
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip frag-off != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip frag-off 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip frag-off != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip frag-off { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip frag-off != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip frag-off { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip frag-off != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip ttl 0 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "name": "ip"
+ }
+ },
+ "right": 0
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip ttl 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "name": "ip"
+ }
+ },
+ "right": 233
+ }
+ }
+]
+
+# ip ttl 33-55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ 33, 55 ]
+ }
+ }
+ }
+]
+
+# ip ttl != 45-50
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 45, 50 ]
+ }
+ }
+ }
+]
+
+# ip ttl {43, 53, 45 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ 43,
+ 45,
+ 53
+ ]
+ }
+ }
+ }
+]
+
+# ip ttl != {43, 53, 45 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 43,
+ 45,
+ 53
+ ]
+ }
+ }
+ }
+]
+
+# ip ttl { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip ttl != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip protocol tcp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ }
+]
+
+# ip protocol != tcp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "tcp"
+ }
+ }
+]
+
+# ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ "icmp",
+ "esp",
+ "ah",
+ "comp",
+ "udp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip protocol != { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "icmp",
+ "esp",
+ "ah",
+ "comp",
+ "udp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip protocol 255
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 255
+ }
+ }
+]
+
+# ip checksum 13172 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "right": 13172
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip checksum 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip checksum != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip checksum 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip checksum != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip checksum { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip checksum != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip checksum { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip checksum != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip saddr 192.168.2.0/24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "prefix": {
+ "addr": "192.168.2.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ip saddr != 192.168.2.0/24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "prefix": {
+ "addr": "192.168.2.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ip saddr 192.168.3.1 ip daddr 192.168.3.100
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "192.168.3.1"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "192.168.3.100"
+ }
+ }
+]
+
+# ip saddr != 1.1.1.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "1.1.1.1"
+ }
+ }
+]
+
+# ip saddr 1.1.1.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "1.1.1.1"
+ }
+ }
+]
+
+# ip daddr 192.168.0.1-192.168.0.250
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ "192.168.0.1", "192.168.0.250" ]
+ }
+ }
+ }
+]
+
+# ip daddr 10.0.0.0-10.255.255.255
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ "10.0.0.0", "10.255.255.255" ]
+ }
+ }
+ }
+]
+
+# ip daddr 172.16.0.0-172.31.255.255
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ "172.16.0.0", "172.31.255.255" ]
+ }
+ }
+ }
+]
+
+# ip daddr 192.168.3.1-192.168.4.250
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ "192.168.3.1", "192.168.4.250" ]
+ }
+ }
+ }
+]
+
+# ip daddr != 192.168.0.1-192.168.0.250
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "192.168.0.1", "192.168.0.250" ]
+ }
+ }
+ }
+]
+
+# ip daddr { 192.168.0.1-192.168.0.250}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ { "range": [ "192.168.0.1", "192.168.0.250" ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip daddr != { 192.168.0.1-192.168.0.250}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ "192.168.0.1", "192.168.0.250" ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ "192.168.5.1",
+ "192.168.5.2",
+ "192.168.5.3"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip daddr != { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "192.168.5.1",
+ "192.168.5.2",
+ "192.168.5.3"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip daddr 192.168.1.2-192.168.1.55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ "192.168.1.2", "192.168.1.55" ]
+ }
+ }
+ }
+]
+
+# ip daddr != 192.168.1.2-192.168.1.55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "192.168.1.2", "192.168.1.55" ]
+ }
+ }
+ }
+]
+
+# ip saddr 192.168.1.3-192.168.33.55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ "192.168.1.3", "192.168.33.55" ]
+ }
+ }
+ }
+]
+
+# ip saddr != 192.168.1.3-192.168.33.55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "192.168.1.3", "192.168.33.55" ]
+ }
+ }
+ }
+]
+
+# ip daddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ip daddr 192.168.0.1 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "192.168.0.1"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip daddr 192.168.0.2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "192.168.0.2"
+ }
+ }
+]
+
+# ip saddr & 0xff == 1
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "0xff"
+ ]
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# ip saddr & 0.0.0.255 < 0.0.0.127
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "0.0.0.255"
+ ]
+ },
+ "op": "<",
+ "right": "0.0.0.127"
+ }
+ }
+]
+
+# ip saddr & 0xffff0000 == 0xffff0000
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "0xffff0000"
+ ]
+ },
+ "right": "0xffff0000"
+ }
+ }
+]
+
+# ip version 4 ip hdrlength 5
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "version",
+ "name": "ip"
+ }
+ },
+ "right": 4
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ip"
+ }
+ },
+ "right": 5
+ }
+ }
+]
+
+# ip hdrlength 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ip"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# ip hdrlength 15
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ip"
+ }
+ },
+ "right": 15
+ }
+ }
+]
+
+# ip hdrlength vmap { 0-4 : drop, 5 : accept, 6 : continue } counter
+[
+ {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ { "range": [ 0, 4 ] },
+ { "drop": null }
+ ],
+ [
+ 5,
+ { "accept": null }
+ ],
+ [
+ 6,
+ { "continue": null }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "counter": null
+ }
+]
+
+# iif "lo" ip daddr set 127.0.0.1
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "127.0.0.1"
+ }
+ }
+]
+
+# iif "lo" ip checksum set 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "name": "ip"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# iif "lo" ip id set 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "name": "ip"
+ }
+ },
+ "right": 0
+ }
+ }
+]
+
+# iif "lo" ip ecn set 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "ecn",
+ "name": "ip"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# iif "lo" ip ecn set ce
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "ecn",
+ "name": "ip"
+ }
+ },
+ "right": "ce"
+ }
+ }
+]
+
+# iif "lo" ip ttl set 23
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "name": "ip"
+ }
+ },
+ "right": 23
+ }
+ }
+]
+
+# iif "lo" ip protocol set 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+
+# iif "lo" ip dscp set af23
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "right": "af23"
+ }
+ }
+]
+
+# iif "lo" ip dscp set cs0
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "right": "cs0"
+ }
+ }
+]
+
diff --git a/tests/py/ip/ip.t.json.output b/tests/py/ip/ip.t.json.output
new file mode 100644
index 00000000..21143089
--- /dev/null
+++ b/tests/py/ip/ip.t.json.output
@@ -0,0 +1,226 @@
+# ip dscp 0x38
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "right": "cs7"
+ }
+ }
+]
+
+# ip dscp != 0x20
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "cs4"
+ }
+ }
+]
+
+# ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ "cs0",
+ "cs1",
+ "af11",
+ "af12",
+ "af13",
+ "cs2",
+ "af21",
+ "af22",
+ "af23",
+ "cs3",
+ "af31",
+ "af32",
+ "af33",
+ "cs4",
+ "af41",
+ "af42",
+ "af43",
+ "cs5",
+ "ef",
+ "cs6",
+ "cs7"
+ ]
+ }
+ }
+ }
+]
+
+# ip protocol tcp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ }
+]
+
+# ip protocol != tcp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 6
+ }
+ }
+]
+
+# ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ 1,
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip protocol != { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 1,
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip saddr & 0xff == 1
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "0.0.0.255"
+ ]
+ },
+ "op": "==",
+ "right": "0.0.0.1"
+ }
+ }
+]
+
+# ip saddr & 0xffff0000 == 0xffff0000
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "prefix": {
+ "addr": "255.255.0.0",
+ "len": 16
+ }
+ }
+ }
+ }
+]
+
+# iif "lo" ip ecn set 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iif"
+ },
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "payload": {
+ "field": "ecn",
+ "name": "ip"
+ }
+ },
+ "right": "ect1"
+ }
+ }
+]
+
diff --git a/tests/py/ip/ip_tcp.t.json b/tests/py/ip/ip_tcp.t.json
new file mode 100644
index 00000000..82b7cdcc
--- /dev/null
+++ b/tests/py/ip/ip_tcp.t.json
@@ -0,0 +1,60 @@
+# ip protocol tcp tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp meta mark set 1 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
diff --git a/tests/py/ip/ip_tcp.t.json.output b/tests/py/ip/ip_tcp.t.json.output
new file mode 100644
index 00000000..bbc318a7
--- /dev/null
+++ b/tests/py/ip/ip_tcp.t.json.output
@@ -0,0 +1,49 @@
+# ip protocol tcp tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp meta mark set 1 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "mangle": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ }
+]
+
diff --git a/tests/py/ip/masquerade.t.json b/tests/py/ip/masquerade.t.json
new file mode 100644
index 00000000..44f371ad
--- /dev/null
+++ b/tests/py/ip/masquerade.t.json
@@ -0,0 +1,411 @@
+# udp dport 53 masquerade
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": null
+ }
+]
+
+# udp dport 53 masquerade random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": "random"
+ }
+ }
+]
+
+# udp dport 53 masquerade random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade random,fully-random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": "persistent"
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "fully-random",
+ "random"
+ ]
+ }
+ }
+]
+
+# ip protocol 6 masquerade to :1024
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "masquerade": {
+ "port": 1024
+ }
+ }
+]
+
+# ip protocol 6 masquerade to :1024-2048
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "masquerade": {
+ "port": {
+ "range": [ 1024, 2048 ]
+ }
+ }
+ }
+]
+
+# tcp dport { 1,2,3,4,5,6,7,8,101,202,303,1001,2002,3003} masquerade
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 101,
+ 202,
+ 303,
+ 1001,
+ 2002,
+ 3003
+ ]
+ }
+ }
+ },
+ {
+ "masquerade": null
+ }
+]
+
+# ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter masquerade
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ "10.0.0.0", "10.2.3.4" ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "masquerade": null
+ }
+]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } masquerade
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": [
+ "established",
+ "new"
+ ]
+ }
+ },
+ {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 22,
+ {
+ "drop": null
+ }
+ ],
+ [
+ 222,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "masquerade": null
+ }
+]
+
diff --git a/tests/py/ip/masquerade.t.json.output b/tests/py/ip/masquerade.t.json.output
new file mode 100644
index 00000000..c6e6ef04
--- /dev/null
+++ b/tests/py/ip/masquerade.t.json.output
@@ -0,0 +1,118 @@
+# udp dport 53 masquerade random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
diff --git a/tests/py/ip/meta.t.json b/tests/py/ip/meta.t.json
new file mode 100644
index 00000000..e538b748
--- /dev/null
+++ b/tests/py/ip/meta.t.json
@@ -0,0 +1,99 @@
+# icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta l4proto icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": "icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta l4proto ipv6-icmp icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": "ipv6-icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# meta l4proto 58 icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "meta": "l4proto"
+ },
+ "right": 58
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "nd-router-advert"
+ }
+ }
+]
+
diff --git a/tests/py/ip/meta.t.json.output b/tests/py/ip/meta.t.json.output
new file mode 100644
index 00000000..5908ca6b
--- /dev/null
+++ b/tests/py/ip/meta.t.json.output
@@ -0,0 +1,45 @@
+# meta l4proto icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmp"
+ }
+ },
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta l4proto ipv6-icmp icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# meta l4proto 58 icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "name": "icmpv6"
+ }
+ },
+ "right": "nd-router-advert"
+ }
+ }
+]
+
diff --git a/tests/py/ip/numgen.t.json b/tests/py/ip/numgen.t.json
new file mode 100644
index 00000000..70514abb
--- /dev/null
+++ b/tests/py/ip/numgen.t.json
@@ -0,0 +1,99 @@
+# ct mark set numgen inc mod 2
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "numgen": {
+ "mod": 2,
+ "mode": "inc"
+ }
+ }
+ }
+ }
+]
+
+# ct mark set numgen inc mod 2 offset 100
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "numgen": {
+ "mod": 2,
+ "mode": "inc",
+ "offset": 100
+ }
+ }
+ }
+ }
+]
+
+# dnat to numgen inc mod 2 map { 0 : 192.168.10.100, 1 : 192.168.20.200 }
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "left": {
+ "numgen": {
+ "mod": 2,
+ "mode": "inc"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 0,
+ "192.168.10.100"
+ ],
+ [
+ 1,
+ "192.168.20.200"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# dnat to numgen inc mod 10 map { 0-5 : 192.168.10.100, 6-9 : 192.168.20.200}
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "left": {
+ "numgen": {
+ "mod": 10,
+ "mode": "inc"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ { "range": [ 0, 5 ] },
+ "192.168.10.100"
+ ],
+ [
+ { "range": [ 6, 9 ] },
+ "192.168.20.200"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/numgen.t.json.output b/tests/py/ip/numgen.t.json.output
new file mode 100644
index 00000000..7a989551
--- /dev/null
+++ b/tests/py/ip/numgen.t.json.output
@@ -0,0 +1,82 @@
+# ct mark set numgen inc mod 2
+[
+ {
+ "mangle": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "right": {
+ "numgen": {
+ "mod": 2,
+ "mode": "inc",
+ "offset": 0
+ }
+ }
+ }
+ }
+]
+
+# dnat to numgen inc mod 2 map { 0 : 192.168.10.100, 1 : 192.168.20.200 }
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "left": {
+ "numgen": {
+ "mod": 2,
+ "mode": "inc",
+ "offset": 0
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 0,
+ "192.168.10.100"
+ ],
+ [
+ 1,
+ "192.168.20.200"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# dnat to numgen inc mod 10 map { 0-5 : 192.168.10.100, 6-9 : 192.168.20.200}
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "left": {
+ "numgen": {
+ "mod": 10,
+ "mode": "inc",
+ "offset": 0
+ }
+ },
+ "right": {
+ "set": [
+ [
+ { "range": [ 0, 5 ] },
+ "192.168.10.100"
+ ],
+ [
+ { "range": [ 6, 9 ] },
+ "192.168.20.200"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/objects.t.json b/tests/py/ip/objects.t.json
new file mode 100644
index 00000000..c83cc6a4
--- /dev/null
+++ b/tests/py/ip/objects.t.json
@@ -0,0 +1,185 @@
+# ip saddr 192.168.1.3 counter name "cnt2"
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "192.168.1.3"
+ }
+ },
+ {
+ "counter": "cnt2"
+ }
+]
+
+# counter name tcp dport map {443 : "cnt1", 80 : "cnt2", 22 : "cnt1"}
+[
+ {
+ "counter": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 443,
+ "cnt1"
+ ],
+ [
+ 80,
+ "cnt2"
+ ],
+ [
+ 22,
+ "cnt1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
+# ip saddr 192.168.1.3 quota name "qt1"
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "192.168.1.3"
+ }
+ },
+ {
+ "quota": "qt1"
+ }
+]
+
+# quota name tcp dport map {443 : "qt1", 80 : "qt2", 22 : "qt1"}
+[
+ {
+ "quota": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 443,
+ "qt1"
+ ],
+ [
+ 80,
+ "qt2"
+ ],
+ [
+ 22,
+ "qt1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
+# ct helper set "cthelp1"
+[
+ {
+ "cthelper": "cthelp1"
+ }
+]
+
+# ct helper set tcp dport map {21 : "cthelp1", 2121 : "cthelp1" }
+[
+ {
+ "cthelper": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 21,
+ "cthelp1"
+ ],
+ [
+ 2121,
+ "cthelp1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
+# ip saddr 192.168.1.3 limit name "lim1"
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "192.168.1.3"
+ }
+ },
+ {
+ "limit": "lim1"
+ }
+]
+
+# limit name tcp dport map {443 : "lim1", 80 : "lim2", 22 : "lim1"}
+[
+ {
+ "limit": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 22,
+ "lim1"
+ ],
+ [
+ 80,
+ "lim2"
+ ],
+ [
+ 443,
+ "lim1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/objects.t.json.output b/tests/py/ip/objects.t.json.output
new file mode 100644
index 00000000..ea0e991e
--- /dev/null
+++ b/tests/py/ip/objects.t.json.output
@@ -0,0 +1,64 @@
+# counter name tcp dport map {443 : "cnt1", 80 : "cnt2", 22 : "cnt1"}
+[
+ {
+ "counter": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 22,
+ "cnt1"
+ ],
+ [
+ 80,
+ "cnt2"
+ ],
+ [
+ 443,
+ "cnt1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
+# quota name tcp dport map {443 : "qt1", 80 : "qt2", 22 : "qt1"}
+[
+ {
+ "quota": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 22,
+ "qt1"
+ ],
+ [
+ 80,
+ "qt2"
+ ],
+ [
+ 443,
+ "qt1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/redirect.t.json b/tests/py/ip/redirect.t.json
new file mode 100644
index 00000000..b22a327d
--- /dev/null
+++ b/tests/py/ip/redirect.t.json
@@ -0,0 +1,610 @@
+# udp dport 53 redirect
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": null
+ }
+]
+
+# udp dport 53 redirect random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": "random"
+ }
+ }
+]
+
+# udp dport 53 redirect random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect random,fully-random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": "persistent"
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "fully-random",
+ "random"
+ ]
+ }
+ }
+]
+
+# tcp dport 22 redirect to :22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "redirect": {
+ "port": 22
+ }
+ }
+]
+
+# udp dport 1234 redirect to :4321
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 1234
+ }
+ },
+ {
+ "redirect": {
+ "port": 4321
+ }
+ }
+]
+
+# ip daddr 172.16.0.1 udp dport 9998 redirect to :6515
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": "172.16.0.1"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 9998
+ }
+ },
+ {
+ "redirect": {
+ "port": 6515
+ }
+ }
+]
+
+# tcp dport 39128 redirect to :993
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 39128
+ }
+ },
+ {
+ "redirect": {
+ "port": 993
+ }
+ }
+]
+
+# ip protocol tcp redirect to :100-200
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ },
+ {
+ "redirect": {
+ "port": {
+ "range": [ 100, 200 ]
+ }
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :993 random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 9128
+ }
+ },
+ {
+ "redirect": {
+ "flags": "random",
+ "port": 993
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :993 fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 9128
+ }
+ },
+ {
+ "redirect": {
+ "flags": "fully-random",
+ "port": 993
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :123 persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 9128
+ }
+ },
+ {
+ "redirect": {
+ "flags": "persistent",
+ "port": 123
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :123 random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 9128
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent"
+ ],
+ "port": 123
+ }
+ }
+]
+
+# tcp dport { 1, 2, 3, 4, 5, 6, 7, 8, 101, 202, 303, 1001, 2002, 3003} redirect
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 101,
+ 202,
+ 303,
+ 1001,
+ 2002,
+ 3003
+ ]
+ }
+ }
+ },
+ {
+ "redirect": null
+ }
+]
+
+# ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter redirect
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "range": [ "10.0.0.0", "10.2.3.4" ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "redirect": null
+ }
+]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } redirect
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "right": [
+ "established",
+ "new"
+ ]
+ }
+ },
+ {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 22,
+ {
+ "drop": null
+ }
+ ],
+ [
+ 222,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "redirect": null
+ }
+]
+
+# ip protocol 6 redirect to :tcp dport map { 22 : 8000, 80 : 8080}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "redirect": {
+ "port": {
+ "map": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ [
+ 22,
+ 8000
+ ],
+ [
+ 80,
+ 8080
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/redirect.t.json.output b/tests/py/ip/redirect.t.json.output
new file mode 100644
index 00000000..3db03be2
--- /dev/null
+++ b/tests/py/ip/redirect.t.json.output
@@ -0,0 +1,140 @@
+# udp dport 53 redirect random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# ip protocol tcp redirect to :100-200
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": 6
+ }
+ },
+ {
+ "redirect": {
+ "port": {
+ "range": [ 100, 200 ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/reject.t.json b/tests/py/ip/reject.t.json
new file mode 100644
index 00000000..e0b8e2b2
--- /dev/null
+++ b/tests/py/ip/reject.t.json
@@ -0,0 +1,94 @@
+# reject
+[
+ {
+ "reject": null
+ }
+]
+
+# reject with icmp type host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-unreachable
+[
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type prot-unreachable
+[
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-prohibited
+[
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type host-prohibited
+[
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# mark 0x80000000 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": "0x80000000"
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
diff --git a/tests/py/ip/reject.t.json.output b/tests/py/ip/reject.t.json.output
new file mode 100644
index 00000000..099320c6
--- /dev/null
+++ b/tests/py/ip/reject.t.json.output
@@ -0,0 +1,24 @@
+# reject with icmp type port-unreachable
+[
+ {
+ "reject": null
+ }
+]
+
+# mark 0x80000000 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": "mark"
+ },
+ "right": 2147483648
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
diff --git a/tests/py/ip/rt.t.json b/tests/py/ip/rt.t.json
new file mode 100644
index 00000000..565427cf
--- /dev/null
+++ b/tests/py/ip/rt.t.json
@@ -0,0 +1,15 @@
+# rt nexthop 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "family": "ip",
+ "key": "nexthop"
+ }
+ },
+ "right": "192.168.0.1"
+ }
+ }
+]
+
diff --git a/tests/py/ip/sets.t.json b/tests/py/ip/sets.t.json
new file mode 100644
index 00000000..dd6abed8
--- /dev/null
+++ b/tests/py/ip/sets.t.json
@@ -0,0 +1,185 @@
+# ip saddr @set1 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "@set1"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip saddr != @set1 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "@set1"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip saddr @set2 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": "@set2"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip saddr != @set2 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "@set2"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip saddr . ip daddr @set5 drop
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ }
+ ]
+ },
+ "right": "@set5"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# add @set5 { ip saddr . ip daddr }
+[
+ {
+ "set": {
+ "elem": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "name": "ip"
+ }
+ }
+ ]
+ },
+ "op": "add",
+ "set": "@set5"
+ }
+ }
+]
+
+# ip saddr { { 1.1.1.0, 3.3.3.0 }, 2.2.2.0 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ "1.1.1.0",
+ "2.2.2.0",
+ "3.3.3.0"
+ ]
+ }
+ }
+ }
+]
+
+# ip saddr { { 1.1.1.0/24, 3.3.3.0/24 }, 2.2.2.0/24 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "name": "ip"
+ }
+ },
+ "right": {
+ "set": [
+ {
+ "prefix": {
+ "addr": "1.1.1.0",
+ "len": 24
+ }
+ },
+ {
+ "prefix": {
+ "addr": "2.2.2.0",
+ "len": 24
+ }
+ },
+ {
+ "prefix": {
+ "addr": "3.3.3.0",
+ "len": 24
+ }
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/snat.t.json b/tests/py/ip/snat.t.json
new file mode 100644
index 00000000..b925b6c7
--- /dev/null
+++ b/tests/py/ip/snat.t.json
@@ -0,0 +1,161 @@
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "range": [ 80, 90 ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport != 80-90 snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 80, 90 ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport {80, 90, 23} snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 80,
+ 90,
+ 23
+ ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport != {80, 90, 23} snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 80,
+ 90,
+ 23
+ ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport != 23-34 snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 23, 34 ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
diff --git a/tests/py/ip/snat.t.json.output b/tests/py/ip/snat.t.json.output
new file mode 100644
index 00000000..4446ae66
--- /dev/null
+++ b/tests/py/ip/snat.t.json.output
@@ -0,0 +1,69 @@
+# iifname "eth0" tcp dport {80, 90, 23} snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": {
+ "set": [
+ 23,
+ 80,
+ 90
+ ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport != {80, 90, 23} snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": "iifname"
+ },
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 80,
+ 90
+ ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
diff --git a/tests/py/ip/tcp.t.json b/tests/py/ip/tcp.t.json
new file mode 100644
index 00000000..e04cc1e2
--- /dev/null
+++ b/tests/py/ip/tcp.t.json
@@ -0,0 +1,59 @@
+# ip protocol tcp tcp dport ssh accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": "ssh"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip protocol ne tcp udp dport ssh accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": "ssh"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/ip/tcp.t.json.output b/tests/py/ip/tcp.t.json.output
new file mode 100644
index 00000000..eb5f53f7
--- /dev/null
+++ b/tests/py/ip/tcp.t.json.output
@@ -0,0 +1,48 @@
+# ip protocol tcp tcp dport ssh accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "tcp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip protocol ne tcp udp dport ssh accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "name": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "name": "udp"
+ }
+ },
+ "right": 22
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/ip/tcpopt.t.json b/tests/py/ip/tcpopt.t.json
new file mode 100644
index 00000000..8bb79917
--- /dev/null
+++ b/tests/py/ip/tcpopt.t.json