summaryrefslogtreecommitdiffstats
path: root/tests/py/ip
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/py/ip
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/py/ip')
-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
35 files changed, 7544 insertions, 0 deletions
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
@@ -0,0 +1,390 @@
+# 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": "sack"
+ }
+ },
+ "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 sack right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack"
+ }
+ },
+ "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
+ }
+ }
+]
+
diff --git a/tests/py/ip/tcpopt.t.json.output b/tests/py/ip/tcpopt.t.json.output
new file mode 100644
index 00000000..ca6714b7
--- /dev/null
+++ b/tests/py/ip/tcpopt.t.json.output
@@ -0,0 +1,15 @@
+# tcp option sack0 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack"
+ }
+ },
+ "right": 1
+ }
+ }
+]
+