summaryrefslogtreecommitdiffstats
path: root/tests/py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:08:37 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:08:37 +0000
commit971e619d8602fa52b1bfcb3ea65b7ab96be85318 (patch)
tree26feb2498c72b796e07b86349d17f544046de279 /tests/py
parentInitial commit. (diff)
downloadnftables-971e619d8602fa52b1bfcb3ea65b7ab96be85318.tar.xz
nftables-971e619d8602fa52b1bfcb3ea65b7ab96be85318.zip
Adding upstream version 1.0.9.upstream/1.0.9upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/py')
-rw-r--r--tests/py/README197
-rw-r--r--tests/py/any/counter.t14
-rw-r--r--tests/py/any/counter.t.json39
-rw-r--r--tests/py/any/counter.t.json.output28
-rw-r--r--tests/py/any/counter.t.payload15
-rw-r--r--tests/py/any/ct.t149
-rw-r--r--tests/py/any/ct.t.json1523
-rw-r--r--tests/py/any/ct.t.json.output666
-rw-r--r--tests/py/any/ct.t.payload518
-rw-r--r--tests/py/any/icmpX.t.netdev9
-rw-r--r--tests/py/any/icmpX.t.netdev.payload36
-rw-r--r--tests/py/any/last.t13
-rw-r--r--tests/py/any/last.t.json16
-rw-r--r--tests/py/any/last.t.json.output14
-rw-r--r--tests/py/any/last.t.payload8
-rw-r--r--tests/py/any/limit.t55
-rw-r--r--tests/py/any/limit.t.json413
-rw-r--r--tests/py/any/limit.t.json.output277
-rw-r--r--tests/py/any/limit.t.payload141
-rw-r--r--tests/py/any/log.t41
-rw-r--r--tests/py/any/log.t.json178
-rw-r--r--tests/py/any/log.t.json.output16
-rw-r--r--tests/py/any/log.t.payload71
-rw-r--r--tests/py/any/meta.t226
-rw-r--r--tests/py/any/meta.t.json2760
-rw-r--r--tests/py/any/meta.t.json.output828
-rw-r--r--tests/py/any/meta.t.payload1074
-rw-r--r--tests/py/any/objects.t16
-rw-r--r--tests/py/any/queue.t33
-rw-r--r--tests/py/any/queue.t.json251
-rw-r--r--tests/py/any/queue.t.json.output9
-rw-r--r--tests/py/any/queue.t.payload81
-rw-r--r--tests/py/any/quota.t25
-rw-r--r--tests/py/any/quota.t.json136
-rw-r--r--tests/py/any/quota.t.payload52
-rw-r--r--tests/py/any/rawpayload.t24
-rw-r--r--tests/py/any/rawpayload.t.json206
-rw-r--r--tests/py/any/rawpayload.t.json.output119
-rw-r--r--tests/py/any/rawpayload.t.payload63
-rw-r--r--tests/py/any/rt.t9
-rw-r--r--tests/py/any/rt.t.json45
-rw-r--r--tests/py/any/rt.t.payload15
-rw-r--r--tests/py/any/tcpopt.t62
-rw-r--r--tests/py/any/tcpopt.t.json622
-rw-r--r--tests/py/any/tcpopt.t.json.output32
-rw-r--r--tests/py/any/tcpopt.t.payload202
-rw-r--r--tests/py/arp/arp.t60
-rw-r--r--tests/py/arp/arp.t.json893
-rw-r--r--tests/py/arp/arp.t.json.output180
-rw-r--r--tests/py/arp/arp.t.payload261
-rw-r--r--tests/py/arp/arp.t.payload.netdev351
-rw-r--r--tests/py/arp/chains.t5
-rw-r--r--tests/py/arp/chains.t.payload0
-rw-r--r--tests/py/bridge/chains.t8
-rw-r--r--tests/py/bridge/chains.t.payload0
-rw-r--r--tests/py/bridge/ether.t12
-rw-r--r--tests/py/bridge/ether.t.json193
-rw-r--r--tests/py/bridge/ether.t.json.output43
-rw-r--r--tests/py/bridge/ether.t.payload60
-rw-r--r--tests/py/bridge/icmpX.t8
-rw-r--r--tests/py/bridge/icmpX.t.json88
-rw-r--r--tests/py/bridge/icmpX.t.json.output56
-rw-r--r--tests/py/bridge/icmpX.t.payload36
-rw-r--r--tests/py/bridge/meta.t13
-rw-r--r--tests/py/bridge/meta.t.json105
-rw-r--r--tests/py/bridge/meta.t.payload37
-rw-r--r--tests/py/bridge/redirect.t5
-rw-r--r--tests/py/bridge/redirect.t.json12
-rw-r--r--tests/py/bridge/redirect.t.payload4
-rw-r--r--tests/py/bridge/reject.t42
-rw-r--r--tests/py/bridge/reject.t.json341
-rw-r--r--tests/py/bridge/reject.t.json.output83
-rw-r--r--tests/py/bridge/reject.t.payload140
-rw-r--r--tests/py/bridge/vlan.t56
-rw-r--r--tests/py/bridge/vlan.t.json894
-rw-r--r--tests/py/bridge/vlan.t.json.output204
-rw-r--r--tests/py/bridge/vlan.t.payload314
-rw-r--r--tests/py/bridge/vlan.t.payload.netdev368
-rw-r--r--tests/py/inet/ah.t47
-rw-r--r--tests/py/inet/ah.t.json412
-rw-r--r--tests/py/inet/ah.t.payload182
-rw-r--r--tests/py/inet/comp.t30
-rw-r--r--tests/py/inet/comp.t.json244
-rw-r--r--tests/py/inet/comp.t.json.output170
-rw-r--r--tests/py/inet/comp.t.payload105
-rw-r--r--tests/py/inet/ct.t15
-rw-r--r--tests/py/inet/ct.t.json60
-rw-r--r--tests/py/inet/ct.t.json.output16
-rw-r--r--tests/py/inet/ct.t.payload17
-rw-r--r--tests/py/inet/dccp.t30
-rw-r--r--tests/py/inet/dccp.t.json276
-rw-r--r--tests/py/inet/dccp.t.json.output18
-rw-r--r--tests/py/inet/dccp.t.payload115
-rw-r--r--tests/py/inet/dnat.t22
-rw-r--r--tests/py/inet/dnat.t.json241
-rw-r--r--tests/py/inet/dnat.t.payload86
-rw-r--r--tests/py/inet/esp.t21
-rw-r--r--tests/py/inet/esp.t.json204
-rw-r--r--tests/py/inet/esp.t.payload91
-rw-r--r--tests/py/inet/ether-ip.t9
-rw-r--r--tests/py/inet/ether-ip.t.json92
-rw-r--r--tests/py/inet/ether-ip.t.json.output43
-rw-r--r--tests/py/inet/ether-ip.t.payload28
-rw-r--r--tests/py/inet/ether-ip.t.payload.netdev29
-rw-r--r--tests/py/inet/ether.t20
-rw-r--r--tests/py/inet/ether.t.json122
-rw-r--r--tests/py/inet/ether.t.json.output31
-rw-r--r--tests/py/inet/ether.t.payload52
-rw-r--r--tests/py/inet/ether.t.payload.bridge44
-rw-r--r--tests/py/inet/ether.t.payload.ip52
-rw-r--r--tests/py/inet/fib.t17
-rw-r--r--tests/py/inet/fib.t.json132
-rw-r--r--tests/py/inet/fib.t.json.output39
-rw-r--r--tests/py/inet/fib.t.payload32
-rw-r--r--tests/py/inet/geneve.t23
-rw-r--r--tests/py/inet/geneve.t.json344
-rw-r--r--tests/py/inet/geneve.t.payload114
-rw-r--r--tests/py/inet/gre.t22
-rw-r--r--tests/py/inet/gre.t.json177
-rw-r--r--tests/py/inet/gre.t.payload78
-rw-r--r--tests/py/inet/gretap.t21
-rw-r--r--tests/py/inet/gretap.t.json195
-rw-r--r--tests/py/inet/gretap.t.payload87
-rw-r--r--tests/py/inet/icmp.t18
-rw-r--r--tests/py/inet/icmp.t.json124
-rw-r--r--tests/py/inet/icmp.t.json.output32
-rw-r--r--tests/py/inet/icmp.t.payload54
-rw-r--r--tests/py/inet/icmpX.t10
-rw-r--r--tests/py/inet/icmpX.t.json125
-rw-r--r--tests/py/inet/icmpX.t.json.output84
-rw-r--r--tests/py/inet/icmpX.t.payload46
-rw-r--r--tests/py/inet/ip.t12
-rw-r--r--tests/py/inet/ip.t.json42
-rw-r--r--tests/py/inet/ip.t.payload11
-rw-r--r--tests/py/inet/ip.t.payload.bridge11
-rw-r--r--tests/py/inet/ip.t.payload.inet14
-rw-r--r--tests/py/inet/ip.t.payload.netdev14
-rw-r--r--tests/py/inet/ip_tcp.t21
-rw-r--r--tests/py/inet/ip_tcp.t.json170
-rw-r--r--tests/py/inet/ip_tcp.t.json.output142
-rw-r--r--tests/py/inet/ip_tcp.t.payload52
-rw-r--r--tests/py/inet/ip_tcp.t.payload.bridge51
-rw-r--r--tests/py/inet/ip_tcp.t.payload.netdev53
-rw-r--r--tests/py/inet/ipsec.t23
-rw-r--r--tests/py/inet/ipsec.t.json157
-rw-r--r--tests/py/inet/ipsec.t.payload45
-rw-r--r--tests/py/inet/map.t10
-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/map.t.payload23
-rw-r--r--tests/py/inet/map.t.payload.ip19
-rw-r--r--tests/py/inet/map.t.payload.netdev23
-rw-r--r--tests/py/inet/meta.t32
-rw-r--r--tests/py/inet/meta.t.json528
-rw-r--r--tests/py/inet/meta.t.json.got86
-rw-r--r--tests/py/inet/meta.t.json.output53
-rw-r--r--tests/py/inet/meta.t.payload175
-rw-r--r--tests/py/inet/meta.t.payload.got40
-rw-r--r--tests/py/inet/osf.t18
-rw-r--r--tests/py/inet/osf.t.json170
-rw-r--r--tests/py/inet/osf.t.payload53
-rw-r--r--tests/py/inet/reject.t41
-rw-r--r--tests/py/inet/reject.t.json331
-rw-r--r--tests/py/inet/reject.t.json.output77
-rw-r--r--tests/py/inet/reject.t.payload.inet144
-rw-r--r--tests/py/inet/rt.t15
-rw-r--r--tests/py/inet/rt.t.json59
-rw-r--r--tests/py/inet/rt.t.json.output25
-rw-r--r--tests/py/inet/rt.t.payload18
-rw-r--r--tests/py/inet/sctp.t73
-rw-r--r--tests/py/inet/sctp.t.json928
-rw-r--r--tests/py/inet/sctp.t.payload351
-rw-r--r--tests/py/inet/sets.t25
-rw-r--r--tests/py/inet/sets.t.json136
-rw-r--r--tests/py/inet/sets.t.payload.bridge42
-rw-r--r--tests/py/inet/sets.t.payload.inet41
-rw-r--r--tests/py/inet/sets.t.payload.netdev41
-rw-r--r--tests/py/inet/snat.t21
-rw-r--r--tests/py/inet/snat.t.json131
-rw-r--r--tests/py/inet/snat.t.payload42
-rw-r--r--tests/py/inet/socket.t15
-rw-r--r--tests/py/inet/socket.t.json74
-rw-r--r--tests/py/inet/socket.t.payload24
-rw-r--r--tests/py/inet/synproxy.t13
-rw-r--r--tests/py/inet/synproxy.t.json64
-rw-r--r--tests/py/inet/synproxy.t.payload24
-rw-r--r--tests/py/inet/tcp.t115
-rw-r--r--tests/py/inet/tcp.t.json1799
-rw-r--r--tests/py/inet/tcp.t.json.output210
-rw-r--r--tests/py/inet/tcp.t.payload674
-rw-r--r--tests/py/inet/tproxy.t21
-rw-r--r--tests/py/inet/tproxy.t.json185
-rw-r--r--tests/py/inet/tproxy.t.payload63
-rw-r--r--tests/py/inet/udp.t45
-rw-r--r--tests/py/inet/udp.t.json583
-rw-r--r--tests/py/inet/udp.t.payload248
-rw-r--r--tests/py/inet/udplite.t38
-rw-r--r--tests/py/inet/udplite.t.json413
-rw-r--r--tests/py/inet/udplite.t.payload178
-rw-r--r--tests/py/inet/vmap.t10
-rw-r--r--tests/py/inet/vmap.t.json144
-rw-r--r--tests/py/inet/vmap.t.payload34
-rw-r--r--tests/py/inet/vmap.t.payload.netdev34
-rw-r--r--tests/py/inet/vxlan.t23
-rw-r--r--tests/py/inet/vxlan.t.json344
-rw-r--r--tests/py/inet/vxlan.t.payload114
-rw-r--r--tests/py/ip/chains.t15
-rw-r--r--tests/py/ip/ct.t36
-rw-r--r--tests/py/ip/ct.t.json481
-rw-r--r--tests/py/ip/ct.t.json.output27
-rw-r--r--tests/py/ip/ct.t.payload136
-rw-r--r--tests/py/ip/dnat.t23
-rw-r--r--tests/py/ip/dnat.t.json743
-rw-r--r--tests/py/ip/dnat.t.json.output65
-rw-r--r--tests/py/ip/dnat.t.payload.ip204
-rw-r--r--tests/py/ip/dup.t7
-rw-r--r--tests/py/ip/dup.t.json46
-rw-r--r--tests/py/ip/dup.t.payload21
-rw-r--r--tests/py/ip/ether.t8
-rw-r--r--tests/py/ip/ether.t.json163
-rw-r--r--tests/py/ip/ether.t.json.output43
-rw-r--r--tests/py/ip/ether.t.payload50
-rw-r--r--tests/py/ip/flowtable.t5
-rw-r--r--tests/py/ip/flowtable.t.json24
-rw-r--r--tests/py/ip/flowtable.t.payload7
-rw-r--r--tests/py/ip/hash.t10
-rw-r--r--tests/py/ip/hash.t.json230
-rw-r--r--tests/py/ip/hash.t.payload49
-rw-r--r--tests/py/ip/icmp.t77
-rw-r--r--tests/py/ip/icmp.t.json1494
-rw-r--r--tests/py/ip/icmp.t.json.output169
-rw-r--r--tests/py/ip/icmp.t.payload.ip619
-rw-r--r--tests/py/ip/igmp.t23
-rw-r--r--tests/py/ip/igmp.t.json273
-rw-r--r--tests/py/ip/igmp.t.payload118
-rw-r--r--tests/py/ip/ip.t135
-rw-r--r--tests/py/ip/ip.t.json1811
-rw-r--r--tests/py/ip/ip.t.json.got62
-rw-r--r--tests/py/ip/ip.t.json.output232
-rw-r--r--tests/py/ip/ip.t.payload558
-rw-r--r--tests/py/ip/ip.t.payload.bridge728
-rw-r--r--tests/py/ip/ip.t.payload.bridge.got24
-rw-r--r--tests/py/ip/ip.t.payload.got18
-rw-r--r--tests/py/ip/ip.t.payload.inet728
-rw-r--r--tests/py/ip/ip.t.payload.inet.got24
-rw-r--r--tests/py/ip/ip.t.payload.netdev728
-rw-r--r--tests/py/ip/ip.t.payload.netdev.got24
-rw-r--r--tests/py/ip/ip_tcp.t9
-rw-r--r--tests/py/ip/ip_tcp.t.json64
-rw-r--r--tests/py/ip/ip_tcp.t.json.output52
-rw-r--r--tests/py/ip/ip_tcp.t.payload16
-rw-r--r--tests/py/ip/masquerade.t30
-rw-r--r--tests/py/ip/masquerade.t.json429
-rw-r--r--tests/py/ip/masquerade.t.json.output123
-rw-r--r--tests/py/ip/masquerade.t.payload142
-rw-r--r--tests/py/ip/meta.t22
-rw-r--r--tests/py/ip/meta.t.json236
-rw-r--r--tests/py/ip/meta.t.json.output48
-rw-r--r--tests/py/ip/meta.t.payload78
-rw-r--r--tests/py/ip/numgen.t9
-rw-r--r--tests/py/ip/numgen.t.json129
-rw-r--r--tests/py/ip/numgen.t.json.output112
-rw-r--r--tests/py/ip/numgen.t.payload40
-rw-r--r--tests/py/ip/objects.t58
-rw-r--r--tests/py/ip/objects.t.json229
-rw-r--r--tests/py/ip/objects.t.json.output64
-rw-r--r--tests/py/ip/objects.t.payload79
-rw-r--r--tests/py/ip/redirect.t51
-rw-r--r--tests/py/ip/redirect.t.json625
-rw-r--r--tests/py/ip/redirect.t.json.output146
-rw-r--r--tests/py/ip/redirect.t.payload220
-rw-r--r--tests/py/ip/reject.t17
-rw-r--r--tests/py/ip/reject.t.json105
-rw-r--r--tests/py/ip/reject.t.json.output28
-rw-r--r--tests/py/ip/reject.t.payload44
-rw-r--r--tests/py/ip/rt.t7
-rw-r--r--tests/py/ip/rt.t.json16
-rw-r--r--tests/py/ip/rt.t.payload5
-rw-r--r--tests/py/ip/sets.t68
-rw-r--r--tests/py/ip/sets.t.json305
-rw-r--r--tests/py/ip/sets.t.json.got62
-rw-r--r--tests/py/ip/sets.t.json.payload.got157
-rw-r--r--tests/py/ip/sets.t.payload.inet106
-rw-r--r--tests/py/ip/sets.t.payload.ip83
-rw-r--r--tests/py/ip/sets.t.payload.ip.got14
-rw-r--r--tests/py/ip/sets.t.payload.netdev107
-rw-r--r--tests/py/ip/sets.t.payload.netdev.got18
-rw-r--r--tests/py/ip/snat.t21
-rw-r--r--tests/py/ip/snat.t.json530
-rw-r--r--tests/py/ip/snat.t.json.output249
-rw-r--r--tests/py/ip/snat.t.payload154
-rw-r--r--tests/py/ip/tcp.t6
-rw-r--r--tests/py/ip/tcp.t.json62
-rw-r--r--tests/py/ip/tcp.t.json.output50
-rw-r--r--tests/py/ip/tcp.t.payload18
-rw-r--r--tests/py/ip/tproxy.t14
-rw-r--r--tests/py/ip/tproxy.t.json126
-rw-r--r--tests/py/ip/tproxy.t.json.output61
-rw-r--r--tests/py/ip/tproxy.t.payload44
-rw-r--r--tests/py/ip6/chains.t17
-rw-r--r--tests/py/ip6/ct.t9
-rw-r--r--tests/py/ip6/ct.t.json293
-rw-r--r--tests/py/ip6/ct.t.payload46
-rw-r--r--tests/py/ip6/dnat.t9
-rw-r--r--tests/py/ip6/dnat.t.json106
-rw-r--r--tests/py/ip6/dnat.t.payload.ip647
-rw-r--r--tests/py/ip6/dst.t21
-rw-r--r--tests/py/ip6/dst.t.json315
-rw-r--r--tests/py/ip6/dst.t.json.output88
-rw-r--r--tests/py/ip6/dst.t.payload.inet131
-rw-r--r--tests/py/ip6/dst.t.payload.ip699
-rw-r--r--tests/py/ip6/dup.t7
-rw-r--r--tests/py/ip6/dup.t.json46
-rw-r--r--tests/py/ip6/dup.t.payload21
-rw-r--r--tests/py/ip6/ether.t8
-rw-r--r--tests/py/ip6/ether.t.json163
-rw-r--r--tests/py/ip6/ether.t.json.output43
-rw-r--r--tests/py/ip6/ether.t.payload49
-rw-r--r--tests/py/ip6/exthdr.t19
-rw-r--r--tests/py/ip6/exthdr.t.json180
-rw-r--r--tests/py/ip6/exthdr.t.json.output60
-rw-r--r--tests/py/ip6/exthdr.t.payload.ip660
-rw-r--r--tests/py/ip6/flowtable.t6
-rw-r--r--tests/py/ip6/flowtable.t.json62
-rw-r--r--tests/py/ip6/flowtable.t.json.output62
-rw-r--r--tests/py/ip6/flowtable.t.payload16
-rw-r--r--tests/py/ip6/frag.t40
-rw-r--r--tests/py/ip6/frag.t.json644
-rw-r--r--tests/py/ip6/frag.t.json.output118
-rw-r--r--tests/py/ip6/frag.t.payload.inet232
-rw-r--r--tests/py/ip6/frag.t.payload.ip6176
-rw-r--r--tests/py/ip6/frag.t.payload.ip6.got43
-rw-r--r--tests/py/ip6/frag.t.payload.netdev232
-rw-r--r--tests/py/ip6/frag.t.payload.netdev.got232
-rw-r--r--tests/py/ip6/hbh.t22
-rw-r--r--tests/py/ip6/hbh.t.json316
-rw-r--r--tests/py/ip6/hbh.t.json.output68
-rw-r--r--tests/py/ip6/hbh.t.payload.inet132
-rw-r--r--tests/py/ip6/hbh.t.payload.ip6100
-rw-r--r--tests/py/ip6/icmpv6.t99
-rw-r--r--tests/py/ip6/icmpv6.t.json1425
-rw-r--r--tests/py/ip6/icmpv6.t.json.output760
-rw-r--r--tests/py/ip6/icmpv6.t.payload.ip6643
-rw-r--r--tests/py/ip6/ip6.t153
-rw-r--r--tests/py/ip6/ip6.t.json1559
-rw-r--r--tests/py/ip6/ip6.t.json.output374
-rw-r--r--tests/py/ip6/ip6.t.payload.inet641
-rw-r--r--tests/py/ip6/ip6.t.payload.ip6481
-rw-r--r--tests/py/ip6/map.t5
-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/map.t.payload10
-rw-r--r--tests/py/ip6/masquerade.t30
-rw-r--r--tests/py/ip6/masquerade.t.json423
-rw-r--r--tests/py/ip6/masquerade.t.json.output98
-rw-r--r--tests/py/ip6/masquerade.t.payload.ip6142
-rw-r--r--tests/py/ip6/meta.t19
-rw-r--r--tests/py/ip6/meta.t.json313
-rw-r--r--tests/py/ip6/meta.t.json.output64
-rw-r--r--tests/py/ip6/meta.t.payload82
-rw-r--r--tests/py/ip6/mh.t42
-rw-r--r--tests/py/ip6/mh.t.json640
-rw-r--r--tests/py/ip6/mh.t.json.output88
-rw-r--r--tests/py/ip6/mh.t.payload.inet267
-rw-r--r--tests/py/ip6/mh.t.payload.ip6201
-rw-r--r--tests/py/ip6/redirect.t49
-rw-r--r--tests/py/ip6/redirect.t.json589
-rw-r--r--tests/py/ip6/redirect.t.json.output146
-rw-r--r--tests/py/ip6/redirect.t.payload.ip6204
-rw-r--r--tests/py/ip6/reject.t16
-rw-r--r--tests/py/ip6/reject.t.json95
-rw-r--r--tests/py/ip6/reject.t.json.output28
-rw-r--r--tests/py/ip6/reject.t.payload.ip640
-rw-r--r--tests/py/ip6/rt.t38
-rw-r--r--tests/py/ip6/rt.t.json576
-rw-r--r--tests/py/ip6/rt.t.json.output88
-rw-r--r--tests/py/ip6/rt.t.payload.inet244
-rw-r--r--tests/py/ip6/rt.t.payload.ip6184
-rw-r--r--tests/py/ip6/rt0.t6
-rw-r--r--tests/py/ip6/rt0.t.json16
-rw-r--r--tests/py/ip6/rt0.t.payload5
-rw-r--r--tests/py/ip6/sets.t48
-rw-r--r--tests/py/ip6/sets.t.json150
-rw-r--r--tests/py/ip6/sets.t.json.got31
-rw-r--r--tests/py/ip6/sets.t.json.payload.got107
-rw-r--r--tests/py/ip6/sets.t.payload0
-rw-r--r--tests/py/ip6/sets.t.payload.inet49
-rw-r--r--tests/py/ip6/sets.t.payload.inet.got9
-rw-r--r--tests/py/ip6/sets.t.payload.ip638
-rw-r--r--tests/py/ip6/sets.t.payload.ip6.got7
-rw-r--r--tests/py/ip6/sets.t.payload.netdev50
-rw-r--r--tests/py/ip6/sets.t.payload.netdev.got9
-rw-r--r--tests/py/ip6/snat.t6
-rw-r--r--tests/py/ip6/snat.t.json54
-rw-r--r--tests/py/ip6/snat.t.payload.ip625
-rw-r--r--tests/py/ip6/srh.t22
-rw-r--r--tests/py/ip6/srh.t.json194
-rw-r--r--tests/py/ip6/srh.t.json.output22
-rw-r--r--tests/py/ip6/srh.t.payload64
-rw-r--r--tests/py/ip6/tproxy.t14
-rw-r--r--tests/py/ip6/tproxy.t.json125
-rw-r--r--tests/py/ip6/tproxy.t.json.output60
-rw-r--r--tests/py/ip6/tproxy.t.payload44
-rw-r--r--tests/py/ip6/vmap.t58
-rw-r--r--tests/py/ip6/vmap.t.json1037
-rw-r--r--tests/py/ip6/vmap.t.json.output336
-rw-r--r--tests/py/ip6/vmap.t.payload.inet420
-rw-r--r--tests/py/ip6/vmap.t.payload.ip6336
-rw-r--r--tests/py/ip6/vmap.t.payload.netdev420
-rw-r--r--tests/py/log1004
-rw-r--r--tests/py/netdev/dup.t8
-rw-r--r--tests/py/netdev/dup.t.json30
-rw-r--r--tests/py/netdev/dup.t.payload14
-rw-r--r--tests/py/netdev/fwd.t9
-rw-r--r--tests/py/netdev/fwd.t.json47
-rw-r--r--tests/py/netdev/fwd.t.json.output27
-rw-r--r--tests/py/netdev/fwd.t.payload20
-rw-r--r--tests/py/netdev/reject.t40
-rw-r--r--tests/py/netdev/reject.t.json293
-rw-r--r--tests/py/netdev/reject.t.payload142
-rwxr-xr-xtests/py/nft-test.py1586
-rwxr-xr-xtests/py/tools/test-sanitizer.sh78
-rw-r--r--tests/py/y14
423 files changed, 69177 insertions, 0 deletions
diff --git a/tests/py/README b/tests/py/README
new file mode 100644
index 0000000..864a966
--- /dev/null
+++ b/tests/py/README
@@ -0,0 +1,197 @@
+Author: Ana Rey <anarey@gmail.com>
+Date: 18/Sept/2014
+
+Here, the automated regression testing for nftables and some test
+files.
+
+This script checks that the rule input and output of nft matches.
+More details here below.
+
+A) What is this testing?
+
+This script tests two different paths:
+
+* The rule input from the command-line. This checks the different steps
+ from the command line to the kernel. This includes the parsing,
+ evaluation and netlink generation steps.
+
+* The output listing that is obtained from the kernel. This checks the
+ different steps from the kernel to the command line: The netlink
+ message parsing, postprocess and textify steps to display the rule
+ listing.
+
+As a final step, this script compares that the rule that is added can
+be listed by nft.
+
+B) What options are available?
+
+The script offers the following options:
+
+* Execute test files:
+
+./nft-test.py # Run all test files
+./nft-test.py path/file.t # Run this test file
+
+If there is a problem, it shows the differences between the rule that
+is added and the rule that is listed by nft.
+
+In case you hit an error, the script doesn't keep testing for more
+families. Unless you specify the --force-family option.
+
+* Execute broken tests:
+
+./nft-test.py -e
+
+This runs tests for rules that need a fix: This mode runs the lines that
+that start with a "-" symbol.
+
+* Debugging:
+
+./nft-test.py -d
+
+This shows all the commands that the script executes, so you can watch
+its internal behaviour.
+
+* Keep testing all families on error.
+
+./nft-test.py -f
+
+Don't stop testing for more families in case of error.
+
+C) What is the structure of the test file?
+
+A test file contains a set of rules that are added in the system.
+
+Here, an example of a test file:
+
+ :input;type filter hook input priority 0 # line 1
+
+ *ip;test-ipv4;input # line 2
+ *ip6;test-ipv6;input # line 3
+ *inet;test-inet;input # line 4
+
+ ah hdrlength != 11-23;ok;ah hdrlength < 11 ah hdrlength > 23 # line 5
+ - tcp dport != {22-25} # line 6
+
+ !set1 ipv4_addr;ok # line 7
+ ?set1 192.168.3.8 192.168.3.9;ok # line 8
+ # This is a commented-line. # line 9
+
+Line 1 defines a chain. The name of this chain is "input". The type is "filter",
+the hook is "input" and the priority is 0.
+
+Line 2 defines a table. The name of the table is 'test-ipv4', the family is ip
+and the chain to be added to it is 'input'. Lines 3 and 4 defines more tables for
+different families so the rules in this test file are also tested there.
+
+Line 5 defines the rule, the ";" character is used as separator of several
+parts:
+
+* Part 1: "ah hdrlength != 11-23" is the rule to check.
+* Part 2: "ok" is the result expected with the execute of this rule.
+* Part 3: "ah hdrlength < 11 ah hdrlength > 23". This is the expected
+ output. You can leave this empty if the output is the same as the
+ input.
+
+Line 6 is a marked line. This means that this rule is tested if
+'-e' is passed as argument to nft-test.py.
+
+Line 7 adds a new set. The name of this set is "set1" and the type
+of this set is "ipv4_addr".
+
+Line 8 adds two elements into the 'set1' set: "192.168.3.8" and
+"192.168.3.9". A whitespace separates the elements of the set.
+
+Line 9 uses the "#" symbol that means that this line is commented out.
+
+D) What is a payload file?
+
+A payload file contains info about the netlink message exchanged to achieve the
+transaction.
+
+The output can be generated in two ways. Let's see an example via socket
+matching.
+
+ # generate an empty payload file
+ $ touch inet/socket.t.payload
+
+ $ ./nft-test.py inet/socket.t # this will generate inet/socket.t.payload.got
+
+ $ mv inet/socket.t.payload.got inet/socket.t.payload
+
+The other way is using nft --debug=netlink. This has a drawback over the former
+option, as rules has to be run one by one and also a comment has to be added
+before every rule in the payload file.
+
+ $ nft --debug=netlink add rule ip sockip4 sockchain socket exists
+ ip sockip4 sockchain
+ [ match name socket rev 3 ]
+
+E) The test folders
+
+The test files are divided in several directories: ip, ip6, inet, arp,
+bridge and any.
+
+ * "ip" folder contains the test files that are executed in ip and inet
+ table.
+
+ * "ip6" folder contains the test files that are executed in ip6 and inet
+ table.
+
+ * "inet" folder contains the test files that are executed in the ip, ip6
+ and inet table.
+
+ * "arp" folder contains the test files that are executed in the arp
+ table.
+
+ * "bridge" folder: Here are the test files are executed in bridge
+ tables.
+
+ * "any" folder: Here are the test files are executed in ip, ip6, inet,
+ arp and bridge tables.
+
+F) Meaning of messages:
+
+* A warning message means the rule input and output of nft mismatches.
+* An error message means the nft-tool shows an error when we add it or
+ the listing is broken after the rule is added.
+* An info message means something that is not necessarily related to any test
+ case and does not indicate faulty behaviour.
+
+G) Acknowledgements
+
+Thanks to the Outreach Program for Women (OPW) for sponsoring this test
+infrastructure and my mentor Pablo Neira.
+
+H) JSON (-j) Mode
+
+This mode is supposed to repeat the same tests using JSON syntax. For each test
+file example.t, there is supposed to be a file example.t.json holding the JSON
+equivalents of each rule in example.t. The file's syntax is similar to payload
+files: An initial comment identifies the rule belonging to the following JSON
+equivalent. Pairs of comment and JSON are separated by a single blank line.
+
+If the example.t.json file does not exist, the test script will warn and create
+(or append to) example.t.json.got. The JSON equivalent written is generated by
+applying the rule in standard syntax and listing the ruleset in JSON format.
+After thorough review, it may be renamed to example.t.json.
+
+One common case for editing the content in example.t.json.got is expected
+differences between input and output. The generated content will match the
+output while it is supposed to match the input.
+
+If a rule is expected to differ in output, the expected output must be recorded
+in example.t.json.output. Its syntax is identical to example.t.json, i.e. pairs
+of comment identifying the rule (in standard syntax) and JSON (output) format
+separated by blank lines. Note: the comment states the rule as in input, not
+output.
+
+If the example.t.json.output file does not exist and output differs from input,
+the file example.t.json.output.got is created with the actual output recorded.
+
+JSON mode will also check the payload created for the rule in JSON syntax by
+comparing it to the recorded one in example.t.payload. Should it differ, it
+will be recorded in example.t.json.payload.got. This is always a bug: A rule's
+JSON equivalent must turn into the same bytecode as the rule itself.
+
+-EOF-
diff --git a/tests/py/any/counter.t b/tests/py/any/counter.t
new file mode 100644
index 0000000..1c72742
--- /dev/null
+++ b/tests/py/any/counter.t
@@ -0,0 +1,14 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*arp;test-arp;input
+*bridge;test-bridge;input
+*netdev;test-netdev;ingress
+
+counter;ok
+counter packets 0 bytes 0;ok;counter
+counter packets 2 bytes 1;ok;counter
+counter bytes 1024 packets 1;ok;counter
diff --git a/tests/py/any/counter.t.json b/tests/py/any/counter.t.json
new file mode 100644
index 0000000..2d1eaa9
--- /dev/null
+++ b/tests/py/any/counter.t.json
@@ -0,0 +1,39 @@
+# counter
+[
+ {
+ "counter": {
+ "bytes": 0,
+ "packets": 0
+ }
+ }
+]
+
+# counter packets 0 bytes 0
+[
+ {
+ "counter": {
+ "bytes": 0,
+ "packets": 0
+ }
+ }
+]
+
+# counter packets 2 bytes 1
+[
+ {
+ "counter": {
+ "bytes": 1,
+ "packets": 2
+ }
+ }
+]
+
+# counter bytes 1024 packets 1
+[
+ {
+ "counter": {
+ "bytes": 1024,
+ "packets": 1
+ }
+ }
+]
diff --git a/tests/py/any/counter.t.json.output b/tests/py/any/counter.t.json.output
new file mode 100644
index 0000000..6a62ffb
--- /dev/null
+++ b/tests/py/any/counter.t.json.output
@@ -0,0 +1,28 @@
+# counter
+[
+ {
+ "counter": null
+ }
+]
+
+# counter packets 0 bytes 0
+[
+ {
+ "counter": null
+ }
+]
+
+# counter packets 2 bytes 1
+[
+ {
+ "counter": null
+ }
+]
+
+# counter bytes 1024 packets 1
+[
+ {
+ "counter": null
+ }
+]
+
diff --git a/tests/py/any/counter.t.payload b/tests/py/any/counter.t.payload
new file mode 100644
index 0000000..23e96ba
--- /dev/null
+++ b/tests/py/any/counter.t.payload
@@ -0,0 +1,15 @@
+# counter
+ip
+ [ counter pkts 0 bytes 0 ]
+
+# counter packets 0 bytes 0
+ip
+ [ counter pkts 0 bytes 0 ]
+
+# counter packets 2 bytes 1
+ip
+ [ counter pkts 2 bytes 1 ]
+
+# counter bytes 1024 packets 1
+ip
+ [ counter pkts 1 bytes 1024 ]
diff --git a/tests/py/any/ct.t b/tests/py/any/ct.t
new file mode 100644
index 0000000..f73fa4e
--- /dev/null
+++ b/tests/py/any/ct.t
@@ -0,0 +1,149 @@
+:output;type filter hook output priority 0
+
+*ip;test-ip4;output
+*ip6;test-ip6;output
+*inet;test-inet;output
+
+ct state new,established, related, untracked;ok;ct state established,related,new,untracked
+ct state != related;ok
+ct state {new,established, related, untracked};ok
+ct state != {new,established, related, untracked};ok
+ct state invalid drop;ok
+ct state established accept;ok
+ct state 8;ok;ct state new
+ct state xxx;fail
+
+ct direction original;ok
+ct direction != original;ok
+ct direction reply;ok
+ct direction != reply;ok
+ct direction {reply, original};ok
+ct direction != {reply, original};ok
+ct direction xxx;fail
+
+ct status expected;ok
+ct status != expected;ok
+ct status seen-reply;ok
+ct status != seen-reply;ok
+ct status {expected, seen-reply, assured, confirmed, dying};ok
+ct status != {expected, seen-reply, assured, confirmed, dying};ok
+ct status expected,seen-reply,assured,confirmed,snat,dnat,dying;ok
+ct status snat;ok
+ct status dnat;ok
+ct status ! dnat;ok
+ct status xxx;fail
+
+ct mark 0;ok;ct mark 0x00000000
+ct mark or 0x23 == 0x11;ok;ct mark | 0x00000023 == 0x00000011
+ct mark or 0x3 != 0x1;ok;ct mark | 0x00000003 != 0x00000001
+ct mark and 0x23 == 0x11;ok;ct mark & 0x00000023 == 0x00000011
+ct mark and 0x3 != 0x1;ok;ct mark & 0x00000003 != 0x00000001
+ct mark xor 0x23 == 0x11;ok;ct mark 0x00000032
+ct mark xor 0x3 != 0x1;ok;ct mark != 0x00000002
+ct mark set ct mark or 0x00000001;ok;ct mark set ct mark | 0x00000001
+
+ct mark 0x00000032;ok
+ct mark != 0x00000032;ok
+ct mark 0x00000032-0x00000045;ok
+ct mark != 0x00000032-0x00000045;ok
+ct mark {0x32, 0x2222, 0x42de3};ok;ct mark { 0x00042de3, 0x00002222, 0x00000032}
+ct mark {0x32-0x2222, 0x4444-0x42de3};ok;ct mark { 0x00000032-0x00002222, 0x00004444-0x00042de3}
+ct mark != {0x32, 0x2222, 0x42de3};ok;ct mark != { 0x00042de3, 0x00002222, 0x00000032}
+
+# ct mark != {0x32, 0x2222, 0x42de3};ok
+# BUG: invalid expression type set
+# nft: src/evaluate.c:975: expr_evaluate_relational: Assertion '0' failed.
+
+ct mark set 0x11 xor 0x1331;ok;ct mark set 0x00001320
+ct mark set 0x11333 and 0x11;ok;ct mark set 0x00000011
+ct mark set 0x12 or 0x11;ok;ct mark set 0x00000013
+ct mark set 0x11;ok;ct mark set 0x00000011
+ct mark set mark;ok;ct mark set meta mark
+ct mark set (meta mark | 0x10) << 8;ok;ct mark set (meta mark | 0x00000010) << 8
+ct mark set mark map { 1 : 10, 2 : 20, 3 : 30 };ok;ct mark set meta mark map { 0x00000003 : 0x0000001e, 0x00000002 : 0x00000014, 0x00000001 : 0x0000000a}
+
+ct mark set {0x11333, 0x11};fail
+ct zone set {123, 127};fail
+ct label set {123, 127};fail
+ct event set {new, related, destroy, label};fail
+
+ct expiration 30s;ok
+ct expiration 30000ms;ok;ct expiration 30s
+ct expiration 1m-1h;ok;ct expiration 60s-3600s
+ct expiration 1d-1h;fail
+ct expiration > 4d23h59m59s;ok
+ct expiration != 233;ok;ct expiration != 3m53s
+ct expiration 33-45;ok;ct expiration 33s-45s
+ct expiration != 33-45;ok;ct expiration != 33s-45s
+ct expiration {33, 55, 67, 88};ok;ct expiration { 1m7s, 33s, 55s, 1m28s}
+ct expiration != {33, 55, 67, 88};ok;ct expiration != { 1m7s, 33s, 55s, 1m28s}
+ct expiration {33-55, 66-88};ok;ct expiration { 33s-55s, 66s-88s}
+ct expiration != {33-55, 66-88};ok;ct expiration != { 33s-55s, 66s-88s}
+
+ct helper "ftp";ok
+ct helper "12345678901234567";fail
+ct helper "";fail
+
+ct state . ct mark { new . 0x12345678, new . 0x34127856, established . 0x12785634};ok
+ct direction . ct mark { original . 0x12345678, reply . 0x87654321};ok
+ct state . ct mark vmap { new . 0x12345678 : drop, established . 0x87654321 : accept};ok
+
+ct original bytes > 100000;ok
+ct reply packets < 100;ok
+ct bytes > 100000;ok
+
+ct avgpkt > 200;ok
+ct original avgpkt < 500;ok
+
+# bogus direction
+ct both bytes gt 1;fail
+# nonsensical
+ct bytes original reply;fail
+
+# missing direction
+ct ip saddr 1.2.3.4;fail
+
+# wrong base (ip6 but ipv4 address given)
+meta nfproto ipv6 ct original ip saddr 1.2.3.4;fail
+
+# direction, but must be used without
+ct original mark 42;fail
+# swapped key and direction
+ct mark original;fail
+
+ct event set new;ok
+ct event set new or related or destroy or foobar;fail
+ct event set new | related | destroy | label;ok;ct event set new,related,destroy,label
+ct event set new,related,destroy,label;ok
+ct event set new,destroy;ok
+ct event set 1;ok;ct event set new
+ct event set 0x0;ok
+
+ct label 127;ok
+ct label set 127;ok
+ct label 128;fail
+
+ct zone 0;ok
+ct zone 23;ok
+ct zone 65536;fail
+ct both zone 1;fail
+ct original zone 1;ok
+ct reply zone 1;ok
+
+ct id 12345;ok
+
+ct zone set 1;ok
+ct original zone set 1;ok
+ct reply zone set 1;ok
+ct zone set mark map { 1 : 1, 2 : 2 };ok;ct zone set meta mark map { 0x00000001 : 1, 0x00000002 : 2}
+ct both zone set 1;fail
+
+ct invalid;fail
+ct invalid original;fail
+ct set invalid original 42;fail
+ct set invalid 42;fail
+
+notrack;ok
+
+ct count 3;ok
+ct count over 3;ok
diff --git a/tests/py/any/ct.t.json b/tests/py/any/ct.t.json
new file mode 100644
index 0000000..a2a0602
--- /dev/null
+++ b/tests/py/any/ct.t.json
@@ -0,0 +1,1523 @@
+# ct state new,established, related, untracked
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "in",
+ "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"
+ }
+ },
+ "op": "in",
+ "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"
+ }
+ },
+ "op": "in",
+ "right": "invalid"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ct state established accept
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "in",
+ "right": "established"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ct state 8
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "in",
+ "right": 8
+ }
+ }
+]
+
+# ct direction original
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "==",
+ "right": "original"
+ }
+ }
+]
+
+# ct direction != original
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "!=",
+ "right": "original"
+ }
+ }
+]
+
+# ct direction reply
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "==",
+ "right": "reply"
+ }
+ }
+]
+
+# ct direction != reply
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "!=",
+ "right": "reply"
+ }
+ }
+]
+
+# ct direction {reply, original}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "in",
+ "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"
+ }
+ },
+ "op": "in",
+ "right": "expected"
+ }
+ }
+]
+
+# ct status != expected
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "!=",
+ "right": "expected"
+ }
+ }
+]
+
+# ct status seen-reply
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "in",
+ "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"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "expected",
+ "seen-reply",
+ "assured",
+ "confirmed",
+ "dying"
+ ]
+ }
+ }
+ }
+]
+
+# ct status != {expected, seen-reply, assured, confirmed, dying}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "expected",
+ "seen-reply",
+ "assured",
+ "confirmed",
+ "dying"
+ ]
+ }
+ }
+ }
+]
+
+# ct status expected,seen-reply,assured,confirmed,snat,dnat,dying
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "in",
+ "right": [
+ "expected",
+ "seen-reply",
+ "assured",
+ "confirmed",
+ "snat",
+ "dnat",
+ "dying"
+ ]
+ }
+ }
+]
+
+# ct status snat
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "in",
+ "right": "snat"
+ }
+ }
+]
+
+# ct status dnat
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "in",
+ "right": "dnat"
+ }
+ }
+]
+
+# ct status ! dnat
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "!",
+ "right": "dnat"
+ }
+ }
+]
+
+# ct mark 0
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "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"
+ ]
+ },
+ "op": "==",
+ "right": "0x11"
+ }
+ }
+]
+
+# ct mark xor 0x3 != 0x1
+[
+ {
+ "match": {
+ "left": {
+ "^": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "0x3"
+ ]
+ },
+ "op": "!=",
+ "right": "0x1"
+ }
+ }
+]
+
+# ct mark set ct mark or 0x00000001
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ 1
+ ]
+ }
+ }
+ }
+]
+
+# ct mark 0x00000032
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "right": "0x00000032"
+ }
+ }
+]
+
+# ct mark != 0x00000032
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": "0x00000032"
+ }
+ }
+]
+
+# ct mark 0x00000032-0x00000045
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "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"
+ }
+ },
+ "op": "in",
+ "right": {
+ "set": [
+ "0x32",
+ "0x2222",
+ "0x42de3"
+ ]
+ }
+ }
+ }
+]
+
+# ct mark {0x32-0x2222, 0x4444-0x42de3}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "in",
+ "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": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": { "^": [ "0x11", "0x1331" ] }
+ }
+ }
+]
+
+# ct mark set 0x11333 and 0x11
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": { "&": [ "0x11333", "0x11" ] }
+ }
+ }
+]
+
+# ct mark set 0x12 or 0x11
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": { "|": [ "0x12", "0x11" ] }
+ }
+ }
+]
+
+# ct mark set 0x11
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": "0x11"
+ }
+ }
+]
+
+# ct mark set mark
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "meta": { "key": "mark" }
+ }
+ }
+ }
+]
+
+# ct mark set (meta mark | 0x10) << 8
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "<<": [
+ {
+ "|": [
+ {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ 16
+ ]
+ },
+ 8
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set mark map { 1 : 10, 2 : 20, 3 : 30 }
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "map": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "data": {
+ "set": [
+ [ 1, 10 ],
+ [ 2, 20 ],
+ [ 3, 30 ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# ct expiration 30s
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "==",
+ "right": "30s"
+ }
+ }
+]
+
+# ct expiration 30000ms
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "==",
+ "right": "30000ms"
+ }
+ }
+]
+
+# ct expiration 1m-1h
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ "1m", "1h" ]
+ }
+ }
+ }
+]
+
+# ct expiration > 4d23h59m59s
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": ">",
+ "right": "4d23h59m59s"
+ }
+ }
+]
+
+# ct expiration != 233
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ct expiration 33-45
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "==",
+ "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"
+ }
+ },
+ "op": "==",
+ "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, 66-88}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] },
+ { "range": [ 66, 88 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ct expiration != {33-55, 66-88}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] },
+ { "range": [ 66, 88 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ct helper "ftp"
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "helper"
+ }
+ },
+ "op": "==",
+ "right": "ftp"
+ }
+ }
+]
+
+# ct state . ct mark { new . 0x12345678, new . 0x34127856, established . 0x12785634}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "concat": [ "new", "0x12345678" ] },
+ { "concat": [ "new", "0x34127856" ] },
+ { "concat": [ "established", "0x12785634" ] }
+ ]
+ }
+ }
+ }
+]
+
+# ct direction . ct mark { original . 0x12345678, reply . 0x87654321}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "original",
+ "0x12345678"
+ ]
+ },
+ {
+ "concat": [
+ "reply",
+ "0x87654321"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct state . ct mark vmap { new . 0x12345678 : drop, established . 0x87654321 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "new",
+ "0x12345678"
+ ]
+ },
+ {
+ "drop": null
+ }
+ ],
+ [
+ {
+ "concat": [
+ "established",
+ "0x87654321"
+ ]
+ },
+ {
+ "accept": 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": {
+ "key": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "value": "new"
+ }
+ }
+]
+
+# ct event set new | related | destroy | label
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "value": [
+ "new",
+ "related",
+ "destroy",
+ "label"
+ ]
+ }
+ }
+]
+
+# ct event set new,related,destroy,label
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "value": [
+ "new",
+ "related",
+ "destroy",
+ "label"
+ ]
+ }
+ }
+]
+
+# ct event set new,destroy
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "value": [
+ "new",
+ "destroy"
+ ]
+ }
+ }
+]
+
+# ct event set 1
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "value": 1
+ }
+ }
+]
+
+# ct event set 0x0
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "value": "0x0"
+ }
+ }
+]
+
+# ct label 127
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "label"
+ }
+ },
+ "op": "in",
+ "right": 127
+ }
+ }
+]
+
+# ct label set 127
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "label"
+ }
+ },
+ "value": 127
+ }
+ }
+]
+
+# ct zone 0
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "zone"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# ct zone 23
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "zone"
+ }
+ },
+ "op": "==",
+ "right": 23
+ }
+ }
+]
+
+# ct original zone 1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "zone"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# ct reply zone 1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "zone"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# ct zone set 1
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "zone"
+ }
+ },
+ "value": 1
+ }
+ }
+]
+
+# ct original zone set 1
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "dir": "original",
+ "key": "zone"
+ }
+ },
+ "value": 1
+ }
+ }
+]
+
+# ct reply zone set 1
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "dir": "reply",
+ "key": "zone"
+ }
+ },
+ "value": 1
+ }
+ }
+]
+
+# ct id 12345
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "id"
+ }
+ },
+ "op": "==",
+ "right": 12345
+ }
+ }
+]
+
+# ct zone set mark map { 1 : 1, 2 : 2 }
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "zone"
+ }
+ },
+ "value": {
+ "map": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "data": {
+ "set": [
+ [ 1, 1 ],
+ [ 2, 2 ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# notrack
+[
+ {
+ "notrack": null
+ }
+]
+
+# ct count 3
+[
+ {
+ "ct count": {
+ "val": 3
+ }
+ }
+]
+
+# ct count over 3
+[
+ {
+ "ct count": {
+ "inv": true,
+ "val": 3
+ }
+ }
+]
+
diff --git a/tests/py/any/ct.t.json.output b/tests/py/any/ct.t.json.output
new file mode 100644
index 0000000..70ade7e
--- /dev/null
+++ b/tests/py/any/ct.t.json.output
@@ -0,0 +1,666 @@
+# ct state new,established, related, untracked
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "in",
+ "right": [
+ "established",
+ "related",
+ "new",
+ "untracked"
+ ]
+ }
+ }
+]
+
+# ct state {new,established, related, untracked}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "==",
+ "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"
+ }
+ },
+ "op": "in",
+ "right": "new"
+ }
+ }
+]
+
+# ct direction {reply, original}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ "op": "==",
+ "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"
+ }
+ },
+ "op": "==",
+ "right": 50
+ }
+ }
+]
+
+# ct mark xor 0x3 != 0x1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": 2
+ }
+ }
+]
+
+# ct mark 0x00000032
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "right": 50
+ }
+ }
+]
+
+# ct mark != 0x00000032
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "!=",
+ "right": 50
+ }
+ }
+]
+
+# ct mark 0x00000032-0x00000045
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "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"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 50,
+ 8738,
+ 273891
+ ]
+ }
+ }
+ }
+]
+
+# ct mark {0x32-0x2222, 0x4444-0x42de3}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "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": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": 4896
+ }
+ }
+]
+
+# ct mark set 0x11333 and 0x11
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": 17
+ }
+ }
+]
+
+# ct mark set 0x12 or 0x11
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": 19
+ }
+ }
+]
+
+# ct mark set 0x11
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": 17
+ }
+ }
+]
+
+# ct expiration 30s
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "==",
+ "right": 30
+ }
+ }
+]
+
+# ct expiration 30000ms
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "==",
+ "right": 30
+ }
+ }
+]
+
+# ct expiration 1m-1h
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 60, 3600 ]
+ }
+ }
+ }
+]
+
+# ct expiration > 4d23h59m59s
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "expiration"
+ }
+ },
+ "op": ">",
+ "right": 431999
+ }
+ }
+]
+
+# ct state . ct mark { new . 0x12345678}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "new",
+ 305419896
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct state . ct mark { new . 0x12345678, new . 0x34127856, established . 0x12785634}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "new",
+ 305419896
+ ]
+ },
+ {
+ "concat": [
+ "established",
+ 309876276
+ ]
+ },
+ {
+ "concat": [
+ "new",
+ 873625686
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct direction . ct mark { original . 0x12345678, reply . 0x87654321}
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "key": "direction"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "original",
+ 305419896
+ ]
+ },
+ {
+ "concat": [
+ "reply",
+ 2271560481
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct state . ct mark vmap { new . 0x12345678 : drop, established . 0x87654321 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "concat": [
+ {
+ "ct": {
+ "key": "state"
+ }
+ },
+ {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "new",
+ 305419896
+ ]
+ },
+ {
+ "drop": null
+ }
+ ],
+ [
+ {
+ "concat": [
+ "established",
+ 2271560481
+ ]
+ },
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ct event set 1
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "value": "new"
+ }
+ }
+]
+
+# ct event set 0x0
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "event"
+ }
+ },
+ "value": 0
+ }
+ }
+]
+
diff --git a/tests/py/any/ct.t.payload b/tests/py/any/ct.t.payload
new file mode 100644
index 0000000..ed868e5
--- /dev/null
+++ b/tests/py/any/ct.t.payload
@@ -0,0 +1,518 @@
+# ct state new,established, related, untracked
+ip test-ip4 output
+ [ ct load state => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000004e ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ct state != related
+ip test-ip4 output
+ [ ct load state => reg 1 ]
+ [ cmp neq reg 1 0x00000004 ]
+
+# ct state {new,established, related, untracked}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000040 : 0 [end]
+ip test-ip4 output
+ [ ct load state => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ct state != {new,established, related, untracked}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000040 : 0 [end]
+ip test-ip4 output
+ [ ct load state => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ct state invalid drop
+ip test-ip4 output
+ [ ct load state => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+ [ immediate reg 0 drop ]
+
+# ct state established accept
+ip test-ip4 output
+ [ ct load state => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000002 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+ [ immediate reg 0 accept ]
+
+# ct state 8
+ip test-ip4 output
+ [ ct load state => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000008 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ct direction original
+ip test-ip4 output
+ [ ct load direction => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ct direction != original
+ip test-ip4 output
+ [ ct load direction => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ct direction reply
+ip test-ip4 output
+ [ ct load direction => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ct direction != reply
+ip test-ip4 output
+ [ ct load direction => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# ct direction {reply, original}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 output
+ [ ct load direction => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ct direction != {reply, original}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 output
+ [ ct load direction => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ct status expected
+ip test-ip4 output
+ [ ct load status => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ct status != expected
+ip test-ip4 output
+ [ ct load status => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# ct status seen-reply
+ip test-ip4 output
+ [ ct load status => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000002 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ct status != seen-reply
+ip test-ip4 output
+ [ ct load status => reg 1 ]
+ [ cmp neq reg 1 0x00000002 ]
+
+# ct status {expected, seen-reply, assured, confirmed, dying}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000008 : 0 [end] element 00000200 : 0 [end]
+ip test-ip4 output
+ [ ct load status => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ct status != {expected, seen-reply, assured, confirmed, dying}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000008 : 0 [end] element 00000200 : 0 [end]
+ip test-ip4 output
+ [ ct load status => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ct mark 0
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ct mark or 0x23 == 0x11
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffdc ) ^ 0x00000023 ]
+ [ cmp eq reg 1 0x00000011 ]
+
+# ct mark or 0x3 != 0x1
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xfffffffc ) ^ 0x00000003 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# ct mark and 0x23 == 0x11
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000023 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000011 ]
+
+# ct mark and 0x3 != 0x1
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000003 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# ct mark xor 0x23 == 0x11
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+
+# ct mark xor 0x3 != 0x1
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ cmp neq reg 1 0x00000002 ]
+
+# ct mark 0x00000032
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+
+# ct mark != 0x00000032
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ cmp neq reg 1 0x00000032 ]
+
+# ct mark 0x00000032-0x00000045
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0x32000000 ]
+ [ cmp lte reg 1 0x45000000 ]
+
+# ct mark != 0x00000032-0x00000045
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ range neq reg 1 0x32000000 0x45000000 ]
+
+# ct mark {0x32, 0x2222, 0x42de3}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000032 : 0 [end] element 00002222 : 0 [end] element 00042de3 : 0 [end]
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ct mark {0x32-0x2222, 0x4444-0x42de3}
+__set%d test-ip4 7
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 32000000 : 0 [end] element 23220000 : 1 [end] element 44440000 : 0 [end] element e42d0400 : 1 [end]
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+
+# ct mark != {0x32, 0x2222, 0x42de3}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000032 : 0 [end] element 00002222 : 0 [end] element 00042de3 : 0 [end]
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ct mark set 0x11 xor 0x1331
+ip test-ip4 output
+ [ immediate reg 1 0x00001320 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set 0x11333 and 0x11
+ip test-ip4 output
+ [ immediate reg 1 0x00000011 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set 0x12 or 0x11
+ip test-ip4 output
+ [ immediate reg 1 0x00000013 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set 0x11
+ip test-ip4 output
+ [ immediate reg 1 0x00000011 ]
+ [ ct set mark with reg 1 ]
+
+# ct expiration 30s
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ cmp eq reg 1 0x00007530 ]
+
+# ct expiration 30000ms
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ cmp eq reg 1 0x00007530 ]
+
+# ct expiration 1m-1h
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0x60ea0000 ]
+ [ cmp lte reg 1 0x80ee3600 ]
+
+# ct expiration > 4d23h59m59s
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gt reg 1 0x18c8bf19 ]
+
+# ct expiration != 233
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ cmp neq reg 1 0x00038e28 ]
+
+# ct expiration 33-45
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0xe8800000 ]
+ [ cmp lte reg 1 0xc8af0000 ]
+
+# ct expiration != 33-45
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ range neq reg 1 0xe8800000 0xc8af0000 ]
+
+# ct expiration {33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 000080e8 : 0 [end] element 0000d6d8 : 0 [end] element 000105b8 : 0 [end] element 000157c0 : 0 [end]
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ct expiration != {33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 000080e8 : 0 [end] element 0000d6d8 : 0 [end] element 000105b8 : 0 [end] element 000157c0 : 0 [end]
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ct expiration {33-55, 66-88}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element e8800000 : 0 [end] element d9d60000 : 1 [end] element d0010100 : 0 [end] element c1570100 : 1 [end]
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+
+# ct expiration != {33-55, 66-88}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element e8800000 : 0 [end] element d9d60000 : 1 [end] element d0010100 : 0 [end] element c1570100 : 1 [end]
+ip test-ip4 output
+ [ ct load expiration => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ct helper "ftp"
+ip test-ip4 output
+ [ ct load helper => reg 1 ]
+ [ cmp eq reg 1 0x00707466 0x00000000 0x00000000 0x00000000 ]
+
+# ct state . ct mark { new . 0x12345678, new . 0x34127856, established . 0x12785634}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 12345678 : 0 [end] element 00000008 34127856 : 0 [end] element 00000002 12785634 : 0 [end]
+ip test-ip4 output
+ [ ct load state => reg 1 ]
+ [ ct load mark => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# ct mark set mark
+ip test-ip4 output
+ [ meta load mark => reg 1 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set (meta mark | 0x10) << 8
+inet test-inet output
+ [ meta load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+ [ bitwise reg 1 = ( reg 1 << 0x00000008 ) ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set mark map { 1 : 10, 2 : 20, 3 : 30 }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00000001 : 0000000a 0 [end] element 00000002 : 00000014 0 [end] element 00000003 : 0000001e 0 [end]
+ip test-ip4 output
+ [ meta load mark => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ ct set mark with reg 1 ]
+
+# ct original bytes > 100000
+ip test-ip4 output
+ [ ct load bytes => reg 1 , dir original ]
+ [ byteorder reg 1 = hton(reg 1, 8, 8) ]
+ [ cmp gt reg 1 0x00000000 0xa0860100 ]
+
+# ct reply packets < 100
+ip test-ip4 output
+ [ ct load packets => reg 1 , dir reply ]
+ [ byteorder reg 1 = hton(reg 1, 8, 8) ]
+ [ cmp lt reg 1 0x00000000 0x64000000 ]
+
+# ct bytes > 100000
+ip test-ip4 output
+ [ ct load bytes => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 8, 8) ]
+ [ cmp gt reg 1 0x00000000 0xa0860100 ]
+
+# ct avgpkt > 200
+ip test-ip4 output
+ [ ct load avgpkt => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 8, 8) ]
+ [ cmp gt reg 1 0x00000000 0xc8000000 ]
+
+# ct original avgpkt < 500
+ip test-ip4 output
+ [ ct load avgpkt => reg 1 , dir original ]
+ [ byteorder reg 1 = hton(reg 1, 8, 8) ]
+ [ cmp lt reg 1 0x00000000 0xf4010000 ]
+
+# ct status expected,seen-reply,assured,confirmed,snat,dnat,dying
+ip test-ip4 output
+ [ ct load status => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000023f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ct status snat
+ip test-ip4 output
+ [ ct load status => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ct status dnat
+ip test-ip4 output
+ [ ct load status => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ct event set new
+ip test-ip4 output
+ [ immediate reg 1 0x00000001 ]
+ [ ct set event with reg 1 ]
+
+# ct event set new | related | destroy | label
+ip test-ip4 output
+ [ immediate reg 1 0x00000407 ]
+ [ ct set event with reg 1 ]
+
+# ct event set new,related,destroy,label
+ip test-ip4 output
+ [ immediate reg 1 0x00000407 ]
+ [ ct set event with reg 1 ]
+
+# ct event set new,destroy
+ip test-ip4 output
+ [ immediate reg 1 0x00000005 ]
+ [ ct set event with reg 1 ]
+
+# ct event set 1
+ip test-ip4 output
+ [ immediate reg 1 0x00000001 ]
+ [ ct set event with reg 1 ]
+
+# ct event set 0x0
+ip test-ip4 output
+ [ immediate reg 1 0x00000000 ]
+ [ ct set event with reg 1 ]
+
+# ct label 127
+ip test-ip4 output
+ [ ct load label => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000000 0x00000000 0x00000000 0x80000000 ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 0x00000000 0x00000000 0x00000000 ]
+
+# ct label set 127
+ip test-ip4 output
+ [ immediate reg 1 0x00000000 0x00000000 0x00000000 0x80000000 ]
+ [ ct set label with reg 1 ]
+
+# ct zone 0
+ip test-ip4 output
+ [ ct load zone => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ct zone 23
+ip test-ip4 output
+ [ ct load zone => reg 1 ]
+ [ cmp eq reg 1 0x00000017 ]
+
+# ct original zone 1
+ip test-ip4 output
+ [ ct load zone => reg 1 , dir original ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ct reply zone 1
+ip test-ip4 output
+ [ ct load zone => reg 1 , dir reply ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ct zone set 1
+ip test-ip4 output
+ [ immediate reg 1 0x00000001 ]
+ [ ct set zone with reg 1 ]
+
+# ct original zone set 1
+ip test-ip4 output
+ [ immediate reg 1 0x00000001 ]
+ [ ct set zone with reg 1 , dir original ]
+
+# ct reply zone set 1
+ip test-ip4 output
+ [ immediate reg 1 0x00000001 ]
+ [ ct set zone with reg 1 , dir reply ]
+
+# ct zone set mark map { 1 : 1, 2 : 2 }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00000001 : 00000001 0 [end] element 00000002 : 00000002 0 [end]
+ip test-ip4 output
+ [ meta load mark => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ ct set zone with reg 1 ]
+
+# notrack
+ip test-ip4 output
+ [ notrack ]
+
+# ct direction . ct mark { original . 0x12345678, reply . 0x87654321}
+__set%d test-ip4 3 size 2
+__set%d test-ip4 0
+ element 00000000 12345678 : 0 [end] element 00000001 87654321 : 0 [end]
+ip test-ip4 output
+ [ ct load direction => reg 1 ]
+ [ ct load mark => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# ct state . ct mark vmap { new . 0x12345678 : drop, established . 0x87654321 : accept}
+__map%d test-ip4 b size 2
+__map%d test-ip4 0
+ element 00000008 12345678 : drop 0 [end] element 00000002 87654321 : accept 0 [end]
+ip test-ip4 output
+ [ ct load state => reg 1 ]
+ [ ct load mark => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ct mark set ct mark or 0x00000001
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xfffffffe ) ^ 0x00000001 ]
+ [ ct set mark with reg 1 ]
+
+# ct id 12345
+ip test-ip4 output
+ [ ct load unknown => reg 1 ]
+ [ cmp eq reg 1 0x39300000 ]
+
+# ct status ! dnat
+ip6
+ [ ct load status => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ct count 3
+ip test-ip4 output
+ [ connlimit count 3 flags 0 ]
+
+# ct count over 3
+ip test-ip4 output
+ [ connlimit count 3 flags 1 ]
+
diff --git a/tests/py/any/icmpX.t.netdev b/tests/py/any/icmpX.t.netdev
new file mode 100644
index 0000000..cf40242
--- /dev/null
+++ b/tests/py/any/icmpX.t.netdev
@@ -0,0 +1,9 @@
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*netdev;test-netdev;ingress,egress
+
+ip protocol icmp icmp type echo-request;ok;icmp type echo-request
+icmp type echo-request;ok
+ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
+icmpv6 type echo-request;ok
diff --git a/tests/py/any/icmpX.t.netdev.payload b/tests/py/any/icmpX.t.netdev.payload
new file mode 100644
index 0000000..8b8107c
--- /dev/null
+++ b/tests/py/any/icmpX.t.netdev.payload
@@ -0,0 +1,36 @@
+# ip protocol icmp icmp type echo-request
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# icmp type echo-request
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# icmpv6 type echo-request
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
diff --git a/tests/py/any/last.t b/tests/py/any/last.t
new file mode 100644
index 0000000..5c53046
--- /dev/null
+++ b/tests/py/any/last.t
@@ -0,0 +1,13 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*arp;test-arp;input
+*bridge;test-bridge;input
+*netdev;test-netdev;ingress
+
+last;ok
+last used 300s;ok;last
+last used foo;fail
diff --git a/tests/py/any/last.t.json b/tests/py/any/last.t.json
new file mode 100644
index 0000000..2a2b9e7
--- /dev/null
+++ b/tests/py/any/last.t.json
@@ -0,0 +1,16 @@
+# last
+[
+ {
+ "last": null
+ }
+]
+
+# last used 300s
+[
+ {
+ "last": {
+ "used": 300000
+ }
+ }
+]
+
diff --git a/tests/py/any/last.t.json.output b/tests/py/any/last.t.json.output
new file mode 100644
index 0000000..b8a977e
--- /dev/null
+++ b/tests/py/any/last.t.json.output
@@ -0,0 +1,14 @@
+# last
+[
+ {
+ "last": null
+ }
+]
+
+# last used 300s
+[
+ {
+ "last": null
+ }
+]
+
diff --git a/tests/py/any/last.t.payload b/tests/py/any/last.t.payload
new file mode 100644
index 0000000..ed47d0f
--- /dev/null
+++ b/tests/py/any/last.t.payload
@@ -0,0 +1,8 @@
+# last
+ip
+ [ last never ]
+
+# last used 300s
+ip
+ [ last 300000 ]
+
diff --git a/tests/py/any/limit.t b/tests/py/any/limit.t
new file mode 100644
index 0000000..a04ef42
--- /dev/null
+++ b/tests/py/any/limit.t
@@ -0,0 +1,55 @@
+:output;type filter hook output priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;output
+*ip6;test-ip6;output
+*inet;test-inet;output
+*arp;test-arp;output
+*bridge;test-bridge;output
+*netdev;test-netdev;ingress,egress
+
+limit rate 400/minute;ok;limit rate 400/minute burst 5 packets
+limit rate 20/second;ok;limit rate 20/second burst 5 packets
+limit rate 400/hour;ok;limit rate 400/hour burst 5 packets
+limit rate 40/day;ok;limit rate 40/day burst 5 packets
+limit rate 400/week;ok;limit rate 400/week burst 5 packets
+limit rate 1023/second burst 10 packets;ok
+limit rate 1023/second burst 10 bytes;fail
+
+limit rate 1 kbytes/second;ok
+limit rate 2 kbytes/second;ok
+limit rate 1025 kbytes/second;ok
+limit rate 1023 mbytes/second;ok
+limit rate 10230 mbytes/second;ok
+limit rate 1023000 mbytes/second;ok
+limit rate 512 kbytes/second burst 5 packets;fail
+
+limit rate 1 bytes / second;ok;limit rate 1 bytes/second
+limit rate 1 kbytes / second;ok;limit rate 1 kbytes/second
+limit rate 1 mbytes / second;ok;limit rate 1 mbytes/second
+limit rate 1 gbytes / second;fail
+
+limit rate 1025 bytes/second burst 512 bytes;ok
+limit rate 1025 kbytes/second burst 1023 kbytes;ok
+limit rate 1025 mbytes/second burst 1025 kbytes;ok
+limit rate 1025000 mbytes/second burst 1023 mbytes;ok
+
+limit rate over 400/minute;ok;limit rate over 400/minute burst 5 packets
+limit rate over 20/second;ok;limit rate over 20/second burst 5 packets
+limit rate over 400/hour;ok;limit rate over 400/hour burst 5 packets
+limit rate over 40/day;ok;limit rate over 40/day burst 5 packets
+limit rate over 400/week;ok;limit rate over 400/week burst 5 packets
+limit rate over 1023/second burst 10 packets;ok
+
+limit rate over 1 kbytes/second;ok
+limit rate over 2 kbytes/second;ok
+limit rate over 1025 kbytes/second;ok
+limit rate over 1023 mbytes/second;ok
+limit rate over 10230 mbytes/second;ok
+limit rate over 1023000 mbytes/second;ok
+
+limit rate over 1025 bytes/second burst 512 bytes;ok
+limit rate over 1025 kbytes/second burst 1023 kbytes;ok
+limit rate over 1025 mbytes/second burst 1025 kbytes;ok
+limit rate over 1025000 mbytes/second burst 1023 mbytes;ok
diff --git a/tests/py/any/limit.t.json b/tests/py/any/limit.t.json
new file mode 100644
index 0000000..e001ba0
--- /dev/null
+++ b/tests/py/any/limit.t.json
@@ -0,0 +1,413 @@
+# 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 1 bytes / second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1,
+ "rate_unit": "bytes"
+ }
+ }
+]
+
+# limit rate 1 kbytes / second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 1 mbytes / second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1,
+ "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/limit.t.json.output b/tests/py/any/limit.t.json.output
new file mode 100644
index 0000000..5a95f5e
--- /dev/null
+++ b/tests/py/any/limit.t.json.output
@@ -0,0 +1,277 @@
+# limit rate 400/minute
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "minute",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate 20/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "second",
+ "rate": 20
+ }
+ }
+]
+
+# limit rate 400/hour
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "hour",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate 40/day
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "day",
+ "rate": 40
+ }
+ }
+]
+
+# limit rate 400/week
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "week",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate 1 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 2 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 2,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 1025 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 1023 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1023,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate 10230 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 10230,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate 1023000 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1023000,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 400/minute
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "minute",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate over 20/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "second",
+ "rate": 20
+ }
+ }
+]
+
+# limit rate over 400/hour
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "hour",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate over 40/day
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "day",
+ "rate": 40
+ }
+ }
+]
+
+# limit rate over 400/week
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "week",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate over 1 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 2 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 2,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 1025 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 1023 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1023,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 10230 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 10230,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 1023000 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 0,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1023000,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
diff --git a/tests/py/any/limit.t.payload b/tests/py/any/limit.t.payload
new file mode 100644
index 0000000..0c7ee94
--- /dev/null
+++ b/tests/py/any/limit.t.payload
@@ -0,0 +1,141 @@
+# limit rate 400/minute
+ip test-ip4 output
+ [ limit rate 400/minute burst 5 type packets flags 0x0 ]
+
+# limit rate 20/second
+ip test-ip4 output
+ [ limit rate 20/second burst 5 type packets flags 0x0 ]
+
+# limit rate 400/hour
+ip test-ip4 output
+ [ limit rate 400/hour burst 5 type packets flags 0x0 ]
+
+# limit rate 400/week
+ip test-ip4 output
+ [ limit rate 400/week burst 5 type packets flags 0x0 ]
+
+# limit rate 40/day
+ip test-ip4 output
+ [ limit rate 40/day burst 5 type packets flags 0x0 ]
+
+# limit rate 1023/second burst 10 packets
+ip test-ip4 output
+ [ limit rate 1023/second burst 10 type packets flags 0x0 ]
+
+# limit rate 1 kbytes/second
+ip test-ip4 output
+ [ limit rate 1024/second burst 0 type bytes flags 0x0 ]
+
+# limit rate 2 kbytes/second
+ip test-ip4 output
+ [ limit rate 2048/second burst 0 type bytes flags 0x0 ]
+
+# limit rate 1025 kbytes/second
+ip test-ip4 output
+ [ limit rate 1049600/second burst 0 type bytes flags 0x0 ]
+
+# limit rate 1023 mbytes/second
+ip test-ip4 output
+ [ limit rate 1072693248/second burst 0 type bytes flags 0x0 ]
+
+# limit rate 10230 mbytes/second
+ip test-ip4 output
+ [ limit rate 10726932480/second burst 0 type bytes flags 0x0 ]
+
+# limit rate 1023000 mbytes/second
+ip test-ip4 output
+ [ limit rate 1072693248000/second burst 0 type bytes flags 0x0 ]
+
+# limit rate 1 bytes / second
+ip
+ [ limit rate 1/second burst 0 type bytes flags 0x0 ]
+
+# limit rate 1 kbytes / second
+ip
+ [ limit rate 1024/second burst 0 type bytes flags 0x0 ]
+
+# limit rate 1 mbytes / second
+ip
+ [ limit rate 1048576/second burst 0 type bytes flags 0x0 ]
+
+
+# limit rate 1025 bytes/second burst 512 bytes
+ip test-ip4 output
+ [ limit rate 1025/second burst 512 type bytes flags 0x0 ]
+
+# limit rate 1025 kbytes/second burst 1023 kbytes
+ip test-ip4 output
+ [ limit rate 1049600/second burst 1047552 type bytes flags 0x0 ]
+
+# limit rate 1025 mbytes/second burst 1025 kbytes
+ip test-ip4 output
+ [ limit rate 1074790400/second burst 1049600 type bytes flags 0x0 ]
+
+# limit rate 1025000 mbytes/second burst 1023 mbytes
+ip test-ip4 output
+ [ limit rate 1074790400000/second burst 1072693248 type bytes flags 0x0 ]
+
+# limit rate over 400/minute
+ip test-ip4 output
+ [ limit rate 400/minute burst 5 type packets flags 0x1 ]
+
+# limit rate over 20/second
+ip test-ip4 output
+ [ limit rate 20/second burst 5 type packets flags 0x1 ]
+
+# limit rate over 400/hour
+ip test-ip4 output
+ [ limit rate 400/hour burst 5 type packets flags 0x1 ]
+
+# limit rate over 400/week
+ip test-ip4 output
+ [ limit rate 400/week burst 5 type packets flags 0x1 ]
+
+# limit rate over 40/day
+ip test-ip4 output
+ [ limit rate 40/day burst 5 type packets flags 0x1 ]
+
+# limit rate over 1023/second burst 10 packets
+ip test-ip4 output
+ [ limit rate 1023/second burst 10 type packets flags 0x1 ]
+
+# limit rate over 1 kbytes/second
+ip test-ip4 output
+ [ limit rate 1024/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 2 kbytes/second
+ip test-ip4 output
+ [ limit rate 2048/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 1025 kbytes/second
+ip test-ip4 output
+ [ limit rate 1049600/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 1023 mbytes/second
+ip test-ip4 output
+ [ limit rate 1072693248/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 10230 mbytes/second
+ip test-ip4 output
+ [ limit rate 10726932480/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 1023000 mbytes/second
+ip test-ip4 output
+ [ limit rate 1072693248000/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 1025 bytes/second burst 512 bytes
+ip test-ip4 output
+ [ limit rate 1025/second burst 512 type bytes flags 0x1 ]
+
+# limit rate over 1025 kbytes/second burst 1023 kbytes
+ip test-ip4 output
+ [ limit rate 1049600/second burst 1047552 type bytes flags 0x1 ]
+
+# limit rate over 1025 mbytes/second burst 1025 kbytes
+ip test-ip4 output
+ [ limit rate 1074790400/second burst 1049600 type bytes flags 0x1 ]
+
+# limit rate over 1025000 mbytes/second burst 1023 mbytes
+ip test-ip4 output
+ [ limit rate 1074790400000/second burst 1072693248 type bytes flags 0x1 ]
+
diff --git a/tests/py/any/log.t b/tests/py/any/log.t
new file mode 100644
index 0000000..f4ccaf0
--- /dev/null
+++ b/tests/py/any/log.t
@@ -0,0 +1,41 @@
+:output;type filter hook output priority 0
+
+*ip;test-ip4;output
+*ip6;test-ip6;output
+*inet;test-inet;output
+*arp;test-arp;output
+*bridge;test-bridge;output
+
+log;ok
+log level emerg;ok
+log level alert;ok
+log level crit;ok
+log level err;ok
+log level warn;ok;log
+log level notice;ok
+log level info;ok
+log level debug;ok
+log level audit;ok
+
+log level emerg group 2;fail
+log level alert group 2 prefix "log test2";fail
+
+# log level audit must reject all other parameters
+log level audit prefix "foo";fail
+log level audit group 42;fail
+log level audit snaplen 23;fail
+log level audit queue-threshold 1337;fail
+log level audit flags all;fail
+
+log prefix aaaaa-aaaaaa group 2 snaplen 33;ok;log prefix "aaaaa-aaaaaa" group 2 snaplen 33
+# TODO: Add an exception: 'queue-threshold' attribute needs 'group' attribute
+# The correct rule is log group 2 queue-threshold 2
+log group 2 queue-threshold 2;ok
+log group 2 snaplen 33;ok
+log group 2 prefix "nft-test: ";ok;log prefix "nft-test: " group 2
+
+log flags all;ok
+log level debug flags ip options flags skuid;ok
+log flags tcp sequence,options;ok
+log flags ip options flags ether flags skuid flags tcp sequence,options;ok;log flags all
+log flags all group 2;fail
diff --git a/tests/py/any/log.t.json b/tests/py/any/log.t.json
new file mode 100644
index 0000000..7bcc20e
--- /dev/null
+++ b/tests/py/any/log.t.json
@@ -0,0 +1,178 @@
+# 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 level audit
+[
+ {
+ "log": {
+ "level": "audit"
+ }
+ }
+]
+
+# 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 0000000..051c448
--- /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/log.t.payload b/tests/py/any/log.t.payload
new file mode 100644
index 0000000..1330445
--- /dev/null
+++ b/tests/py/any/log.t.payload
@@ -0,0 +1,71 @@
+# log
+ip test-ip4 output
+ [ log ]
+
+# log level emerg
+ip test-ip4 output
+ [ log level 0 ]
+
+# log level alert
+ip test-ip4 output
+ [ log level 1 ]
+
+# log level crit
+ip test-ip4 output
+ [ log level 2 ]
+
+# log level err
+ip test-ip4 output
+ [ log level 3 ]
+
+# log level warn
+ip test-ip4 output
+ [ log level 4 ]
+
+# log level notice
+ip test-ip4 output
+ [ log level 5 ]
+
+# log level info
+ip test-ip4 output
+ [ log level 6 ]
+
+# log level debug
+ip test-ip4 output
+ [ log level 7 ]
+
+# log level audit
+ip test-ip4 output
+ [ log level 8 ]
+
+# log prefix aaaaa-aaaaaa group 2 snaplen 33
+ip test-ip4 output
+ [ log prefix aaaaa-aaaaaa group 2 snaplen 33 qthreshold 0 ]
+
+# log group 2 queue-threshold 2
+ip test-ip4 output
+ [ log group 2 snaplen 0 qthreshold 2 ]
+
+# log group 2 snaplen 33
+ip test-ip4 output
+ [ log group 2 snaplen 33 qthreshold 0 ]
+
+# log group 2 prefix "nft-test: "
+ip test-ip4 output
+ [ log prefix nft-test: group 2 snaplen 0 qthreshold 0 ]
+
+# log flags all
+ip test-ip4 output
+ [ log tcpseq tcpopt ipopt uid macdecode ]
+
+# log level debug flags ip options flags skuid
+ip test-ip4 output
+ [ log level 7 ipopt uid ]
+
+# log flags tcp sequence,options
+ip test-ip4 output
+ [ log tcpseq tcpopt ]
+
+# log flags ip options flags ether flags skuid flags tcp sequence,options
+ip test-ip4 output
+ [ log tcpseq tcpopt ipopt uid macdecode ]
diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t
new file mode 100644
index 0000000..12fabb7
--- /dev/null
+++ b/tests/py/any/meta.t
@@ -0,0 +1,226 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*arp;test-arp;input
+*bridge;test-bridge;input
+*netdev;test-netdev;ingress,egress
+
+meta length 1000;ok
+meta length 22;ok
+meta length != 233;ok
+meta length 33-45;ok
+meta length != 33-45;ok
+meta length { 33, 55, 67, 88};ok
+meta length { 33-55, 67-88};ok
+meta length { 33-55, 56-88, 100-120};ok;meta length { 33-88, 100-120}
+meta length != { 33, 55, 67, 88};ok
+meta length { 33-55, 66-88};ok
+meta length != { 33-55, 66-88};ok
+
+meta protocol { ip, arp, ip6, vlan };ok;meta protocol { ip6, ip, 8021q, arp}
+meta protocol != {ip, arp, ip6, 8021q};ok
+meta protocol ip;ok
+meta protocol != ip;ok
+
+meta l4proto 22;ok
+meta l4proto != 233;ok
+meta l4proto 33-45;ok
+meta l4proto != 33-45;ok
+meta l4proto { 33, 55, 67, 88};ok
+meta l4proto != { 33, 55, 67, 88};ok
+meta l4proto { 33-55, 66-88};ok
+meta l4proto != { 33-55, 66-88};ok
+
+meta priority root;ok
+meta priority none;ok
+meta priority 0x87654321;ok;meta priority 8765:4321
+meta priority 2271560481;ok;meta priority 8765:4321
+meta priority 1:1234;ok
+meta priority bcad:dadc;ok
+meta priority aabb:0;ok
+meta priority != bcad:dadc;ok
+meta priority != aabb:0;ok
+meta priority bcad:dada-bcad:dadc;ok
+meta priority != bcad:dada-bcad:dadc;ok
+meta priority {bcad:dada, bcad:dadc, aaaa:bbbb};ok
+meta priority set cafe:beef;ok
+meta priority != {bcad:dada, bcad:dadc, aaaa:bbbb};ok
+
+meta mark 0x4;ok;meta mark 0x00000004
+meta mark 0x32;ok;meta mark 0x00000032
+meta mark and 0x03 == 0x01;ok;meta mark & 0x00000003 == 0x00000001
+meta mark and 0x03 != 0x01;ok;meta mark & 0x00000003 != 0x00000001
+meta mark 0x10;ok;meta mark 0x00000010
+meta mark != 0x10;ok;meta mark != 0x00000010
+meta mark 0xffffff00/24;ok
+
+meta mark or 0x03 == 0x01;ok;meta mark | 0x00000003 == 0x00000001
+meta mark or 0x03 != 0x01;ok;meta mark | 0x00000003 != 0x00000001
+meta mark xor 0x03 == 0x01;ok;meta mark 0x00000002
+meta mark xor 0x03 != 0x01;ok;meta mark != 0x00000002
+
+meta iif "lo" accept;ok;iif "lo" accept
+meta iif != "lo" accept;ok;iif != "lo" accept
+
+meta iifname "dummy0";ok;iifname "dummy0"
+meta iifname != "dummy0";ok;iifname != "dummy0"
+meta iifname {"dummy0", "lo"};ok;iifname {"dummy0", "lo"}
+meta iifname != {"dummy0", "lo"};ok;iifname != {"dummy0", "lo"}
+meta iifname "dummy*";ok;iifname "dummy*"
+meta iifname "dummy\*";ok;iifname "dummy\*"
+meta iifname "";fail
+
+meta iiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre};ok
+meta iiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre};ok
+meta iiftype != ether;ok
+meta iiftype ether;ok
+meta iiftype != ppp;ok
+meta iiftype ppp;ok
+
+meta oif "lo" accept;ok;oif "lo" accept
+meta oif != "lo" accept;ok;oif != "lo" accept
+
+meta oifname "dummy0";ok;oifname "dummy0"
+meta oifname != "dummy0";ok;oifname != "dummy0"
+meta oifname { "dummy0", "lo"};ok;oifname { "dummy0", "lo"}
+meta oifname "dummy*";ok;oifname "dummy*"
+meta oifname "dummy\*";ok;oifname "dummy\*"
+meta oifname "";fail
+
+meta oiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre};ok
+meta oiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre};ok
+meta oiftype != ether;ok
+meta oiftype ether;ok
+
+meta skuid {"bin", "root", "daemon"} accept;ok;meta skuid { 0, 1, 2} accept
+meta skuid != {"bin", "root", "daemon"} accept;ok;meta skuid != { 1, 0, 2} accept
+meta skuid "root";ok;meta skuid 0
+meta skuid != "root";ok;meta skuid != 0
+meta skuid lt 3000 accept;ok;meta skuid < 3000 accept
+meta skuid gt 3000 accept;ok;meta skuid > 3000 accept
+meta skuid eq 3000 accept;ok;meta skuid 3000 accept
+meta skuid 3001-3005 accept;ok
+meta skuid != 2001-2005 accept;ok
+meta skuid { 2001-2005, 3001-3005} accept;ok
+meta skuid != { 2001-2005, 3001-3005} accept;ok
+
+meta skgid {"bin", "root", "daemon"} accept;ok;meta skgid { 0, 1, 2} accept
+meta skgid != {"bin", "root", "daemon"} accept;ok;meta skgid != { 1, 0, 2} accept
+meta skgid "root";ok;meta skgid 0
+meta skgid != "root";ok;meta skgid != 0
+meta skgid lt 3000 accept;ok;meta skgid < 3000 accept
+meta skgid gt 3000 accept;ok;meta skgid > 3000 accept
+meta skgid eq 3000 accept;ok;meta skgid 3000 accept
+meta skgid 2001-2005 accept;ok
+meta skgid != 2001-2005 accept;ok
+
+# BUG: meta nftrace 2 and meta nftrace 1
+# $ sudo nft add rule ip test input meta nftrace 2
+# <cmdline>:1:37-37: Error: Value 2 exceeds valid range 0-1
+# add rule ip test input meta nftrace 2
+# ^
+# $ sudo nft add rule ip test input meta nftrace 1
+# <cmdline>:1:1-37: Error: Could not process rule: Operation not supported
+# add rule ip test input meta nftrace 1
+# -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+meta mark set 0xffffffc8 xor 0x16;ok;meta mark set 0xffffffde
+meta mark set 0x16 and 0x16;ok;meta mark set 0x00000016
+meta mark set 0xffffffe9 or 0x16;ok;meta mark set 0xffffffff
+meta mark set 0xffffffde and 0x16;ok;meta mark set 0x00000016
+meta mark set 0xf045ffde or 0x10;ok;meta mark set 0xf045ffde
+meta mark set 0xffffffde or 0x16;ok;meta mark set 0xffffffde
+meta mark set 0x32 or 0xfffff;ok;meta mark set 0x000fffff
+meta mark set 0xfffe xor 0x16;ok;meta mark set 0x0000ffe8
+
+meta mark set {0xffff, 0xcc};fail
+meta pkttype set {unicast, multicast, broadcast};fail
+
+meta iif "lo";ok;iif "lo"
+meta oif "lo";ok;oif "lo"
+meta oifname "dummy2" accept;ok;oifname "dummy2" accept
+meta skuid 3000;ok
+meta skgid 3000;ok
+# BUG: meta nftrace 1;ok
+# <cmdline>:1:1-37: Error: Could not process rule: Operation not supported
+- meta nftrace 1;ok
+meta rtclassid "cosmos";ok
+
+meta pkttype broadcast;ok
+meta pkttype host;ok
+meta pkttype multicast;ok
+meta pkttype != broadcast;ok
+meta pkttype != host;ok
+meta pkttype != multicast;ok
+meta pkttype broadcastttt;fail
+pkttype { broadcast, multicast} accept;ok;meta pkttype { broadcast, multicast} accept
+
+meta cpu 1;ok
+meta cpu != 1;ok
+meta cpu 1-3;ok
+meta cpu != 1-2;ok
+meta cpu { 2,3};ok
+meta cpu { 2-3, 5-7};ok
+meta cpu != { 2,3};ok
+
+meta iifgroup 0;ok;iifgroup "default"
+meta iifgroup != 0;ok;iifgroup != "default"
+meta iifgroup "default";ok;iifgroup "default"
+meta iifgroup != "default";ok;iifgroup != "default"
+meta iifgroup {"default", 11};ok;iifgroup {"default", 11}
+meta iifgroup != {"default", 11};ok;iifgroup != {"default", 11}
+meta iifgroup { 11,33};ok;iifgroup { 11,33}
+meta iifgroup {11-33, 44-55};ok;iifgroup {11-33, 44-55}
+meta iifgroup != { 11,33};ok;iifgroup != { 11,33}
+meta iifgroup != {11-33, 44-55};ok;iifgroup != {11-33, 44-55}
+meta oifgroup 0;ok;oifgroup "default"
+meta oifgroup != 0;ok;oifgroup != "default"
+meta oifgroup "default";ok;oifgroup "default"
+meta oifgroup != "default";ok;oifgroup != "default"
+meta oifgroup {"default", 11};ok;oifgroup {"default", 11}
+meta oifgroup != {"default", 11};ok;oifgroup != {"default", 11}
+meta oifgroup { 11,33};ok;oifgroup { 11,33}
+meta oifgroup {11-33, 44-55};ok;oifgroup {11-33, 44-55}
+meta oifgroup != { 11,33};ok;oifgroup != { 11,33}
+meta oifgroup != {11-33, 44-55};ok;oifgroup != {11-33, 44-55}
+
+meta cgroup 1048577;ok
+meta cgroup != 1048577;ok
+meta cgroup { 1048577, 1048578 };ok
+meta cgroup != { 1048577, 1048578};ok
+meta cgroup 1048577-1048578;ok
+meta cgroup != 1048577-1048578;ok
+
+meta iif . meta oif { "lo" . "lo" };ok;iif . oif { "lo" . "lo" }
+meta iif . meta oif . meta mark { "lo" . "lo" . 0x0000000a };ok;iif . oif . meta mark { "lo" . "lo" . 0x0000000a }
+meta iif . meta oif vmap { "lo" . "lo" : drop };ok;iif . oif vmap { "lo" . "lo" : drop }
+
+meta random eq 1;ok;meta random 1
+meta random gt 1000000;ok;meta random > 1000000
+
+meta time "1970-05-23 21:07:14" drop;ok
+meta time 12341234 drop;ok;meta time "1970-05-23 22:07:14" drop
+meta time "2019-06-21 17:00:00" drop;ok
+meta time "2019-07-01 00:00:00" drop;ok
+meta time "2019-07-01 00:01:00" drop;ok
+meta time "2019-07-01 00:00:01" drop;ok
+meta time < "2022-07-01 11:00:00" accept;ok
+meta time > "2022-07-01 11:00:00" accept;ok
+meta day "Saturday" drop;ok
+meta day 6 drop;ok;meta day "Saturday" drop
+meta day "Satturday" drop;fail
+meta hour "17:00" drop;ok
+meta hour "17:00:00" drop;ok;meta hour "17:00" drop
+meta hour "17:00:01" drop;ok
+meta hour "00:00" drop;ok
+meta hour "00:01" drop;ok
+time < "2022-07-01 11:00:00" accept;ok;meta time < "2022-07-01 11:00:00" accept
+time > "2022-07-01 11:00:00" accept;ok;meta time > "2022-07-01 11:00:00" accept
+
+meta time "meh";fail
+meta hour "24:00" drop;fail
+meta day 7 drop;fail
diff --git a/tests/py/any/meta.t.json b/tests/py/any/meta.t.json
new file mode 100644
index 0000000..4734bbf
--- /dev/null
+++ b/tests/py/any/meta.t.json
@@ -0,0 +1,2760 @@
+# meta length 1000
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "==",
+ "right": 1000
+ }
+ }
+]
+
+# meta length 22
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# meta length != 233
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# meta length 33-45
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# meta length != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# meta length { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# meta length { 33-55, 67-88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] },
+ { "range": [ 67, 88 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta length { 33-55, 56-88, 100-120}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 33, 88 ] },
+ { "range": [ 100, 120 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta length != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# meta length { 33-55, 66-88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] },
+ { "range": [ 66, 88 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta length != { 33-55, 66-88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "length" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] },
+ { "range": [ 66, 88 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta protocol { ip, arp, ip6, vlan }
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "protocol" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "ip",
+ "arp",
+ "ip6",
+ "vlan"
+ ]
+ }
+ }
+ }
+]
+
+# meta protocol != {ip, arp, ip6, 8021q}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "protocol" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ip",
+ "arp",
+ "ip6",
+ "8021q"
+ ]
+ }
+ }
+ }
+]
+
+# meta protocol ip
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "protocol" }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ }
+]
+
+# meta protocol != ip
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "protocol" }
+ },
+ "op": "!=",
+ "right": "ip"
+ }
+ }
+]
+
+# meta l4proto 22
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# meta l4proto != 233
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# meta l4proto 33-45
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# meta l4proto != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# meta l4proto { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto { 33-55, 66-88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] },
+ { "range": [ 66, 88 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto != { 33-55, 66-88}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] },
+ { "range": [ 66, 88 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta priority root
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": "root"
+ }
+ }
+]
+
+# meta priority none
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": "none"
+ }
+ }
+]
+
+# meta priority 0x87654321
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": "0x87654321"
+ }
+ }
+]
+
+# meta priority 2271560481
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": 2271560481
+ }
+ }
+]
+
+# meta priority 1:1234
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": "1:1234"
+ }
+ }
+]
+
+# meta priority bcad:dadc
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": "bcad:dadc"
+ }
+ }
+]
+
+# meta priority aabb:0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": "aabb:0"
+ }
+ }
+]
+
+# meta priority != bcad:dadc
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "!=",
+ "right": "bcad:dadc"
+ }
+ }
+]
+
+# meta priority != aabb:0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "!=",
+ "right": "aabb:0"
+ }
+ }
+]
+
+# meta priority bcad:dada-bcad:dadc
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": {
+ "range": [ "bcad:dada", "bcad:dadc" ]
+ }
+ }
+ }
+]
+
+# meta priority != bcad:dada-bcad:dadc
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "bcad:dada", "bcad:dadc" ]
+ }
+ }
+ }
+]
+
+# meta priority {bcad:dada, bcad:dadc, aaaa:bbbb}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "bcad:dada",
+ "bcad:dadc",
+ "aaaa:bbbb"
+ ]
+ }
+ }
+ }
+]
+
+# meta priority set cafe:beef
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "priority" }
+ },
+ "value": "cafe:beef"
+ }
+ }
+]
+
+# meta priority != {bcad:dada, bcad:dadc, aaaa:bbbb}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "aaaa:bbbb",
+ "bcad:dada",
+ "bcad:dadc"
+ ]
+ }
+ }
+ }
+]
+
+# meta mark 0x4
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": "0x4"
+ }
+ }
+]
+
+# meta mark 0x32
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": "0x32"
+ }
+ }
+]
+
+# meta mark and 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "meta": { "key": "mark" }
+ },
+ "0x03"
+ ]
+ },
+ "op": "==",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark and 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "meta": { "key": "mark" }
+ },
+ "0x03"
+ ]
+ },
+ "op": "!=",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark 0x10
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": "0x10"
+ }
+ }
+]
+
+# meta mark != 0x10
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "!=",
+ "right": "0x10"
+ }
+ }
+]
+
+# meta mark 0xffffff00/24
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": 4294967040,
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# meta mark or 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "meta": { "key": "mark" }
+ },
+ "0x03"
+ ]
+ },
+ "op": "==",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark or 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "meta": { "key": "mark" }
+ },
+ "0x03"
+ ]
+ },
+ "op": "!=",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark xor 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "^": [
+ {
+ "meta": { "key": "mark" }
+ },
+ "0x03"
+ ]
+ },
+ "op": "==",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta mark xor 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "^": [
+ {
+ "meta": { "key": "mark" }
+ },
+ "0x03"
+ ]
+ },
+ "op": "!=",
+ "right": "0x01"
+ }
+ }
+]
+
+# meta iif "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta iif != "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "!=",
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta iifname "dummy0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "dummy0"
+ }
+ }
+]
+
+# meta iifname != "dummy0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "!=",
+ "right": "dummy0"
+ }
+ }
+]
+
+# meta iifname {"dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "dummy0",
+ "lo"
+ ]
+ }
+ }
+ }
+]
+
+# meta iifname != {"dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "dummy0",
+ "lo"
+ ]
+ }
+ }
+ }
+]
+
+# meta iifname "dummy*"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "dummy*"
+ }
+ }
+]
+
+# meta iifname "dummy\*"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "dummy\\*"
+ }
+ }
+]
+
+# meta iiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "ether",
+ "ppp",
+ "ipip",
+ "ipip6",
+ "loopback",
+ "sit",
+ "ipgre"
+ ]
+ }
+ }
+ }
+]
+
+# meta iiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ether",
+ "ppp",
+ "ipip",
+ "ipip6",
+ "loopback",
+ "sit",
+ "ipgre"
+ ]
+ }
+ }
+ }
+]
+
+# meta iiftype != ether
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "!=",
+ "right": "ether"
+ }
+ }
+]
+
+# meta iiftype ether
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "==",
+ "right": "ether"
+ }
+ }
+]
+
+# meta iiftype != ppp
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "!=",
+ "right": "ppp"
+ }
+ }
+]
+
+# meta iiftype ppp
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "==",
+ "right": "ppp"
+ }
+ }
+]
+
+# meta oif "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta oif != "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oif" }
+ },
+ "op": "!=",
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta oifname "dummy0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifname" }
+ },
+ "op": "==",
+ "right": "dummy0"
+ }
+ }
+]
+
+# meta oifname != "dummy0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifname" }
+ },
+ "op": "!=",
+ "right": "dummy0"
+ }
+ }
+]
+
+# meta oifname { "dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifname" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "dummy0",
+ "lo"
+ ]
+ }
+ }
+ }
+]
+
+# meta oifname "dummy*"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifname" }
+ },
+ "op": "==",
+ "right": "dummy*"
+ }
+ }
+]
+
+# meta oifname "dummy\*"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifname" }
+ },
+ "op": "==",
+ "right": "dummy\\*"
+ }
+ }
+]
+
+# meta oiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oiftype" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "ether",
+ "ppp",
+ "ipip",
+ "ipip6",
+ "loopback",
+ "sit",
+ "ipgre"
+ ]
+ }
+ }
+ }
+]
+
+# meta oiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oiftype" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ether",
+ "ppp",
+ "ipip",
+ "ipip6",
+ "loopback",
+ "sit",
+ "ipgre"
+ ]
+ }
+ }
+ }
+]
+
+# meta oiftype != ether
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oiftype" }
+ },
+ "op": "!=",
+ "right": "ether"
+ }
+ }
+]
+
+# meta oiftype ether
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oiftype" }
+ },
+ "op": "==",
+ "right": "ether"
+ }
+ }
+]
+
+# meta skuid {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "bin",
+ "root",
+ "daemon"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid != {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "bin",
+ "root",
+ "daemon"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "==",
+ "right": "root"
+ }
+ }
+]
+
+# meta skuid != "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "!=",
+ "right": "root"
+ }
+ }
+]
+
+# meta skuid lt 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "<",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid gt 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": ">",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid eq 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "==",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid 3001-3005 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 3001, 3005 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid != 2001-2005 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 2001, 2005 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid { 2001-2005, 3001-3005} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 2001, 2005 ] },
+ { "range": [ 3001, 3005 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid != { 2001-2005, 3001-3005} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 2001, 2005 ] },
+ { "range": [ 3001, 3005 ] }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "bin",
+ "root",
+ "daemon"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid != {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "bin",
+ "root",
+ "daemon"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "==",
+ "right": "root"
+ }
+ }
+]
+
+# meta skgid != "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "!=",
+ "right": "root"
+ }
+ }
+]
+
+# meta skgid lt 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "<",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid gt 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": ">",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid eq 3000 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "==",
+ "right": 3000
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid 2001-2005 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 2001, 2005 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid != 2001-2005 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 2001, 2005 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta mark set 0xffffffc8 xor 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": { "^": [ "0xffffffc8", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0x16 and 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": { "&": [ "0x16", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0xffffffe9 or 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": { "|": [ "0xffffffe9", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0xffffffde and 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": { "&": [ "0xffffffde", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0xf045ffde or 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": { "|": [ "0xf045ffde", "0x10" ] }
+ }
+ }
+]
+
+# meta mark set 0xffffffde or 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": { "|": [ "0xffffffde", "0x16" ] }
+ }
+ }
+]
+
+# meta mark set 0x32 or 0xfffff
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": { "|": [ "0x32", "0xfffff" ] }
+ }
+ }
+]
+
+# meta mark set 0xfffe xor 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": { "^": [ "0xfffe", "0x16" ] }
+ }
+ }
+]
+
+# meta iif "lo"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ }
+]
+
+# meta oif "lo"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ }
+]
+
+# meta oifname "dummy2" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifname" }
+ },
+ "op": "==",
+ "right": "dummy2"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid 3000
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "==",
+ "right": 3000
+ }
+ }
+]
+
+# meta skgid 3000
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "==",
+ "right": 3000
+ }
+ }
+]
+
+# meta rtclassid "cosmos"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "rtclassid" }
+ },
+ "op": "==",
+ "right": "cosmos"
+ }
+ }
+]
+
+# meta pkttype broadcast
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "pkttype" }
+ },
+ "op": "==",
+ "right": "broadcast"
+ }
+ }
+]
+
+# meta pkttype host
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "pkttype" }
+ },
+ "op": "==",
+ "right": "host"
+ }
+ }
+]
+
+# meta pkttype multicast
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "pkttype" }
+ },
+ "op": "==",
+ "right": "multicast"
+ }
+ }
+]
+
+# meta pkttype != broadcast
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "pkttype" }
+ },
+ "op": "!=",
+ "right": "broadcast"
+ }
+ }
+]
+
+# meta pkttype != host
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "pkttype" }
+ },
+ "op": "!=",
+ "right": "host"
+ }
+ }
+]
+
+# meta pkttype != multicast
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "pkttype" }
+ },
+ "op": "!=",
+ "right": "multicast"
+ }
+ }
+]
+
+# pkttype { broadcast, multicast} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "pkttype" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "broadcast",
+ "multicast"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta cpu 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cpu" }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# meta cpu != 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cpu" }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# meta cpu 1-3
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cpu" }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 1, 3 ]
+ }
+ }
+ }
+]
+
+# meta cpu != 1-2
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cpu" }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 1, 2 ]
+ }
+ }
+ }
+]
+
+# meta cpu { 2,3}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cpu" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 2,
+ 3
+ ]
+ }
+ }
+ }
+]
+
+# meta cpu { 2-3, 5-7}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cpu" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 2, 3 ] },
+ { "range": [ 5, 7 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta cpu != { 2,3}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cpu" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 2,
+ 3
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# meta iifgroup != 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# meta iifgroup "default"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "==",
+ "right": "default"
+ }
+ }
+]
+
+# meta iifgroup != "default"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "!=",
+ "right": "default"
+ }
+ }
+]
+
+# meta iifgroup {"default", 11}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "default",
+ 11
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup != {"default", 11}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "default",
+ 11
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup { 11,33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 11,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup {11-33, 44-55}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 11, 33 ] },
+ { "range": [ 44, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup != { 11,33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 11,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# meta iifgroup != {11-33, 44-55}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 11, 33 ] },
+ { "range": [ 44, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# meta oifgroup != 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# meta oifgroup "default"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "==",
+ "right": "default"
+ }
+ }
+]
+
+# meta oifgroup != "default"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "!=",
+ "right": "default"
+ }
+ }
+]
+
+# meta oifgroup {"default", 11}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "default",
+ 11
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup != {"default", 11}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "default",
+ 11
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup { 11,33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 11,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup {11-33, 44-55}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 11, 33 ] },
+ { "range": [ 44, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup != { 11,33}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 11,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# meta oifgroup != {11-33, 44-55}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 11, 33 ] },
+ { "range": [ 44, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# meta cgroup 1048577
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cgroup" }
+ },
+ "op": "==",
+ "right": 1048577
+ }
+ }
+]
+
+# meta cgroup != 1048577
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cgroup" }
+ },
+ "op": "!=",
+ "right": 1048577
+ }
+ }
+]
+
+# meta cgroup { 1048577, 1048578 }
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cgroup" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 1048577,
+ 1048578
+ ]
+ }
+ }
+ }
+]
+
+# meta cgroup != { 1048577, 1048578}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cgroup" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 1048577,
+ 1048578
+ ]
+ }
+ }
+ }
+]
+
+# meta cgroup 1048577-1048578
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cgroup" }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 1048577, 1048578 ]
+ }
+ }
+ }
+]
+
+# meta cgroup != 1048577-1048578
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cgroup" }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 1048577, 1048578 ]
+ }
+ }
+ }
+]
+
+# meta cgroup {1048577-1048578}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cgroup" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [ 1048577, 1048578 ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta cgroup != { 1048577-1048578}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "cgroup" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ {
+ "range": [ 1048577, 1048578 ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta iif . meta oif { "lo" . "lo" }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "meta": { "key": "iif" }
+ },
+ {
+ "meta": { "key": "oif" }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "lo",
+ "lo"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta iif . meta oif . meta mark { "lo" . "lo" . 0x0000000a }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "meta": { "key": "iif" }
+ },
+ {
+ "meta": { "key": "oif" }
+ },
+ {
+ "meta": { "key": "mark" }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "lo",
+ "lo",
+ "0x0000000a"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta iif . meta oif vmap { "lo" . "lo" : drop }
+[
+ {
+ "vmap": {
+ "key": {
+ "concat": [
+ {
+ "meta": { "key": "iif" }
+ },
+ {
+ "meta": { "key": "oif" }
+ }
+ ]
+ },
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "lo",
+ "lo"
+ ]
+ },
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# meta random eq 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "random" }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# meta random gt 1000000
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "random" }
+ },
+ "op": ">",
+ "right": 1000000
+ }
+ }
+]
+
+# meta time "1970-05-23 21:07:14" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "1970-05-23 21:07:14"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time 12341234 drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "12341234"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time "2019-06-21 17:00:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "2019-06-21 17:00:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time "2019-07-01 00:00:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "2019-07-01 00:00:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time "2019-07-01 00:01:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "2019-07-01 00:01:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time "2019-07-01 00:00:01" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "2019-07-01 00:00:01"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time < "2022-07-01 11:00:00" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "<",
+ "right": "2022-07-01 11:00:00"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta time > "2022-07-01 11:00:00" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": ">",
+ "right": "2022-07-01 11:00:00"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta day "Saturday" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "day"
+ }
+ },
+ "op": "==",
+ "right": "Saturday"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta day 6 drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "day"
+ }
+ },
+ "op": "==",
+ "right": "6"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "17:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "17:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "17:00:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "17:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "17:00:01" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "17:00:01"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "00:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "00:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "00:01" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "00:01"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# time < "2022-07-01 11:00:00" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "<",
+ "right": "2022-07-01 11:00:00"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# time > "2022-07-01 11:00:00" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": ">",
+ "right": "2022-07-01 11:00:00"
+ }
+ },
+ {
+ "accept": null
+ }
+]
diff --git a/tests/py/any/meta.t.json.output b/tests/py/any/meta.t.json.output
new file mode 100644
index 0000000..4e9e669
--- /dev/null
+++ b/tests/py/any/meta.t.json.output
@@ -0,0 +1,828 @@
+# meta protocol { ip, arp, ip6, vlan }
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "protocol" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "ip",
+ "arp",
+ "8021q",
+ "ip6"
+ ]
+ }
+ }
+ }
+]
+
+# meta protocol != {ip, arp, ip6, 8021q}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "protocol" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ip",
+ "arp",
+ "8021q",
+ "ip6"
+ ]
+ }
+ }
+ }
+]
+
+# meta priority 0x87654321
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": "8765:4321"
+ }
+ }
+]
+
+# meta priority 2271560481
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": "8765:4321"
+ }
+ }
+]
+
+# meta priority {bcad:dada, bcad:dadc, aaaa:bbbb}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "priority" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "aaaa:bbbb",
+ "bcad:dada",
+ "bcad:dadc"
+ ]
+ }
+ }
+ }
+]
+
+# meta mark 0x4
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": 4
+ }
+ }
+]
+
+# meta mark 0x32
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": 50
+ }
+ }
+]
+
+# meta mark and 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "meta": { "key": "mark" }
+ },
+ 3
+ ]
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# meta mark and 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "meta": { "key": "mark" }
+ },
+ 3
+ ]
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# meta mark 0x10
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": 16
+ }
+ }
+]
+
+# meta mark != 0x10
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "!=",
+ "right": 16
+ }
+ }
+]
+
+# meta mark or 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "meta": { "key": "mark" }
+ },
+ 3
+ ]
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# meta mark or 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "|": [
+ {
+ "meta": { "key": "mark" }
+ },
+ 3
+ ]
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# meta mark xor 0x03 == 0x01
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# meta mark xor 0x03 != 0x01
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "!=",
+ "right": 2
+ }
+ }
+]
+
+# meta iifname {"dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "lo",
+ "dummy0"
+ ]
+ }
+ }
+ }
+]
+
+# meta iifname != {"dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "lo",
+ "dummy0"
+ ]
+ }
+ }
+ }
+]
+
+# meta oifname { "dummy0", "lo"}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifname" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "lo",
+ "dummy0"
+ ]
+ }
+ }
+ }
+]
+
+# meta skuid {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "==",
+ "right": {
+ "set": [ 0, 1, 2 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid != {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [ 0, 1, 2 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skuid "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# meta skuid != "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skuid" }
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# meta skgid {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "==",
+ "right": {
+ "set": [ 0, 1, 2 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid != {"bin", "root", "daemon"} accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [ 0, 1, 2 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta skgid "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# meta skgid != "root"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "skgid" }
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# meta mark set 0xffffffc8 xor 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 4294967262
+ }
+ }
+]
+
+# meta mark set 0x16 and 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 22
+ }
+ }
+]
+
+# meta mark set 0xffffffe9 or 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 4294967295
+ }
+ }
+]
+
+# meta mark set 0xffffffde and 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 22
+ }
+ }
+]
+
+# meta mark set 0xf045ffde or 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 4031119326
+ }
+ }
+]
+
+# meta mark set 0xffffffde or 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 4294967262
+ }
+ }
+]
+
+# meta mark set 0x32 or 0xfffff
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 1048575
+ }
+ }
+]
+
+# meta mark set 0xfffe xor 0x16
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 65512
+ }
+ }
+]
+
+# meta iifgroup 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "==",
+ "right": "default"
+ }
+ }
+]
+
+# meta iifgroup != 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifgroup" }
+ },
+ "op": "!=",
+ "right": "default"
+ }
+ }
+]
+
+# meta oifgroup 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "==",
+ "right": "default"
+ }
+ }
+]
+
+# meta oifgroup != 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "oifgroup" }
+ },
+ "op": "!=",
+ "right": "default"
+ }
+ }
+]
+
+# meta iif . meta oif . meta mark { "lo" . "lo" . 0x0000000a }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "meta": { "key": "iif" }
+ },
+ {
+ "meta": { "key": "oif" }
+ },
+ {
+ "meta": { "key": "mark" }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "lo",
+ "lo",
+ 10
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta time "1970-05-23 21:07:14" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "1970-05-23 21:07:14"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time 12341234 drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "1970-05-23 22:07:14"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time "2019-06-21 17:00:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "2019-06-21 17:00:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time "2019-07-01 00:00:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "2019-07-01 00:00:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time "2019-07-01 00:01:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "2019-07-01 00:01:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta time "2019-07-01 00:00:01" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "time"
+ }
+ },
+ "op": "==",
+ "right": "2019-07-01 00:00:01"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta day "Saturday" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "day"
+ }
+ },
+ "op": "==",
+ "right": "Saturday"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta day 6 drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "day"
+ }
+ },
+ "op": "==",
+ "right": "Saturday"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "17:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "17:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "17:00:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "17:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "17:00:01" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "17:00:01"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "00:00" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "00:00"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# meta hour "00:01" drop
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "hour"
+ }
+ },
+ "op": "==",
+ "right": "00:01"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
diff --git a/tests/py/any/meta.t.payload b/tests/py/any/meta.t.payload
new file mode 100644
index 0000000..16dc121
--- /dev/null
+++ b/tests/py/any/meta.t.payload
@@ -0,0 +1,1074 @@
+# meta length 1000
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ cmp eq reg 1 0x000003e8 ]
+
+# meta length 22
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# meta length != 233
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# meta length 33-45
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# meta length != 33-45
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# meta length { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta length { 33-55, 67-88}
+__set%d test-ip4 7
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 21000000 : 0 [end] element 38000000 : 1 [end] element 43000000 : 0 [end] element 59000000 : 1 [end]
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+
+# meta length { 33-55, 56-88, 100-120}
+__set%d test-ip4 7
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 21000000 : 0 [end] element 59000000 : 1 [end] element 64000000 : 0 [end] element 79000000 : 1 [end]
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+
+# meta length != { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta protocol { ip, arp, ip6, vlan }
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000608 : 0 [end] element 0000dd86 : 0 [end] element 00000081 : 0 [end]
+ip test-ip4 input
+ [ meta load protocol => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta protocol != {ip, arp, ip6, 8021q}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000608 : 0 [end] element 0000dd86 : 0 [end] element 00000081 : 0 [end]
+ip test-ip4 input
+ [ meta load protocol => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta protocol ip
+ip test-ip4 input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# meta protocol != ip
+ip test-ip4 input
+ [ meta load protocol => reg 1 ]
+ [ cmp neq reg 1 0x00000008 ]
+
+# meta l4proto 22
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# meta l4proto != 233
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# meta l4proto 33-45
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# meta l4proto != 33-45
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# meta l4proto { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta l4proto != { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta mark 0x4
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x00000004 ]
+
+# meta mark 0x32
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+
+# meta mark and 0x03 == 0x01
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000003 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# meta mark and 0x03 != 0x01
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000003 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# meta mark 0x10
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x00000010 ]
+
+# meta mark != 0x10
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ cmp neq reg 1 0x00000010 ]
+
+# meta mark 0xffffff00/24
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffff00 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0xffffff00 ]
+
+# meta mark or 0x03 == 0x01
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xfffffffc ) ^ 0x00000003 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# meta mark or 0x03 != 0x01
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xfffffffc ) ^ 0x00000003 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# meta mark xor 0x03 == 0x01
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# meta mark xor 0x03 != 0x01
+ip test-ip4 input
+ [ meta load mark => reg 1 ]
+ [ cmp neq reg 1 0x00000002 ]
+
+# meta iif "lo" accept
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 0 accept ]
+
+# meta iif != "lo" accept
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+ [ immediate reg 0 accept ]
+
+# meta iifname "dummy0"
+ip test-ip4 input
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x6d6d7564 0x00003079 0x00000000 0x00000000 ]
+
+# meta iifname != "dummy0"
+ip test-ip4 input
+ [ meta load iifname => reg 1 ]
+ [ cmp neq reg 1 0x6d6d7564 0x00003079 0x00000000 0x00000000 ]
+
+# meta iifname {"dummy0", "lo"}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 6d6d7564 00003079 00000000 00000000 : 0 [end] element 00006f6c 00000000 00000000 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load iifname => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta iifname != {"dummy0", "lo"}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 6d6d7564 00003079 00000000 00000000 : 0 [end] element 00006f6c 00000000 00000000 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load iifname => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta iifname "dummy*"
+ip test-ip4 input
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x6d6d7564 0x00000079 ]
+
+# meta iifname "dummy\*"
+ip test-ip4 input
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x6d6d7564 0x00002a79 0x00000000 0x00000000 ]
+
+# meta iiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000200 : 0 [end] element 00000300 : 0 [end] element 00000301 : 0 [end] element 00000304 : 0 [end] element 00000308 : 0 [end] element 0000030a : 0 [end]
+ip test-ip4 input
+ [ meta load iiftype => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta iiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000200 : 0 [end] element 00000300 : 0 [end] element 00000301 : 0 [end] element 00000304 : 0 [end] element 00000308 : 0 [end] element 0000030a : 0 [end]
+ip test-ip4 input
+ [ meta load iiftype => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta iiftype != ether
+ip test-ip4 input
+ [ meta load iiftype => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# meta iiftype ether
+ip test-ip4 input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# meta iiftype != ppp
+ip test-ip4 input
+ [ meta load iiftype => reg 1 ]
+ [ cmp neq reg 1 0x00000200 ]
+
+# meta iiftype ppp
+ip test-ip4 input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000200 ]
+
+# meta oif "lo" accept
+ip test-ip4 input
+ [ meta load oif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 0 accept ]
+
+# meta oif != "lo" accept
+ip test-ip4 input
+ [ meta load oif => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+ [ immediate reg 0 accept ]
+
+# meta oifname "dummy0"
+ip test-ip4 input
+ [ meta load oifname => reg 1 ]
+ [ cmp eq reg 1 0x6d6d7564 0x00003079 0x00000000 0x00000000 ]
+
+# meta oifname != "dummy0"
+ip test-ip4 input
+ [ meta load oifname => reg 1 ]
+ [ cmp neq reg 1 0x6d6d7564 0x00003079 0x00000000 0x00000000 ]
+
+# meta oifname { "dummy0", "lo"}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 6d6d7564 00003079 00000000 00000000 : 0 [end] element 00006f6c 00000000 00000000 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load oifname => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta oifname "dummy*"
+ip test-ip4 input
+ [ meta load oifname => reg 1 ]
+ [ cmp eq reg 1 0x6d6d7564 0x00000079 ]
+
+# meta oifname "dummy\*"
+ip test-ip4 input
+ [ meta load oifname => reg 1 ]
+ [ cmp eq reg 1 0x6d6d7564 0x00002a79 0x00000000 0x00000000 ]
+
+# meta oiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000200 : 0 [end] element 00000300 : 0 [end] element 00000301 : 0 [end] element 00000304 : 0 [end] element 00000308 : 0 [end] element 0000030a : 0 [end]
+ip test-ip4 input
+ [ meta load oiftype => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta oiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000200 : 0 [end] element 00000300 : 0 [end] element 00000301 : 0 [end] element 00000304 : 0 [end] element 00000308 : 0 [end] element 0000030a : 0 [end]
+ip test-ip4 input
+ [ meta load oiftype => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta oiftype != ether
+ip test-ip4 input
+ [ meta load oiftype => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# meta oiftype ether
+ip test-ip4 input
+ [ meta load oiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# meta skuid {"bin", "root", "daemon"} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000000 : 0 [end] element 00000002 : 0 [end]
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# meta skuid != {"bin", "root", "daemon"} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000000 : 0 [end] element 00000002 : 0 [end]
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# meta skuid "root"
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta skuid != "root"
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# meta skuid lt 3000 accept
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp lt reg 1 0xb80b0000 ]
+ [ immediate reg 0 accept ]
+
+# meta skuid gt 3000 accept
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gt reg 1 0xb80b0000 ]
+ [ immediate reg 0 accept ]
+
+# meta skuid eq 3000 accept
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ cmp eq reg 1 0x00000bb8 ]
+ [ immediate reg 0 accept ]
+
+# meta skuid 3001-3005 accept
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0xb90b0000 ]
+ [ cmp lte reg 1 0xbd0b0000 ]
+ [ immediate reg 0 accept ]
+
+# meta skuid != 2001-2005 accept
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ range neq reg 1 0xd1070000 0xd5070000 ]
+ [ immediate reg 0 accept ]
+
+# meta skgid {"bin", "root", "daemon"} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000000 : 0 [end] element 00000002 : 0 [end]
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# meta skgid != {"bin", "root", "daemon"} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000000 : 0 [end] element 00000002 : 0 [end]
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# meta skgid "root"
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta skgid != "root"
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# meta skgid lt 3000 accept
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp lt reg 1 0xb80b0000 ]
+ [ immediate reg 0 accept ]
+
+# meta skgid gt 3000 accept
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gt reg 1 0xb80b0000 ]
+ [ immediate reg 0 accept ]
+
+# meta skgid eq 3000 accept
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ cmp eq reg 1 0x00000bb8 ]
+ [ immediate reg 0 accept ]
+
+# meta skgid 2001-2005 accept
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0xd1070000 ]
+ [ cmp lte reg 1 0xd5070000 ]
+ [ immediate reg 0 accept ]
+
+# meta skgid != 2001-2005 accept
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ range neq reg 1 0xd1070000 0xd5070000 ]
+ [ immediate reg 0 accept ]
+
+# meta mark set 0xffffffc8 xor 0x16
+ip test-ip4 input
+ [ immediate reg 1 0xffffffde ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set 0x16 and 0x16
+ip test-ip4 input
+ [ immediate reg 1 0x00000016 ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set 0xffffffe9 or 0x16
+ip test-ip4 input
+ [ immediate reg 1 0xffffffff ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set 0xffffffde and 0x16
+ip test-ip4 input
+ [ immediate reg 1 0x00000016 ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set 0xf045ffde or 0x10
+ip test-ip4 input
+ [ immediate reg 1 0xf045ffde ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set 0xffffffde or 0x16
+ip test-ip4 input
+ [ immediate reg 1 0xffffffde ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set 0x32 or 0xfffff
+ip test-ip4 input
+ [ immediate reg 1 0x000fffff ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set 0xfffe xor 0x16
+ip test-ip4 input
+ [ immediate reg 1 0x0000ffe8 ]
+ [ meta set mark with reg 1 ]
+
+# meta iif "lo"
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# meta oif "lo"
+ip test-ip4 input
+ [ meta load oif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# meta oifname "dummy2" accept
+ip test-ip4 input
+ [ meta load oifname => reg 1 ]
+ [ cmp eq reg 1 0x6d6d7564 0x00003279 0x00000000 0x00000000 ]
+ [ immediate reg 0 accept ]
+
+# meta skuid 3000
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ cmp eq reg 1 0x00000bb8 ]
+
+# meta skgid 3000
+ip test-ip4 input
+ [ meta load skgid => reg 1 ]
+ [ cmp eq reg 1 0x00000bb8 ]
+
+# meta rtclassid "cosmos"
+ip test-ip4 input
+ [ meta load rtclassid => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta pkttype broadcast
+ip test-ip4 input
+ [ meta load pkttype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# meta pkttype host
+ip test-ip4 input
+ [ meta load pkttype => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta pkttype multicast
+ip test-ip4 input
+ [ meta load pkttype => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# meta pkttype != broadcast
+ip test-ip4 input
+ [ meta load pkttype => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# meta pkttype != host
+ip test-ip4 input
+ [ meta load pkttype => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# meta pkttype != multicast
+ip test-ip4 input
+ [ meta load pkttype => reg 1 ]
+ [ cmp neq reg 1 0x00000002 ]
+
+# pkttype { broadcast, multicast} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000002 : 0 [end]
+ip test-ip4 input
+ [ meta load pkttype => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# meta cpu 1
+ip test-ip4 input
+ [ meta load cpu => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# meta cpu != 1
+ip test-ip4 input
+ [ meta load cpu => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# meta cpu 1-3
+ip test-ip4 input
+ [ meta load cpu => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0x01000000 ]
+ [ cmp lte reg 1 0x03000000 ]
+
+# meta cpu != 1-2
+ip test-ip4 input
+ [ meta load cpu => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ range neq reg 1 0x01000000 0x02000000 ]
+
+# meta cpu { 2,3}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000002 : 0 [end] element 00000003 : 0 [end]
+ip test-ip4 input
+ [ meta load cpu => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta cpu != { 2,3}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000002 : 0 [end] element 00000003 : 0 [end]
+ip test-ip4 input
+ [ meta load cpu => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta cpu { 2-3, 5-7}
+__set%d test-ip4 7
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 02000000 : 0 [end] element 04000000 : 1 [end] element 05000000 : 0 [end] element 08000000 : 1 [end]
+ip test-ip4 input
+ [ meta load cpu => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+
+# meta iifgroup 0
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta iifgroup != 0
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# meta iifgroup "default"
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta iifgroup != "default"
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# meta iifgroup { 11,33}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 0000000b : 0 [end] element 00000021 : 0 [end]
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta oifgroup 0
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta oifgroup != 0
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# meta oifgroup "default"
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta oifgroup != "default"
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# meta oifgroup { 11,33}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 0000000b : 0 [end] element 00000021 : 0 [end]
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta cgroup 1048577
+ip test-ip4 input
+ [ meta load cgroup => reg 1 ]
+ [ cmp eq reg 1 0x00100001 ]
+
+# meta cgroup != 1048577
+ip test-ip4 input
+ [ meta load cgroup => reg 1 ]
+ [ cmp neq reg 1 0x00100001 ]
+
+# meta cgroup { 1048577, 1048578 }
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00100001 : 0 [end] element 00100002 : 0 [end]
+ip test-ip4 input
+ [ meta load cgroup => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta cgroup != { 1048577, 1048578}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00100001 : 0 [end] element 00100002 : 0 [end]
+ip test-ip4 input
+ [ meta load cgroup => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta cgroup 1048577-1048578
+ip test-ip4 input
+ [ meta load cgroup => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0x01001000 ]
+ [ cmp lte reg 1 0x02001000 ]
+
+# meta cgroup != 1048577-1048578
+ip test-ip4 input
+ [ meta load cgroup => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ range neq reg 1 0x01001000 0x02001000 ]
+
+# meta iif . meta oif { "lo" . "lo" }
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 00000001 : 0 [end]
+ip test-ip4 output
+ [ meta load iif => reg 1 ]
+ [ meta load oif => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta iif . meta oif . meta mark { "lo" . "lo" . 0x0000000a }
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 00000001 0000000a : 0 [end]
+ip test-ip4 output
+ [ meta load iif => reg 1 ]
+ [ meta load oif => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta iif . meta oif vmap { "lo" . "lo" : drop }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00000001 00000001 : drop 0 [end]
+ip test-ip4 output
+ [ meta load iif => reg 1 ]
+ [ meta load oif => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# meta random eq 1
+ip test-ip4 input
+ [ meta load prandom => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# meta random gt 1000000
+ip test-ip4 input
+ [ meta load prandom => reg 1 ]
+ [ cmp gt reg 1 0x40420f00 ]
+
+# meta priority root
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0xffffffff ]
+
+# meta priority none
+netdev test-netdev ingress
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta priority 1:1234
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0x00011234 ]
+
+# meta priority bcad:dadc
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0xbcaddadc ]
+
+# meta priority aabb:0
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0xaabb0000 ]
+
+# meta priority != bcad:dadc
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp neq reg 1 0xbcaddadc ]
+
+# meta priority != aabb:0
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp neq reg 1 0xaabb0000 ]
+
+# meta priority bcad:dada-bcad:dadc
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0xdadaadbc ]
+ [ cmp lte reg 1 0xdcdaadbc ]
+
+# meta priority != bcad:dada-bcad:dadc
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ range neq reg 1 0xdadaadbc 0xdcdaadbc ]
+
+# meta priority {bcad:dada, bcad:dadc, aaaa:bbbb}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element bcaddada : 0 [end] element bcaddadc : 0 [end] element aaaabbbb : 0 [end]
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta priority set cafe:beef
+ip test-ip4 input
+ [ immediate reg 1 0xcafebeef ]
+ [ meta set priority with reg 1 ]
+
+# meta priority != {bcad:dada, bcad:dadc, aaaa:bbbb}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element bcaddada : 0 [end] element bcaddadc : 0 [end] element aaaabbbb : 0 [end]
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta priority 0x87654321
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0x87654321 ]
+
+# meta priority 2271560481
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0x87654321 ]
+
+# meta length { 33-55, 66-88}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 21000000 : 0 [end] element 38000000 : 1 [end] element 42000000 : 0 [end] element 59000000 : 1 [end]
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+
+# meta length != { 33-55, 66-88}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 21000000 : 0 [end] element 38000000 : 1 [end] element 42000000 : 0 [end] element 59000000 : 1 [end]
+ip test-ip4 input
+ [ meta load len => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta l4proto { 33-55, 66-88}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 00000021 : 0 [end] element 00000038 : 1 [end] element 00000042 : 0 [end] element 00000059 : 1 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta l4proto != { 33-55, 66-88}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 00000021 : 0 [end] element 00000038 : 1 [end] element 00000042 : 0 [end] element 00000059 : 1 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta skuid { 2001-2005, 3001-3005} accept
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element d1070000 : 0 [end] element d6070000 : 1 [end] element b90b0000 : 0 [end] element be0b0000 : 1 [end]
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# meta iifgroup {"default", 11}
+__set%d test-ip4 3 size 2
+__set%d test-ip4 0
+ element 00000000 : 0 [end] element 0000000b : 0 [end]
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta iifgroup != {"default", 11}
+__set%d test-ip4 3 size 2
+__set%d test-ip4 0
+ element 00000000 : 0 [end] element 0000000b : 0 [end]
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta iifgroup {11-33, 44-55}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 0b000000 : 0 [end] element 22000000 : 1 [end] element 2c000000 : 0 [end] element 38000000 : 1 [end]
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+
+# meta iifgroup != { 11,33}
+__set%d test-ip4 3 size 2
+__set%d test-ip4 0
+ element 0000000b : 0 [end] element 00000021 : 0 [end]
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta iifgroup != {11-33, 44-55}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 0b000000 : 0 [end] element 22000000 : 1 [end] element 2c000000 : 0 [end] element 38000000 : 1 [end]
+ip test-ip4 input
+ [ meta load iifgroup => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta oifgroup {"default", 11}
+__set%d test-ip4 3 size 2
+__set%d test-ip4 0
+ element 00000000 : 0 [end] element 0000000b : 0 [end]
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta oifgroup {11-33, 44-55}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 0b000000 : 0 [end] element 22000000 : 1 [end] element 2c000000 : 0 [end] element 38000000 : 1 [end]
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+
+# meta oifgroup != { 11,33}
+__set%d test-ip4 3 size 2
+__set%d test-ip4 0
+ element 0000000b : 0 [end] element 00000021 : 0 [end]
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta oifgroup != {11-33, 44-55}
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 0b000000 : 0 [end] element 22000000 : 1 [end] element 2c000000 : 0 [end] element 38000000 : 1 [end]
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta skuid != { 2001-2005, 3001-3005} accept
+__set%d test-ip4 7 size 5
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element d1070000 : 0 [end] element d6070000 : 1 [end] element b90b0000 : 0 [end] element be0b0000 : 1 [end]
+ip test-ip4 input
+ [ meta load skuid => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# meta oifgroup != {"default", 11}
+__set%d test-ip4 3 size 2
+__set%d test-ip4 0
+ element 00000000 : 0 [end] element 0000000b : 0 [end]
+ip test-ip4 input
+ [ meta load oifgroup => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta time "1970-05-23 21:07:14" drop
+ip meta-test input
+ [ meta load time => reg 1 ]
+ [ cmp eq reg 1 0x43f05400 0x002bd503 ]
+ [ immediate reg 0 drop ]
+
+# meta time 12341234 drop
+ip meta-test input
+ [ meta load time => reg 1 ]
+ [ cmp eq reg 1 0x74a8f400 0x002bd849 ]
+ [ immediate reg 0 drop ]
+
+# meta time "2019-06-21 17:00:00" drop
+ip meta-test input
+ [ meta load time => reg 1 ]
+ [ cmp eq reg 1 0x767d6000 0x15aa3ebc ]
+ [ immediate reg 0 drop ]
+
+# meta time "2019-07-01 00:00:00" drop
+ip meta-test input
+ [ meta load time => reg 1 ]
+ [ cmp eq reg 1 0xe750c000 0x15ad18e0 ]
+ [ immediate reg 0 drop ]
+
+# meta time "2019-07-01 00:01:00" drop
+ip meta-test input
+ [ meta load time => reg 1 ]
+ [ cmp eq reg 1 0xdf981800 0x15ad18ee ]
+ [ immediate reg 0 drop ]
+
+# meta time "2019-07-01 00:00:01" drop
+ip meta-test input
+ [ meta load time => reg 1 ]
+ [ cmp eq reg 1 0x22eb8a00 0x15ad18e1 ]
+ [ immediate reg 0 drop ]
+
+# meta time < "2022-07-01 11:00:00" accept
+ip test-ip4 input
+ [ meta load time => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 8, 8) ]
+ [ cmp lt reg 1 0xf3a8fd16 0x00a07719 ]
+ [ immediate reg 0 accept ]
+
+# meta time > "2022-07-01 11:00:00" accept
+ip test-ip4 input
+ [ meta load time => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 8, 8) ]
+ [ cmp gt reg 1 0xf3a8fd16 0x00a07719 ]
+ [ immediate reg 0 accept ]
+
+# meta day "Saturday" drop
+ip test-ip4 input
+ [ meta load day => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 0 drop ]
+
+# meta day 6 drop
+ip test-ip4 input
+ [ meta load day => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 0 drop ]
+
+# meta hour "17:00" drop
+ip test-ip4 input
+ [ meta load hour => reg 1 ]
+ [ cmp eq reg 1 0x0000d2f0 ]
+ [ immediate reg 0 drop ]
+
+# meta hour "17:00:00" drop
+ip test-ip4 input
+ [ meta load hour => reg 1 ]
+ [ cmp eq reg 1 0x0000d2f0 ]
+ [ immediate reg 0 drop ]
+
+# meta hour "17:00:01" drop
+ip meta-test input
+ [ meta load hour => reg 1 ]
+ [ cmp eq reg 1 0x0000d2f1 ]
+ [ immediate reg 0 drop ]
+
+# meta hour "00:00" drop
+ip meta-test input
+ [ meta load hour => reg 1 ]
+ [ cmp eq reg 1 0x00013560 ]
+ [ immediate reg 0 drop ]
+
+# meta hour "00:01" drop
+ip meta-test input
+ [ meta load hour => reg 1 ]
+ [ cmp eq reg 1 0x0001359c ]
+ [ immediate reg 0 drop ]
+
+# time < "2022-07-01 11:00:00" accept
+ip test-ip4 input
+ [ meta load time => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 8, 8) ]
+ [ cmp lt reg 1 0xf3a8fd16 0x00a07719 ]
+ [ immediate reg 0 accept ]
+
+# time > "2022-07-01 11:00:00" accept
+ip test-ip4 input
+ [ meta load time => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 8, 8) ]
+ [ cmp gt reg 1 0xf3a8fd16 0x00a07719 ]
+ [ immediate reg 0 accept ]
diff --git a/tests/py/any/objects.t b/tests/py/any/objects.t
new file mode 100644
index 0000000..7b51f91
--- /dev/null
+++ b/tests/py/any/objects.t
@@ -0,0 +1,16 @@
+:output;type filter hook output priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;output
+*ip6;test-ip6;output
+*inet;test-inet;output
+*arp;test-arp;output
+*bridge;test-bridge;output
+*netdev;test-netdev;ingress,egress
+
+%cnt1 type counter;ok
+%qt1 type quota 25 mbytes;ok
+%qt2 type quota over 1 kbytes;ok
+%lim0 type limit rate 400/minute;ok
+%lim2 type limit rate over 1024 bytes/second burst 512 bytes;ok
diff --git a/tests/py/any/queue.t b/tests/py/any/queue.t
new file mode 100644
index 0000000..2e51136
--- /dev/null
+++ b/tests/py/any/queue.t
@@ -0,0 +1,33 @@
+:output;type filter hook output priority 0
+
+*ip;test-ip4;output
+*ip6;test-ip6;output
+*inet;test-inet;output
+*bridge;test-bridge;output
+
+queue;ok;queue to 0
+queue num 2;ok;queue to 2
+queue num 65535;ok;queue to 65535
+queue num 65536;fail
+queue num 2-3;ok;queue to 2-3
+queue num 1-65535;ok;queue to 1-65535
+queue num 4-5 fanout bypass;ok;queue flags bypass,fanout to 4-5
+queue num 4-5 fanout;ok;queue flags fanout to 4-5
+queue num 4-5 bypass;ok;queue flags bypass to 4-5
+
+queue to symhash mod 2 offset 65536;fail
+queue num symhash mod 65536;fail
+queue to symhash mod 65536;ok
+queue flags fanout to symhash mod 65536;fail
+queue flags bypass,fanout to symhash mod 65536;fail
+queue flags bypass to numgen inc mod 65536;ok
+queue to jhash oif . meta mark mod 32;ok
+queue to 2;ok
+queue to 65535;ok
+queue flags bypass to 65535;ok
+queue flags bypass to 1-65535;ok
+queue flags bypass,fanout to 1-65535;ok
+queue to 1-65535;ok
+queue to oif;fail
+queue num oif;fail
+queue flags bypass to oifname map { "eth0" : 0, "ppp0" : 2, "eth1" : 2 };ok
diff --git a/tests/py/any/queue.t.json b/tests/py/any/queue.t.json
new file mode 100644
index 0000000..5f7f901
--- /dev/null
+++ b/tests/py/any/queue.t.json
@@ -0,0 +1,251 @@
+# 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 ]
+ }
+ }
+ }
+]
+
+# queue to symhash mod 65536
+[
+ {
+ "queue": {
+ "num": {
+ "symhash": {
+ "mod": 65536
+ }
+ }
+ }
+ }
+]
+
+# queue flags bypass to numgen inc mod 65536
+[
+ {
+ "queue": {
+ "flags": "bypass",
+ "num": {
+ "numgen": {
+ "mod": 65536,
+ "mode": "inc",
+ "offset": 0
+ }
+ }
+ }
+ }
+]
+
+# queue to jhash oif . meta mark mod 32
+[
+ {
+ "queue": {
+ "num": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "meta": {
+ "key": "oif"
+ }
+ },
+ {
+ "meta": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "mod": 32
+ }
+ }
+ }
+ }
+]
+
+# queue flags bypass to oifname map { "eth0" : 0, "ppp0" : 2, "eth1" : 2 }
+[
+ {
+ "queue": {
+ "flags": "bypass",
+ "num": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "eth0",
+ 0
+ ],
+ [
+ "ppp0",
+ 2
+ ],
+ [
+ "eth1",
+ 2
+ ]
+ ]
+ },
+ "key": {
+ "meta": {
+ "key": "oifname"
+ }
+ }
+ }
+ }
+ }
+ }
+]
+
+# queue to 2
+[
+ {
+ "queue": {
+ "num": 2
+ }
+ }
+]
+
+# queue to 65535
+[
+ {
+ "queue": {
+ "num": 65535
+ }
+ }
+]
+
+# queue flags bypass to 65535
+[
+ {
+ "queue": {
+ "flags": "bypass",
+ "num": 65535
+ }
+ }
+]
+
+# queue flags bypass to 1-65535
+[
+ {
+ "queue": {
+ "flags": "bypass",
+ "num": {
+ "range": [
+ 1,
+ 65535
+ ]
+ }
+ }
+ }
+]
+
+# queue flags bypass,fanout to 1-65535
+[
+ {
+ "queue": {
+ "flags": [
+ "bypass",
+ "fanout"
+ ],
+ "num": {
+ "range": [
+ 1,
+ 65535
+ ]
+ }
+ }
+ }
+]
+
+# queue to 1-65535
+[
+ {
+ "queue": {
+ "num": {
+ "range": [
+ 1,
+ 65535
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/any/queue.t.json.output b/tests/py/any/queue.t.json.output
new file mode 100644
index 0000000..1104d76
--- /dev/null
+++ b/tests/py/any/queue.t.json.output
@@ -0,0 +1,9 @@
+# queue
+[
+ {
+ "queue": {
+ "num": 0
+ }
+ }
+]
+
diff --git a/tests/py/any/queue.t.payload b/tests/py/any/queue.t.payload
new file mode 100644
index 0000000..2f22193
--- /dev/null
+++ b/tests/py/any/queue.t.payload
@@ -0,0 +1,81 @@
+# queue
+ip test-ip4 output
+ [ queue num 0 ]
+
+# queue num 2
+ip test-ip4 output
+ [ queue num 2 ]
+
+# queue num 65535
+ip test-ip4 output
+ [ queue num 65535 ]
+
+# queue num 2-3
+ip test-ip4 output
+ [ queue num 2-3 ]
+
+# queue num 1-65535
+ip test-ip4 output
+ [ queue num 1-65535 ]
+
+# queue num 4-5 fanout bypass
+ip test-ip4 output
+ [ queue num 4-5 bypass fanout ]
+
+# queue num 4-5 fanout
+ip test-ip4 output
+ [ queue num 4-5 fanout ]
+
+# queue num 4-5 bypass
+ip test-ip4 output
+ [ queue num 4-5 bypass ]
+
+# queue to symhash mod 65536
+ip
+ [ hash reg 1 = symhash() % mod 65536 ]
+ [ queue sreg_qnum 1 ]
+
+# queue to jhash oif . meta mark mod 32
+ip
+ [ meta load oif => reg 2 ]
+ [ meta load mark => reg 13 ]
+ [ hash reg 1 = jhash(reg 2, 8, 0x0) % mod 32 ]
+ [ queue sreg_qnum 1 ]
+
+# queue flags bypass to numgen inc mod 65536
+ip
+ [ numgen reg 1 = inc mod 65536 ]
+ [ queue sreg_qnum 1 bypass ]
+
+# queue flags bypass to oifname map { "eth0" : 0, "ppp0" : 2, "eth1" : 2 }
+__map%d test-ip4 b size 3
+__map%d test-ip4 0
+ element 30687465 00000000 00000000 00000000 : 00000000 0 [end] element 30707070 00000000 00000000 00000000 : 00000002 0 [end] element 31687465 00000000 00000000 00000000 : 00000002 0 [end]
+ip
+ [ meta load oifname => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ queue sreg_qnum 1 bypass ]
+
+# queue to 2
+ip
+ [ queue num 2 ]
+
+# queue to 65535
+ip
+ [ queue num 65535 ]
+
+# queue flags bypass to 65535
+ip
+ [ queue num 65535 bypass ]
+
+# queue flags bypass to 1-65535
+ip
+ [ queue num 1-65535 bypass ]
+
+# queue flags bypass,fanout to 1-65535
+ip
+ [ queue num 1-65535 bypass fanout ]
+
+# queue to 1-65535
+ip
+ [ queue num 1-65535 ]
diff --git a/tests/py/any/quota.t b/tests/py/any/quota.t
new file mode 100644
index 0000000..79dd765
--- /dev/null
+++ b/tests/py/any/quota.t
@@ -0,0 +1,25 @@
+:output;type filter hook output priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;output
+*ip6;test-ip6;output
+*inet;test-inet;output
+*arp;test-arp;output
+*bridge;test-bridge;output
+*netdev;test-netdev;ingress,egress
+
+quota 1025 bytes;ok
+quota 1 kbytes;ok
+quota 2 kbytes;ok
+quota 1025 kbytes;ok
+quota 1023 mbytes;ok
+quota 10230 mbytes;ok
+quota 1023000 mbytes;ok
+
+quota over 1 kbytes;ok
+quota over 2 kbytes;ok
+quota over 1025 kbytes;ok
+quota over 1023 mbytes;ok
+quota over 10230 mbytes;ok
+quota over 1023000 mbytes;ok
diff --git a/tests/py/any/quota.t.json b/tests/py/any/quota.t.json
new file mode 100644
index 0000000..59ccc72
--- /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/quota.t.payload b/tests/py/any/quota.t.payload
new file mode 100644
index 0000000..31cfccb
--- /dev/null
+++ b/tests/py/any/quota.t.payload
@@ -0,0 +1,52 @@
+# quota 1025 bytes
+ip test-ip4 output
+ [ quota bytes 1025 consumed 0 flags 0 ]
+
+# quota 1 kbytes
+ip test-ip4 output
+ [ quota bytes 1024 consumed 0 flags 0 ]
+
+# quota 2 kbytes
+ip test-ip4 output
+ [ quota bytes 2048 consumed 0 flags 0 ]
+
+# quota 1025 kbytes
+ip test-ip4 output
+ [ quota bytes 1049600 consumed 0 flags 0 ]
+
+# quota 1023 mbytes
+ip test-ip4 output
+ [ quota bytes 1072693248 consumed 0 flags 0 ]
+
+# quota 10230 mbytes
+ip test-ip4 output
+ [ quota bytes 10726932480 consumed 0 flags 0 ]
+
+# quota 1023000 mbytes
+ip test-ip4 output
+ [ quota bytes 1072693248000 consumed 0 flags 0 ]
+
+# quota over 1 kbytes
+ip test-ip4 output
+ [ quota bytes 1024 consumed 0 flags 1 ]
+
+# quota over 2 kbytes
+ip test-ip4 output
+ [ quota bytes 2048 consumed 0 flags 1 ]
+
+# quota over 1025 kbytes
+ip test-ip4 output
+ [ quota bytes 1049600 consumed 0 flags 1 ]
+
+# quota over 1023 mbytes
+ip test-ip4 output
+ [ quota bytes 1072693248 consumed 0 flags 1 ]
+
+# quota over 10230 mbytes
+ip test-ip4 output
+ [ quota bytes 10726932480 consumed 0 flags 1 ]
+
+# quota over 1023000 mbytes
+ip test-ip4 output
+ [ quota bytes 1072693248000 consumed 0 flags 1 ]
+
diff --git a/tests/py/any/rawpayload.t b/tests/py/any/rawpayload.t
new file mode 100644
index 0000000..5bc9d35
--- /dev/null
+++ b/tests/py/any/rawpayload.t
@@ -0,0 +1,24 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+meta l4proto { tcp, udp, sctp} @th,16,16 { 22, 23, 80 };ok;meta l4proto { 6, 17, 132} th dport { 22, 23, 80}
+meta l4proto tcp @th,16,16 { 22, 23, 80};ok;tcp dport { 22, 23, 80}
+@nh,8,8 0xff;ok
+@nh,8,16 0x0;ok
+
+# out of range (0-1)
+@th,16,1 2;fail
+
+@ll,0,0 2;fail
+@ll,0,1;fail
+@ll,0,1 1;ok;@ll,0,8 & 0x80 == 0x80
+@ll,0,8 & 0x80 == 0x80;ok
+@ll,0,128 0xfedcba987654321001234567890abcde;ok
+
+meta l4proto 91 @th,400,16 0x0 accept;ok
+
+@ih,32,32 0x14000000;ok
diff --git a/tests/py/any/rawpayload.t.json b/tests/py/any/rawpayload.t.json
new file mode 100644
index 0000000..4cae4d4
--- /dev/null
+++ b/tests/py/any/rawpayload.t.json
@@ -0,0 +1,206 @@
+# meta l4proto { tcp, udp, sctp} @th,16,16 { 22, 23, 80 }
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "tcp",
+ "udp",
+ "sctp"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "th",
+ "len": 16,
+ "offset": 16
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 22,
+ 23,
+ 80
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto tcp @th,16,16 { 22, 23, 80}
+[
+ {
+ "match": {
+ "left": { "meta": { "key": "l4proto" } },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "th",
+ "len": 16,
+ "offset": 16
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 22,
+ 23,
+ 80
+ ]
+ }
+ }
+ }
+]
+
+# @nh,8,8 0xff
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 8,
+ "offset": 8
+ }
+ },
+ "op": "==",
+ "right": "0xff"
+ }
+ }
+]
+
+# @nh,8,16 0x0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 16,
+ "offset": 8
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# @ll,0,1 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "ll",
+ "len": 1,
+ "offset": 0
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# @ll,0,8 & 0x80 == 0x80
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "base": "ll",
+ "len": 8,
+ "offset": 0
+ }
+ },
+ "0x80"
+ ]
+ },
+ "op": "==",
+ "right": "0x80"
+ }
+ }
+]
+
+# @ll,0,128 0xfedcba987654321001234567890abcde
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "ll",
+ "len": 128,
+ "offset": 0
+ }
+ },
+ "op": "==",
+ "right": "0xfedcba987654321001234567890abcde"
+ }
+ }
+]
+
+# meta l4proto 91 @th,400,16 0x0 accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 91
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "th",
+ "len": 16,
+ "offset": 400
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# @ih,32,32 0x14000000
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "ih",
+ "len": 32,
+ "offset": 32
+ }
+ },
+ "op": "==",
+ "right": 335544320
+ }
+ }
+]
+
diff --git a/tests/py/any/rawpayload.t.json.output b/tests/py/any/rawpayload.t.json.output
new file mode 100644
index 0000000..291b237
--- /dev/null
+++ b/tests/py/any/rawpayload.t.json.output
@@ -0,0 +1,119 @@
+# meta l4proto { tcp, udp, sctp} @th,16,16 { 22, 23, 80 }
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 132
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "th"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 22,
+ 23,
+ 80
+ ]
+ }
+ }
+ }
+]
+
+# meta l4proto tcp @th,16,16 { 22, 23, 80}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 22,
+ 23,
+ 80
+ ]
+ }
+ }
+ }
+]
+
+# @ll,0,1 1
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "base": "ll",
+ "len": 8,
+ "offset": 0
+ }
+ },
+ 128
+ ]
+ },
+ "op": "==",
+ "right": 128
+ }
+ }
+]
+
+# @ll,0,8 & 0x80 == 0x80
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "base": "ll",
+ "len": 8,
+ "offset": 0
+ }
+ },
+ 128
+ ]
+ },
+ "op": "==",
+ "right": 128
+ }
+ }
+]
+
+# @nh,8,8 0xff
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 8,
+ "offset": 8
+ }
+ },
+ "op": "==",
+ "right": 255
+ }
+ }
+]
diff --git a/tests/py/any/rawpayload.t.payload b/tests/py/any/rawpayload.t.payload
new file mode 100644
index 0000000..fe2377e
--- /dev/null
+++ b/tests/py/any/rawpayload.t.payload
@@ -0,0 +1,63 @@
+# meta l4proto { tcp, udp, sctp} @th,16,16 { 22, 23, 80 }
+__set%d test-inet 3 size 3
+__set%d test-inet 0
+ element 00000006 : 0 [end] element 00000011 : 0 [end] element 00000084 : 0 [end]
+__set%d test-inet 3 size 3
+__set%d test-inet 0
+ element 00001600 : 0 [end] element 00001700 : 0 [end] element 00005000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta l4proto tcp @th,16,16 { 22, 23, 80}
+__set%d test-inet 3 size 3
+__set%d test-inet 0
+ element 00001600 : 0 [end] element 00001700 : 0 [end] element 00005000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# @nh,8,8 0xff
+inet test-inet input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ cmp eq reg 1 0x000000ff ]
+
+# @nh,8,16 0x0
+inet test-inet input
+ [ payload load 2b @ network header + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# @ll,0,1 1
+inet test-inet input
+ [ payload load 1b @ link header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000080 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# @ll,0,8 & 0x80 == 0x80
+inet test-inet input
+ [ payload load 1b @ link header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000080 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# @ll,0,128 0xfedcba987654321001234567890abcde
+inet test-inet input
+ [ payload load 16b @ link header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x98badcfe 0x10325476 0x67452301 0xdebc0a89 ]
+
+# meta l4proto 91 @th,400,16 0x0 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000005b ]
+ [ payload load 2b @ transport header + 50 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ immediate reg 0 accept ]
+
+# @ih,32,32 0x14000000
+inet test-inet input
+ [ payload load 4b @ inner header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000014 ]
+
diff --git a/tests/py/any/rt.t b/tests/py/any/rt.t
new file mode 100644
index 0000000..3ce57e0
--- /dev/null
+++ b/tests/py/any/rt.t
@@ -0,0 +1,9 @@
+:output;type filter hook input priority 0
+
+*ip;test-ip4;output
+*ip6;test-ip6;output
+*inet;test-inet;output
+
+rt classid "cosmos";ok
+rt ipsec exists;ok
+rt ipsec missing;ok
diff --git a/tests/py/any/rt.t.json b/tests/py/any/rt.t.json
new file mode 100644
index 0000000..2ca6fe0
--- /dev/null
+++ b/tests/py/any/rt.t.json
@@ -0,0 +1,45 @@
+# rt classid "cosmos"
+[
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "key": "classid"
+ }
+ },
+ "op": "==",
+ "right": "cosmos"
+ }
+ }
+]
+
+# rt ipsec exists
+[
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "key": "ipsec"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# rt ipsec missing
+[
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "key": "ipsec"
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
diff --git a/tests/py/any/rt.t.payload b/tests/py/any/rt.t.payload
new file mode 100644
index 0000000..e1ecb28
--- /dev/null
+++ b/tests/py/any/rt.t.payload
@@ -0,0 +1,15 @@
+# rt classid "cosmos"
+ip test-ip4 input
+ [ rt load classid => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# rt ipsec exists
+ip test-ip4 input
+ [ rt load ipsec => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# rt ipsec missing
+ip test-ip4 input
+ [ rt load ipsec => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
new file mode 100644
index 0000000..177f01c
--- /dev/null
+++ b/tests/py/any/tcpopt.t
@@ -0,0 +1,62 @@
+:input;type filter hook input priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+
+tcp option eol exists;ok
+tcp option nop exists;ok
+tcp option maxseg exists;ok
+tcp option maxseg length 1;ok
+tcp option maxseg size 1;ok
+tcp option window length 1;ok
+tcp option window count 1;ok
+tcp option sack-perm exists;ok
+tcp option sack-perm length 1;ok
+tcp option sack exists;ok
+tcp option sack length 1;ok
+tcp option sack left 1;ok
+tcp option sack0 left 1;ok;tcp option sack left 1
+tcp option sack1 left 1;ok
+tcp option sack2 left 1;ok
+tcp option sack3 left 1;ok
+tcp option sack right 1;ok
+tcp option sack0 right 1;ok;tcp option sack right 1
+tcp option sack1 right 1;ok
+tcp option sack2 right 1;ok
+tcp option sack3 right 1;ok
+tcp option timestamp exists;ok
+tcp option timestamp length 1;ok
+tcp option timestamp tsval 1;ok
+tcp option timestamp tsecr 1;ok
+tcp option 255 missing;ok
+tcp option 6 exists;ok
+tcp option @255,8,8 255;ok
+
+tcp option foobar;fail
+tcp option foo bar;fail
+tcp option eol left;fail
+tcp option eol left 1;fail
+tcp option sack window;fail
+tcp option sack window 1;fail
+tcp option 256 exists;fail
+tcp option @255,8,8 256;fail
+
+tcp option window exists;ok
+tcp option window missing;ok
+
+tcp option maxseg size set 1360;ok
+
+tcp option md5sig exists;ok
+tcp option fastopen exists;ok
+tcp option mptcp exists;ok
+
+tcp option mptcp subtype 0;ok
+tcp option mptcp subtype 1;ok
+tcp option mptcp subtype { 0, 2};ok
+
+reset tcp option mptcp;ok
+reset tcp option 2;ok;reset tcp option maxseg
+reset tcp option 123;ok
+reset tcp option meh;fail
+reset tcp option 256;fail
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
new file mode 100644
index 0000000..4466f14
--- /dev/null
+++ b/tests/py/any/tcpopt.t.json
@@ -0,0 +1,622 @@
+# tcp option eol exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "eol"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option nop exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "nop"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option maxseg exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "maxseg"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option maxseg length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "maxseg"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option maxseg size 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "size",
+ "name": "maxseg"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option window length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "window"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option window count 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "count",
+ "name": "window"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack-perm exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "sack-perm"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option sack-perm length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "sack-perm"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option sack length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack0 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack1 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack1"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack2 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack2"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack3 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack3"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack0 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack1 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack1"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack2 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack2"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack3 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack3"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option timestamp exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "timestamp"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option timestamp length 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "length",
+ "name": "timestamp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option timestamp tsval 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "tsval",
+ "name": "timestamp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option timestamp tsecr 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "tsecr",
+ "name": "timestamp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option 255 missing
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "base": 255,
+ "len": 8,
+ "offset": 0
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
+# tcp option 6 exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "base": 6,
+ "len": 8,
+ "offset": 0
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option @255,8,8 255
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "base": 255,
+ "len": 8,
+ "offset": 8
+ }
+ },
+ "op": "==",
+ "right": 255
+ }
+ }
+]
+
+# tcp option window exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "window"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option window missing
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "window"
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
+# tcp option maxseg size set 1360
+[
+ {
+ "mangle": {
+ "key": {
+ "tcp option": {
+ "field": "size",
+ "name": "maxseg"
+ }
+ },
+ "value": 1360
+ }
+ }
+]
+
+# tcp option md5sig exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "md5sig"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option fastopen exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "fastopen"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option mptcp exists
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "name": "mptcp"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# tcp option mptcp subtype 0
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "subtype",
+ "name": "mptcp"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# tcp option mptcp subtype 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "subtype",
+ "name": "mptcp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option mptcp subtype { 0, 2}
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "subtype",
+ "name": "mptcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 0,
+ 2
+ ]
+ }
+ }
+ }
+]
+
+# reset tcp option mptcp
+[
+ {
+ "reset": {
+ "tcp option": {
+ "name": "mptcp"
+ }
+ }
+ }
+]
+
+# reset tcp option 2
+[
+ {
+ "reset": {
+ "tcp option": {
+ "name": "maxseg"
+ }
+ }
+ }
+]
+
+# reset tcp option 123
+[
+ {
+ "reset": {
+ "tcp option": {
+ "base": 123,
+ "len": 0,
+ "offset": 0
+ }
+ }
+ }
+]
diff --git a/tests/py/any/tcpopt.t.json.output b/tests/py/any/tcpopt.t.json.output
new file mode 100644
index 0000000..ad0d25f
--- /dev/null
+++ b/tests/py/any/tcpopt.t.json.output
@@ -0,0 +1,32 @@
+# tcp option sack0 left 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "left",
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# tcp option sack0 right 1
+[
+ {
+ "match": {
+ "left": {
+ "tcp option": {
+ "field": "right",
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
new file mode 100644
index 0000000..99b8985
--- /dev/null
+++ b/tests/py/any/tcpopt.t.payload
@@ -0,0 +1,202 @@
+# tcp option eol exists
+inet
+ [ exthdr load tcpopt 1b @ 0 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option nop exists
+inet
+ [ exthdr load tcpopt 1b @ 1 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option maxseg exists
+inet
+ [ exthdr load tcpopt 1b @ 2 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option maxseg length 1
+inet
+ [ exthdr load tcpopt 1b @ 2 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option maxseg size 1
+inet
+ [ exthdr load tcpopt 2b @ 2 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# tcp option window length 1
+inet
+ [ exthdr load tcpopt 1b @ 3 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option window count 1
+inet
+ [ exthdr load tcpopt 1b @ 3 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option sack-perm exists
+inet
+ [ exthdr load tcpopt 1b @ 4 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option sack-perm length 1
+inet
+ [ exthdr load tcpopt 1b @ 4 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option sack exists
+inet
+ [ exthdr load tcpopt 1b @ 5 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option sack length 1
+inet
+ [ exthdr load tcpopt 1b @ 5 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option sack left 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option sack0 left 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option sack1 left 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 10 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option sack2 left 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 18 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option sack3 left 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 26 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option sack right 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 6 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option sack0 right 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 6 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option sack1 right 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 14 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option sack2 right 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 22 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option sack3 right 1
+inet
+ [ exthdr load tcpopt 4b @ 5 + 30 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option timestamp exists
+inet
+ [ exthdr load tcpopt 1b @ 8 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option timestamp length 1
+inet
+ [ exthdr load tcpopt 1b @ 8 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option timestamp tsval 1
+inet
+ [ exthdr load tcpopt 4b @ 8 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option timestamp tsecr 1
+inet
+ [ exthdr load tcpopt 4b @ 8 + 6 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# tcp option 255 missing
+inet
+ [ exthdr load tcpopt 1b @ 255 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# tcp option 6 exists
+inet
+ [ exthdr load tcpopt 1b @ 6 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option @255,8,8 255
+inet
+ [ exthdr load tcpopt 1b @ 255 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x000000ff ]
+
+# tcp option window exists
+inet
+ [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option window missing
+inet
+ [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# tcp option maxseg size set 1360
+inet
+ [ immediate reg 1 0x00005005 ]
+ [ exthdr write tcpopt reg 1 => 2b @ 2 + 2 ]
+
+# tcp option md5sig exists
+inet
+ [ exthdr load tcpopt 1b @ 19 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option fastopen exists
+inet
+ [ exthdr load tcpopt 1b @ 34 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option mptcp exists
+inet
+ [ exthdr load tcpopt 1b @ 30 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# tcp option mptcp subtype 0
+inet
+ [ exthdr load tcpopt 1b @ 30 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# tcp option mptcp subtype 1
+inet
+ [ exthdr load tcpopt 1b @ 30 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+
+# tcp option mptcp subtype { 0, 2}
+__set%d test-inet 3 size 2
+__set%d test-inet 0
+ element 00000000 : 0 [end] element 00000020 : 0 [end]
+inet
+ [ exthdr load tcpopt 1b @ 30 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# reset tcp option mptcp
+ip test-ip4 input
+ [ exthdr reset tcpopt 30 ]
+
+# reset tcp option 2
+ip test-ip4 input
+ [ exthdr reset tcpopt 2 ]
+
+# reset tcp option 123
+ip test-ip4 input
+ [ exthdr reset tcpopt 123 ]
diff --git a/tests/py/arp/arp.t b/tests/py/arp/arp.t
new file mode 100644
index 0000000..222b91c
--- /dev/null
+++ b/tests/py/arp/arp.t
@@ -0,0 +1,60 @@
+# filter chains available are: input, output, forward
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*arp;test-arp;input
+*netdev;test-netdev;ingress,egress
+
+arp htype 1;ok
+arp htype != 1;ok
+arp htype 22;ok
+arp htype != 233;ok
+arp htype 33-45;ok
+arp htype != 33-45;ok
+arp htype { 33, 55, 67, 88};ok
+arp htype != { 33, 55, 67, 88};ok
+
+arp ptype 0x0800;ok;arp ptype ip
+
+arp hlen 22;ok
+arp hlen != 233;ok
+arp hlen 33-45;ok
+arp hlen != 33-45;ok
+arp hlen { 33, 55, 67, 88};ok
+arp hlen != { 33, 55, 67, 88};ok
+
+arp plen 22;ok
+arp plen != 233;ok
+arp plen 33-45;ok
+arp plen != 33-45;ok
+arp plen { 33, 55, 67, 88};ok
+arp plen != { 33, 55, 67, 88};ok
+
+arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request};ok
+arp operation != {nak, inreply, inrequest, rreply, rrequest, reply, request};ok
+arp operation 1-2;ok
+arp operation request;ok
+arp operation reply;ok
+arp operation rrequest;ok
+arp operation rreply;ok
+arp operation inrequest;ok
+arp operation inreply;ok
+arp operation nak;ok
+arp operation != request;ok
+arp operation != reply;ok
+arp operation != rrequest;ok
+arp operation != rreply;ok
+arp operation != inrequest;ok
+arp operation != inreply;ok
+arp operation != nak;ok
+
+arp saddr ip 1.2.3.4;ok
+arp daddr ip 4.3.2.1;ok
+arp saddr ether aa:bb:cc:aa:bb:cc;ok
+arp daddr ether aa:bb:cc:aa:bb:cc;ok
+
+arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee;ok
+arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1;ok;arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee
+
+meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566;ok;iifname "invalid" arp htype 1 arp ptype ip arp hlen 6 arp plen 4 arp daddr ip 192.168.143.16 arp daddr ether set 11:22:33:44:55:66
diff --git a/tests/py/arp/arp.t.json b/tests/py/arp/arp.t.json
new file mode 100644
index 0000000..7ce7609
--- /dev/null
+++ b/tests/py/arp/arp.t.json
@@ -0,0 +1,893 @@
+# arp htype 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# arp htype != 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# arp htype 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# arp htype != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# arp htype 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp htype != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp htype { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp htype != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp ptype 0x0800
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ptype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "0x0800"
+ }
+ }
+]
+
+# arp hlen 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# arp hlen != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# arp hlen 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp hlen != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp hlen { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp hlen != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp plen 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# arp plen != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# arp plen 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp plen != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# arp plen { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp plen != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "nak",
+ "inreply",
+ "inrequest",
+ "rreply",
+ "rrequest",
+ "reply",
+ "request"
+ ]
+ }
+ }
+ }
+]
+
+# arp operation != {nak, inreply, inrequest, rreply, rrequest, reply, request}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "nak",
+ "inreply",
+ "inrequest",
+ "rreply",
+ "rrequest",
+ "reply",
+ "request"
+ ]
+ }
+ }
+ }
+]
+
+# arp operation 1-2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ "request",
+ "reply"
+ ]
+ }
+ }
+ }
+]
+
+# arp operation request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "request"
+ }
+ }
+]
+
+# arp operation reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "reply"
+ }
+ }
+]
+
+# arp operation rrequest
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "rrequest"
+ }
+ }
+]
+
+# arp operation rreply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "rreply"
+ }
+ }
+]
+
+# arp operation inrequest
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "inrequest"
+ }
+ }
+]
+
+# arp operation inreply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "inreply"
+ }
+ }
+]
+
+# arp operation nak
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "nak"
+ }
+ }
+]
+
+# arp operation != request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "request"
+ }
+ }
+]
+
+# arp operation != reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "reply"
+ }
+ }
+]
+
+# arp operation != rrequest
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "rrequest"
+ }
+ }
+]
+
+# arp operation != rreply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "rreply"
+ }
+ }
+]
+
+# arp operation != inrequest
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "inrequest"
+ }
+ }
+]
+
+# arp operation != inreply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "inreply"
+ }
+ }
+]
+
+# arp operation != nak
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": "nak"
+ }
+ }
+]
+
+# arp saddr ip 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr ip",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# arp daddr ip 4.3.2.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr ip",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "4.3.2.1"
+ }
+ }
+]
+
+# arp saddr ether aa:bb:cc:aa:bb:cc
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr ether",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "aa:bb:cc:aa:bb:cc"
+ }
+ }
+]
+
+# arp daddr ether aa:bb:cc:aa:bb:cc
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr ether",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "aa:bb:cc:aa:bb:cc"
+ }
+ }
+]
+
+# arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr ip",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.1"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr ether",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "fe:ed:00:c0:ff:ee"
+ }
+ }
+]
+
+# arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr ether",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "fe:ed:00:c0:ff:ee"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr ip",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.1"
+ }
+ }
+]
+
+# 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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "invalid"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ptype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "0x0800"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 4
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "base": "nh",
+ "len": 32,
+ "offset": 192
+ }
+ },
+ "op": "==",
+ "right": "0xc0a88f10"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "base": "nh",
+ "len": 48,
+ "offset": 144
+ }
+ },
+ "value": "0x112233445566"
+ }
+ }
+]
+
diff --git a/tests/py/arp/arp.t.json.output b/tests/py/arp/arp.t.json.output
new file mode 100644
index 0000000..afa75b2
--- /dev/null
+++ b/tests/py/arp/arp.t.json.output
@@ -0,0 +1,180 @@
+# arp ptype 0x0800
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ptype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ }
+]
+
+# arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "request",
+ "reply",
+ "rrequest",
+ "rreply",
+ "inrequest",
+ "inreply",
+ "nak"
+ ]
+ }
+ }
+ }
+]
+
+# arp operation != {nak, inreply, inrequest, rreply, rrequest, reply, request}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "operation",
+ "protocol": "arp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "request",
+ "reply",
+ "rrequest",
+ "rreply",
+ "inrequest",
+ "inreply",
+ "nak"
+ ]
+ }
+ }
+ }
+]
+
+# arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr ip",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.1"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr ether",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "fe:ed:00:c0:ff:ee"
+ }
+ }
+]
+
+# 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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "invalid"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "htype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ptype",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hlen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "plen",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": 4
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr ip",
+ "protocol": "arp"
+ }
+ },
+ "op": "==",
+ "right": "192.168.143.16"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "daddr ether",
+ "protocol": "arp"
+ }
+ },
+ "value": "11:22:33:44:55:66"
+ }
+ }
+]
+
diff --git a/tests/py/arp/arp.t.payload b/tests/py/arp/arp.t.payload
new file mode 100644
index 0000000..d56927b
--- /dev/null
+++ b/tests/py/arp/arp.t.payload
@@ -0,0 +1,261 @@
+# arp htype 1
+arp test-arp input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# arp htype != 1
+arp test-arp input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000100 ]
+
+# arp htype 22
+arp test-arp input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# arp htype != 233
+arp test-arp input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# arp htype 33-45
+arp test-arp input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# arp htype != 33-45
+arp test-arp input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# arp htype { 33, 55, 67, 88}
+__set%d test-arp 3
+__set%d test-arp 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+arp test-arp input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# arp htype != { 33, 55, 67, 88}
+__set%d test-arp 3
+__set%d test-arp 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+arp test-arp input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# arp ptype 0x0800
+arp test-arp input
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# arp hlen 22
+arp test-arp input
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# arp hlen != 233
+arp test-arp input
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# arp hlen 33-45
+arp test-arp input
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# arp hlen != 33-45
+arp test-arp input
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# arp hlen { 33, 55, 67, 88}
+__set%d test-arp 3
+__set%d test-arp 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+arp test-arp input
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# arp hlen != { 33, 55, 67, 88}
+__set%d test-arp 3
+__set%d test-arp 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+arp test-arp input
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# arp plen 22
+arp test-arp input
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# arp plen != 233
+arp test-arp input
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# arp plen 33-45
+arp test-arp input
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# arp plen != 33-45
+arp test-arp input
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# arp plen { 33, 55, 67, 88}
+__set%d test-arp 3
+__set%d test-arp 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+arp test-arp input
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# arp plen != { 33, 55, 67, 88}
+__set%d test-arp 3
+__set%d test-arp 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+arp test-arp input
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request}
+__set%d test-arp 3
+__set%d test-arp 0
+ element 00000a00 : 0 [end] element 00000900 : 0 [end] element 00000800 : 0 [end] element 00000400 : 0 [end] element 00000300 : 0 [end] element 00000200 : 0 [end] element 00000100 : 0 [end]
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# arp operation != {nak, inreply, inrequest, rreply, rrequest, reply, request}
+__set%d test-arp 3
+__set%d test-arp 0
+ element 00000a00 : 0 [end] element 00000900 : 0 [end] element 00000800 : 0 [end] element 00000400 : 0 [end] element 00000300 : 0 [end] element 00000200 : 0 [end] element 00000100 : 0 [end]
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# arp operation 1-2
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00000100 ]
+ [ cmp lte reg 1 0x00000200 ]
+
+# arp operation request
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# arp operation reply
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000200 ]
+
+# arp operation rrequest
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000300 ]
+
+# arp operation rreply
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000400 ]
+
+# arp operation inrequest
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000800 ]
+
+# arp operation inreply
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000900 ]
+
+# arp operation nak
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000a00 ]
+
+# arp operation != request
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000100 ]
+
+# arp operation != reply
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000200 ]
+
+# arp operation != rrequest
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000300 ]
+
+# arp operation != rreply
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000400 ]
+
+# arp operation != inrequest
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000800 ]
+
+# arp operation != inreply
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000900 ]
+
+# arp operation != nak
+arp test-arp input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000a00 ]
+
+# meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566
+arp test-arp input
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x61766e69 0x0064696c 0x00000000 0x00000000 ]
+ [ payload load 4b @ network header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00080100 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000406 ]
+ [ payload load 4b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x108fa8c0 ]
+ [ immediate reg 1 0x44332211 0x00006655 ]
+ [ payload write reg 1 => 6b @ network header + 18 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# arp saddr ip 1.2.3.4
+arp test-arp input
+ [ payload load 4b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+
+# arp daddr ip 4.3.2.1
+arp test-arp input
+ [ payload load 4b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x01020304 ]
+
+# arp saddr ether aa:bb:cc:aa:bb:cc
+arp test-arp input
+ [ payload load 6b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+
+# arp daddr ether aa:bb:cc:aa:bb:cc
+arp test-arp input
+ [ payload load 6b @ network header + 18 => reg 1 ]
+ [ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+
+# arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee
+arp
+ [ payload load 10b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x0101a8c0 0xc000edfe 0x0000eeff ]
+
+# arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1
+arp
+ [ payload load 10b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x0101a8c0 0xc000edfe 0x0000eeff ]
+
diff --git a/tests/py/arp/arp.t.payload.netdev b/tests/py/arp/arp.t.payload.netdev
new file mode 100644
index 0000000..92df240
--- /dev/null
+++ b/tests/py/arp/arp.t.payload.netdev
@@ -0,0 +1,351 @@
+# arp htype 1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# arp htype != 1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000100 ]
+
+# arp htype 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# arp htype != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# arp htype 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# arp htype != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# arp htype { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# arp htype != { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# arp ptype 0x0800
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# arp hlen 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# arp hlen != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# arp hlen 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# arp hlen != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# arp hlen { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# arp hlen != { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# arp plen 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# arp plen != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# arp plen 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# arp plen != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# arp plen { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# arp plen != { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 1b @ network header + 5 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000a00 : 0 [end] element 00000900 : 0 [end] element 00000800 : 0 [end] element 00000400 : 0 [end] element 00000300 : 0 [end] element 00000200 : 0 [end] element 00000100 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# arp operation != {nak, inreply, inrequest, rreply, rrequest, reply, request}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000a00 : 0 [end] element 00000900 : 0 [end] element 00000800 : 0 [end] element 00000400 : 0 [end] element 00000300 : 0 [end] element 00000200 : 0 [end] element 00000100 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# arp operation 1-2
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00000100 ]
+ [ cmp lte reg 1 0x00000200 ]
+
+# arp operation request
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# arp operation reply
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000200 ]
+
+# arp operation rrequest
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000300 ]
+
+# arp operation rreply
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000400 ]
+
+# arp operation inrequest
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000800 ]
+
+# arp operation inreply
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000900 ]
+
+# arp operation nak
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000a00 ]
+
+# arp operation != request
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000100 ]
+
+# arp operation != reply
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000200 ]
+
+# arp operation != rrequest
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000300 ]
+
+# arp operation != rreply
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000400 ]
+
+# arp operation != inrequest
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000800 ]
+
+# arp operation != inreply
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000900 ]
+
+# arp operation != nak
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000a00 ]
+
+# meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566
+netdev test-netdev ingress
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x61766e69 0x0064696c 0x00000000 0x00000000 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 4b @ network header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00080100 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000406 ]
+ [ payload load 4b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x108fa8c0 ]
+ [ immediate reg 1 0x44332211 0x00006655 ]
+ [ payload write reg 1 => 6b @ network header + 18 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# arp saddr ip 1.2.3.4
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 4b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+
+# arp daddr ip 4.3.2.1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 4b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x01020304 ]
+
+# arp saddr ether aa:bb:cc:aa:bb:cc
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 6b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+
+# arp daddr ether aa:bb:cc:aa:bb:cc
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 6b @ network header + 18 => reg 1 ]
+ [ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+
+# arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 10b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x0101a8c0 0xc000edfe 0x0000eeff ]
+
+# arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 10b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x0101a8c0 0xc000edfe 0x0000eeff ]
+
diff --git a/tests/py/arp/chains.t b/tests/py/arp/chains.t
new file mode 100644
index 0000000..1ea39f7
--- /dev/null
+++ b/tests/py/arp/chains.t
@@ -0,0 +1,5 @@
+# filter chains available are: input, output
+:input;type filter hook input priority 0
+:output;type filter hook output priority 0
+
+*arp;test-arp;input,output
diff --git a/tests/py/arp/chains.t.payload b/tests/py/arp/chains.t.payload
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/py/arp/chains.t.payload
diff --git a/tests/py/bridge/chains.t b/tests/py/bridge/chains.t
new file mode 100644
index 0000000..e071d9a
--- /dev/null
+++ b/tests/py/bridge/chains.t
@@ -0,0 +1,8 @@
+# filter chains available are: prerouting, input, output, forward, postrouting
+:filter-pre;type filter hook prerouting priority 0
+:filter-output;type filter hook output priority 0
+:filter-forward;type filter hook forward priority 0
+:filter-input;type filter hook input priority 0
+:filter-post;type filter hook postrouting priority 0
+
+*bridge;test-bridge;filter-pre,filter-output,filter-forward,filter-input,filter-post
diff --git a/tests/py/bridge/chains.t.payload b/tests/py/bridge/chains.t.payload
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/py/bridge/chains.t.payload
diff --git a/tests/py/bridge/ether.t b/tests/py/bridge/ether.t
new file mode 100644
index 0000000..e4f75d1
--- /dev/null
+++ b/tests/py/bridge/ether.t
@@ -0,0 +1,12 @@
+:input;type filter hook input priority 0
+
+*bridge;test-bridge;input
+
+tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept;ok;tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04 accept
+tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04;ok
+tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4;ok
+ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4 accept;ok
+
+ether daddr 00:01:02:03:04:05 ether saddr set ff:fe:dc:ba:98:76 drop;ok
+
+ether daddr set {01:00:5e:00:01:01, 01:00:5e:00:02:02};fail
diff --git a/tests/py/bridge/ether.t.json b/tests/py/bridge/ether.t.json
new file mode 100644
index 0000000..485ceee
--- /dev/null
+++ b/tests/py/bridge/ether.t.json
@@ -0,0 +1,193 @@
+# 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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "==",
+ "right": "ether"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:01:02:03:04:05"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "value": "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 0000000..5bb2e47
--- /dev/null
+++ b/tests/py/bridge/ether.t.json.output
@@ -0,0 +1,43 @@
+# 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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/bridge/ether.t.payload b/tests/py/bridge/ether.t.payload
new file mode 100644
index 0000000..eaff9c3
--- /dev/null
+++ b/tests/py/bridge/ether.t.payload
@@ -0,0 +1,60 @@
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+bridge test-bridge input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04
+bridge test-bridge input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4
+bridge test-bridge input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+
+# ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4 accept
+bridge test-bridge input
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ immediate reg 0 accept ]
+
+# ether daddr 00:01:02:03:04:05 ether saddr set ff:fe:dc:ba:98:76 drop
+bridge test-bridge input
+ [ payload load 6b @ link header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x03020100 0x00000504 ]
+ [ immediate reg 1 0xbadcfeff 0x00007698 ]
+ [ payload write reg 1 => 6b @ link header + 6 csum_type 0 csum_off 0 csum_flags 0x0 ]
+ [ immediate reg 0 drop ]
+
diff --git a/tests/py/bridge/icmpX.t b/tests/py/bridge/icmpX.t
new file mode 100644
index 0000000..7c35c26
--- /dev/null
+++ b/tests/py/bridge/icmpX.t
@@ -0,0 +1,8 @@
+:input;type filter hook input priority 0
+
+*bridge;test-bridge;input
+
+ip protocol icmp icmp type echo-request;ok;ip protocol 1 icmp type echo-request
+icmp type echo-request;ok
+ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;ip6 nexthdr 58 icmpv6 type echo-request
+icmpv6 type echo-request;ok
diff --git a/tests/py/bridge/icmpX.t.json b/tests/py/bridge/icmpX.t.json
new file mode 100644
index 0000000..2dd341e
--- /dev/null
+++ b/tests/py/bridge/icmpX.t.json
@@ -0,0 +1,88 @@
+# ip protocol icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "icmpv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "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 0000000..8cf4679
--- /dev/null
+++ b/tests/py/bridge/icmpX.t.json.output
@@ -0,0 +1,56 @@
+# ip protocol icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": 58
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
diff --git a/tests/py/bridge/icmpX.t.payload b/tests/py/bridge/icmpX.t.payload
new file mode 100644
index 0000000..f9ea7b6
--- /dev/null
+++ b/tests/py/bridge/icmpX.t.payload
@@ -0,0 +1,36 @@
+# ip protocol icmp icmp type echo-request
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# icmp type echo-request
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# icmpv6 type echo-request
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
diff --git a/tests/py/bridge/meta.t b/tests/py/bridge/meta.t
new file mode 100644
index 0000000..171aa61
--- /dev/null
+++ b/tests/py/bridge/meta.t
@@ -0,0 +1,13 @@
+:input;type filter hook input priority 0
+
+*bridge;test-bridge;input
+
+meta obrname "br0";ok
+meta ibrname "br0";ok
+meta ibrvproto vlan;ok;meta ibrvproto 8021q
+meta ibrpvid 100;ok
+
+meta protocol ip udp dport 67;ok
+meta protocol ip6 udp dport 67;ok
+
+meta broute set 1;fail
diff --git a/tests/py/bridge/meta.t.json b/tests/py/bridge/meta.t.json
new file mode 100644
index 0000000..d7dc9d7
--- /dev/null
+++ b/tests/py/bridge/meta.t.json
@@ -0,0 +1,105 @@
+# meta obrname "br0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "obrname" }
+ },
+ "op": "==",
+ "right": "br0"
+ }
+ }
+]
+
+# meta ibrname "br0"
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "ibrname" }
+ },
+ "op": "==",
+ "right": "br0"
+ }
+ }
+]
+
+# meta ibrvproto vlan
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "ibrvproto" }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ }
+]
+
+# meta ibrpvid 100
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "ibrpvid" }
+ },
+ "op": "==",
+ "right": 100
+ }
+ }
+]
+
+# meta protocol ip udp dport 67
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 67
+ }
+ }
+]
+
+# meta protocol ip6 udp dport 67
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 67
+ }
+ }
+]
diff --git a/tests/py/bridge/meta.t.payload b/tests/py/bridge/meta.t.payload
new file mode 100644
index 0000000..0a39842
--- /dev/null
+++ b/tests/py/bridge/meta.t.payload
@@ -0,0 +1,37 @@
+# meta obrname "br0"
+bridge test-bridge input
+ [ meta load bri_oifname => reg 1 ]
+ [ cmp eq reg 1 0x00307262 0x00000000 0x00000000 0x00000000 ]
+
+# meta ibrname "br0"
+bridge test-bridge input
+ [ meta load bri_iifname => reg 1 ]
+ [ cmp eq reg 1 0x00307262 0x00000000 0x00000000 0x00000000 ]
+
+# meta ibrvproto vlan
+bridge test-bridge input
+ [ meta load bri_iifvproto => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+
+# meta ibrpvid 100
+bridge test-bridge input
+ [ meta load bri_iifpvid => reg 1 ]
+ [ cmp eq reg 1 0x00000064 ]
+
+# meta protocol ip udp dport 67
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00004300 ]
+
+# meta protocol ip6 udp dport 67
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00004300 ]
diff --git a/tests/py/bridge/redirect.t b/tests/py/bridge/redirect.t
new file mode 100644
index 0000000..5181e79
--- /dev/null
+++ b/tests/py/bridge/redirect.t
@@ -0,0 +1,5 @@
+:prerouting;type filter hook prerouting priority 0
+
+*bridge;test-bridge;prerouting
+
+meta broute set 1;ok
diff --git a/tests/py/bridge/redirect.t.json b/tests/py/bridge/redirect.t.json
new file mode 100644
index 0000000..7e32b32
--- /dev/null
+++ b/tests/py/bridge/redirect.t.json
@@ -0,0 +1,12 @@
+# meta broute set 1
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "broute" }
+ },
+ "value": 1
+ }
+ }
+]
+
diff --git a/tests/py/bridge/redirect.t.payload b/tests/py/bridge/redirect.t.payload
new file mode 100644
index 0000000..1fcfa5f
--- /dev/null
+++ b/tests/py/bridge/redirect.t.payload
@@ -0,0 +1,4 @@
+# meta broute set 1
+bridge test-bridge prerouting
+ [ immediate reg 1 0x00000001 ]
+ [ meta set broute with reg 1 ]
diff --git a/tests/py/bridge/reject.t b/tests/py/bridge/reject.t
new file mode 100644
index 0000000..336b51b
--- /dev/null
+++ b/tests/py/bridge/reject.t
@@ -0,0 +1,42 @@
+:input;type filter hook input priority 0
+
+*bridge;test-bridge;input
+
+# The output is specific for bridge family
+reject with icmp host-unreachable;ok
+reject with icmp net-unreachable;ok
+reject with icmp prot-unreachable;ok
+reject with icmp port-unreachable;ok
+reject with icmp net-prohibited;ok
+reject with icmp host-prohibited;ok
+reject with icmp admin-prohibited;ok
+
+reject with icmpv6 no-route;ok
+reject with icmpv6 admin-prohibited;ok
+reject with icmpv6 addr-unreachable;ok
+reject with icmpv6 port-unreachable;ok
+
+mark 12345 ip protocol tcp reject with tcp reset;ok;meta mark 0x00003039 ip protocol 6 reject with tcp reset
+
+reject;ok
+ether type ip reject;ok;reject with icmp port-unreachable
+ether type ip6 reject;ok;reject with icmpv6 port-unreachable
+
+reject with icmpx host-unreachable;ok
+reject with icmpx no-route;ok
+reject with icmpx admin-prohibited;ok
+reject with icmpx port-unreachable;ok;reject
+
+ether type ipv6 reject with icmp host-unreachable;fail
+ether type ip6 reject with icmp host-unreachable;fail
+ether type ip reject with icmpv6 no-route;fail
+ether type vlan reject;ok;ether type 8021q reject
+ether type arp reject;fail
+ether type vlan reject with tcp reset;ok;meta l4proto 6 ether type 8021q reject with tcp reset
+ether type arp reject with tcp reset;fail
+ip protocol udp reject with tcp reset;fail
+
+ether type ip reject with icmpx admin-prohibited;ok
+ether type ip6 reject with icmpx admin-prohibited;ok
+ether type 8021q reject with icmpx admin-prohibited;ok
+ether type arp reject with icmpx admin-prohibited;fail
diff --git a/tests/py/bridge/reject.t.json b/tests/py/bridge/reject.t.json
new file mode 100644
index 0000000..9f9e6c1
--- /dev/null
+++ b/tests/py/bridge/reject.t.json
@@ -0,0 +1,341 @@
+# reject with icmp host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp net-unreachable
+[
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp prot-unreachable
+[
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp net-prohibited
+[
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp host-prohibited
+[
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmpv6 no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 addr-unreachable
+[
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# mark 12345 ip protocol tcp reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": 12345
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject
+[
+ {
+ "reject": null
+ }
+]
+
+# ether type ip reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# ether type ip6 reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# reject with icmpx host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# ether type ip reject with icmpx admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# ether type ip6 reject with icmpx admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# ether type vlan reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# ether type vlan reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "vlan"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# ether type 8021q reject with icmpx admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "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 0000000..b8a44f0
--- /dev/null
+++ b/tests/py/bridge/reject.t.json.output
@@ -0,0 +1,83 @@
+# mark 12345 ip protocol tcp reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "right": 12345
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# ether type ip reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# ether type ip6 reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# ether type vlan reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ },
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
diff --git a/tests/py/bridge/reject.t.payload b/tests/py/bridge/reject.t.payload
new file mode 100644
index 0000000..bad9adc
--- /dev/null
+++ b/tests/py/bridge/reject.t.payload
@@ -0,0 +1,140 @@
+# reject with icmp host-unreachable
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 1 ]
+
+# reject with icmp net-unreachable
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 0 ]
+
+# reject with icmp prot-unreachable
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 2 ]
+
+# reject with icmp port-unreachable
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 3 ]
+
+# reject with icmp net-prohibited
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 9 ]
+
+# reject with icmp host-prohibited
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 10 ]
+
+# reject with icmp admin-prohibited
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 13 ]
+
+# reject with icmpv6 no-route
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 0 ]
+
+# reject with icmpv6 admin-prohibited
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 1 ]
+
+# reject with icmpv6 addr-unreachable
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 3 ]
+
+# reject with icmpv6 port-unreachable
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 4 ]
+
+# mark 12345 ip protocol tcp reject with tcp reset
+bridge test-bridge input
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x00003039 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ reject type 1 code 0 ]
+
+# reject
+bridge test-bridge input
+ [ reject type 2 code 1 ]
+
+# ether type ip reject
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 3 ]
+
+# ether type ip6 reject
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 4 ]
+
+# reject with icmpx host-unreachable
+bridge test-bridge input
+ [ reject type 2 code 2 ]
+
+# reject with icmpx no-route
+bridge test-bridge input
+ [ reject type 2 code 0 ]
+
+# reject with icmpx admin-prohibited
+bridge test-bridge input
+ [ reject type 2 code 3 ]
+
+# reject with icmpx port-unreachable
+bridge test-bridge input
+ [ reject type 2 code 1 ]
+
+# ether type ip reject with icmpx admin-prohibited
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 2 code 3 ]
+
+# ether type ip6 reject with icmpx admin-prohibited
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 2 code 3 ]
+
+# ether type vlan reject
+bridge
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ reject type 2 code 1 ]
+
+# ether type vlan reject with tcp reset
+bridge
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ reject type 1 code 0 ]
+
+# ether type 8021q reject with icmpx admin-prohibited
+bridge
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ reject type 2 code 3 ]
+
diff --git a/tests/py/bridge/vlan.t b/tests/py/bridge/vlan.t
new file mode 100644
index 0000000..8fa90da
--- /dev/null
+++ b/tests/py/bridge/vlan.t
@@ -0,0 +1,56 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*bridge;test-bridge;input
+*netdev;test-netdev;ingress,egress
+
+vlan id 4094;ok
+vlan id 0;ok
+# bad vlan id
+vlan id 4096;fail
+vlan id 4094 vlan dei 0;ok
+vlan id 4094 vlan dei 1;ok
+vlan id 4094 vlan dei != 1;ok
+vlan id 4094 vlan cfi 1;ok;vlan id 4094 vlan dei 1
+# bad dei
+vlan id 4094 vlan dei 2;fail
+vlan id 4094 vlan dei 1 vlan pcp 8;fail
+vlan id 4094 vlan dei 1 vlan pcp 7;ok
+vlan id 4094 vlan dei 1 vlan pcp 3;ok
+
+ether type vlan vlan id 4094;ok;vlan id 4094
+ether type vlan vlan id 0;ok;vlan id 0
+ether type vlan vlan id 4094 vlan dei 0;ok;vlan id 4094 vlan dei 0
+ether type vlan vlan id 4094 vlan dei 1;ok;vlan id 4094 vlan dei 1
+ether type vlan vlan id 4094 vlan dei 2;fail
+
+vlan id 4094 tcp dport 22;ok
+vlan id 1 ip saddr 10.0.0.1;ok
+vlan id 1 ip saddr 10.0.0.0/23;ok
+vlan id 1 ip saddr 10.0.0.0/23 udp dport 53;ok
+ether type vlan vlan id 1 ip saddr 10.0.0.0/23 udp dport 53;ok;vlan id 1 ip saddr 10.0.0.0/23 udp dport 53
+
+vlan id { 1, 2, 4, 100, 4095 } vlan pcp 1-3;ok
+vlan id { 1, 2, 4, 100, 4096 };fail
+
+ether type vlan ip protocol 1 accept;ok;ether type 8021q ip protocol 1 accept
+
+# IEEE 802.1AD
+ether type 8021ad vlan id 1 ip protocol 6 accept;ok
+ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip counter;ok
+ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip ip protocol 6;ok;ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 ip protocol 6
+
+# illegal dependencies
+ether type ip vlan id 1;fail
+ether type ip vlan id 1 ip saddr 10.0.0.1;fail
+
+# mangling
+vlan id 1 vlan id set 2;ok
+
+ether saddr 00:01:02:03:04:05 vlan id 1;ok
+vlan id 2 ether saddr 0:1:2:3:4:6;ok;ether saddr 00:01:02:03:04:06 vlan id 2
+
+ether saddr . vlan id { 0a:0b:0c:0d:0e:0f . 42, 0a:0b:0c:0d:0e:0f . 4095 };ok
+
+ether saddr 00:11:22:33:44:55 counter ether type 8021q;ok
diff --git a/tests/py/bridge/vlan.t.json b/tests/py/bridge/vlan.t.json
new file mode 100644
index 0000000..7dfcdb4
--- /dev/null
+++ b/tests/py/bridge/vlan.t.json
@@ -0,0 +1,894 @@
+# vlan id 4094
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ }
+]
+
+# vlan id 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# vlan id 4094 vlan dei 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dei",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# vlan id 4094 vlan dei 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dei",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# vlan id 4094 vlan dei != 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dei",
+ "protocol": "vlan"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# vlan id 4094 vlan cfi 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dei",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# vlan id 4094 vlan dei 1 vlan pcp 7
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dei",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "pcp",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 7
+ }
+ }
+]
+
+# vlan id 4094 vlan dei 1 vlan pcp 3
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dei",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "pcp",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 3
+ }
+ }
+]
+
+# ether type vlan vlan id 4094
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ }
+]
+
+# ether type vlan vlan id 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# ether type vlan vlan id 4094 vlan dei 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dei",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# ether type vlan vlan id 4094 vlan dei 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dei",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# vlan id 4094 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 4094
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# vlan id 1 ip saddr 10.0.0.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "10.0.0.1"
+ }
+ }
+]
+
+# vlan id 1 ip saddr 10.0.0.0/23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "10.0.0.0",
+ "len": 23
+ }
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ }
+]
+
+# ether type vlan vlan id 1 ip saddr 10.0.0.0/23 udp dport 53
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "10.0.0.0",
+ "len": 23
+ }
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ }
+]
+
+# vlan id { 1, 2, 4, 100, 4095 } vlan pcp 1-3
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 1,
+ 2,
+ 4,
+ 100,
+ 4095
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "pcp",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 1, 3 ]
+ }
+ }
+ }
+]
+
+# ether type vlan ip protocol 1 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "vlan"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "icmp"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ether type 8021ad vlan id 1 ip protocol 6 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021ad"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip counter
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021ad"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "counter": {
+ "bytes": 0,
+ "packets": 0
+ }
+ }
+]
+
+# ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip ip protocol 6
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021ad"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ }
+]
+
+# vlan id 1 vlan id set 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "value": 2
+ }
+ }
+]
+
+# ether saddr 00:01:02:03:04:05 vlan id 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:01:02:03:04:05"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# vlan id 2 ether saddr 0:1:2:3:4:6
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:01:02:03:04:06"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# ether saddr . vlan id { 0a:0b:0c:0d:0e:0f . 42, 0a:0b:0c:0d:0e:0f . 4095 }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "0a:0b:0c:0d:0e:0f",
+ 42
+ ]
+ },
+ {
+ "concat": [
+ "0a:0b:0c:0d:0e:0f",
+ 4095
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ether saddr 00:11:22:33:44:55 counter ether type 8021q
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:11:22:33:44:55"
+ }
+ },
+ {
+ "counter": {
+ "bytes": 0,
+ "packets": 0
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ }
+]
diff --git a/tests/py/bridge/vlan.t.json.output b/tests/py/bridge/vlan.t.json.output
new file mode 100644
index 0000000..2f90c8f
--- /dev/null
+++ b/tests/py/bridge/vlan.t.json.output
@@ -0,0 +1,204 @@
+# ether type vlan ip protocol 1 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ether type 8021ad vlan id 1 ip protocol 6 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021ad"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip counter
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021ad"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "counter": null
+ }
+]
+
+# ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip ip protocol 6
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "8021ad"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": "8021q"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ }
+]
diff --git a/tests/py/bridge/vlan.t.payload b/tests/py/bridge/vlan.t.payload
new file mode 100644
index 0000000..2592bb9
--- /dev/null
+++ b/tests/py/bridge/vlan.t.payload
@@ -0,0 +1,314 @@
+# vlan id 4094
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+
+# vlan id 0
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# vlan id 4094 vlan cfi 1
+bridge
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+
+# vlan id 4094 vlan dei 0
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# vlan id 4094 vlan dei != 1
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000010 ]
+
+# vlan id 4094 vlan dei 1
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+
+# ether type vlan vlan id 4094
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+
+# ether type vlan vlan id 0
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ether type vlan vlan id 4094 vlan dei 0
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ether type vlan vlan id 4094 vlan dei 1
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+
+# vlan id 4094 tcp dport 22
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# vlan id 1 ip saddr 10.0.0.1
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0100000a ]
+
+# vlan id 1 ip saddr 10.0.0.0/23
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00feffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000a ]
+
+# vlan id 1 ip saddr 10.0.0.0/23 udp dport 53
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00feffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+
+# ether type vlan vlan id 1 ip saddr 10.0.0.0/23 udp dport 53
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00feffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+
+# vlan id 4094 vlan dei 1 vlan pcp 7
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000e0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x000000e0 ]
+
+# vlan id 4094 vlan dei 1 vlan pcp 3
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000e0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000060 ]
+
+# vlan id { 1, 2, 4, 100, 4095 } vlan pcp 1-3
+__set%d test-bridge 3
+__set%d test-bridge 0
+ element 00000100 : 0 [end] element 00000200 : 0 [end] element 00000400 : 0 [end] element 00006400 : 0 [end] element 0000ff0f : 0 [end]
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000e0 ) ^ 0x00000000 ]
+ [ cmp gte reg 1 0x00000020 ]
+ [ cmp lte reg 1 0x00000060 ]
+
+# ether type vlan ip protocol 1 accept
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 0 accept ]
+
+# ether type 8021ad vlan id 1 ip protocol 6 accept
+bridge
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0000a888 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 0 accept ]
+
+# ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip counter
+bridge
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0000a888 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 18 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000200 ]
+ [ payload load 2b @ link header + 20 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ counter pkts 0 bytes 0 ]
+
+# ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip ip protocol 6
+bridge
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0000a888 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 18 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000200 ]
+ [ payload load 2b @ link header + 20 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# vlan id 1 vlan id set 2
+bridge
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000200 ]
+ [ payload write reg 1 => 2b @ link header + 14 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# ether saddr 00:01:02:03:04:05 vlan id 1
+bridge test-bridge input
+ [ payload load 8b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x03020100 0x00810504 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# vlan id 2 ether saddr 0:1:2:3:4:6
+bridge test-bridge input
+ [ payload load 8b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x03020100 0x00810604 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000200 ]
+
+# ether saddr . vlan id { 0a:0b:0c:0d:0e:0f . 42, 0a:0b:0c:0d:0e:0f . 4095 }
+__set%d test-bridge 3 size 2
+__set%d test-bridge 0
+ element 0d0c0b0a 00000f0e 00002a00 : 0 [end] element 0d0c0b0a 00000f0e 0000ff0f : 0 [end]
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ payload load 2b @ link header + 14 => reg 10 ]
+ [ bitwise reg 10 = ( reg 10 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ether saddr 00:11:22:33:44:55 counter ether type 8021q
+bridge test-bridge input
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x33221100 0x00005544 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
diff --git a/tests/py/bridge/vlan.t.payload.netdev b/tests/py/bridge/vlan.t.payload.netdev
new file mode 100644
index 0000000..f334194
--- /dev/null
+++ b/tests/py/bridge/vlan.t.payload.netdev
@@ -0,0 +1,368 @@
+# vlan id 4094
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+
+# vlan id 0
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# vlan id 4094 vlan dei 0
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# vlan id 4094 vlan dei != 1
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000010 ]
+
+# vlan id 4094 vlan cfi 1
+netdev
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+
+# vlan id 4094 vlan dei 1
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+
+# ether type vlan vlan id 4094
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+
+# ether type vlan vlan id 0
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ether type vlan vlan id 4094 vlan dei 0
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ether type vlan vlan id 4094 vlan dei 1
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+
+# vlan id 4094 tcp dport 22
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# vlan id 1 ip saddr 10.0.0.1
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0100000a ]
+
+# vlan id 1 ip saddr 10.0.0.0/23
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00feffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000a ]
+
+# vlan id 1 ip saddr 10.0.0.0/23 udp dport 53
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00feffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+
+# ether type vlan vlan id 1 ip saddr 10.0.0.0/23 udp dport 53
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00feffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+
+# vlan id 4094 vlan dei 1 vlan pcp 7
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000e0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x000000e0 ]
+
+# vlan id 4094 vlan dei 1 vlan pcp 3
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000fe0f ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000010 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000e0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000060 ]
+
+# vlan id { 1, 2, 4, 100, 4095 } vlan pcp 1-3
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000100 : 0 [end] element 00000200 : 0 [end] element 00000400 : 0 [end] element 00006400 : 0 [end] element 0000ff0f : 0 [end]
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 1b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000e0 ) ^ 0x00000000 ]
+ [ cmp gte reg 1 0x00000020 ]
+ [ cmp lte reg 1 0x00000060 ]
+
+# ether type vlan ip protocol 1 accept
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 0 accept ]
+
+# ether type 8021ad vlan id 1 ip protocol 6 accept
+netdev
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0000a888 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 0 accept ]
+
+# ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip counter
+netdev
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0000a888 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 18 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000200 ]
+ [ payload load 2b @ link header + 20 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ counter pkts 0 bytes 0 ]
+
+# ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip ip protocol 6
+netdev
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0000a888 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 18 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000200 ]
+ [ payload load 2b @ link header + 20 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# vlan id 1 vlan id set 2
+netdev
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000200 ]
+ [ payload write reg 1 => 2b @ link header + 14 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# vlan id 2 ether saddr 0:1:2:3:4:6
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 8b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x03020100 0x00810604 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000200 ]
+
+# ether saddr 00:01:02:03:04:05 vlan id 1
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 8b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x03020100 0x00810504 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# ether saddr . vlan id { 0a:0b:0c:0d:0e:0f . 42, 0a:0b:0c:0d:0e:0f . 4095 }
+__set%d test-netdev 3 size 2
+__set%d test-netdev 0
+ element 0d0c0b0a 00000f0e 00002a00 : 0 [end] element 0d0c0b0a 00000f0e 0000ff0f : 0 [end]
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ payload load 2b @ link header + 14 => reg 10 ]
+ [ bitwise reg 10 = ( reg 10 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ether saddr 00:11:22:33:44:55 counter ether type 8021q
+bridge test-bridge input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x33221100 0x00005544 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
diff --git a/tests/py/inet/ah.t b/tests/py/inet/ah.t
new file mode 100644
index 0000000..83b6202
--- /dev/null
+++ b/tests/py/inet/ah.t
@@ -0,0 +1,47 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+- ah nexthdr esp;ok
+- ah nexthdr ah;ok
+- ah nexthdr comp;ok
+- ah nexthdr udp;ok
+- ah nexthdr udplite;ok
+- ah nexthdr tcp;ok
+- ah nexthdr dccp;ok
+- ah nexthdr sctp;ok
+
+- ah nexthdr { esp, ah, comp, udp, udplite, tcp, dccp, sctp};ok;ah nexthdr { 6, 132, 50, 17, 136, 33, 51, 108}
+- ah nexthdr != { esp, ah, comp, udp, udplite, tcp, dccp, sctp};ok
+
+ah hdrlength 11-23;ok
+ah hdrlength != 11-23;ok
+ah hdrlength {11, 23, 44 };ok
+ah hdrlength != {11, 23, 44 };ok
+
+ah reserved 22;ok
+ah reserved != 233;ok
+ah reserved 33-45;ok
+ah reserved != 33-45;ok
+ah reserved {23, 100};ok
+ah reserved != {23, 100};ok
+
+ah spi 111;ok
+ah spi != 111;ok
+ah spi 111-222;ok
+ah spi != 111-222;ok
+ah spi {111, 122};ok
+ah spi != {111, 122};ok
+
+# sequence
+ah sequence 123;ok
+ah sequence != 123;ok
+ah sequence {23, 25, 33};ok
+ah sequence != {23, 25, 33};ok
+ah sequence 23-33;ok
+ah sequence != 23-33;ok
diff --git a/tests/py/inet/ah.t.json b/tests/py/inet/ah.t.json
new file mode 100644
index 0000000..217280b
--- /dev/null
+++ b/tests/py/inet/ah.t.json
@@ -0,0 +1,412 @@
+# ah hdrlength 11-23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 11, 23 ]
+ }
+ }
+ }
+]
+
+# ah hdrlength != 11-23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 11, 23 ]
+ }
+ }
+ }
+]
+
+# ah hdrlength {11, 23, 44 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 11,
+ 23,
+ 44
+ ]
+ }
+ }
+ }
+]
+
+# ah hdrlength != {11, 23, 44 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 11,
+ 23,
+ 44
+ ]
+ }
+ }
+ }
+]
+
+# ah reserved 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ah reserved != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ah reserved 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ah reserved != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ah reserved {23, 100}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 23,
+ 100
+ ]
+ }
+ }
+ }
+]
+
+# ah reserved != {23, 100}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "reserved",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 100
+ ]
+ }
+ }
+ }
+]
+
+# ah spi 111
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": 111
+ }
+ }
+]
+
+# ah spi != 111
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": 111
+ }
+ }
+]
+
+# ah spi 111-222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 111, 222 ]
+ }
+ }
+ }
+]
+
+# ah spi != 111-222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 111, 222 ]
+ }
+ }
+ }
+]
+
+# ah spi {111, 122}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 111,
+ 122
+ ]
+ }
+ }
+ }
+]
+
+# ah spi != {111, 122}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 111,
+ 122
+ ]
+ }
+ }
+ }
+]
+
+# ah sequence 123
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": 123
+ }
+ }
+]
+
+# ah sequence != 123
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": 123
+ }
+ }
+]
+
+# ah sequence {23, 25, 33}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 23,
+ 25,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# ah sequence != {23, 25, 33}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 25,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# ah sequence 23-33
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "ah"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 23, 33 ]
+ }
+ }
+ }
+]
+
+# ah sequence != 23-33
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "ah"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 23, 33 ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/ah.t.payload b/tests/py/inet/ah.t.payload
new file mode 100644
index 0000000..7ddd72d
--- /dev/null
+++ b/tests/py/inet/ah.t.payload
@@ -0,0 +1,182 @@
+# ah hdrlength 11-23
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp gte reg 1 0x0000000b ]
+ [ cmp lte reg 1 0x00000017 ]
+
+# ah hdrlength != 11-23
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ range neq reg 1 0x0000000b 0x00000017 ]
+
+# ah hdrlength {11, 23, 44 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 0000000b : 0 [end] element 00000017 : 0 [end] element 0000002c : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ah hdrlength != {11, 23, 44 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 0000000b : 0 [end] element 00000017 : 0 [end] element 0000002c : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ah reserved 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ah reserved != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ah reserved 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ah reserved != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ah reserved {23, 100}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001700 : 0 [end] element 00006400 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ah reserved != {23, 100}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001700 : 0 [end] element 00006400 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ah spi 111
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x6f000000 ]
+
+# ah spi != 111
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x6f000000 ]
+
+# ah spi 111-222
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x6f000000 ]
+ [ cmp lte reg 1 0xde000000 ]
+
+# ah spi != 111-222
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x6f000000 0xde000000 ]
+
+# ah spi {111, 122}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 6f000000 : 0 [end] element 7a000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ah spi != {111, 122}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 6f000000 : 0 [end] element 7a000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ah sequence 123
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x7b000000 ]
+
+# ah sequence != 123
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp neq reg 1 0x7b000000 ]
+
+# ah sequence {23, 25, 33}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 17000000 : 0 [end] element 19000000 : 0 [end] element 21000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ah sequence != {23, 25, 33}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 17000000 : 0 [end] element 19000000 : 0 [end] element 21000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ah sequence 23-33
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp gte reg 1 0x17000000 ]
+ [ cmp lte reg 1 0x21000000 ]
+
+# ah sequence != 23-33
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ range neq reg 1 0x17000000 0x21000000 ]
+
diff --git a/tests/py/inet/comp.t b/tests/py/inet/comp.t
new file mode 100644
index 0000000..2ef5382
--- /dev/null
+++ b/tests/py/inet/comp.t
@@ -0,0 +1,30 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+# BUG: nft: payload.c:88: payload_expr_pctx_update: Assertion `left->payload.base + 1 <= (__PROTO_BASE_MAX - 1)' failed.
+- comp nexthdr esp;ok;comp nexthdr 50
+comp nexthdr != esp;ok;comp nexthdr != 50
+
+- comp nexthdr {esp, ah, comp, udp, udplite, tcp, tcp, dccp, sctp};ok
+# comp flags ## 8-bit field. Reserved for future use. MUST be set to zero.
+
+# Bug comp flags: to list. List the decimal value.
+comp flags 0x0;ok
+comp flags != 0x23;ok
+comp flags 0x33-0x45;ok
+comp flags != 0x33-0x45;ok
+comp flags {0x33, 0x55, 0x67, 0x88};ok
+comp flags != {0x33, 0x55, 0x67, 0x88};ok
+
+comp cpi 22;ok
+comp cpi != 233;ok
+comp cpi 33-45;ok
+comp cpi != 33-45;ok
+comp cpi {33, 55, 67, 88};ok
+comp cpi != {33, 55, 67, 88};ok
diff --git a/tests/py/inet/comp.t.json b/tests/py/inet/comp.t.json
new file mode 100644
index 0000000..c9f6fca
--- /dev/null
+++ b/tests/py/inet/comp.t.json
@@ -0,0 +1,244 @@
+# comp nexthdr != esp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": "esp"
+ }
+ }
+]
+
+# comp flags 0x0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": "0x0"
+ }
+ }
+]
+
+# comp flags != 0x23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": "0x23"
+ }
+ }
+]
+
+# comp flags 0x33-0x45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ "0x33", "0x45" ]
+ }
+ }
+ }
+]
+
+# comp flags != 0x33-0x45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "0x33", "0x45" ]
+ }
+ }
+ }
+]
+
+# comp flags {0x33, 0x55, 0x67, 0x88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "0x33",
+ "0x55",
+ "0x67",
+ "0x88"
+ ]
+ }
+ }
+ }
+]
+
+# comp flags != {0x33, 0x55, 0x67, 0x88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "0x33",
+ "0x55",
+ "0x67",
+ "0x88"
+ ]
+ }
+ }
+ }
+]
+
+# comp cpi 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# comp cpi != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# comp cpi 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# comp cpi != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# comp cpi {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# comp cpi != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "cpi",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/comp.t.json.output b/tests/py/inet/comp.t.json.output
new file mode 100644
index 0000000..435c3de
--- /dev/null
+++ b/tests/py/inet/comp.t.json.output
@@ -0,0 +1,170 @@
+# comp nexthdr != esp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": 50
+ }
+ }
+]
+
+# comp flags 0x0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# comp flags != 0x23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": 35
+ }
+ }
+]
+
+# comp flags 0x33-0x45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 51, 69 ]
+ }
+ }
+ }
+]
+
+# comp flags != 0x33-0x45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 51, 69 ]
+ }
+ }
+ }
+]
+
+# comp flags {0x33, 0x55, 0x67, 0x88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 51,
+ 85,
+ 103,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# comp flags != {0x33, 0x55, 0x67, 0x88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 51,
+ 85,
+ 103,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# comp flags { 0x33-0x55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 51, 85 ] }
+ ]
+ }
+ }
+ }
+]
+
+# comp flags != { 0x33-0x55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "comp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 51, 85 ] }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/comp.t.payload b/tests/py/inet/comp.t.payload
new file mode 100644
index 0000000..024e47c
--- /dev/null
+++ b/tests/py/inet/comp.t.payload
@@ -0,0 +1,105 @@
+# comp nexthdr != esp
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000032 ]
+
+# comp flags 0x0
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# comp flags != 0x23
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp neq reg 1 0x00000023 ]
+
+# comp flags 0x33-0x45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000033 ]
+ [ cmp lte reg 1 0x00000045 ]
+
+# comp flags != 0x33-0x45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ range neq reg 1 0x00000033 0x00000045 ]
+
+# comp flags {0x33, 0x55, 0x67, 0x88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000033 : 0 [end] element 00000055 : 0 [end] element 00000067 : 0 [end] element 00000088 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# comp flags != {0x33, 0x55, 0x67, 0x88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000033 : 0 [end] element 00000055 : 0 [end] element 00000067 : 0 [end] element 00000088 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# comp cpi 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# comp cpi != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# comp cpi 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# comp cpi != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# comp cpi {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# comp cpi != {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000006c ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
diff --git a/tests/py/inet/ct.t b/tests/py/inet/ct.t
new file mode 100644
index 0000000..5312b32
--- /dev/null
+++ b/tests/py/inet/ct.t
@@ -0,0 +1,15 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+
+*inet;test-inet;input
+
+meta nfproto ipv4 ct original saddr 1.2.3.4;ok;ct original ip saddr 1.2.3.4
+ct original ip6 saddr ::1;ok
+
+ct original ip daddr 1.2.3.4 accept;ok
+
+# missing protocol context
+ct original saddr ::1;fail
+
+# wrong protocol context
+ct original ip saddr ::1;fail
diff --git a/tests/py/inet/ct.t.json b/tests/py/inet/ct.t.json
new file mode 100644
index 0000000..223ac9e
--- /dev/null
+++ b/tests/py/inet/ct.t.json
@@ -0,0 +1,60 @@
+# meta nfproto ipv4 ct original saddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "saddr"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# ct original ip6 saddr ::1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "ip6 saddr"
+ }
+ },
+ "op": "==",
+ "right": "::1"
+ }
+ }
+]
+
+# ct original ip daddr 1.2.3.4 accept
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "ip daddr"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/inet/ct.t.json.output b/tests/py/inet/ct.t.json.output
new file mode 100644
index 0000000..74c436a
--- /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",
+ "key": "saddr"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ }
+]
+
diff --git a/tests/py/inet/ct.t.payload b/tests/py/inet/ct.t.payload
new file mode 100644
index 0000000..f7a2ef2
--- /dev/null
+++ b/tests/py/inet/ct.t.payload
@@ -0,0 +1,17 @@
+# meta nfproto ipv4 ct original saddr 1.2.3.4
+ip test-ip4 output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ ct load src => reg 1 , dir original ]
+ [ cmp eq reg 1 0x04030201 ]
+
+# ct original ip6 saddr ::1
+inet test-inet input
+ [ ct load src_ip6 => reg 1 , dir original ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x01000000 ]
+
+# ct original ip daddr 1.2.3.4 accept
+inet test-inet input
+ [ ct load dst_ip => reg 1 , dir original ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ immediate reg 0 accept ]
diff --git a/tests/py/inet/dccp.t b/tests/py/inet/dccp.t
new file mode 100644
index 0000000..99cddbe
--- /dev/null
+++ b/tests/py/inet/dccp.t
@@ -0,0 +1,30 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+dccp sport 21-35;ok
+dccp sport != 21-35;ok
+dccp sport {23, 24, 25};ok
+dccp sport != {23, 24, 25};ok
+
+dccp sport 20-50;ok
+
+# dccp dport 21-35;ok
+# dccp dport != 21-35;ok
+dccp dport {23, 24, 25};ok
+dccp dport != {23, 24, 25};ok
+
+dccp type {request, response, data, ack, dataack, closereq, close, reset, sync, syncack};ok
+dccp type != {request, response, data, ack, dataack, closereq, close, reset, sync, syncack};ok
+dccp type request;ok
+dccp type != request;ok
+
+dccp option 0 exists;ok
+dccp option 43 missing;ok
+dccp option 255 exists;ok
+dccp option 256 exists;fail
diff --git a/tests/py/inet/dccp.t.json b/tests/py/inet/dccp.t.json
new file mode 100644
index 0000000..9f47e97
--- /dev/null
+++ b/tests/py/inet/dccp.t.json
@@ -0,0 +1,276 @@
+# dccp sport 21-35
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "dccp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 21, 35 ]
+ }
+ }
+ }
+]
+
+# dccp sport != 21-35
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 21, 35 ]
+ }
+ }
+ }
+]
+
+# dccp sport {23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "dccp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# dccp sport != {23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# dccp sport 20-50
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "dccp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 20, 50 ]
+ }
+ }
+ }
+]
+
+# dccp dport {23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "dccp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# dccp dport != {23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# dccp type {request, response, data, ack, dataack, closereq, close, reset, sync, syncack}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "dccp"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "request",
+ "response",
+ "data",
+ "ack",
+ "dataack",
+ "closereq",
+ "close",
+ "reset",
+ "sync",
+ "syncack"
+ ]
+ }
+ }
+ }
+]
+
+# dccp type request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "dccp"
+ }
+ },
+ "op": "==",
+ "right": "request"
+ }
+ }
+]
+
+# dccp type != request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "dccp"
+ }
+ },
+ "op": "!=",
+ "right": "request"
+ }
+ }
+]
+
+# dccp option 0 exists
+[
+ {
+ "match": {
+ "left": {
+ "dccp option": {
+ "type": 0
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# dccp option 43 missing
+[
+ {
+ "match": {
+ "left": {
+ "dccp option": {
+ "type": 43
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
+# dccp option 255 exists
+[
+ {
+ "match": {
+ "left": {
+ "dccp option": {
+ "type": 255
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
diff --git a/tests/py/inet/dccp.t.json.output b/tests/py/inet/dccp.t.json.output
new file mode 100644
index 0000000..146741d
--- /dev/null
+++ b/tests/py/inet/dccp.t.json.output
@@ -0,0 +1,18 @@
+# dccp sport ftp-data - re-mail-ck
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "dccp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 20, 50 ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/dccp.t.payload b/tests/py/inet/dccp.t.payload
new file mode 100644
index 0000000..c0b87be
--- /dev/null
+++ b/tests/py/inet/dccp.t.payload
@@ -0,0 +1,115 @@
+# dccp sport 21-35
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00001500 ]
+ [ cmp lte reg 1 0x00002300 ]
+
+# dccp sport != 21-35
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ range neq reg 1 0x00001500 0x00002300 ]
+
+# dccp sport {23, 24, 25}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001700 : 0 [end] element 00001800 : 0 [end] element 00001900 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# dccp sport != {23, 24, 25}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001700 : 0 [end] element 00001800 : 0 [end] element 00001900 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# dccp sport 20-50
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00001400 ]
+ [ cmp lte reg 1 0x00003200 ]
+
+# dccp dport {23, 24, 25}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00001700 : 0 [end] element 00001800 : 0 [end] element 00001900 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# dccp dport != {23, 24, 25}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00001700 : 0 [end] element 00001800 : 0 [end] element 00001900 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# dccp type {request, response, data, ack, dataack, closereq, close, reset, sync, syncack}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000000 : 0 [end] element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000006 : 0 [end] element 00000008 : 0 [end] element 0000000a : 0 [end] element 0000000c : 0 [end] element 0000000e : 0 [end] element 00000010 : 0 [end] element 00000012 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 1b @ transport header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000001e ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# dccp type != {request, response, data, ack, dataack, closereq, close, reset, sync, syncack}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000000 : 0 [end] element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000006 : 0 [end] element 00000008 : 0 [end] element 0000000a : 0 [end] element 0000000c : 0 [end] element 0000000e : 0 [end] element 00000010 : 0 [end] element 00000012 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 1b @ transport header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000001e ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# dccp type request
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 1b @ transport header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000001e ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# dccp type != request
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000021 ]
+ [ payload load 1b @ transport header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000001e ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# dccp option 0 exists
+ip test-inet input
+ [ exthdr load 1b @ 0 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# dccp option 43 missing
+ip test-inet input
+ [ exthdr load 1b @ 43 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# dccp option 255 exists
+ip test-inet input
+ [ exthdr load 1b @ 255 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
diff --git a/tests/py/inet/dnat.t b/tests/py/inet/dnat.t
new file mode 100644
index 0000000..e4e169f
--- /dev/null
+++ b/tests/py/inet/dnat.t
@@ -0,0 +1,22 @@
+:prerouting;type nat hook prerouting priority 0
+
+*inet;test-inet;prerouting
+
+iifname "foo" tcp dport 80 redirect to :8080;ok
+
+iifname "eth0" tcp dport 443 dnat ip to 192.168.3.2;ok
+iifname "eth0" tcp dport 443 dnat ip6 to [dead::beef]:4443;ok
+meta l4proto tcp dnat to :80;ok;meta l4proto 6 dnat to :80
+
+dnat ip to ct mark map { 0x00000014 : 1.2.3.4};ok
+dnat ip to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4};ok
+
+dnat ip6 to 1.2.3.4;fail
+dnat to 1.2.3.4;fail
+dnat ip6 to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4};fail
+ip6 daddr dead::beef dnat to 10.1.2.3;fail
+
+meta l4proto { tcp, udp } dnat ip to 1.1.1.1:80;ok;meta l4proto { 6, 17} dnat ip to 1.1.1.1:80
+ip protocol { tcp, udp } dnat ip to 1.1.1.1:80;ok;ip protocol { 6, 17} dnat ip to 1.1.1.1:80
+meta l4proto { tcp, udp } tcp dport 20 dnat to 1.1.1.1:80;fail
+ip protocol { tcp, udp } tcp dport 20 dnat to 1.1.1.1:80;fail
diff --git a/tests/py/inet/dnat.t.json b/tests/py/inet/dnat.t.json
new file mode 100644
index 0000000..c341a04
--- /dev/null
+++ b/tests/py/inet/dnat.t.json
@@ -0,0 +1,241 @@
+# iifname "foo" tcp dport 80 redirect to :8080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "foo"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 80
+ }
+ },
+ {
+ "redirect": {
+ "port": 8080
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 443 dnat ip to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 443
+ }
+ },
+ {
+ "dnat": {
+ "addr": "192.168.3.2",
+ "family": "ip"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 443 dnat ip6 to [dead::beef]:4443
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 443
+ }
+ },
+ {
+ "dnat": {
+ "addr": "dead::beef",
+ "family": "ip6",
+ "port": 4443
+ }
+ }
+]
+
+# dnat ip to ct mark map { 0x00000014 : 1.2.3.4}
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ 20,
+ "1.2.3.4"
+ ]
+ ]
+ },
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# dnat ip to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4}
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ 20,
+ "1.1.1.1"
+ ]
+ },
+ "1.2.3.4"
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# meta l4proto { tcp, udp } dnat ip to 1.1.1.1:80
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 6,
+ 17
+ ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": "1.1.1.1",
+ "family": "ip",
+ "port": 80
+ }
+ }
+]
+
+# ip protocol { tcp, udp } dnat ip to 1.1.1.1:80
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 6,
+ 17
+ ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": "1.1.1.1",
+ "family": "ip",
+ "port": 80
+ }
+ }
+]
+
+# meta l4proto tcp dnat to :80
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "dnat": {
+ "port": 80
+ }
+ }
+]
+
diff --git a/tests/py/inet/dnat.t.payload b/tests/py/inet/dnat.t.payload
new file mode 100644
index 0000000..ce1601a
--- /dev/null
+++ b/tests/py/inet/dnat.t.payload
@@ -0,0 +1,86 @@
+# iifname "foo" tcp dport 80 redirect to :8080
+inet test-inet prerouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x006f6f66 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005000 ]
+ [ immediate reg 1 0x0000901f ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
+# iifname "eth0" tcp dport 443 dnat ip to 192.168.3.2
+inet test-inet prerouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000bb01 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport 443 dnat ip6 to [dead::beef]:4443
+inet test-inet prerouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000bb01 ]
+ [ immediate reg 1 0x0000adde 0x00000000 0x00000000 0xefbe0000 ]
+ [ immediate reg 2 0x00005b11 ]
+ [ nat dnat ip6 addr_min reg 1 proto_min reg 2 flags 0x2 ]
+
+# dnat ip to ct mark map { 0x00000014 : 1.2.3.4}
+__map%d test-inet b size 1
+__map%d test-inet 0
+ element 00000014 : 04030201 0 [end]
+inet test-inet prerouting
+ [ ct load mark => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# dnat ip to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4}
+__map%d test-inet b size 1
+__map%d test-inet 0
+ element 00000014 01010101 : 04030201 0 [end]
+inet test-inet prerouting
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ ct load mark => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# meta l4proto { tcp, udp } dnat ip to 1.1.1.1:80
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000006 : 0 [end] element 00000011 : 0 [end]
+inet
+ [ meta load l4proto => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 1 0x01010101 ]
+ [ immediate reg 2 0x00005000 ]
+ [ nat dnat ip addr_min reg 1 proto_min reg 2 flags 0x2 ]
+
+# ip protocol { tcp, udp } dnat ip to 1.1.1.1:80
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000006 : 0 [end] element 00000011 : 0 [end]
+inet
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 1 0x01010101 ]
+ [ immediate reg 2 0x00005000 ]
+ [ nat dnat ip addr_min reg 1 proto_min reg 2 flags 0x2 ]
+
+# meta l4proto tcp dnat to :80
+inet
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x00005000 ]
+ [ nat dnat inet proto_min reg 1 flags 0x2 ]
+
diff --git a/tests/py/inet/esp.t b/tests/py/inet/esp.t
new file mode 100644
index 0000000..536260c
--- /dev/null
+++ b/tests/py/inet/esp.t
@@ -0,0 +1,21 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+esp spi 100;ok
+esp spi != 100;ok
+esp spi 111-222;ok
+esp spi != 111-222;ok
+esp spi { 100, 102};ok
+esp spi != { 100, 102};ok
+
+esp sequence 22;ok
+esp sequence 22-24;ok
+esp sequence != 22-24;ok
+esp sequence { 22, 24};ok
+esp sequence != { 22, 24};ok
diff --git a/tests/py/inet/esp.t.json b/tests/py/inet/esp.t.json
new file mode 100644
index 0000000..a9dedd6
--- /dev/null
+++ b/tests/py/inet/esp.t.json
@@ -0,0 +1,204 @@
+# esp spi 100
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "esp"
+ }
+ },
+ "op": "==",
+ "right": 100
+ }
+ }
+]
+
+# esp spi != 100
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "esp"
+ }
+ },
+ "op": "!=",
+ "right": 100
+ }
+ }
+]
+
+# esp spi 111-222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "esp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 111, 222 ]
+ }
+ }
+ }
+]
+
+# esp spi != 111-222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 111, 222 ]
+ }
+ }
+ }
+]
+
+# esp spi { 100, 102}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "esp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 100,
+ 102
+ ]
+ }
+ }
+ }
+]
+
+# esp spi != { 100, 102}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 100,
+ 102
+ ]
+ }
+ }
+ }
+]
+
+# esp sequence 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "esp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# esp sequence 22-24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "esp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 22, 24 ]
+ }
+ }
+ }
+]
+
+# esp sequence != 22-24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 22, 24 ]
+ }
+ }
+ }
+]
+
+# esp sequence { 22, 24}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "esp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 22,
+ 24
+ ]
+ }
+ }
+ }
+]
+
+# esp sequence != { 22, 24}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 22,
+ 24
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/esp.t.payload b/tests/py/inet/esp.t.payload
new file mode 100644
index 0000000..0353b05
--- /dev/null
+++ b/tests/py/inet/esp.t.payload
@@ -0,0 +1,91 @@
+# esp spi 100
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x64000000 ]
+
+# esp spi != 100
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x64000000 ]
+
+# esp spi 111-222
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 0 => reg 1 ]
+ [ cmp gte reg 1 0x6f000000 ]
+ [ cmp lte reg 1 0xde000000 ]
+
+# esp spi != 111-222
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 0 => reg 1 ]
+ [ range neq reg 1 0x6f000000 0xde000000 ]
+
+# esp spi { 100, 102}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 64000000 : 0 [end] element 66000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# esp spi != { 100, 102}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 64000000 : 0 [end] element 66000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# esp sequence 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# esp sequence 22-24
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x16000000 ]
+ [ cmp lte reg 1 0x18000000 ]
+
+# esp sequence != 22-24
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x16000000 0x18000000 ]
+
+# esp sequence { 22, 24}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 16000000 : 0 [end] element 18000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# esp sequence != { 22, 24}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 16000000 : 0 [end] element 18000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
diff --git a/tests/py/inet/ether-ip.t b/tests/py/inet/ether-ip.t
new file mode 100644
index 0000000..759124d
--- /dev/null
+++ b/tests/py/inet/ether-ip.t
@@ -0,0 +1,9 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept;ok;tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4 accept
+tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04;ok
diff --git a/tests/py/inet/ether-ip.t.json b/tests/py/inet/ether-ip.t.json
new file mode 100644
index 0000000..8f35b3d
--- /dev/null
+++ b/tests/py/inet/ether-ip.t.json
@@ -0,0 +1,92 @@
+# 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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "==",
+ "right": "ether"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "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 0000000..f659113
--- /dev/null
+++ b/tests/py/inet/ether-ip.t.json.output
@@ -0,0 +1,43 @@
+# 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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/inet/ether-ip.t.payload b/tests/py/inet/ether-ip.t.payload
new file mode 100644
index 0000000..62e37a5
--- /dev/null
+++ b/tests/py/inet/ether-ip.t.payload
@@ -0,0 +1,28 @@
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 8b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00080411 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ immediate reg 0 accept ]
+
+# tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
diff --git a/tests/py/inet/ether-ip.t.payload.netdev b/tests/py/inet/ether-ip.t.payload.netdev
new file mode 100644
index 0000000..b0fa6d8
--- /dev/null
+++ b/tests/py/inet/ether-ip.t.payload.netdev
@@ -0,0 +1,29 @@
+# tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 8b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00080411 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ immediate reg 0 accept ]
+
diff --git a/tests/py/inet/ether.t b/tests/py/inet/ether.t
new file mode 100644
index 0000000..8625f70
--- /dev/null
+++ b/tests/py/inet/ether.t
@@ -0,0 +1,20 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*bridge;test-bridge;input
+*netdev;test-netdev;ingress,egress
+
+tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept;ok;tcp dport 22 ether saddr 00:0f:54:0c:11:04 accept
+tcp dport 22 ether saddr 00:0f:54:0c:11:04 accept;ok
+
+ether saddr 00:0f:54:0c:11:04 accept;ok
+
+vlan id 1;ok
+ether type vlan vlan id 2;ok;vlan id 2
+
+# invalid dependency
+ether type ip vlan id 1;fail
diff --git a/tests/py/inet/ether.t.json b/tests/py/inet/ether.t.json
new file mode 100644
index 0000000..c7a7f88
--- /dev/null
+++ b/tests/py/inet/ether.t.json
@@ -0,0 +1,122 @@
+# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "==",
+ "right": "ether"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ether saddr 00:0f:54:0c:11:04 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# vlan id 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# ether type vlan vlan id 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
diff --git a/tests/py/inet/ether.t.json.output b/tests/py/inet/ether.t.json.output
new file mode 100644
index 0000000..9ae8c44
--- /dev/null
+++ b/tests/py/inet/ether.t.json.output
@@ -0,0 +1,31 @@
+# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/inet/ether.t.payload b/tests/py/inet/ether.t.payload
new file mode 100644
index 0000000..8b74a78
--- /dev/null
+++ b/tests/py/inet/ether.t.payload
@@ -0,0 +1,52 @@
+# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# ether saddr 00:0f:54:0c:11:04 accept
+inet test-inet input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# vlan id 1
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# ether type vlan vlan id 2
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000200 ]
+
diff --git a/tests/py/inet/ether.t.payload.bridge b/tests/py/inet/ether.t.payload.bridge
new file mode 100644
index 0000000..0128d5f
--- /dev/null
+++ b/tests/py/inet/ether.t.payload.bridge
@@ -0,0 +1,44 @@
+# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept
+bridge test-bridge input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 accept
+bridge test-bridge input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# ether saddr 00:0f:54:0c:11:04 accept
+bridge test-bridge input
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# vlan id 1
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# ether type vlan vlan id 2
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000200 ]
+
diff --git a/tests/py/inet/ether.t.payload.ip b/tests/py/inet/ether.t.payload.ip
new file mode 100644
index 0000000..7c91f41
--- /dev/null
+++ b/tests/py/inet/ether.t.payload.ip
@@ -0,0 +1,52 @@
+# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# ether saddr 00:0f:54:0c:11:04 accept
+ip test-ip4 input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# vlan id 1
+ip test-ip4 input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# ether type vlan vlan id 2
+ip test-ip4 input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ link header + 14 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000200 ]
+
diff --git a/tests/py/inet/fib.t b/tests/py/inet/fib.t
new file mode 100644
index 0000000..dbe45d9
--- /dev/null
+++ b/tests/py/inet/fib.t
@@ -0,0 +1,17 @@
+:prerouting;type filter hook prerouting priority 0
+
+*ip;test-ip;prerouting
+*ip6;test-ip6;prerouting
+
+fib saddr . daddr oif lo;fail
+fib iif . oif . daddr oif lo;fail
+fib mark oif lo;fail
+fib saddr . iif oif ne 0;ok;fib saddr . iif oif != 0
+fib saddr . iif oifname "lo";ok
+
+fib daddr . iif type local;ok
+fib daddr . iif type vmap { blackhole : drop, prohibit : drop, unicast : accept };ok
+fib daddr . oif type local;fail
+
+fib daddr oif exists;ok
+fib daddr oif missing;ok
diff --git a/tests/py/inet/fib.t.json b/tests/py/inet/fib.t.json
new file mode 100644
index 0000000..c298915
--- /dev/null
+++ b/tests/py/inet/fib.t.json
@@ -0,0 +1,132 @@
+# 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"
+ }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ }
+]
+
+# fib daddr . iif type local
+[
+ {
+ "match": {
+ "left": {
+ "fib": {
+ "flags": [
+ "daddr",
+ "iif"
+ ],
+ "result": "type"
+ }
+ },
+ "op": "==",
+ "right": "local"
+ }
+ }
+]
+
+# fib daddr . iif type vmap { blackhole : drop, prohibit : drop, unicast : accept }
+[
+ {
+ "vmap": {
+ "key": {
+ "fib": {
+ "flags": [
+ "daddr",
+ "iif"
+ ],
+ "result": "type"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "blackhole",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "prohibit",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "unicast",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# fib daddr oif exists
+[
+ {
+ "match": {
+ "left": {
+ "fib": {
+ "flags": [
+ "daddr"
+ ],
+ "result": "oif"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# fib daddr oif missing
+[
+ {
+ "match": {
+ "left": {
+ "fib": {
+ "flags": [
+ "daddr"
+ ],
+ "result": "oif"
+ }
+ },
+ "op": "==",
+ "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 0000000..52cd46b
--- /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 }
+[
+ {
+ "vmap": {
+ "key": {
+ "fib": {
+ "flags": [
+ "daddr",
+ "iif"
+ ],
+ "result": "type"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "unicast",
+ {
+ "accept": null
+ }
+ ],
+ [
+ "blackhole",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "prohibit",
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/fib.t.payload b/tests/py/inet/fib.t.payload
new file mode 100644
index 0000000..050857d
--- /dev/null
+++ b/tests/py/inet/fib.t.payload
@@ -0,0 +1,32 @@
+# fib saddr . iif oif ne 0
+ip test-ip prerouting
+ [ fib saddr . iif oif => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# fib saddr . iif oifname "lo"
+ip test-ip prerouting
+ [ fib saddr . iif oifname => reg 1 ]
+ [ cmp eq reg 1 0x00006f6c 0x00000000 0x00000000 0x00000000 ]
+
+# fib daddr . iif type local
+ip test-ip prerouting
+ [ fib daddr . iif type => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# fib daddr . iif type vmap { blackhole : drop, prohibit : drop, unicast : accept }
+__map%d test-ip b
+__map%d test-ip 0
+ element 00000006 : drop 0 [end] element 00000008 : drop 0 [end] element 00000001 : accept 0 [end]
+ip test-ip prerouting
+ [ fib daddr . iif type => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# fib daddr oif exists
+ip test-ip prerouting
+ [ fib daddr oif present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# fib daddr oif missing
+ip test-ip prerouting
+ [ fib daddr oif present => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
diff --git a/tests/py/inet/geneve.t b/tests/py/inet/geneve.t
new file mode 100644
index 0000000..101f6df
--- /dev/null
+++ b/tests/py/inet/geneve.t
@@ -0,0 +1,23 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+geneve vni 10;fail
+udp dport 6081 geneve vni 10;ok
+udp dport 6081 geneve ip saddr 10.141.11.2;ok
+udp dport 6081 geneve ip saddr 10.141.11.0/24;ok
+udp dport 6081 geneve ip protocol 1;ok
+udp dport 6081 geneve udp sport 8888;ok
+udp dport 6081 geneve icmp type echo-reply;ok
+udp dport 6081 geneve ether saddr 62:87:4d:d6:19:05;ok
+udp dport 6081 geneve vlan id 10;ok
+udp dport 6081 geneve ip dscp 0x02;ok
+udp dport 6081 geneve ip dscp 0x02;ok
+udp dport 6081 geneve ip saddr . geneve ip daddr { 1.2.3.4 . 4.3.2.1 };ok
+
+udp dport 6081 geneve ip saddr set 1.2.3.4;fail
diff --git a/tests/py/inet/geneve.t.json b/tests/py/inet/geneve.t.json
new file mode 100644
index 0000000..a299fcd
--- /dev/null
+++ b/tests/py/inet/geneve.t.json
@@ -0,0 +1,344 @@
+# udp dport 6081 geneve vni 10
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vni",
+ "protocol": "geneve",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": 10
+ }
+ }
+]
+
+# udp dport 6081 geneve ip saddr 10.141.11.2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": "10.141.11.2"
+ }
+ }
+]
+
+# udp dport 6081 geneve ip saddr 10.141.11.0/24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "10.141.11.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# udp dport 6081 geneve ip protocol 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# udp dport 6081 geneve udp sport 8888
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": 8888
+ }
+ }
+]
+
+# udp dport 6081 geneve icmp type echo-reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": "echo-reply"
+ }
+ }
+]
+
+# udp dport 6081 geneve ether saddr 62:87:4d:d6:19:05
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": "62:87:4d:d6:19:05"
+ }
+ }
+]
+
+# udp dport 6081 geneve vlan id 10
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": 10
+ }
+ }
+]
+
+# udp dport 6081 geneve ip dscp 0x02
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# udp dport 6081 geneve ip dscp 0x02
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip",
+ "tunnel": "geneve"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# udp dport 6081 geneve ip saddr . geneve ip daddr { 1.2.3.4 . 4.3.2.1 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6081
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "geneve"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip",
+ "tunnel": "geneve"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.2.3.4",
+ "4.3.2.1"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/geneve.t.payload b/tests/py/inet/geneve.t.payload
new file mode 100644
index 0000000..1ce54de
--- /dev/null
+++ b/tests/py/inet/geneve.t.payload
@@ -0,0 +1,114 @@
+# udp dport 6081 geneve vni 10
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 3b @ unknown header + 4 => reg 1 ] ]
+ [ cmp eq reg 1 0x000a0000 ]
+
+# udp dport 6081 geneve ip saddr 10.141.11.2
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 4b @ network header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x020b8d0a ]
+
+# udp dport 6081 geneve ip saddr 10.141.11.0/24
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 3b @ network header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x000b8d0a ]
+
+# udp dport 6081 geneve ip protocol 1
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 1b @ network header + 9 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# udp dport 6081 geneve udp sport 8888
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ meta load l4proto => reg 1 ] ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 2b @ transport header + 0 => reg 1 ] ]
+ [ cmp eq reg 1 0x0000b822 ]
+
+# udp dport 6081 geneve icmp type echo-reply
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 2b @ link header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 2 hdrsize 8 flags f [ meta load l4proto => reg 1 ] ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 1b @ transport header + 0 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# udp dport 6081 geneve ether saddr 62:87:4d:d6:19:05
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 6b @ link header + 6 => reg 1 ] ]
+ [ cmp eq reg 1 0xd64d8762 0x00000519 ]
+
+# udp dport 6081 geneve vlan id 10
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 2b @ link header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 2b @ link header + 14 => reg 1 ] ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000a00 ]
+
+# udp dport 6081 geneve ip dscp 0x02
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 1b @ network header + 1 => reg 1 ] ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# udp dport 6081 geneve ip saddr . geneve ip daddr { 1.2.3.4 . 4.3.2.1 }
+__set%d test-ip4 3 size 1
+__set%d test-ip4 0
+ element 04030201 01020304 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000c117 ]
+ [ inner type 2 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 4b @ network header + 12 => reg 1 ] ]
+ [ inner type 2 hdrsize 8 flags f [ payload load 4b @ network header + 16 => reg 9 ] ]
+ [ lookup reg 1 set __set%d ]
+
diff --git a/tests/py/inet/gre.t b/tests/py/inet/gre.t
new file mode 100644
index 0000000..a3e046a
--- /dev/null
+++ b/tests/py/inet/gre.t
@@ -0,0 +1,22 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+gre version 0;ok
+gre ip saddr 10.141.11.2;ok
+gre ip saddr 10.141.11.0/24;ok
+gre ip protocol 1;ok
+gre udp sport 8888;ok
+gre icmp type echo-reply;ok
+gre ether saddr 62:87:4d:d6:19:05;fail
+gre vlan id 10;fail
+gre ip dscp 0x02;ok
+gre ip dscp 0x02;ok
+gre ip saddr . gre ip daddr { 1.2.3.4 . 4.3.2.1 };ok
+
+gre ip saddr set 1.2.3.4;fail
diff --git a/tests/py/inet/gre.t.json b/tests/py/inet/gre.t.json
new file mode 100644
index 0000000..c443176
--- /dev/null
+++ b/tests/py/inet/gre.t.json
@@ -0,0 +1,177 @@
+# gre version 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "version",
+ "protocol": "gre"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# gre ip saddr 10.141.11.2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "gre"
+ }
+ },
+ "op": "==",
+ "right": "10.141.11.2"
+ }
+ }
+]
+
+# gre ip saddr 10.141.11.0/24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "gre"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "10.141.11.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# gre ip protocol 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip",
+ "tunnel": "gre"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# gre udp sport 8888
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp",
+ "tunnel": "gre"
+ }
+ },
+ "op": "==",
+ "right": 8888
+ }
+ }
+]
+
+# gre icmp type echo-reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp",
+ "tunnel": "gre"
+ }
+ },
+ "op": "==",
+ "right": "echo-reply"
+ }
+ }
+]
+
+# gre ip dscp 0x02
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip",
+ "tunnel": "gre"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# gre ip dscp 0x02
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip",
+ "tunnel": "gre"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# gre ip saddr . gre ip daddr { 1.2.3.4 . 4.3.2.1 }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "gre"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip",
+ "tunnel": "gre"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.2.3.4",
+ "4.3.2.1"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/gre.t.payload b/tests/py/inet/gre.t.payload
new file mode 100644
index 0000000..333133e
--- /dev/null
+++ b/tests/py/inet/gre.t.payload
@@ -0,0 +1,78 @@
+# gre version 0
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000007 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# gre ip saddr 10.141.11.2
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 3 hdrsize 4 flags c [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 3 hdrsize 4 flags c [ payload load 4b @ network header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x020b8d0a ]
+
+# gre ip saddr 10.141.11.0/24
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 3 hdrsize 4 flags c [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 3 hdrsize 4 flags c [ payload load 3b @ network header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x000b8d0a ]
+
+# gre ip protocol 1
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 3 hdrsize 4 flags c [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 3 hdrsize 4 flags c [ payload load 1b @ network header + 9 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# gre udp sport 8888
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 3 hdrsize 4 flags c [ meta load l4proto => reg 1 ] ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ inner type 3 hdrsize 4 flags c [ payload load 2b @ transport header + 0 => reg 1 ] ]
+ [ cmp eq reg 1 0x0000b822 ]
+
+# gre icmp type echo-reply
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 3 hdrsize 4 flags c [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 3 hdrsize 4 flags c [ meta load l4proto => reg 1 ] ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ inner type 3 hdrsize 4 flags c [ payload load 1b @ transport header + 0 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# gre ip dscp 0x02
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 3 hdrsize 4 flags c [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 3 hdrsize 4 flags c [ payload load 1b @ network header + 1 => reg 1 ] ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# gre ip saddr . gre ip daddr { 1.2.3.4 . 4.3.2.1 }
+__set%d test-ip4 3 size 1
+__set%d test-ip4 0
+ element 04030201 01020304 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 3 hdrsize 4 flags c [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 3 hdrsize 4 flags c [ payload load 4b @ network header + 12 => reg 1 ] ]
+ [ inner type 3 hdrsize 4 flags c [ payload load 4b @ network header + 16 => reg 9 ] ]
+ [ lookup reg 1 set __set%d ]
+
diff --git a/tests/py/inet/gretap.t b/tests/py/inet/gretap.t
new file mode 100644
index 0000000..cd7ee21
--- /dev/null
+++ b/tests/py/inet/gretap.t
@@ -0,0 +1,21 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+gretap ip saddr 10.141.11.2;ok
+gretap ip saddr 10.141.11.0/24;ok
+gretap ip protocol 1;ok
+gretap udp sport 8888;ok
+gretap icmp type echo-reply;ok
+gretap ether saddr 62:87:4d:d6:19:05;ok
+gretap vlan id 10;ok
+gretap ip dscp 0x02;ok
+gretap ip dscp 0x02;ok
+gretap ip saddr . gretap ip daddr { 1.2.3.4 . 4.3.2.1 };ok
+
+gretap ip saddr set 1.2.3.4;fail
diff --git a/tests/py/inet/gretap.t.json b/tests/py/inet/gretap.t.json
new file mode 100644
index 0000000..36fa978
--- /dev/null
+++ b/tests/py/inet/gretap.t.json
@@ -0,0 +1,195 @@
+# gretap ip saddr 10.141.11.2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "gretap"
+ }
+ },
+ "op": "==",
+ "right": "10.141.11.2"
+ }
+ }
+]
+
+# gretap ip saddr 10.141.11.0/24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "gretap"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "10.141.11.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# gretap ip protocol 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip",
+ "tunnel": "gretap"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# gretap udp sport 8888
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp",
+ "tunnel": "gretap"
+ }
+ },
+ "op": "==",
+ "right": 8888
+ }
+ }
+]
+
+# gretap icmp type echo-reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp",
+ "tunnel": "gretap"
+ }
+ },
+ "op": "==",
+ "right": "echo-reply"
+ }
+ }
+]
+
+# gretap ether saddr 62:87:4d:d6:19:05
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether",
+ "tunnel": "gretap"
+ }
+ },
+ "op": "==",
+ "right": "62:87:4d:d6:19:05"
+ }
+ }
+]
+
+# gretap vlan id 10
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan",
+ "tunnel": "gretap"
+ }
+ },
+ "op": "==",
+ "right": 10
+ }
+ }
+]
+
+# gretap ip dscp 0x02
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip",
+ "tunnel": "gretap"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# gretap ip dscp 0x02
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip",
+ "tunnel": "gretap"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# gretap ip saddr . gretap ip daddr { 1.2.3.4 . 4.3.2.1 }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "gretap"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip",
+ "tunnel": "gretap"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.2.3.4",
+ "4.3.2.1"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/gretap.t.payload b/tests/py/inet/gretap.t.payload
new file mode 100644
index 0000000..654c71e
--- /dev/null
+++ b/tests/py/inet/gretap.t.payload
@@ -0,0 +1,87 @@
+# gretap ip saddr 10.141.11.2
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 4 hdrsize 4 flags e [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 4b @ network header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x020b8d0a ]
+
+# gretap ip saddr 10.141.11.0/24
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 4 hdrsize 4 flags e [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 3b @ network header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x000b8d0a ]
+
+# gretap ip protocol 1
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 4 hdrsize 4 flags e [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 1b @ network header + 9 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# gretap udp sport 8888
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 4 hdrsize 4 flags e [ meta load l4proto => reg 1 ] ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 2b @ transport header + 0 => reg 1 ] ]
+ [ cmp eq reg 1 0x0000b822 ]
+
+# gretap icmp type echo-reply
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 2b @ link header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 4 hdrsize 4 flags e [ meta load l4proto => reg 1 ] ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 1b @ transport header + 0 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# gretap ether saddr 62:87:4d:d6:19:05
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 6b @ link header + 6 => reg 1 ] ]
+ [ cmp eq reg 1 0xd64d8762 0x00000519 ]
+
+# gretap vlan id 10
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 2b @ link header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 2b @ link header + 14 => reg 1 ] ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000a00 ]
+
+# gretap ip dscp 0x02
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 4 hdrsize 4 flags e [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 1b @ network header + 1 => reg 1 ] ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# gretap ip saddr . gretap ip daddr { 1.2.3.4 . 4.3.2.1 }
+__set%d test-ip4 3 size 1
+__set%d test-ip4 0
+ element 04030201 01020304 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000002f ]
+ [ inner type 4 hdrsize 4 flags e [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 4b @ network header + 12 => reg 1 ] ]
+ [ inner type 4 hdrsize 4 flags e [ payload load 4b @ network header + 16 => reg 9 ] ]
+ [ lookup reg 1 set __set%d ]
+
diff --git a/tests/py/inet/icmp.t b/tests/py/inet/icmp.t
new file mode 100644
index 0000000..9014f84
--- /dev/null
+++ b/tests/py/inet/icmp.t
@@ -0,0 +1,18 @@
+:output;type filter hook output priority 0
+
+*inet;test-inet;output
+
+# without nfproto specified, these should add an implicit dependency on
+# the likely l3 proto (i.e., IPv6 for icmpv6 and IPv4 for icmp)
+
+icmp type echo-request;ok
+icmpv6 type echo-request;ok
+
+# make sure only those nfproto matches are dropped if
+# the next statement would add it as a dependency anyway
+
+meta nfproto ipv4 icmp type echo-request;ok;icmp type echo-request
+meta nfproto ipv4 icmpv6 type echo-request;ok
+
+meta nfproto ipv6 icmp type echo-request;ok
+meta nfproto ipv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
diff --git a/tests/py/inet/icmp.t.json b/tests/py/inet/icmp.t.json
new file mode 100644
index 0000000..64be2b3
--- /dev/null
+++ b/tests/py/inet/icmp.t.json
@@ -0,0 +1,124 @@
+# icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv4 icmp type echo-request
+[
+ {
+ "match": {
+ "left": { "meta": { "key": "nfproto" } },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv4 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": { "meta": { "key": "nfproto" } },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv6 icmp type echo-request
+[
+ {
+ "match": {
+ "left": { "meta": { "key": "nfproto" } },
+ "op": "==",
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": { "meta": { "key": "nfproto" } },
+ "op": "==",
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
diff --git a/tests/py/inet/icmp.t.json.output b/tests/py/inet/icmp.t.json.output
new file mode 100644
index 0000000..062c82f
--- /dev/null
+++ b/tests/py/inet/icmp.t.json.output
@@ -0,0 +1,32 @@
+# meta nfproto ipv4 icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta nfproto ipv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
diff --git a/tests/py/inet/icmp.t.payload b/tests/py/inet/icmp.t.payload
new file mode 100644
index 0000000..f98cfc3
--- /dev/null
+++ b/tests/py/inet/icmp.t.payload
@@ -0,0 +1,54 @@
+# icmp type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# icmpv6 type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# meta nfproto ipv4 icmp type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# meta nfproto ipv4 icmpv6 type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# meta nfproto ipv6 icmp type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# meta nfproto ipv6 icmpv6 type echo-request
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
diff --git a/tests/py/inet/icmpX.t b/tests/py/inet/icmpX.t
new file mode 100644
index 0000000..9430b3d
--- /dev/null
+++ b/tests/py/inet/icmpX.t
@@ -0,0 +1,10 @@
+:input;type filter hook input priority 0
+
+*inet;test-inet;input
+
+ip protocol icmp icmp type echo-request;ok;ip protocol 1 icmp type echo-request
+icmp type echo-request;ok
+ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;ip6 nexthdr 58 icmpv6 type echo-request
+icmpv6 type echo-request;ok
+# must not remove 'ip protocol' dependency, this explicitly matches icmpv6-in-ipv4.
+ip protocol ipv6-icmp meta l4proto ipv6-icmp icmpv6 type 1;ok;ip protocol 58 icmpv6 type destination-unreachable
diff --git a/tests/py/inet/icmpX.t.json b/tests/py/inet/icmpX.t.json
new file mode 100644
index 0000000..8e13091
--- /dev/null
+++ b/tests/py/inet/icmpX.t.json
@@ -0,0 +1,125 @@
+# ip protocol icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "icmpv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip protocol ipv6-icmp meta l4proto ipv6-icmp icmpv6 type 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "ipv6-icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": "ipv6-icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "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 0000000..7765cd9
--- /dev/null
+++ b/tests/py/inet/icmpX.t.json.output
@@ -0,0 +1,84 @@
+# ip protocol icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": 58
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# ip protocol ipv6-icmp meta l4proto ipv6-icmp icmpv6 type 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 58
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "destination-unreachable"
+ }
+ }
+]
+
diff --git a/tests/py/inet/icmpX.t.payload b/tests/py/inet/icmpX.t.payload
new file mode 100644
index 0000000..9a761ee
--- /dev/null
+++ b/tests/py/inet/icmpX.t.payload
@@ -0,0 +1,46 @@
+# ip protocol icmp icmp type echo-request
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# icmp type echo-request
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# icmpv6 type echo-request
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# ip protocol ipv6-icmp meta l4proto ipv6-icmp icmpv6 type 1
+inet filter input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
diff --git a/tests/py/inet/ip.t b/tests/py/inet/ip.t
new file mode 100644
index 0000000..bdb3330
--- /dev/null
+++ b/tests/py/inet/ip.t
@@ -0,0 +1,12 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*inet;test-inet;input
+*bridge;test-bridge;input
+*netdev;test-netdev;ingress,egress
+
+ip saddr . ip daddr . ether saddr { 1.1.1.1 . 2.2.2.2 . ca:fe:ca:fe:ca:fe };ok
+ip saddr vmap { 10.0.1.0-10.0.1.255 : accept, 10.0.1.1-10.0.2.255 : drop };fail
+ip saddr vmap { 3.3.3.3-3.3.3.4 : accept, 1.1.1.1-1.1.1.255 : accept, 1.1.1.0-1.1.2.1 : drop};fail
diff --git a/tests/py/inet/ip.t.json b/tests/py/inet/ip.t.json
new file mode 100644
index 0000000..638fb7d
--- /dev/null
+++ b/tests/py/inet/ip.t.json
@@ -0,0 +1,42 @@
+# 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",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.1.1.1",
+ "2.2.2.2",
+ "ca:fe:ca:fe:ca:fe"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/ip.t.payload b/tests/py/inet/ip.t.payload
new file mode 100644
index 0000000..589a5cd
--- /dev/null
+++ b/tests/py/inet/ip.t.payload
@@ -0,0 +1,11 @@
+# ip saddr . ip daddr . ether saddr { 1.1.1.1 . 2.2.2.2 . ca:fe:ca:fe:ca:fe }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 01010101 02020202 fecafeca 0000feca : 0 [end]
+inet test-ip input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ payload load 6b @ link header + 6 => reg 10 ]
+ [ lookup reg 1 set __set%d ]
diff --git a/tests/py/inet/ip.t.payload.bridge b/tests/py/inet/ip.t.payload.bridge
new file mode 100644
index 0000000..57dbc9e
--- /dev/null
+++ b/tests/py/inet/ip.t.payload.bridge
@@ -0,0 +1,11 @@
+# ip saddr . ip daddr . ether saddr { 1.1.1.1 . 2.2.2.2 . ca:fe:ca:fe:ca:fe }
+__set%d test-bridge 3
+__set%d test-bridge 0
+ element 01010101 02020202 fecafeca 0000feca : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ payload load 6b @ link header + 6 => reg 10 ]
+ [ lookup reg 1 set __set%d ]
diff --git a/tests/py/inet/ip.t.payload.inet b/tests/py/inet/ip.t.payload.inet
new file mode 100644
index 0000000..8df41de
--- /dev/null
+++ b/tests/py/inet/ip.t.payload.inet
@@ -0,0 +1,14 @@
+# ip saddr . ip daddr . ether saddr { 1.1.1.1 . 2.2.2.2 . ca:fe:ca:fe:ca:fe }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 01010101 02020202 fecafeca 0000feca : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ payload load 6b @ link header + 6 => reg 10 ]
+ [ lookup reg 1 set __set%d ]
+
diff --git a/tests/py/inet/ip.t.payload.netdev b/tests/py/inet/ip.t.payload.netdev
new file mode 100644
index 0000000..95be919
--- /dev/null
+++ b/tests/py/inet/ip.t.payload.netdev
@@ -0,0 +1,14 @@
+# ip saddr . ip daddr . ether saddr { 1.1.1.1 . 2.2.2.2 . ca:fe:ca:fe:ca:fe }
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 01010101 02020202 fecafeca 0000feca : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ payload load 6b @ link header + 6 => reg 10 ]
+ [ lookup reg 1 set __set%d ]
+
diff --git a/tests/py/inet/ip_tcp.t b/tests/py/inet/ip_tcp.t
new file mode 100644
index 0000000..03bafc0
--- /dev/null
+++ b/tests/py/inet/ip_tcp.t
@@ -0,0 +1,21 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*inet;test-inet;input
+*bridge;test-bridge;input
+*netdev;test-netdev;ingress,egress
+
+# must not remove ip dependency -- ONLY ipv4 packets should be matched
+ip protocol tcp tcp dport 22;ok;ip protocol 6 tcp dport 22
+
+# could in principle remove it here since ipv4 is implied via saddr.
+ip protocol tcp ip saddr 1.2.3.4 tcp dport 22;ok;ip protocol 6 ip saddr 1.2.3.4 tcp dport 22
+
+# but not here.
+ip protocol tcp counter ip saddr 1.2.3.4 tcp dport 22;ok;ip protocol 6 counter ip saddr 1.2.3.4 tcp dport 22
+
+# or here.
+ip protocol tcp counter tcp dport 22;ok;ip protocol 6 counter tcp dport 22
+
+ether type ip tcp dport 22;ok
diff --git a/tests/py/inet/ip_tcp.t.json b/tests/py/inet/ip_tcp.t.json
new file mode 100644
index 0000000..87cb9bf
--- /dev/null
+++ b/tests/py/inet/ip_tcp.t.json
@@ -0,0 +1,170 @@
+# ip protocol tcp tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp ip saddr 1.2.3.4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp counter ip saddr 1.2.3.4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp counter tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ether type ip tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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 0000000..acad8b1
--- /dev/null
+++ b/tests/py/inet/ip_tcp.t.json.output
@@ -0,0 +1,142 @@
+# ip protocol tcp tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp ip saddr 1.2.3.4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp counter ip saddr 1.2.3.4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp counter tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
diff --git a/tests/py/inet/ip_tcp.t.payload b/tests/py/inet/ip_tcp.t.payload
new file mode 100644
index 0000000..1e16f85
--- /dev/null
+++ b/tests/py/inet/ip_tcp.t.payload
@@ -0,0 +1,52 @@
+# ip protocol tcp tcp dport 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp ip saddr 1.2.3.4 tcp dport 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp counter ip saddr 1.2.3.4 tcp dport 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp counter tcp dport 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ether type ip tcp dport 22
+inet test-inet input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
diff --git a/tests/py/inet/ip_tcp.t.payload.bridge b/tests/py/inet/ip_tcp.t.payload.bridge
new file mode 100644
index 0000000..0344cd6
--- /dev/null
+++ b/tests/py/inet/ip_tcp.t.payload.bridge
@@ -0,0 +1,51 @@
+# ip protocol tcp tcp dport 22
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp ip saddr 1.2.3.4 tcp dport 22
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp counter ip saddr 1.2.3.4 tcp dport 22
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp counter tcp dport 22
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ether type ip tcp dport 22
+bridge test-bridge input
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
diff --git a/tests/py/inet/ip_tcp.t.payload.netdev b/tests/py/inet/ip_tcp.t.payload.netdev
new file mode 100644
index 0000000..915a787
--- /dev/null
+++ b/tests/py/inet/ip_tcp.t.payload.netdev
@@ -0,0 +1,53 @@
+# ip protocol tcp tcp dport 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp ip saddr 1.2.3.4 tcp dport 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp counter ip saddr 1.2.3.4 tcp dport 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp counter tcp dport 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ether type ip tcp dport 22
+netdev test-netdev ingress
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ link header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
diff --git a/tests/py/inet/ipsec.t b/tests/py/inet/ipsec.t
new file mode 100644
index 0000000..b18df39
--- /dev/null
+++ b/tests/py/inet/ipsec.t
@@ -0,0 +1,23 @@
+:ipsec-forw;type filter hook forward priority 0
+
+*ip;ipsec-ip4;ipsec-forw
+*ip6;ipsec-ip6;ipsec-forw
+*inet;ipsec-inet;ipsec-forw
+
+ipsec in reqid 1;ok
+ipsec in spnum 0 reqid 1;ok;ipsec in reqid 1
+
+ipsec out reqid 0xffffffff;ok;ipsec out reqid 4294967295
+ipsec out spnum 0x100000000;fail
+
+ipsec i reqid 1;fail
+
+ipsec out spi 1-561;ok
+
+ipsec in spnum 2 ip saddr { 1.2.3.4, 10.6.0.0/16 };ok
+ipsec in ip6 daddr dead::beef;ok
+ipsec out ip6 saddr dead::feed;ok
+
+ipsec in spnum 256 reqid 1;fail
+
+counter ipsec out ip daddr 192.168.1.2;ok
diff --git a/tests/py/inet/ipsec.t.json b/tests/py/inet/ipsec.t.json
new file mode 100644
index 0000000..18a64f3
--- /dev/null
+++ b/tests/py/inet/ipsec.t.json
@@ -0,0 +1,157 @@
+# ipsec in reqid 1
+[
+ {
+ "match": {
+ "left": {
+ "ipsec": {
+ "dir": "in",
+ "key": "reqid",
+ "spnum": 0
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# ipsec in spnum 0 reqid 1
+[
+ {
+ "match": {
+ "left": {
+ "ipsec": {
+ "dir": "in",
+ "key": "reqid",
+ "spnum": 0
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# ipsec out reqid 0xffffffff
+[
+ {
+ "match": {
+ "left": {
+ "ipsec": {
+ "dir": "out",
+ "key": "reqid",
+ "spnum": 0
+ }
+ },
+ "op": "==",
+ "right": 4294967295
+ }
+ }
+]
+
+# ipsec out spi 1-561
+[
+ {
+ "match": {
+ "left": {
+ "ipsec": {
+ "dir": "out",
+ "key": "spi",
+ "spnum": 0
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 1,
+ 561
+ ]
+ }
+ }
+ }
+]
+
+# ipsec in spnum 2 ip saddr { 1.2.3.4, 10.6.0.0/16 }
+[
+ {
+ "match": {
+ "left": {
+ "ipsec": {
+ "dir": "in",
+ "family": "ip",
+ "key": "saddr",
+ "spnum": 2
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "1.2.3.4",
+ {
+ "prefix": {
+ "addr": "10.6.0.0",
+ "len": 16
+ }
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ipsec in ip6 daddr dead::beef
+[
+ {
+ "match": {
+ "left": {
+ "ipsec": {
+ "dir": "in",
+ "family": "ip6",
+ "key": "daddr",
+ "spnum": 0
+ }
+ },
+ "op": "==",
+ "right": "dead::beef"
+ }
+ }
+]
+
+# ipsec out ip6 saddr dead::feed
+[
+ {
+ "match": {
+ "left": {
+ "ipsec": {
+ "dir": "out",
+ "family": "ip6",
+ "key": "saddr",
+ "spnum": 0
+ }
+ },
+ "op": "==",
+ "right": "dead::feed"
+ }
+ }
+]
+
+# counter ipsec out ip daddr 192.168.1.2
+[
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "ipsec": {
+ "dir": "out",
+ "family": "ip",
+ "key": "daddr",
+ "spnum": 0
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.2"
+ }
+ }
+]
diff --git a/tests/py/inet/ipsec.t.payload b/tests/py/inet/ipsec.t.payload
new file mode 100644
index 0000000..9648255
--- /dev/null
+++ b/tests/py/inet/ipsec.t.payload
@@ -0,0 +1,45 @@
+# ipsec in reqid 1
+ip ipsec-ip4 ipsec-input
+ [ xfrm load in 0 reqid => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ipsec in spnum 0 reqid 1
+ip ipsec-ip4 ipsec-input
+ [ xfrm load in 0 reqid => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ipsec out reqid 0xffffffff
+ip ipsec-ip4 ipsec-input
+ [ xfrm load out 0 reqid => reg 1 ]
+ [ cmp eq reg 1 0xffffffff ]
+
+# ipsec out spi 1-561
+inet ipsec-inet ipsec-post
+ [ xfrm load out 0 spi => reg 1 ]
+ [ cmp gte reg 1 0x01000000 ]
+ [ cmp lte reg 1 0x31020000 ]
+
+# ipsec in spnum 2 ip saddr { 1.2.3.4, 10.6.0.0/16 }
+__set%d ipsec-ip4 7 size 5
+__set%d ipsec-ip4 0
+ element 00000000 : 1 [end] element 04030201 : 0 [end] element 05030201 : 1 [end] element 0000060a : 0 [end] element 0000070a : 1 [end]
+ip ipsec-ip4 ipsec-input
+ [ xfrm load in 2 saddr4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ipsec in ip6 daddr dead::beef
+ip ipsec-ip4 ipsec-forw
+ [ xfrm load in 0 daddr6 => reg 1 ]
+ [ cmp eq reg 1 0x0000adde 0x00000000 0x00000000 0xefbe0000 ]
+
+# ipsec out ip6 saddr dead::feed
+ip ipsec-ip4 ipsec-forw
+ [ xfrm load out 0 saddr6 => reg 1 ]
+ [ cmp eq reg 1 0x0000adde 0x00000000 0x00000000 0xedfe0000 ]
+
+# counter ipsec out ip daddr 192.168.1.2
+ip ipsec-ip4 ipsec-forw
+ [ counter pkts 0 bytes 0 ]
+ [ xfrm load out 0 daddr4 => reg 1 ]
+ [ cmp eq reg 1 0x0201a8c0 ]
+
diff --git a/tests/py/inet/map.t b/tests/py/inet/map.t
new file mode 100644
index 0000000..5a7161b
--- /dev/null
+++ b/tests/py/inet/map.t
@@ -0,0 +1,10 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+mark set ip saddr map { 10.2.3.2 : 0x0000002a, 10.2.3.1 : 0x00000017};ok;meta mark set ip saddr map { 10.2.3.1 : 0x00000017, 10.2.3.2 : 0x0000002a}
+mark set ip hdrlength map { 5 : 0x00000017, 4 : 0x00000001};ok;meta mark set ip hdrlength map { 4 : 0x00000001, 5 : 0x00000017}
diff --git a/tests/py/inet/map.t.json b/tests/py/inet/map.t.json
new file mode 100644
index 0000000..1cb28e0
--- /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": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "10.2.3.2",
+ "0x0000002a"
+ ],
+ [
+ "10.2.3.1",
+ "0x00000017"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# mark set ip hdrlength map { 5 : 0x00000017, 4 : 0x00000001}
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ip"
+ }
+ },
+ "data": {
+ "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 0000000..b0bb7dd
--- /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": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "10.2.3.1",
+ 23
+ ],
+ [
+ "10.2.3.2",
+ 42
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# mark set ip hdrlength map { 5 : 0x00000017, 4 : 0x00000001}
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ip"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 4,
+ 1
+ ],
+ [
+ 5,
+ 23
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/map.t.payload b/tests/py/inet/map.t.payload
new file mode 100644
index 0000000..50344ad
--- /dev/null
+++ b/tests/py/inet/map.t.payload
@@ -0,0 +1,23 @@
+# mark set ip saddr map { 10.2.3.2 : 0x0000002a, 10.2.3.1 : 0x00000017}
+__map%d test-inet b
+__map%d test-inet 0
+ element 0203020a : 0000002a 0 [end] element 0103020a : 00000017 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
+# mark set ip hdrlength map { 5 : 0x00000017, 4 : 0x00000001}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00000005 : 00000017 0 [end] element 00000004 : 00000001 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
diff --git a/tests/py/inet/map.t.payload.ip b/tests/py/inet/map.t.payload.ip
new file mode 100644
index 0000000..3e45667
--- /dev/null
+++ b/tests/py/inet/map.t.payload.ip
@@ -0,0 +1,19 @@
+# mark set ip saddr map { 10.2.3.2 : 0x0000002a, 10.2.3.1 : 0x00000017}
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 0203020a : 0000002a 0 [end] element 0103020a : 00000017 0 [end]
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
+# mark set ip hdrlength map { 5 : 0x00000017, 4 : 0x00000001}
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00000005 : 00000017 0 [end] element 00000004 : 00000001 0 [end]
+ip test-ip4 input
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
diff --git a/tests/py/inet/map.t.payload.netdev b/tests/py/inet/map.t.payload.netdev
new file mode 100644
index 0000000..2e60f09
--- /dev/null
+++ b/tests/py/inet/map.t.payload.netdev
@@ -0,0 +1,23 @@
+# mark set ip saddr map { 10.2.3.2 : 0x0000002a, 10.2.3.1 : 0x00000017}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 0203020a : 0000002a 0 [end] element 0103020a : 00000017 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
+# mark set ip hdrlength map { 5 : 0x00000017, 4 : 0x00000001}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00000005 : 00000017 0 [end] element 00000004 : 00000001 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
diff --git a/tests/py/inet/meta.t b/tests/py/inet/meta.t
new file mode 100644
index 0000000..5c062b3
--- /dev/null
+++ b/tests/py/inet/meta.t
@@ -0,0 +1,32 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+
+*inet;test-inet;input
+
+meta nfproto ipv4;ok
+meta nfproto ipv6;ok
+meta nfproto {ipv4, ipv6};ok
+meta nfproto != {ipv4, ipv6};ok
+meta nfproto ipv6 tcp dport 22;ok
+meta nfproto ipv4 tcp dport 22;ok
+meta nfproto ipv4 ip saddr 1.2.3.4;ok;ip saddr 1.2.3.4
+meta nfproto ipv6 meta l4proto tcp;ok;meta nfproto ipv6 meta l4proto 6
+meta nfproto ipv4 counter ip saddr 1.2.3.4;ok
+
+meta protocol ip udp dport 67;ok
+meta protocol ip6 udp dport 67;ok
+
+meta ipsec exists;ok
+meta secpath missing;ok;meta ipsec missing
+meta ibrname "br0";fail
+meta obrname "br0";fail
+meta mark set ct mark >> 8;ok
+
+meta mark . tcp dport { 0x0000000a-0x00000014 . 80-90, 0x00100000-0x00100123 . 100-120 };ok
+ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 1.2.3.6-1.2.3.8 . 0x00000200-0x00000300 };ok
+ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 5.6.7.8 . 0x00000200 };ok
+
+meta mark set ip dscp;ok
+meta mark set ip dscp | 0x40;ok
+meta mark set ip6 dscp;ok
+meta mark set ip6 dscp | 0x40;ok
diff --git a/tests/py/inet/meta.t.json b/tests/py/inet/meta.t.json
new file mode 100644
index 0000000..3ba0fd1
--- /dev/null
+++ b/tests/py/inet/meta.t.json
@@ -0,0 +1,528 @@
+# meta nfproto ipv4
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ }
+]
+
+# meta nfproto ipv6
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv6"
+ }
+ }
+]
+
+# meta nfproto {ipv4, ipv6}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "ipv4",
+ "ipv6"
+ ]
+ }
+ }
+ }
+]
+
+# meta nfproto != {ipv4, ipv6}
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "ipv4",
+ "ipv6"
+ ]
+ }
+ }
+ }
+]
+
+# meta nfproto ipv6 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# meta nfproto ipv4 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# meta nfproto ipv4 ip saddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# meta nfproto ipv6 meta l4proto tcp
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ }
+]
+
+# meta nfproto ipv4 counter ip saddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# meta ipsec exists
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "ipsec"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# meta secpath missing
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "secpath" }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
+# meta mark set ct mark >> 8
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ ">>": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ 8
+ ]
+ }
+ }
+ }
+]
+
+# meta protocol ip udp dport 67
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 67
+ }
+ }
+]
+
+# meta protocol ip6 udp dport 67
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 67
+ }
+ }
+]
+
+# meta mark . tcp dport { 0x0000000a-0x00000014 . 80-90, 0x00100000-0x00100123 . 100-120 }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ {
+ "range": [
+ 10,
+ 20
+ ]
+ },
+ {
+ "range": [
+ 80,
+ 90
+ ]
+ }
+ ]
+ },
+ {
+ "concat": [
+ {
+ "range": [
+ 1048576,
+ 1048867
+ ]
+ },
+ {
+ "range": [
+ 100,
+ 120
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 1.2.3.6-1.2.3.8 . 0x00000200-0x00000300 }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "meta": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.2.3.4",
+ 256
+ ]
+ },
+ {
+ "concat": [
+ {
+ "range": [
+ "1.2.3.6",
+ "1.2.3.8"
+ ]
+ },
+ {
+ "range": [
+ 512,
+ 768
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 5.6.7.8 . 0x00000200 }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "meta": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.2.3.4",
+ 256
+ ]
+ },
+ {
+ "concat": [
+ "5.6.7.8",
+ 512
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# meta mark set ip dscp
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ }
+ }
+ }
+]
+
+# meta mark set ip dscp | 0x40
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ 64
+ ]
+ }
+ }
+ }
+]
+
+# meta mark set ip6 dscp
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ }
+ }
+ }
+]
+
+# meta mark set ip6 dscp | 0x40
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 64
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/meta.t.json.got b/tests/py/inet/meta.t.json.got
new file mode 100644
index 0000000..f2fad0b
--- /dev/null
+++ b/tests/py/inet/meta.t.json.got
@@ -0,0 +1,86 @@
+# meta mark set ip dscp
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ }
+ }
+ }
+]
+
+# meta mark set ip dscp | 0x40
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ 64
+ ]
+ }
+ }
+ }
+]
+
+# meta mark set ip6 dscp
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ }
+ }
+ }
+]
+
+# meta mark set ip6 dscp | 0x40
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 64
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/meta.t.json.output b/tests/py/inet/meta.t.json.output
new file mode 100644
index 0000000..3e7dd21
--- /dev/null
+++ b/tests/py/inet/meta.t.json.output
@@ -0,0 +1,53 @@
+# meta nfproto ipv4 ip saddr 1.2.3.4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ }
+]
+
+# meta nfproto ipv6 meta l4proto tcp
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": 6
+ }
+ }
+]
+
+# meta secpath missing
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "ipsec"
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
diff --git a/tests/py/inet/meta.t.payload b/tests/py/inet/meta.t.payload
new file mode 100644
index 0000000..c53b507
--- /dev/null
+++ b/tests/py/inet/meta.t.payload
@@ -0,0 +1,175 @@
+# meta nfproto ipv4
+ip test-ip4 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# meta nfproto ipv6
+ip test-ip4 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+
+# meta nfproto {ipv4, ipv6}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000002 : 0 [end] element 0000000a : 0 [end]
+ip test-ip4 input
+ [ meta load nfproto => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta nfproto != {ipv4, ipv6}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000002 : 0 [end] element 0000000a : 0 [end]
+ip test-ip4 input
+ [ meta load nfproto => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# meta nfproto ipv6 tcp dport 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# meta nfproto ipv4 tcp dport 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# meta nfproto ipv4 ip saddr 1.2.3.4
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+
+# meta nfproto ipv6 meta l4proto tcp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# meta nfproto ipv4 counter ip saddr 1.2.3.4
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+
+# meta ipsec exists
+inet test-inet input
+ [ meta load secpath => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# meta secpath missing
+inet test-inet input
+ [ meta load secpath => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta mark set ct mark >> 8
+inet test-inet input
+ [ ct load mark => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000008 ) ]
+ [ meta set mark with reg 1 ]
+
+# meta protocol ip udp dport 67
+inet test-inet input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00004300 ]
+
+# meta protocol ip6 udp dport 67
+inet test-inet input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00004300 ]
+
+# meta mark . tcp dport { 0x0000000a-0x00000014 . 80-90, 0x00100000-0x00100123 . 100-120 }
+__set%d test-inet 87 size 1
+__set%d test-inet 0
+ element 0a000000 00005000 - 14000000 00005a00 : 0 [end] element 00001000 00006400 - 23011000 00007800 : 0 [end]
+ip test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ meta load mark => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ payload load 2b @ transport header + 2 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 1.2.3.6-1.2.3.8 . 0x00000200-0x00000300 }
+__set%d test-inet 87 size 2
+__set%d test-inet 0
+ element 04030201 00010000 - 04030201 00010000 : 0 [end] element 06030201 00020000 - 08030201 00030000 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ meta load mark => reg 9 ]
+ [ byteorder reg 9 = hton(reg 9, 4, 4) ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 5.6.7.8 . 0x00000200 }
+__set%d test-inet 3 size 2
+__set%d test-inet 0
+ element 04030201 00000100 : 0 [end] element 08070605 00000200 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ meta load mark => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta mark set ip dscp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ip dscp | 0x40
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffbf ) ^ 0x00000040 ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ip6 dscp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ip6 dscp | 0x40
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffbf ) ^ 0x00000040 ]
+ [ meta set mark with reg 1 ]
+
diff --git a/tests/py/inet/meta.t.payload.got b/tests/py/inet/meta.t.payload.got
new file mode 100644
index 0000000..be3f566
--- /dev/null
+++ b/tests/py/inet/meta.t.payload.got
@@ -0,0 +1,40 @@
+# meta mark set ip dscp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ip dscp | 0x40
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffbf ) ^ 0x00000040 ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ip6 dscp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ip6 dscp | 0x40
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffbf ) ^ 0x00000040 ]
+ [ meta set mark with reg 1 ]
+
diff --git a/tests/py/inet/osf.t b/tests/py/inet/osf.t
new file mode 100644
index 0000000..c828541
--- /dev/null
+++ b/tests/py/inet/osf.t
@@ -0,0 +1,18 @@
+:osfchain;type filter hook input priority 0
+
+*ip;osfip;osfchain
+*ip6;osfip6;osfchain
+*inet;osfinet;osfchain
+
+osf name "Linux";ok
+osf ttl loose name "Linux";ok
+osf ttl skip name "Linux";ok
+osf ttl skip version "Linux:3.0";ok
+osf ttl skip version "morethan:sixteenbytes";fail
+osf ttl nottl name "Linux";fail
+osf name "morethansixteenbytes";fail
+osf name ;fail
+osf name { "Windows", "MacOs" };ok
+osf version { "Windows:XP", "MacOs:Sierra" };ok
+ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 };ok
+ct mark set osf version map { "Windows:XP" : 0x00000003, "MacOs:Sierra" : 0x00000004 };ok
diff --git a/tests/py/inet/osf.t.json b/tests/py/inet/osf.t.json
new file mode 100644
index 0000000..cedb7f6
--- /dev/null
+++ b/tests/py/inet/osf.t.json
@@ -0,0 +1,170 @@
+# osf name "Linux"
+[
+ {
+ "match": {
+ "left": {
+ "osf": {
+ "key": "name"
+ }
+ },
+ "op": "==",
+ "right": "Linux"
+ }
+ }
+]
+
+# osf ttl loose name "Linux"
+[
+ {
+ "match": {
+ "left": {
+ "osf": {
+ "key": "name",
+ "ttl": "loose"
+ }
+ },
+ "op": "==",
+ "right": "Linux"
+ }
+ }
+]
+
+# osf ttl skip name "Linux"
+[
+ {
+ "match": {
+ "left": {
+ "osf": {
+ "key": "name",
+ "ttl": "skip"
+ }
+ },
+ "op": "==",
+ "right": "Linux"
+ }
+ }
+]
+
+# osf ttl skip version "Linux:3.0"
+[
+ {
+ "match": {
+ "left": {
+ "osf": {
+ "key": "version",
+ "ttl": "skip"
+ }
+ },
+ "op": "==",
+ "right": "Linux:3.0"
+ }
+ }
+]
+
+# osf name { "Windows", "MacOs" }
+[
+ {
+ "match": {
+ "left": {
+ "osf": {
+ "key": "name"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "MacOs",
+ "Windows"
+ ]
+ }
+ }
+ }
+]
+
+# osf version { "Windows:XP", "MacOs:Sierra" }
+[
+ {
+ "match": {
+ "left": {
+ "osf": {
+ "key": "version"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "Windows:XP",
+ "MacOs:Sierra"
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 }
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "MacOs",
+ 2
+ ],
+ [
+ "Windows",
+ 1
+ ]
+ ]
+ },
+ "key": {
+ "osf": {
+ "key": "name"
+ }
+ }
+ }
+ }
+ }
+ }
+]
+
+# ct mark set osf version map { "Windows:XP" : 0x00000003, "MacOs:Sierra" : 0x00000004 }
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "Windows:XP",
+ 3
+ ],
+ [
+ "MacOs:Sierra",
+ 4
+ ]
+ ]
+ },
+ "key": {
+ "osf": {
+ "key": "version"
+ }
+ }
+ }
+ }
+ }
+ }
+]
diff --git a/tests/py/inet/osf.t.payload b/tests/py/inet/osf.t.payload
new file mode 100644
index 0000000..6ddab97
--- /dev/null
+++ b/tests/py/inet/osf.t.payload
@@ -0,0 +1,53 @@
+# osf name "Linux"
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl loose name "Linux"
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl skip name "Linux"
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl skip version "Linux:3.0"
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x2e333a78 0x00000030 0x00000000 ]
+
+# osf name { "Windows", "MacOs" }
+__set%d osfinet 3 size 2
+__set%d osfinet 0
+ element 646e6957 0073776f 00000000 00000000 : 0 [end] element 4f63614d 00000073 00000000 00000000 : 0 [end]
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# osf version { "Windows:XP", "MacOs:Sierra" }
+__set%d osfinet 3 size 2
+__set%d osfinet 0
+ element 646e6957 3a73776f 00005058 00000000 : 0 [end] element 4f63614d 69533a73 61727265 00000000 : 0 [end]
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 }
+__map%d osfinet b size 2
+__map%d osfinet 0
+ element 646e6957 0073776f 00000000 00000000 : 00000001 0 [end] element 4f63614d 00000073 00000000 00000000 : 00000002 0 [end]
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set osf version map { "Windows:XP" : 0x00000003, "MacOs:Sierra" : 0x00000004 }
+__map%d osfinet b size 2
+__map%d osfinet 0
+ element 646e6957 3a73776f 00005058 00000000 : 00000003 0 [end] element 4f63614d 69533a73 61727265 00000000 : 00000004 0 [end]
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ ct set mark with reg 1 ]
diff --git a/tests/py/inet/reject.t b/tests/py/inet/reject.t
new file mode 100644
index 0000000..61a6d55
--- /dev/null
+++ b/tests/py/inet/reject.t
@@ -0,0 +1,41 @@
+:input;type filter hook input priority 0
+
+*inet;test-inet;input
+
+reject with icmp host-unreachable;ok
+reject with icmp net-unreachable;ok
+reject with icmp prot-unreachable;ok
+reject with icmp port-unreachable;ok
+reject with icmp net-prohibited;ok
+reject with icmp host-prohibited;ok
+reject with icmp admin-prohibited;ok
+
+reject with icmpv6 no-route;ok
+reject with icmpv6 admin-prohibited;ok
+reject with icmpv6 addr-unreachable;ok
+reject with icmpv6 port-unreachable;ok
+
+mark 12345 reject with tcp reset;ok;meta l4proto 6 meta mark 0x00003039 reject with tcp reset
+
+reject;ok
+meta nfproto ipv4 reject;ok;reject with icmp port-unreachable
+meta nfproto ipv6 reject;ok;reject with icmpv6 port-unreachable
+
+reject with icmpx host-unreachable;ok
+reject with icmpx no-route;ok
+reject with icmpx admin-prohibited;ok
+reject with icmpx port-unreachable;ok;reject
+reject with icmpx 3;ok;reject with icmpx admin-prohibited
+
+meta nfproto ipv4 reject with icmp host-unreachable;ok;reject with icmp host-unreachable
+meta nfproto ipv6 reject with icmpv6 no-route;ok;reject with icmpv6 no-route
+
+meta nfproto ipv6 reject with icmp host-unreachable;fail
+meta nfproto ipv4 ip protocol icmp reject with icmpv6 no-route;fail
+meta nfproto ipv6 ip protocol icmp reject with icmp host-unreachable;fail
+meta l4proto udp reject with tcp reset;fail
+
+meta nfproto ipv4 reject with icmpx admin-prohibited;ok
+meta nfproto ipv6 reject with icmpx admin-prohibited;ok
+
+ether saddr aa:bb:cc:dd:ee:ff ip daddr 192.168.0.1 reject;ok;ether saddr aa:bb:cc:dd:ee:ff ip daddr 192.168.0.1 reject with icmp port-unreachable
diff --git a/tests/py/inet/reject.t.json b/tests/py/inet/reject.t.json
new file mode 100644
index 0000000..02ac900
--- /dev/null
+++ b/tests/py/inet/reject.t.json
@@ -0,0 +1,331 @@
+# reject with icmp host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp net-unreachable
+[
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp prot-unreachable
+[
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp net-prohibited
+[
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp host-prohibited
+[
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmpv6 no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 addr-unreachable
+[
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# mark 12345 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": 12345
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject
+[
+ {
+ "reject": null
+ }
+]
+
+# meta nfproto ipv4 reject
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# meta nfproto ipv6 reject
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv6"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# reject with icmpx host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx 3
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# meta nfproto ipv4 reject with icmp host-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# meta nfproto ipv6 reject with icmpv6 no-route
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# meta nfproto ipv4 reject with icmpx admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "nfproto"
+ }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# meta nfproto ipv6 reject with icmpx admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "nfproto"
+ }
+ },
+ "op": "==",
+ "right": "ipv6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# ether saddr aa:bb:cc:dd:ee:ff ip daddr 192.168.0.1 reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "aa:bb:cc:dd:ee:ff"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ },
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
diff --git a/tests/py/inet/reject.t.json.output b/tests/py/inet/reject.t.json.output
new file mode 100644
index 0000000..496ce55
--- /dev/null
+++ b/tests/py/inet/reject.t.json.output
@@ -0,0 +1,77 @@
+# mark 12345 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": 12345
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# meta nfproto ipv4 reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# meta nfproto ipv6 reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# meta nfproto ipv4 reject with icmp host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# meta nfproto ipv6 reject with icmpv6 no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
diff --git a/tests/py/inet/reject.t.payload.inet b/tests/py/inet/reject.t.payload.inet
new file mode 100644
index 0000000..828cb83
--- /dev/null
+++ b/tests/py/inet/reject.t.payload.inet
@@ -0,0 +1,144 @@
+# reject with icmp host-unreachable
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 0 code 1 ]
+
+# reject with icmp net-unreachable
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 0 code 0 ]
+
+# reject with icmp prot-unreachable
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 0 code 2 ]
+
+# reject with icmp port-unreachable
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 0 code 3 ]
+
+# reject with icmp net-prohibited
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 0 code 9 ]
+
+# reject with icmp host-prohibited
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 0 code 10 ]
+
+# reject with icmp admin-prohibited
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 0 code 13 ]
+
+# reject with icmpv6 no-route
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ reject type 0 code 0 ]
+
+# reject with icmpv6 admin-prohibited
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ reject type 0 code 1 ]
+
+# reject with icmpv6 addr-unreachable
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ reject type 0 code 3 ]
+
+# reject with icmpv6 port-unreachable
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ reject type 0 code 4 ]
+
+# mark 12345 reject with tcp reset
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x00003039 ]
+ [ reject type 1 code 0 ]
+
+# reject
+inet test-inet input
+ [ reject type 2 code 1 ]
+
+# meta nfproto ipv4 reject
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 0 code 3 ]
+
+# meta nfproto ipv6 reject
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ reject type 0 code 4 ]
+
+# reject with icmpx host-unreachable
+inet test-inet input
+ [ reject type 2 code 2 ]
+
+# reject with icmpx no-route
+inet test-inet input
+ [ reject type 2 code 0 ]
+
+# reject with icmpx admin-prohibited
+inet test-inet input
+ [ reject type 2 code 3 ]
+
+# reject with icmpx port-unreachable
+inet test-inet input
+ [ reject type 2 code 1 ]
+
+# reject with icmpx 3
+inet test-inet input
+ [ reject type 2 code 3 ]
+
+# meta nfproto ipv4 reject with icmp host-unreachable
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 0 code 1 ]
+
+# meta nfproto ipv6 reject with icmpv6 no-route
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ reject type 0 code 0 ]
+
+# meta nfproto ipv4 reject with icmpx admin-prohibited
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ reject type 2 code 3 ]
+
+# meta nfproto ipv6 reject with icmpx admin-prohibited
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ reject type 2 code 3 ]
+
+# ether saddr aa:bb:cc:dd:ee:ff ip daddr 192.168.0.1 reject
+inet test-inet input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 8b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0xddccbbaa 0x0008ffee ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+ [ reject type 0 code 3 ]
+
diff --git a/tests/py/inet/rt.t b/tests/py/inet/rt.t
new file mode 100644
index 0000000..a0e0d00
--- /dev/null
+++ b/tests/py/inet/rt.t
@@ -0,0 +1,15 @@
+:output;type filter hook output priority 0
+
+*inet;test-inet;output
+
+meta nfproto ipv4 rt nexthop 192.168.0.1;ok;meta nfproto ipv4 rt ip nexthop 192.168.0.1
+rt ip6 nexthop fd00::1;ok
+
+# missing context
+rt nexthop 192.168.0.1;fail
+rt nexthop fd00::1;fail
+
+# wrong context
+rt ip nexthop fd00::1;fail
+
+tcp option maxseg size set rt mtu;ok
diff --git a/tests/py/inet/rt.t.json b/tests/py/inet/rt.t.json
new file mode 100644
index 0000000..6dbea41
--- /dev/null
+++ b/tests/py/inet/rt.t.json
@@ -0,0 +1,59 @@
+# meta nfproto ipv4 rt nexthop 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "key": "nexthop"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# rt ip6 nexthop fd00::1
+[
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "family": "ip6",
+ "key": "nexthop"
+ }
+ },
+ "op": "==",
+ "right": "fd00::1"
+ }
+ }
+]
+
+# tcp option maxseg size set rt mtu
+[
+ {
+ "mangle": {
+ "key": {
+ "tcp option": {
+ "field": "size",
+ "name": "maxseg"
+ }
+ },
+ "value": {
+ "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 0000000..382ef87
--- /dev/null
+++ b/tests/py/inet/rt.t.json.output
@@ -0,0 +1,25 @@
+# meta nfproto ipv4 rt nexthop 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "nfproto" }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "family": "ip",
+ "key": "nexthop"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ }
+]
+
diff --git a/tests/py/inet/rt.t.payload b/tests/py/inet/rt.t.payload
new file mode 100644
index 0000000..84dea12
--- /dev/null
+++ b/tests/py/inet/rt.t.payload
@@ -0,0 +1,18 @@
+# meta nfproto ipv4 rt nexthop 192.168.0.1
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ rt load nexthop4 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
+# rt ip6 nexthop fd00::1
+inet test-inet output
+ [ rt load nexthop6 => reg 1 ]
+ [ cmp eq reg 1 0x000000fd 0x00000000 0x00000000 0x01000000 ]
+
+# tcp option maxseg size set rt mtu
+inet test-inet output
+ [ rt load tcpmss => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 2, 2) ]
+ [ exthdr write tcpopt reg 1 => 2b @ 2 + 2 ]
+
diff --git a/tests/py/inet/sctp.t b/tests/py/inet/sctp.t
new file mode 100644
index 0000000..016173b
--- /dev/null
+++ b/tests/py/inet/sctp.t
@@ -0,0 +1,73 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+sctp sport 23;ok
+sctp sport != 23;ok
+sctp sport 23-44;ok
+sctp sport != 23-44;ok
+sctp sport { 23, 24, 25};ok
+sctp sport != { 23, 24, 25};ok
+
+sctp dport 23;ok
+sctp dport != 23;ok
+sctp dport 23-44;ok
+sctp dport != 23-44;ok
+sctp dport { 23, 24, 25};ok
+sctp dport != { 23, 24, 25};ok
+
+sctp checksum 1111;ok
+sctp checksum != 11;ok
+sctp checksum 21-333;ok
+sctp checksum != 32-111;ok
+sctp checksum { 22, 33, 44};ok
+sctp checksum != { 22, 33, 44};ok
+
+sctp vtag 22;ok
+sctp vtag != 233;ok
+sctp vtag 33-45;ok
+sctp vtag != 33-45;ok
+sctp vtag {33, 55, 67, 88};ok
+sctp vtag != {33, 55, 67, 88};ok
+
+# assert all chunk types are recognized
+sctp chunk data exists;ok
+sctp chunk init exists;ok
+sctp chunk init-ack exists;ok
+sctp chunk sack exists;ok
+sctp chunk heartbeat exists;ok
+sctp chunk heartbeat-ack exists;ok
+sctp chunk abort exists;ok
+sctp chunk shutdown exists;ok
+sctp chunk shutdown-ack exists;ok
+sctp chunk error exists;ok
+sctp chunk cookie-echo exists;ok
+sctp chunk cookie-ack exists;ok
+sctp chunk ecne exists;ok
+sctp chunk cwr exists;ok
+sctp chunk shutdown-complete exists;ok
+sctp chunk asconf-ack exists;ok
+sctp chunk forward-tsn exists;ok
+sctp chunk asconf exists;ok
+
+# test common header fields in random chunk types
+sctp chunk data type 0;ok
+sctp chunk init flags 23;ok
+sctp chunk init-ack length 42;ok
+
+# test one custom field in every applicable chunk type
+sctp chunk data stream 1337;ok
+sctp chunk init initial-tsn 5;ok
+sctp chunk init-ack num-outbound-streams 3;ok
+sctp chunk sack a-rwnd 1;ok
+sctp chunk shutdown cum-tsn-ack 65535;ok
+sctp chunk ecne lowest-tsn 5;ok
+sctp chunk cwr lowest-tsn 8;ok
+sctp chunk asconf-ack seqno 12345;ok
+sctp chunk forward-tsn new-cum-tsn 31337;ok
+sctp chunk asconf seqno 12345;ok
diff --git a/tests/py/inet/sctp.t.json b/tests/py/inet/sctp.t.json
new file mode 100644
index 0000000..75a9b01
--- /dev/null
+++ b/tests/py/inet/sctp.t.json
@@ -0,0 +1,928 @@
+# sctp sport 23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": 23
+ }
+ }
+]
+
+# sctp sport != 23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": 23
+ }
+ }
+]
+
+# sctp sport 23-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 23, 44 ]
+ }
+ }
+ }
+]
+
+# sctp sport != 23-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 23, 44 ]
+ }
+ }
+ }
+]
+
+# sctp sport { 23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# sctp sport != { 23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# sctp dport 23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": 23
+ }
+ }
+]
+
+# sctp dport != 23
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": 23
+ }
+ }
+]
+
+# sctp dport 23-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 23, 44 ]
+ }
+ }
+ }
+]
+
+# sctp dport != 23-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 23, 44 ]
+ }
+ }
+ }
+]
+
+# sctp dport { 23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# sctp dport != { 23, 24, 25}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 24,
+ 25
+ ]
+ }
+ }
+ }
+]
+
+# sctp checksum 1111
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": 1111
+ }
+ }
+]
+
+# sctp checksum != 11
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": 11
+ }
+ }
+]
+
+# sctp checksum 21-333
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 21, 333 ]
+ }
+ }
+ }
+]
+
+# sctp checksum != 32-111
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 32, 111 ]
+ }
+ }
+ }
+]
+
+# sctp checksum { 22, 33, 44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 22,
+ 33,
+ 44
+ ]
+ }
+ }
+ }
+]
+
+# sctp checksum != { 22, 33, 44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 22,
+ 33,
+ 44
+ ]
+ }
+ }
+ }
+]
+
+# sctp vtag 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# sctp vtag != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# sctp vtag 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# sctp vtag != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# sctp vtag {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "protocol": "sctp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# sctp vtag != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vtag",
+ "protocol": "sctp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# sctp chunk data exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "data"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk init exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "init"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk init-ack exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "init-ack"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk sack exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk heartbeat exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "heartbeat"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk heartbeat-ack exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "heartbeat-ack"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk abort exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "abort"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk shutdown exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "shutdown"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk shutdown-ack exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "shutdown-ack"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk error exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "error"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk cookie-echo exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "cookie-echo"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk cookie-ack exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "cookie-ack"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk ecne exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "ecne"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk cwr exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "cwr"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk shutdown-complete exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "shutdown-complete"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk asconf-ack exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "asconf-ack"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk forward-tsn exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "forward-tsn"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk asconf exists
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "name": "asconf"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# sctp chunk data type 0
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "type",
+ "name": "data"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# sctp chunk init flags 23
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "flags",
+ "name": "init"
+ }
+ },
+ "op": "==",
+ "right": 23
+ }
+ }
+]
+
+# sctp chunk init-ack length 42
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "length",
+ "name": "init-ack"
+ }
+ },
+ "op": "==",
+ "right": 42
+ }
+ }
+]
+
+# sctp chunk data stream 1337
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "stream",
+ "name": "data"
+ }
+ },
+ "op": "==",
+ "right": 1337
+ }
+ }
+]
+
+# sctp chunk init initial-tsn 5
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "initial-tsn",
+ "name": "init"
+ }
+ },
+ "op": "==",
+ "right": 5
+ }
+ }
+]
+
+# sctp chunk init-ack num-outbound-streams 3
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "num-outbound-streams",
+ "name": "init-ack"
+ }
+ },
+ "op": "==",
+ "right": 3
+ }
+ }
+]
+
+# sctp chunk sack a-rwnd 1
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "a-rwnd",
+ "name": "sack"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# sctp chunk shutdown cum-tsn-ack 65535
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "cum-tsn-ack",
+ "name": "shutdown"
+ }
+ },
+ "op": "==",
+ "right": 65535
+ }
+ }
+]
+
+# sctp chunk ecne lowest-tsn 5
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "lowest-tsn",
+ "name": "ecne"
+ }
+ },
+ "op": "==",
+ "right": 5
+ }
+ }
+]
+
+# sctp chunk cwr lowest-tsn 8
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "lowest-tsn",
+ "name": "cwr"
+ }
+ },
+ "op": "==",
+ "right": 8
+ }
+ }
+]
+
+# sctp chunk asconf-ack seqno 12345
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "seqno",
+ "name": "asconf-ack"
+ }
+ },
+ "op": "==",
+ "right": 12345
+ }
+ }
+]
+
+# sctp chunk forward-tsn new-cum-tsn 31337
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "new-cum-tsn",
+ "name": "forward-tsn"
+ }
+ },
+ "op": "==",
+ "right": 31337
+ }
+ }
+]
+
+# sctp chunk asconf seqno 12345
+[
+ {
+ "match": {
+ "left": {
+ "sctp chunk": {
+ "field": "seqno",
+ "name": "asconf"
+ }
+ },
+ "op": "==",
+ "right": 12345
+ }
+ }
+]
+
diff --git a/tests/py/inet/sctp.t.payload b/tests/py/inet/sctp.t.payload
new file mode 100644
index 0000000..7337e2e
--- /dev/null
+++ b/tests/py/inet/sctp.t.payload
@@ -0,0 +1,351 @@
+# sctp sport 23
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00001700 ]
+
+# sctp sport != 23
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00001700 ]
+
+# sctp sport 23-44
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00001700 ]
+ [ cmp lte reg 1 0x00002c00 ]
+
+# sctp sport != 23-44
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ range neq reg 1 0x00001700 0x00002c00 ]
+
+# sctp sport { 23, 24, 25}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001700 : 0 [end] element 00001800 : 0 [end] element 00001900 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# sctp sport != { 23, 24, 25}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001700 : 0 [end] element 00001800 : 0 [end] element 00001900 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# sctp dport 23
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001700 ]
+
+# sctp dport != 23
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x00001700 ]
+
+# sctp dport 23-44
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00001700 ]
+ [ cmp lte reg 1 0x00002c00 ]
+
+# sctp dport != 23-44
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00001700 0x00002c00 ]
+
+# sctp dport { 23, 24, 25}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001700 : 0 [end] element 00001800 : 0 [end] element 00001900 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# sctp dport != { 23, 24, 25}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001700 : 0 [end] element 00001800 : 0 [end] element 00001900 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# sctp checksum 1111
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x57040000 ]
+
+# sctp checksum != 11
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp neq reg 1 0x0b000000 ]
+
+# sctp checksum 21-333
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp gte reg 1 0x15000000 ]
+ [ cmp lte reg 1 0x4d010000 ]
+
+# sctp checksum != 32-111
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ range neq reg 1 0x20000000 0x6f000000 ]
+
+# sctp checksum { 22, 33, 44}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 16000000 : 0 [end] element 21000000 : 0 [end] element 2c000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# sctp checksum != { 22, 33, 44}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 16000000 : 0 [end] element 21000000 : 0 [end] element 2c000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# sctp vtag 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# sctp vtag != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp neq reg 1 0xe9000000 ]
+
+# sctp vtag 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# sctp vtag != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# sctp vtag {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# sctp vtag != {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# sctp chunk data exists
+ip
+ [ exthdr load 1b @ 0 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk init exists
+ip
+ [ exthdr load 1b @ 1 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk init-ack exists
+ip
+ [ exthdr load 1b @ 2 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk sack exists
+ip
+ [ exthdr load 1b @ 3 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk heartbeat exists
+ip
+ [ exthdr load 1b @ 4 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk heartbeat-ack exists
+ip
+ [ exthdr load 1b @ 5 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk abort exists
+ip
+ [ exthdr load 1b @ 6 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk shutdown exists
+ip
+ [ exthdr load 1b @ 7 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk shutdown-ack exists
+ip
+ [ exthdr load 1b @ 8 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk error exists
+ip
+ [ exthdr load 1b @ 9 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk cookie-echo exists
+ip
+ [ exthdr load 1b @ 10 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk cookie-ack exists
+ip
+ [ exthdr load 1b @ 11 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk ecne exists
+ip
+ [ exthdr load 1b @ 12 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk cwr exists
+ip
+ [ exthdr load 1b @ 13 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk shutdown-complete exists
+ip
+ [ exthdr load 1b @ 14 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk asconf-ack exists
+ip
+ [ exthdr load 1b @ 128 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk forward-tsn exists
+ip
+ [ exthdr load 1b @ 192 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk asconf exists
+ip
+ [ exthdr load 1b @ 193 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# sctp chunk data type 0
+ip
+ [ exthdr load 1b @ 0 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# sctp chunk init flags 23
+ip
+ [ exthdr load 1b @ 1 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000017 ]
+
+# sctp chunk init-ack length 42
+ip
+ [ exthdr load 2b @ 2 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00002a00 ]
+
+# sctp chunk data stream 1337
+ip
+ [ exthdr load 2b @ 0 + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003905 ]
+
+# sctp chunk init initial-tsn 5
+ip
+ [ exthdr load 4b @ 1 + 16 => reg 1 ]
+ [ cmp eq reg 1 0x05000000 ]
+
+# sctp chunk init-ack num-outbound-streams 3
+ip
+ [ exthdr load 2b @ 2 + 12 => reg 1 ]
+ [ cmp eq reg 1 0x00000300 ]
+
+# sctp chunk sack a-rwnd 1
+ip
+ [ exthdr load 4b @ 3 + 8 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# sctp chunk shutdown cum-tsn-ack 65535
+ip
+ [ exthdr load 4b @ 7 + 4 => reg 1 ]
+ [ cmp eq reg 1 0xffff0000 ]
+
+# sctp chunk ecne lowest-tsn 5
+ip
+ [ exthdr load 4b @ 12 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x05000000 ]
+
+# sctp chunk cwr lowest-tsn 8
+ip
+ [ exthdr load 4b @ 13 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x08000000 ]
+
+# sctp chunk asconf-ack seqno 12345
+ip
+ [ exthdr load 4b @ 128 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x39300000 ]
+
+# sctp chunk forward-tsn new-cum-tsn 31337
+ip
+ [ exthdr load 4b @ 192 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x697a0000 ]
+
+# sctp chunk asconf seqno 12345
+ip
+ [ exthdr load 4b @ 193 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x39300000 ]
+
diff --git a/tests/py/inet/sets.t b/tests/py/inet/sets.t
new file mode 100644
index 0000000..5b22e1f
--- /dev/null
+++ b/tests/py/inet/sets.t
@@ -0,0 +1,25 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*inet;test-inet;input
+*bridge;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+!set1 type ipv4_addr timeout 60s;ok
+?set1 192.168.3.4 timeout 30s, 10.2.1.1;ok
+
+!set2 type ipv6_addr timeout 23d23h59m59s;ok
+?set2 dead::beef timeout 5s;ok
+
+ip saddr @set1 drop;ok
+ip saddr != @set2 drop;fail
+
+ip6 daddr != @set2 accept;ok
+ip6 daddr @set1 drop;fail
+
+!set3 type ipv4_addr . ipv4_addr . inet_service flags interval;ok
+?set3 10.0.0.0/8 . 192.168.1.3-192.168.1.9 . 1024-65535;ok
+
+ip saddr . ip daddr . tcp dport @set3 accept;ok
+ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept;ok
diff --git a/tests/py/inet/sets.t.json b/tests/py/inet/sets.t.json
new file mode 100644
index 0000000..b44ffc2
--- /dev/null
+++ b/tests/py/inet/sets.t.json
@@ -0,0 +1,136 @@
+# ip saddr @set1 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "@set1"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip6 daddr != @set2 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": "@set2"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip saddr . ip daddr . tcp dport @set3 accept
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": "@set3"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ {
+ "prefix": {
+ "addr": "10.0.0.0",
+ "len": 8
+ }
+ },
+ {
+ "range": [
+ 10,
+ 23
+ ]
+ }
+ ]
+ },
+ {
+ "concat": [
+ {
+ "range": [
+ "192.168.1.1",
+ "192.168.3.8"
+ ]
+ },
+ {
+ "range": [
+ 80,
+ 443
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
diff --git a/tests/py/inet/sets.t.payload.bridge b/tests/py/inet/sets.t.payload.bridge
new file mode 100644
index 0000000..3dd9d57
--- /dev/null
+++ b/tests/py/inet/sets.t.payload.bridge
@@ -0,0 +1,42 @@
+# ip saddr @set1 drop
+bridge test-inet input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set1 ]
+ [ immediate reg 0 drop ]
+
+# ip6 daddr != @set2 accept
+bridge test-inet input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ lookup reg 1 set set2 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip saddr . ip daddr . tcp dport @set3 accept
+bridge
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ payload load 2b @ transport header + 2 => reg 10 ]
+ [ lookup reg 1 set set3 ]
+ [ immediate reg 0 accept ]
+
+# ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept
+__set%d test-inet 87
+__set%d test-inet 0
+ element 0000000a 00000a00 - ffffff0a 00001700 : 0 [end] element 0101a8c0 00005000 - 0803a8c0 0000bb01 : 0 [end]
+bridge
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ payload load 2b @ transport header + 2 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
diff --git a/tests/py/inet/sets.t.payload.inet b/tests/py/inet/sets.t.payload.inet
new file mode 100644
index 0000000..53c6b18
--- /dev/null
+++ b/tests/py/inet/sets.t.payload.inet
@@ -0,0 +1,41 @@
+# ip saddr @set1 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set1 ]
+ [ immediate reg 0 drop ]
+
+# ip6 daddr != @set2 accept
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ lookup reg 1 set set2 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip saddr . ip daddr . tcp dport @set3 accept
+inet
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ payload load 2b @ transport header + 2 => reg 10 ]
+ [ lookup reg 1 set set3 ]
+ [ immediate reg 0 accept ]
+
+# ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept
+__set%d test-inet 87
+__set%d test-inet 0
+ element 0000000a 00000a00 - ffffff0a 00001700 : 0 [end] element 0101a8c0 00005000 - 0803a8c0 0000bb01 : 0 [end]
+inet
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ payload load 2b @ transport header + 2 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
diff --git a/tests/py/inet/sets.t.payload.netdev b/tests/py/inet/sets.t.payload.netdev
new file mode 100644
index 0000000..e31aeb9
--- /dev/null
+++ b/tests/py/inet/sets.t.payload.netdev
@@ -0,0 +1,41 @@
+# ip saddr @set1 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set1 ]
+ [ immediate reg 0 drop ]
+
+# ip6 daddr != @set2 accept
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ lookup reg 1 set set2 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip saddr . ip daddr . tcp dport @set3 accept
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ payload load 2b @ transport header + 2 => reg 10 ]
+ [ lookup reg 1 set set3 ]
+ [ immediate reg 0 accept ]
+
+# ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept
+__set%d test-netdev 87
+__set%d test-netdev 0
+ element 0000000a 00000a00 - ffffff0a 00001700 : 0 [end] element 0101a8c0 00005000 - 0803a8c0 0000bb01 : 0 [end]
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ payload load 2b @ transport header + 2 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
diff --git a/tests/py/inet/snat.t b/tests/py/inet/snat.t
new file mode 100644
index 0000000..cf23b5c
--- /dev/null
+++ b/tests/py/inet/snat.t
@@ -0,0 +1,21 @@
+:postrouting;type nat hook postrouting priority 0
+
+*inet;test-inet;postrouting
+
+# explicit family: 'snat to ip':
+iifname "eth0" tcp dport 81 snat ip to 192.168.3.2;ok
+
+# infer snat target family from network header base:
+iifname "eth0" tcp dport 81 ip saddr 10.1.1.1 snat to 192.168.3.2;ok;iifname "eth0" tcp dport 81 ip saddr 10.1.1.1 snat ip to 192.168.3.2
+iifname "eth0" tcp dport 81 snat ip6 to dead::beef;ok
+
+iifname "foo" masquerade random;ok
+
+
+snat to 192.168.3.2;fail
+snat ip6 to 192.168.3.2;fail
+snat to dead::beef;fail
+snat ip to dead::beef;fail
+snat ip daddr 1.2.3.4 to dead::beef;fail
+snat ip daddr 1.2.3.4 ip6 to dead::beef;fail
+snat ip6 saddr dead::beef to 1.2.3.4;fail
diff --git a/tests/py/inet/snat.t.json b/tests/py/inet/snat.t.json
new file mode 100644
index 0000000..4671625
--- /dev/null
+++ b/tests/py/inet/snat.t.json
@@ -0,0 +1,131 @@
+# iifname "eth0" tcp dport 81 snat ip to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 81
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2",
+ "family": "ip"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 81 ip saddr 10.1.1.1 snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 81
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "10.1.1.1"
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2",
+ "family": "ip"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 81 snat ip6 to dead::beef
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 81
+ }
+ },
+ {
+ "snat": {
+ "addr": "dead::beef",
+ "family": "ip6"
+ }
+ }
+]
+
+# iifname "foo" masquerade random
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "foo"
+ }
+ },
+ {
+ "masquerade": {
+ "flags": "random"
+ }
+ }
+]
+
diff --git a/tests/py/inet/snat.t.payload b/tests/py/inet/snat.t.payload
new file mode 100644
index 0000000..50519c6
--- /dev/null
+++ b/tests/py/inet/snat.t.payload
@@ -0,0 +1,42 @@
+# iifname "eth0" tcp dport 81 snat ip to 192.168.3.2
+inet test-inet postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005100 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat snat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport 81 ip saddr 10.1.1.1 snat to 192.168.3.2
+inet test-inet postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005100 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0101010a ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat snat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport 81 snat ip6 to dead::beef
+inet test-inet postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005100 ]
+ [ immediate reg 1 0x0000adde 0x00000000 0x00000000 0xefbe0000 ]
+ [ nat snat ip6 addr_min reg 1 ]
+
+# iifname "foo" masquerade random
+inet test-inet postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x006f6f66 0x00000000 0x00000000 0x00000000 ]
+ [ masq flags 0x4 ]
diff --git a/tests/py/inet/socket.t b/tests/py/inet/socket.t
new file mode 100644
index 0000000..05e9ebb
--- /dev/null
+++ b/tests/py/inet/socket.t
@@ -0,0 +1,15 @@
+:sockchain;type filter hook prerouting priority -150
+
+*ip;sockip4;sockchain
+*ip6;sockip6;sockchain
+*inet;sockin;sockchain
+
+socket transparent 0;ok
+socket transparent 1;ok
+socket transparent 2;fail
+
+socket mark 0x00000005;ok
+
+socket wildcard 0;ok
+socket wildcard 1;ok
+socket wildcard 2;fail
diff --git a/tests/py/inet/socket.t.json b/tests/py/inet/socket.t.json
new file mode 100644
index 0000000..fa48e79
--- /dev/null
+++ b/tests/py/inet/socket.t.json
@@ -0,0 +1,74 @@
+# socket transparent 0
+[
+ {
+ "match": {
+ "left": {
+ "socket": {
+ "key": "transparent"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# socket transparent 1
+[
+ {
+ "match": {
+ "left": {
+ "socket": {
+ "key": "transparent"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# socket mark 0x00000005
+[
+ {
+ "match": {
+ "left": {
+ "socket": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "right": 5
+ }
+ }
+]
+
+# socket wildcard 0
+[
+ {
+ "match": {
+ "left": {
+ "socket": {
+ "key": "wildcard"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# socket wildcard 1
+[
+ {
+ "match": {
+ "left": {
+ "socket": {
+ "key": "wildcard"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
diff --git a/tests/py/inet/socket.t.payload b/tests/py/inet/socket.t.payload
new file mode 100644
index 0000000..e66ccbf
--- /dev/null
+++ b/tests/py/inet/socket.t.payload
@@ -0,0 +1,24 @@
+# socket transparent 0
+inet sockin sockchain
+ [ socket load transparent => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# socket transparent 1
+inet sockin sockchain
+ [ socket load transparent => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# socket mark 0x00000005
+inet sockin sockchain
+ [ socket load mark => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+
+# socket wildcard 0
+inet sockin sockchain
+ [ socket load wildcard => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# socket wildcard 1
+inet sockin sockchain
+ [ socket load wildcard => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
diff --git a/tests/py/inet/synproxy.t b/tests/py/inet/synproxy.t
new file mode 100644
index 0000000..55a05e1
--- /dev/null
+++ b/tests/py/inet/synproxy.t
@@ -0,0 +1,13 @@
+:synproxychain;type filter hook input priority 0
+
+*ip;synproxyip;synproxychain
+*ip6;synproxyip6;synproxychain
+*inet;synproxyinet;synproxychain
+
+synproxy;ok
+synproxy mss 1460 wscale 7;ok
+synproxy mss 1460 wscale 5 timestamp sack-perm;ok
+synproxy timestamp sack-perm;ok
+synproxy timestamp;ok
+synproxy sack-perm;ok
+
diff --git a/tests/py/inet/synproxy.t.json b/tests/py/inet/synproxy.t.json
new file mode 100644
index 0000000..1dd85a6
--- /dev/null
+++ b/tests/py/inet/synproxy.t.json
@@ -0,0 +1,64 @@
+# synproxy
+[
+ {
+ "synproxy":null
+ }
+]
+
+# synproxy mss 1460 wscale 7
+[
+ {
+ "synproxy": {
+ "mss": 1460,
+ "wscale": 7
+ }
+ }
+]
+
+# synproxy timestamp
+[
+ {
+ "synproxy": {
+ "flags": [
+ "timestamp"
+ ]
+ }
+ }
+]
+
+# synproxy timestamp sack-perm
+[
+ {
+ "synproxy": {
+ "flags": [
+ "timestamp",
+ "sack-perm"
+ ]
+ }
+ }
+]
+
+# synproxy mss 1460 wscale 5 timestamp sack-perm
+[
+ {
+ "synproxy": {
+ "flags": [
+ "timestamp",
+ "sack-perm"
+ ],
+ "mss": 1460,
+ "wscale": 5
+ }
+ }
+]
+
+# synproxy sack-perm
+[
+ {
+ "synproxy": {
+ "flags": [
+ "sack-perm"
+ ]
+ }
+ }
+]
diff --git a/tests/py/inet/synproxy.t.payload b/tests/py/inet/synproxy.t.payload
new file mode 100644
index 0000000..dd318b9
--- /dev/null
+++ b/tests/py/inet/synproxy.t.payload
@@ -0,0 +1,24 @@
+# synproxy
+inet synproxyinet synproxychain
+ [ synproxy mss 0 wscale 0 ]
+
+# synproxy mss 1460 wscale 7
+inet synproxyinet synproxychain
+ [ synproxy mss 1460 wscale 7 ]
+
+# synproxy mss 1460 wscale 5 timestamp sack-perm
+inet synproxyinet synproxychain
+ [ synproxy mss 1460 wscale 5 ]
+
+# synproxy timestamp sack-perm
+inet synproxyinet synproxychain
+ [ synproxy mss 0 wscale 0 ]
+
+# synproxy timestamp
+inet synproxyinet synproxychain
+ [ synproxy mss 0 wscale 0 ]
+
+# synproxy sack-perm
+inet synproxyinet synproxychain
+ [ synproxy mss 0 wscale 0 ]
+
diff --git a/tests/py/inet/tcp.t b/tests/py/inet/tcp.t
new file mode 100644
index 0000000..f51ebd3
--- /dev/null
+++ b/tests/py/inet/tcp.t
@@ -0,0 +1,115 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+tcp dport set {1, 2, 3};fail
+
+tcp dport 22;ok
+tcp dport != 233;ok
+tcp dport 33-45;ok
+tcp dport != 33-45;ok
+tcp dport { 33, 55, 67, 88};ok
+tcp dport != { 33, 55, 67, 88};ok
+tcp dport {telnet, http, https} accept;ok;tcp dport { 443, 23, 80} accept
+tcp dport vmap { 22 : accept, 23 : drop };ok
+tcp dport vmap { 25:accept, 28:drop };ok
+tcp dport { 22, 53, 80, 110 };ok
+tcp dport != { 22, 53, 80, 110 };ok
+# BUG: invalid expression type set
+# nft: src/evaluate.c:975: expr_evaluate_relational: Assertion '0' failed.
+
+tcp sport 22;ok
+tcp sport != 233;ok
+tcp sport 33-45;ok
+tcp sport != 33-45;ok
+tcp sport { 33, 55, 67, 88};ok
+tcp sport != { 33, 55, 67, 88};ok
+tcp sport vmap { 25:accept, 28:drop };ok
+
+tcp sport 8080 drop;ok
+tcp sport 1024 tcp dport 22;ok
+tcp sport 1024 tcp dport 22 tcp sequence 0;ok
+
+tcp sequence 0 tcp sport 1024 tcp dport 22;ok
+tcp sequence 0 tcp sport { 1024, 1022} tcp dport 22;ok;tcp sequence 0 tcp sport { 1022, 1024} tcp dport 22
+
+tcp sequence 22;ok
+tcp sequence != 233;ok
+tcp sequence 33-45;ok
+tcp sequence != 33-45;ok
+tcp sequence { 33, 55, 67, 88};ok
+tcp sequence != { 33, 55, 67, 88};ok
+
+tcp ackseq 42949672 drop;ok
+tcp ackseq 22;ok
+tcp ackseq != 233;ok
+tcp ackseq 33-45;ok
+tcp ackseq != 33-45;ok
+tcp ackseq { 33, 55, 67, 88};ok
+tcp ackseq != { 33, 55, 67, 88};ok
+
+- tcp doff 22;ok
+- tcp doff != 233;ok
+- tcp doff 33-45;ok
+- tcp doff != 33-45;ok
+- tcp doff { 33, 55, 67, 88};ok
+- tcp doff != { 33, 55, 67, 88};ok
+
+# BUG reserved
+# BUG: It is accepted but it is not shown then. tcp reserver
+
+tcp flags { fin, syn, rst, psh, ack, urg, ecn, cwr} drop;ok
+tcp flags != { fin, urg, ecn, cwr} drop;ok
+tcp flags cwr;ok
+tcp flags != cwr;ok
+tcp flags == syn;ok
+tcp flags fin,syn / fin,syn;ok
+tcp flags != syn / fin,syn;ok
+tcp flags & syn != 0;ok;tcp flags syn
+tcp flags & syn == 0;ok;tcp flags ! syn
+tcp flags & (syn | ack) != 0;ok;tcp flags syn,ack
+tcp flags & (syn | ack) == 0;ok;tcp flags ! syn,ack
+# it should be possible to transform this to: tcp flags syn
+tcp flags & syn == syn;ok
+tcp flags & syn != syn;ok
+tcp flags & (fin | syn | rst | ack) syn;ok;tcp flags syn / fin,syn,rst,ack
+tcp flags & (fin | syn | rst | ack) == syn;ok;tcp flags syn / fin,syn,rst,ack
+tcp flags & (fin | syn | rst | ack) != syn;ok;tcp flags != syn / fin,syn,rst,ack
+tcp flags & (fin | syn | rst | ack) == (syn | ack);ok;tcp flags syn,ack / fin,syn,rst,ack
+tcp flags & (fin | syn | rst | ack) != (syn | ack);ok;tcp flags != syn,ack / fin,syn,rst,ack
+tcp flags & (syn | ack) == (syn | ack);ok;tcp flags syn,ack / syn,ack
+tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr;ok;tcp flags == 0xff
+tcp flags { syn, syn | ack };ok
+tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack };ok
+tcp flags ! fin,rst;ok
+tcp flags & (fin | syn | rst | ack) ! syn;fail
+
+tcp window 22222;ok
+tcp window 22;ok
+tcp window != 233;ok
+tcp window 33-45;ok
+tcp window != 33-45;ok
+tcp window { 33, 55, 67, 88};ok
+tcp window != { 33, 55, 67, 88};ok
+
+tcp checksum 22;ok
+tcp checksum != 233;ok
+tcp checksum 33-45;ok
+tcp checksum != 33-45;ok
+tcp checksum { 33, 55, 67, 88};ok
+tcp checksum != { 33, 55, 67, 88};ok
+
+tcp urgptr 1234 accept;ok
+tcp urgptr 22;ok
+tcp urgptr != 233;ok
+tcp urgptr 33-45;ok
+tcp urgptr != 33-45;ok
+tcp urgptr { 33, 55, 67, 88};ok
+tcp urgptr != { 33, 55, 67, 88};ok
+
+tcp doff 8;ok
diff --git a/tests/py/inet/tcp.t.json b/tests/py/inet/tcp.t.json
new file mode 100644
index 0000000..8439c2b
--- /dev/null
+++ b/tests/py/inet/tcp.t.json
@@ -0,0 +1,1799 @@
+# tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp dport != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp dport 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp dport != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp dport { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport {telnet, http, https} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "telnet",
+ "http",
+ "https"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp dport vmap { 22 : accept, 23 : drop }
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 22,
+ {
+ "accept": null
+ }
+ ],
+ [
+ 23,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport vmap { 25:accept, 28:drop }
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 25,
+ {
+ "accept": null
+ }
+ ],
+ [
+ 28,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport { 22, 53, 80, 110 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 22,
+ 53,
+ 80,
+ 110
+ ]
+ }
+ }
+ }
+]
+
+# tcp dport != { 22, 53, 80, 110 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 22,
+ 53,
+ 80,
+ 110
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp sport != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp sport 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp sport != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp sport { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport vmap { 25:accept, 28:drop }
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 25,
+ {
+ "accept": null
+ }
+ ],
+ [
+ 28,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# tcp sport 8080 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 8080
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# tcp sport 1024 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 1024
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp sport 1024 tcp dport 22 tcp sequence 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 1024
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# tcp sequence 0 tcp sport 1024 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 1024
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp sequence 0 tcp sport { 1024, 1022} tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 1024,
+ 1022
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp sequence 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp sequence != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp sequence 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp sequence != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp sequence { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp sequence != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp ackseq 42949672 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 42949672
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# tcp ackseq 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp ackseq != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp ackseq 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp ackseq != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp ackseq { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp ackseq != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ackseq",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp flags { fin, syn, rst, psh, ack, urg, ecn, cwr} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "fin",
+ "syn",
+ "rst",
+ "psh",
+ "ack",
+ "urg",
+ "ecn",
+ "cwr"
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# tcp flags != { fin, urg, ecn, cwr} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "fin",
+ "urg",
+ "ecn",
+ "cwr"
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# tcp flags cwr
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "in",
+ "right": "cwr"
+ }
+ }
+]
+
+# tcp flags != cwr
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": "cwr"
+ }
+ }
+]
+
+# tcp flags == syn
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": "syn"
+ }
+ }
+]
+
+# tcp flags & (syn|fin) == (syn|fin)
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ {
+ "|": [
+ "syn",
+ "fin"
+ ]
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "|": [
+ "syn",
+ "fin"
+ ]
+ }
+ }
+ }
+]
+
+# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ {
+ "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ]
+ }
+ ]
+ },
+ "op": "==",
+ "right": { "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ] }
+ }
+ }
+]
+
+# tcp window 22222
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22222
+ }
+ }
+]
+
+# tcp window 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp window != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp window 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp window != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp window { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp window != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "window",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp checksum 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp checksum != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp checksum 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp checksum != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp checksum { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp checksum != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp urgptr 1234 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 1234
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp urgptr 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp urgptr != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# tcp urgptr 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp urgptr != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# tcp urgptr { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp urgptr != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "urgptr",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# tcp doff 8
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "doff",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 8
+ }
+ }
+]
+
+# tcp flags { syn, syn | ack }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "|": [
+ "syn",
+ "ack"
+ ]
+ },
+ "syn"
+ ]
+ }
+ }
+ }
+]
+
+# tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack }
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ {
+ "|": [
+ {
+ "|": [
+ {
+ "|": [
+ {
+ "|": [
+ {
+ "|": [
+ "fin",
+ "syn"
+ ]
+ },
+ "rst"
+ ]
+ },
+ "psh"
+ ]
+ },
+ "ack"
+ ]
+ },
+ "urg"
+ ]
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "|": [
+ {
+ "|": [
+ "fin",
+ "psh"
+ ]
+ },
+ "ack"
+ ]
+ },
+ "fin",
+ {
+ "|": [
+ "psh",
+ "ack"
+ ]
+ },
+ "ack"
+ ]
+ }
+ }
+ }
+]
+
+# tcp flags ! fin,rst
+[
+ {
+ "match": {
+ "op": "!",
+ "left": {
+ "payload": {
+ "protocol": "tcp",
+ "field": "flags"
+ }
+ },
+ "right": [
+ "fin",
+ "rst"
+ ]
+ }
+ }
+]
+
+# tcp flags fin,syn / fin,syn
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ [
+ "fin",
+ "syn"
+ ]
+ ]
+ },
+ "op": "==",
+ "right": [
+ "fin",
+ "syn"
+ ]
+ }
+ }
+]
+
+# tcp flags != syn / fin,syn
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ [
+ "fin",
+ "syn"
+ ]
+ ]
+ },
+ "op": "!=",
+ "right": "syn"
+ }
+ }
+]
+
+# tcp flags & syn == 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!",
+ "right": "syn"
+ }
+ }
+]
+
+# tcp flags & syn != 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "in",
+ "right": "syn"
+ }
+ }
+]
+
+# tcp flags & (syn | ack) != 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "in",
+ "right": [
+ "syn",
+ "ack"
+ ]
+ }
+ }
+]
+
+# tcp flags & (syn | ack) == 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!",
+ "right": [
+ "syn",
+ "ack"
+ ]
+ }
+ }
+]
+
+# tcp flags & syn == syn
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "syn"
+ ]
+ },
+ "op": "==",
+ "right": "syn"
+ }
+ }
+]
+
+# tcp flags & syn != syn
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "syn"
+ ]
+ },
+ "op": "!=",
+ "right": "syn"
+ }
+ }
+]
+
+# tcp flags & (fin | syn | rst | ack) syn
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ [
+ "fin",
+ "syn",
+ "rst",
+ "ack"
+ ]
+ ]
+ },
+ "op": "==",
+ "right": "syn"
+ }
+ }
+]
+
+# tcp flags & (fin | syn | rst | ack) == syn
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ [
+ "fin",
+ "syn",
+ "rst",
+ "ack"
+ ]
+ ]
+ },
+ "op": "==",
+ "right": "syn"
+ }
+ }
+]
+
+
+# tcp flags & (fin | syn | rst | ack) != syn
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ [
+ "fin",
+ "syn",
+ "rst",
+ "ack"
+ ]
+ ]
+ },
+ "op": "!=",
+ "right": "syn"
+ }
+ }
+]
+
+# tcp flags & (fin | syn | rst | ack) == (syn | ack)
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ [
+ "fin",
+ "syn",
+ "rst",
+ "ack"
+ ]
+ ]
+ },
+ "op": "==",
+ "right": [
+ "syn",
+ "ack"
+ ]
+ }
+ }
+]
+
+# tcp flags & (fin | syn | rst | ack) != (syn | ack)
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ [
+ "fin",
+ "syn",
+ "rst",
+ "ack"
+ ]
+ ]
+ },
+ "op": "!=",
+ "right": [
+ "syn",
+ "ack"
+ ]
+ }
+ }
+]
+
+# tcp flags & (syn | ack) == (syn | ack)
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ [
+ "syn",
+ "ack"
+ ]
+ ]
+ },
+ "op": "==",
+ "right": [
+ "syn",
+ "ack"
+ ]
+ }
+ }
+]
+
diff --git a/tests/py/inet/tcp.t.json.output b/tests/py/inet/tcp.t.json.output
new file mode 100644
index 0000000..c471e8d
--- /dev/null
+++ b/tests/py/inet/tcp.t.json.output
@@ -0,0 +1,210 @@
+# tcp dport {telnet, http, https} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 23,
+ 80,
+ 443
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp sequence 0 tcp sport { 1024, 1022} tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 1022,
+ 1024
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# tcp flags & (syn|fin) == (syn|fin)
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ {
+ "|": [
+ "fin",
+ "syn"
+ ]
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "|": [
+ "fin",
+ "syn"
+ ]
+ }
+ }
+ }
+]
+
+# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 255
+ }
+ }
+]
+
+# tcp flags { syn, syn | ack }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "syn",
+ {
+ "|": [
+ "syn",
+ "ack"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack }
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "flags",
+ "protocol": "tcp"
+ }
+ },
+ {
+ "|": [
+ {
+ "|": [
+ {
+ "|": [
+ {
+ "|": [
+ {
+ "|": [
+ "fin",
+ "syn"
+ ]
+ },
+ "rst"
+ ]
+ },
+ "psh"
+ ]
+ },
+ "ack"
+ ]
+ },
+ "urg"
+ ]
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "fin",
+ {
+ "|": [
+ {
+ "|": [
+ "fin",
+ "psh"
+ ]
+ },
+ "ack"
+ ]
+ },
+ {
+ "|": [
+ "psh",
+ "ack"
+ ]
+ },
+ "ack"
+ ]
+ }
+ }
+ }
+]
diff --git a/tests/py/inet/tcp.t.payload b/tests/py/inet/tcp.t.payload
new file mode 100644
index 0000000..1cfe500
--- /dev/null
+++ b/tests/py/inet/tcp.t.payload
@@ -0,0 +1,674 @@
+# tcp dport 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# tcp dport != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# tcp dport 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# tcp dport != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# tcp dport { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp dport != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# tcp dport {telnet, http, https} accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001700 : 0 [end] element 00005000 : 0 [end] element 0000bb01 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# tcp dport vmap { 22 : accept, 23 : drop }
+__map%d test-inet b
+__map%d test-inet 0
+ element 00001600 : accept 0 [end] element 00001700 : drop 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# tcp dport vmap { 25:accept, 28:drop }
+__map%d test-inet b
+__map%d test-inet 0
+ element 00001900 : accept 0 [end] element 00001c00 : drop 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# tcp dport { 22, 53, 80, 110 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001600 : 0 [end] element 00003500 : 0 [end] element 00005000 : 0 [end] element 00006e00 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp dport != { 22, 53, 80, 110 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00001600 : 0 [end] element 00003500 : 0 [end] element 00005000 : 0 [end] element 00006e00 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# tcp sport 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# tcp sport != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# tcp sport 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# tcp sport != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# tcp sport { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp sport != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# tcp sport vmap { 25:accept, 28:drop }
+__map%d test-inet b
+__map%d test-inet 0
+ element 00001900 : accept 0 [end] element 00001c00 : drop 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# tcp sport 8080 drop
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000901f ]
+ [ immediate reg 0 drop ]
+
+# tcp sport 1024 tcp dport 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x16000004 ]
+
+# tcp sport 1024 tcp dport 22 tcp sequence 0
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x16000004 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# tcp sequence 0 tcp sport 1024 tcp dport 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ payload load 4b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x16000004 ]
+
+# tcp sequence 0 tcp sport { 1024, 1022} tcp dport 22
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000004 : 0 [end] element 0000fe03 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# tcp sequence 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# tcp sequence != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp neq reg 1 0xe9000000 ]
+
+# tcp sequence 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# tcp sequence != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# tcp sequence { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp sequence != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# tcp ackseq 42949672 drop
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x285c8f02 ]
+ [ immediate reg 0 drop ]
+
+# tcp ackseq 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# tcp ackseq != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp neq reg 1 0xe9000000 ]
+
+# tcp ackseq 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# tcp ackseq != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# tcp ackseq { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp ackseq != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ transport header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# tcp flags { fin, syn, rst, psh, ack, urg, ecn, cwr} drop
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000001 : 0 [end] element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000008 : 0 [end] element 00000010 : 0 [end] element 00000020 : 0 [end] element 00000040 : 0 [end] element 00000080 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 drop ]
+
+# tcp flags != { fin, urg, ecn, cwr} drop
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000001 : 0 [end] element 00000020 : 0 [end] element 00000040 : 0 [end] element 00000080 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 drop ]
+
+# tcp flags cwr
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000080 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# tcp flags != cwr
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ cmp neq reg 1 0x00000080 ]
+
+# tcp flags == syn
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# tcp flags fin,syn / fin,syn
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000003 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000003 ]
+
+# tcp flags != syn / fin,syn
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000003 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000002 ]
+
+# tcp flags & syn != 0
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000002 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# tcp flags & syn == 0
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000002 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# tcp flags & (syn | ack) != 0
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000012 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# tcp flags & (syn | ack) == 0
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000012 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# tcp flags & syn == syn
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000002 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# tcp flags & syn != syn
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000002 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000002 ]
+
+# tcp flags & (fin | syn | rst | ack) syn
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# tcp flags & (fin | syn | rst | ack) == syn
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# tcp flags & (fin | syn | rst | ack) != syn
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000002 ]
+
+# tcp flags & (fin | syn | rst | ack) == (syn | ack)
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000012 ]
+
+# tcp flags & (fin | syn | rst | ack) != (syn | ack)
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000012 ]
+
+# tcp flags & (syn | ack) == (syn | ack)
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000012 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000012 ]
+
+# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000ff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x000000ff ]
+
+# tcp window 22222
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x0000ce56 ]
+
+# tcp window 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# tcp window != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 14 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# tcp window 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 14 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# tcp window != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 14 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# tcp window { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 14 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp window != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 14 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# tcp checksum 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# tcp checksum != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 16 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# tcp checksum 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# tcp checksum != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 16 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# tcp checksum { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp checksum != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# tcp urgptr 1234 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 18 => reg 1 ]
+ [ cmp eq reg 1 0x0000d204 ]
+ [ immediate reg 0 accept ]
+
+# tcp urgptr 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 18 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# tcp urgptr != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 18 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# tcp urgptr 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 18 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# tcp urgptr != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 18 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# tcp urgptr { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 18 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp urgptr != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 18 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# tcp doff 8
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000080 ]
+
+# tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000001 : 0 [end] element 00000010 : 0 [end] element 00000018 : 0 [end] element 00000019 : 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000003f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp flags { syn, syn | ack }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000002 : 0 [end] element 00000012 : 0 [end]
+inet
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# tcp flags ! fin,rst
+inet
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 1b @ transport header + 13 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000005 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
diff --git a/tests/py/inet/tproxy.t b/tests/py/inet/tproxy.t
new file mode 100644
index 0000000..d23bbcb
--- /dev/null
+++ b/tests/py/inet/tproxy.t
@@ -0,0 +1,21 @@
+:y;type filter hook prerouting priority -150
+
+*inet;x;y
+
+tproxy;fail
+meta l4proto 17 tproxy to 192.0.2.1;fail
+meta l4proto 6 tproxy to 192.0.2.1:50080;fail
+meta l4proto 17 tproxy ip to 192.0.2.1;ok
+meta l4proto 6 tproxy ip to 192.0.2.1:50080;ok
+ip protocol 6 tproxy ip6 to [2001:db8::1];fail
+
+meta l4proto 6 tproxy to [2001:db8::1];fail
+meta l4proto 17 tproxy to [2001:db8::1]:50080;fail
+meta l4proto 6 tproxy ip6 to [2001:db8::1];ok
+meta l4proto 17 tproxy ip6 to [2001:db8::1]:50080;ok
+ip6 nexthdr 6 tproxy ip to 192.0.2.1;fail
+
+meta l4proto 17 tproxy ip to :50080;ok
+meta l4proto 17 tproxy ip6 to :50080;ok
+meta l4proto 17 tproxy to :50080;ok
+ip daddr 0.0.0.0/0 meta l4proto 6 tproxy ip to :2000;ok
diff --git a/tests/py/inet/tproxy.t.json b/tests/py/inet/tproxy.t.json
new file mode 100644
index 0000000..7b3b11c
--- /dev/null
+++ b/tests/py/inet/tproxy.t.json
@@ -0,0 +1,185 @@
+# meta l4proto 17 tproxy ip to 192.0.2.1
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "192.0.2.1",
+ "family": "ip"
+ }
+ }
+]
+
+# meta l4proto 6 tproxy ip to 192.0.2.1:50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "192.0.2.1",
+ "family": "ip",
+ "port": 50080
+ }
+ }
+]
+
+# meta l4proto 6 tproxy ip6 to [2001:db8::1]
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "2001:db8::1",
+ "family": "ip6"
+ }
+ }
+]
+
+# meta l4proto 17 tproxy ip6 to [2001:db8::1]:50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "2001:db8::1",
+ "family": "ip6",
+ "port": 50080
+ }
+ }
+]
+
+# meta l4proto 17 tproxy ip to :50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "family": "ip",
+ "port": 50080
+ }
+ }
+]
+
+# meta l4proto 17 tproxy ip6 to :50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "family": "ip6",
+ "port": 50080
+ }
+ }
+]
+
+# meta l4proto 17 tproxy to :50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "port": 50080
+ }
+ }
+]
+
+# ip daddr 0.0.0.0/0 meta l4proto 6 tproxy ip to :2000
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "0.0.0.0",
+ "len": 0
+ }
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "family": "ip",
+ "port": 2000
+ }
+ }
+]
diff --git a/tests/py/inet/tproxy.t.payload b/tests/py/inet/tproxy.t.payload
new file mode 100644
index 0000000..24bf8f6
--- /dev/null
+++ b/tests/py/inet/tproxy.t.payload
@@ -0,0 +1,63 @@
+# meta l4proto 17 tproxy ip to 192.0.2.1
+inet x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0x010200c0 ]
+ [ tproxy ip addr reg 1 ]
+
+# meta l4proto 6 tproxy ip to 192.0.2.1:50080
+inet x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x010200c0 ]
+ [ immediate reg 2 0x0000a0c3 ]
+ [ tproxy ip addr reg 1 port reg 2 ]
+
+# meta l4proto 6 tproxy ip6 to [2001:db8::1]
+inet x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0xb80d0120 0x00000000 0x00000000 0x01000000 ]
+ [ tproxy ip6 addr reg 1 ]
+
+# meta l4proto 17 tproxy ip6 to [2001:db8::1]:50080
+inet x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0xb80d0120 0x00000000 0x00000000 0x01000000 ]
+ [ immediate reg 2 0x0000a0c3 ]
+ [ tproxy ip6 addr reg 1 port reg 2 ]
+
+# meta l4proto 17 tproxy to :50080
+inet x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0x0000a0c3 ]
+ [ tproxy port reg 1 ]
+
+# meta l4proto 17 tproxy ip to :50080
+inet x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0x0000a0c3 ]
+ [ tproxy ip port reg 1 ]
+
+# meta l4proto 17 tproxy ip6 to :50080
+inet x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0x0000a0c3 ]
+ [ tproxy ip6 port reg 1 ]
+
+# ip daddr 0.0.0.0/0 meta l4proto 6 tproxy ip to :2000
+inet x y
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000000 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x0000d007 ]
+ [ tproxy ip port reg 1 ]
+
diff --git a/tests/py/inet/udp.t b/tests/py/inet/udp.t
new file mode 100644
index 0000000..7f21c8e
--- /dev/null
+++ b/tests/py/inet/udp.t
@@ -0,0 +1,45 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+udp sport 80 accept;ok
+udp sport != 60 accept;ok
+udp sport 50-70 accept;ok
+udp sport != 50-60 accept;ok
+udp sport { 49, 50} drop;ok
+udp sport != { 50, 60} accept;ok
+
+udp dport set {1, 2, 3};fail
+
+udp dport 80 accept;ok
+udp dport != 60 accept;ok
+udp dport 70-75 accept;ok
+udp dport != 50-60 accept;ok
+udp dport { 49, 50} drop;ok
+udp dport != { 50, 60} accept;ok
+
+udp length 6666;ok
+udp length != 6666;ok
+udp length 50-65 accept;ok
+udp length != 50-65 accept;ok
+udp length { 50, 65} accept;ok
+udp length != { 50, 65} accept;ok
+
+udp checksum 6666 drop;ok
+udp checksum != { 444, 555} accept;ok
+
+udp checksum 22;ok
+udp checksum != 233;ok
+udp checksum 33-45;ok
+udp checksum != 33-45;ok
+udp checksum { 33, 55, 67, 88};ok
+udp checksum != { 33, 55, 67, 88};ok
+
+# limit impact to lo
+iif "lo" udp checksum set 0;ok
+iif "lo" udp dport set 65535;ok
diff --git a/tests/py/inet/udp.t.json b/tests/py/inet/udp.t.json
new file mode 100644
index 0000000..665998e
--- /dev/null
+++ b/tests/py/inet/udp.t.json
@@ -0,0 +1,583 @@
+# udp sport 80 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 80
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp sport != 60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": 60
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp sport 50-70 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 50, 70 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp sport != 50-60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 60 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp sport { 49, 50} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udp sport != { 50, 60} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 50,
+ 60
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport 80 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 80
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport != 60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": 60
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport 70-75 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 70, 75 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport != 50-60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 60 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp dport { 49, 50} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udp dport != { 50, 60} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 50,
+ 60
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp length 6666
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6666
+ }
+ }
+]
+
+# udp length != 6666
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": 6666
+ }
+ }
+]
+
+# udp length 50-65 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 50, 65 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp length != 50-65 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 65 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp length { 50, 65} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 50,
+ 65
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp length != { 50, 65} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 50,
+ 65
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp checksum 6666 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 6666
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udp checksum != { 444, 555} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 444,
+ 555
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udp checksum 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# udp checksum != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# udp checksum 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# udp checksum != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# udp checksum { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# udp checksum != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# iif "lo" udp checksum set 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udp"
+ }
+ },
+ "value": 0
+ }
+ }
+]
+
+# iif "lo" udp dport set 65535
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "value": 65535
+ }
+ }
+]
+
diff --git a/tests/py/inet/udp.t.payload b/tests/py/inet/udp.t.payload
new file mode 100644
index 0000000..e6beda7
--- /dev/null
+++ b/tests/py/inet/udp.t.payload
@@ -0,0 +1,248 @@
+# udp sport 80 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00005000 ]
+ [ immediate reg 0 accept ]
+
+# udp sport != 60 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00003c00 ]
+ [ immediate reg 0 accept ]
+
+# udp sport 50-70 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00003200 ]
+ [ cmp lte reg 1 0x00004600 ]
+ [ immediate reg 0 accept ]
+
+# udp sport != 50-60 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ range neq reg 1 0x00003200 0x00003c00 ]
+ [ immediate reg 0 accept ]
+
+# udp sport { 49, 50} drop
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00003100 : 0 [end] element 00003200 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 drop ]
+
+# udp sport != { 50, 60} accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00003200 : 0 [end] element 00003c00 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# udp dport 80 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005000 ]
+ [ immediate reg 0 accept ]
+
+# udp dport != 60 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x00003c00 ]
+ [ immediate reg 0 accept ]
+
+# udp dport 70-75 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00004600 ]
+ [ cmp lte reg 1 0x00004b00 ]
+ [ immediate reg 0 accept ]
+
+# udp dport != 50-60 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00003200 0x00003c00 ]
+ [ immediate reg 0 accept ]
+
+# udp dport { 49, 50} drop
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00003100 : 0 [end] element 00003200 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 drop ]
+
+# udp dport != { 50, 60} accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00003200 : 0 [end] element 00003c00 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# udp length 6666
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000a1a ]
+
+# udp length != 6666
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x00000a1a ]
+
+# udp length 50-65 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00003200 ]
+ [ cmp lte reg 1 0x00004100 ]
+ [ immediate reg 0 accept ]
+
+# udp length != 50-65 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x00003200 0x00004100 ]
+ [ immediate reg 0 accept ]
+
+# udp length { 50, 65} accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00003200 : 0 [end] element 00004100 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# udp length != { 50, 65} accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00003200 : 0 [end] element 00004100 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# udp checksum 6666 drop
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000a1a ]
+ [ immediate reg 0 drop ]
+
+# udp checksum != { 444, 555} accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 0000bc01 : 0 [end] element 00002b02 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# udp checksum 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# udp checksum != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# udp checksum 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# udp checksum != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# udp checksum { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# udp checksum != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# iif "lo" udp checksum set 0
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0x00000000 ]
+ [ payload write reg 1 => 2b @ transport header + 6 csum_type 1 csum_off 6 csum_flags 0x0 ]
+
+# iif "lo" udp dport set 65535
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0x0000ffff ]
+ [ payload write reg 1 => 2b @ transport header + 2 csum_type 1 csum_off 6 csum_flags 0x0 ]
diff --git a/tests/py/inet/udplite.t b/tests/py/inet/udplite.t
new file mode 100644
index 0000000..6a54709
--- /dev/null
+++ b/tests/py/inet/udplite.t
@@ -0,0 +1,38 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+udplite sport 80 accept;ok
+udplite sport != 60 accept;ok
+udplite sport 50-70 accept;ok
+udplite sport != 50-60 accept;ok
+udplite sport { 49, 50} drop;ok
+udplite sport != { 49, 50} accept;ok
+
+udplite dport 80 accept;ok
+udplite dport != 60 accept;ok
+udplite dport 70-75 accept;ok
+udplite dport != 50-60 accept;ok
+udplite dport { 49, 50} drop;ok
+udplite dport != { 49, 50} accept;ok
+
+- udplite csumcov 6666;ok
+- udplite csumcov != 6666;ok
+- udplite csumcov 50-65 accept;ok
+- udplite csumcov != 50-65 accept;ok
+- udplite csumcov { 50, 65} accept;ok
+- udplite csumcov != { 50, 65} accept;ok
+
+udplite checksum 6666 drop;ok
+udplite checksum != { 444, 555} accept;ok
+udplite checksum 22;ok
+udplite checksum != 233;ok
+udplite checksum 33-45;ok
+udplite checksum != 33-45;ok
+udplite checksum { 33, 55, 67, 88};ok
+udplite checksum != { 33, 55, 67, 88};ok
diff --git a/tests/py/inet/udplite.t.json b/tests/py/inet/udplite.t.json
new file mode 100644
index 0000000..713a534
--- /dev/null
+++ b/tests/py/inet/udplite.t.json
@@ -0,0 +1,413 @@
+# udplite sport 80 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": 80
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite sport != 60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": 60
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite sport 50-70 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 50, 70 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite sport != 50-60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 60 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite sport { 49, 50} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udplite sport != { 49, 50} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport 80 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": 80
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport != 60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": 60
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport 70-75 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 70, 75 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport != 50-60 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 50, 60 ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite dport { 49, 50} drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udplite dport != { 49, 50} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 49,
+ 50
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite checksum 6666 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": 6666
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# udplite checksum != { 444, 555} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 444,
+ 555
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# udplite checksum 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# udplite checksum != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# udplite checksum 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# udplite checksum != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# udplite checksum { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udplite"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# udplite checksum != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "udplite"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/udplite.t.payload b/tests/py/inet/udplite.t.payload
new file mode 100644
index 0000000..de9d09e
--- /dev/null
+++ b/tests/py/inet/udplite.t.payload
@@ -0,0 +1,178 @@
+# udplite sport 80 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00005000 ]
+ [ immediate reg 0 accept ]
+
+# udplite sport != 60 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00003c00 ]
+ [ immediate reg 0 accept ]
+
+# udplite sport 50-70 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00003200 ]
+ [ cmp lte reg 1 0x00004600 ]
+ [ immediate reg 0 accept ]
+
+# udplite sport != 50-60 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ range neq reg 1 0x00003200 0x00003c00 ]
+ [ immediate reg 0 accept ]
+
+# udplite sport { 49, 50} drop
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00003100 : 0 [end] element 00003200 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 drop ]
+
+# udplite sport != { 49, 50} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00003100 : 0 [end] element 00003200 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# udplite dport 80 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005000 ]
+ [ immediate reg 0 accept ]
+
+# udplite dport != 60 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x00003c00 ]
+ [ immediate reg 0 accept ]
+
+# udplite dport 70-75 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00004600 ]
+ [ cmp lte reg 1 0x00004b00 ]
+ [ immediate reg 0 accept ]
+
+# udplite dport != 50-60 accept
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00003200 0x00003c00 ]
+ [ immediate reg 0 accept ]
+
+# udplite dport { 49, 50} drop
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00003100 : 0 [end] element 00003200 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 drop ]
+
+# udplite dport != { 49, 50} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00003100 : 0 [end] element 00003200 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# udplite checksum 6666 drop
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000a1a ]
+ [ immediate reg 0 drop ]
+
+# udplite checksum != { 444, 555} accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 0000bc01 : 0 [end] element 00002b02 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# udplite checksum 22
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# udplite checksum != 233
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# udplite checksum 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# udplite checksum != 33-45
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# udplite checksum { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# udplite checksum != { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
diff --git a/tests/py/inet/vmap.t b/tests/py/inet/vmap.t
new file mode 100644
index 0000000..0ac6e56
--- /dev/null
+++ b/tests/py/inet/vmap.t
@@ -0,0 +1,10 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+iifname . ip protocol . th dport vmap { "eth0" . tcp . 22 : accept, "eth1" . udp . 67 : drop };ok;iifname . ip protocol . th dport vmap { "eth0" . 6 . 22 : accept, "eth1" . 17 . 67 : drop }
+ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e };ok
+udp length . @th,160,128 vmap { 47-63 . 0xe373135363130333131303735353203 : accept };ok
diff --git a/tests/py/inet/vmap.t.json b/tests/py/inet/vmap.t.json
new file mode 100644
index 0000000..37472cc
--- /dev/null
+++ b/tests/py/inet/vmap.t.json
@@ -0,0 +1,144 @@
+# iifname . ip protocol . th dport vmap { "eth0" . tcp . 22 : accept, "eth1" . udp . 67 : drop }
+[
+ {
+ "vmap": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "eth0",
+ 6,
+ 22
+ ]
+ },
+ {
+ "accept": null
+ }
+ ],
+ [
+ {
+ "concat": [
+ "eth1",
+ 17,
+ 67
+ ]
+ },
+ {
+ "drop": null
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "th"
+ }
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "base": "ih",
+ "len": 32,
+ "offset": 32
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.1.1.1",
+ 20
+ ]
+ },
+ {
+ "concat": [
+ "2.2.2.2",
+ 30
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# udp length . @th,160,128 vmap { 47-63 . 0xe373135363130333131303735353203 : accept }
+[
+ {
+ "vmap": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ {
+ "range": [
+ 47,
+ 63
+ ]
+ },
+ "0xe373135363130333131303735353203"
+ ]
+ },
+ {
+ "accept": null
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "payload": {
+ "field": "length",
+ "protocol": "udp"
+ }
+ },
+ {
+ "payload": {
+ "base": "th",
+ "len": 128,
+ "offset": 160
+ }
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/vmap.t.payload b/tests/py/inet/vmap.t.payload
new file mode 100644
index 0000000..29ec846
--- /dev/null
+++ b/tests/py/inet/vmap.t.payload
@@ -0,0 +1,34 @@
+# iifname . ip protocol . th dport vmap { "eth0" . tcp . 22 : accept, "eth1" . udp . 67 : drop }
+__map%d test-inet b size 2
+__map%d test-inet 0
+ element 30687465 00000000 00000000 00000000 00000006 00001600 : accept 0 [end] element 31687465 00000000 00000000 00000000 00000011 00004300 : drop 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ meta load iifname => reg 1 ]
+ [ payload load 1b @ network header + 9 => reg 2 ]
+ [ payload load 2b @ transport header + 2 => reg 13 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e }
+__set%d test-inet 3 size 2
+__set%d test-inet 0
+ element 01010101 14000000 : 0 [end] element 02020202 1e000000 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ inner header + 4 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# udp length . @th,160,128 vmap { 47-63 . 0xe373135363130333131303735353203 : accept }
+__map%d x 8f size 1
+__map%d x 0
+ element 00002f00 3531370e 33303136 37303131 03323535 - 00003f00 3531370e 33303136 37303131 03323535 : accept 0 [end]
+inet x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ payload load 16b @ transport header + 20 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
diff --git a/tests/py/inet/vmap.t.payload.netdev b/tests/py/inet/vmap.t.payload.netdev
new file mode 100644
index 0000000..3f51bb3
--- /dev/null
+++ b/tests/py/inet/vmap.t.payload.netdev
@@ -0,0 +1,34 @@
+# iifname . ip protocol . th dport vmap { "eth0" . tcp . 22 : accept, "eth1" . udp . 67 : drop }
+__map%d test-netdev b size 2
+__map%d test-netdev 0
+ element 30687465 00000000 00000000 00000000 00000006 00001600 : accept 0 [end] element 31687465 00000000 00000000 00000000 00000011 00004300 : drop 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load iifname => reg 1 ]
+ [ payload load 1b @ network header + 9 => reg 2 ]
+ [ payload load 2b @ transport header + 2 => reg 13 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e }
+__set%d test-netdev 3 size 2
+__set%d test-netdev 0
+ element 01010101 14000000 : 0 [end] element 02020202 1e000000 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ inner header + 4 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# udp length . @th,160,128 vmap { 47-63 . 0xe373135363130333131303735353203 : accept }
+__map%d test-netdev 8f size 1
+__map%d test-netdev 0
+ element 00002f00 3531370e 33303136 37303131 03323535 - 00003f00 3531370e 33303136 37303131 03323535 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ payload load 16b @ transport header + 20 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
diff --git a/tests/py/inet/vxlan.t b/tests/py/inet/vxlan.t
new file mode 100644
index 0000000..10cdb7a
--- /dev/null
+++ b/tests/py/inet/vxlan.t
@@ -0,0 +1,23 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+vxlan vni 10;fail
+udp dport 4789 vxlan vni 10;ok
+udp dport 4789 vxlan ip saddr 10.141.11.2;ok
+udp dport 4789 vxlan ip saddr 10.141.11.0/24;ok
+udp dport 4789 vxlan ip protocol 1;ok
+udp dport 4789 vxlan udp sport 8888;ok
+udp dport 4789 vxlan icmp type echo-reply;ok
+udp dport 4789 vxlan ether saddr 62:87:4d:d6:19:05;ok
+udp dport 4789 vxlan vlan id 10;ok
+udp dport 4789 vxlan ip dscp 0x02;ok
+udp dport 4789 vxlan ip dscp 0x02;ok
+udp dport 4789 vxlan ip saddr . vxlan ip daddr { 1.2.3.4 . 4.3.2.1 };ok
+
+udp dport 4789 vxlan ip saddr set 1.2.3.4;fail
diff --git a/tests/py/inet/vxlan.t.json b/tests/py/inet/vxlan.t.json
new file mode 100644
index 0000000..91b3d29
--- /dev/null
+++ b/tests/py/inet/vxlan.t.json
@@ -0,0 +1,344 @@
+# udp dport 4789 vxlan vni 10
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "vni",
+ "protocol": "vxlan",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": 10
+ }
+ }
+]
+
+# udp dport 4789 vxlan ip saddr 10.141.11.2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": "10.141.11.2"
+ }
+ }
+]
+
+# udp dport 4789 vxlan ip saddr 10.141.11.0/24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "10.141.11.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# udp dport 4789 vxlan ip protocol 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# udp dport 4789 vxlan udp sport 8888
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sport",
+ "protocol": "udp",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": 8888
+ }
+ }
+]
+
+# udp dport 4789 vxlan icmp type echo-reply
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": "echo-reply"
+ }
+ }
+]
+
+# udp dport 4789 vxlan ether saddr 62:87:4d:d6:19:05
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": "62:87:4d:d6:19:05"
+ }
+ }
+]
+
+# udp dport 4789 vxlan vlan id 10
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "vlan",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": 10
+ }
+ }
+]
+
+# udp dport 4789 vxlan ip dscp 0x02
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# udp dport 4789 vxlan ip dscp 0x02
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip",
+ "tunnel": "vxlan"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# udp dport 4789 vxlan ip saddr . vxlan ip daddr { 1.2.3.4 . 4.3.2.1 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 4789
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip",
+ "tunnel": "vxlan"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip",
+ "tunnel": "vxlan"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.2.3.4",
+ "4.3.2.1"
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/inet/vxlan.t.payload b/tests/py/inet/vxlan.t.payload
new file mode 100644
index 0000000..cde8e56
--- /dev/null
+++ b/tests/py/inet/vxlan.t.payload
@@ -0,0 +1,114 @@
+# udp dport 4789 vxlan vni 10
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 3b @ unknown header + 4 => reg 1 ] ]
+ [ cmp eq reg 1 0x000a0000 ]
+
+# udp dport 4789 vxlan ip saddr 10.141.11.2
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 4b @ network header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x020b8d0a ]
+
+# udp dport 4789 vxlan ip saddr 10.141.11.0/24
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 3b @ network header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x000b8d0a ]
+
+# udp dport 4789 vxlan ip protocol 1
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 1b @ network header + 9 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# udp dport 4789 vxlan udp sport 8888
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ meta load l4proto => reg 1 ] ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 2b @ transport header + 0 => reg 1 ] ]
+ [ cmp eq reg 1 0x0000b822 ]
+
+# udp dport 4789 vxlan icmp type echo-reply
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 2b @ link header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 1 hdrsize 8 flags f [ meta load l4proto => reg 1 ] ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 1b @ transport header + 0 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# udp dport 4789 vxlan ether saddr 62:87:4d:d6:19:05
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 6b @ link header + 6 => reg 1 ] ]
+ [ cmp eq reg 1 0xd64d8762 0x00000519 ]
+
+# udp dport 4789 vxlan vlan id 10
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 2b @ link header + 12 => reg 1 ] ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 2b @ link header + 14 => reg 1 ] ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000a00 ]
+
+# udp dport 4789 vxlan ip dscp 0x02
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 1b @ network header + 1 => reg 1 ] ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# udp dport 4789 vxlan ip saddr . vxlan ip daddr { 1.2.3.4 . 4.3.2.1 }
+__set%d test-netdev 3 size 1
+__set%d test-netdev 0
+ element 04030201 01020304 : 0 [end]
+netdev test-netdev ingress
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000b512 ]
+ [ inner type 1 hdrsize 8 flags f [ meta load protocol => reg 1 ] ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 4b @ network header + 12 => reg 1 ] ]
+ [ inner type 1 hdrsize 8 flags f [ payload load 4b @ network header + 16 => reg 9 ] ]
+ [ lookup reg 1 set __set%d ]
+
diff --git a/tests/py/ip/chains.t b/tests/py/ip/chains.t
new file mode 100644
index 0000000..fc3745e
--- /dev/null
+++ b/tests/py/ip/chains.t
@@ -0,0 +1,15 @@
+# filter chains available are: input, output, forward, prerouting, postrouting
+:filter-input;type filter hook input priority 0
+:filter-pre;type filter hook prerouting priority 0
+:filter-forw;type filter hook forward priority 0
+:filter-out;type filter hook output priority 0
+:filter-post;type filter hook postrouting priority 0
+# nat chains available are: input, output, prerouting, postrouting
+:nat-input-t;type nat hook input priority 0
+:nat-pre-t;type nat hook prerouting priority 0
+:nat-out-t;type nat hook output priority 0
+:nat-post-t;type nat hook postrouting priority 0
+# route chain available are: output
+:route-out-t;type route hook output priority 0
+
+*ip;test-ip4;filter-input,filter-pre,filter-forw,filter-out,filter-post,nat-input-t,nat-pre-t,nat-out-t,nat-post-t,route-out-t
diff --git a/tests/py/ip/ct.t b/tests/py/ip/ct.t
new file mode 100644
index 0000000..a0a2228
--- /dev/null
+++ b/tests/py/ip/ct.t
@@ -0,0 +1,36 @@
+:output;type filter hook output priority 0
+
+*ip;test-ip4;output
+
+ct original ip saddr 192.168.0.1;ok
+ct reply ip saddr 192.168.0.1;ok
+ct original ip daddr 192.168.0.1;ok
+ct reply ip daddr 192.168.0.1;ok
+
+# same, but with a netmask
+ct original ip saddr 192.168.1.0/24;ok
+ct reply ip saddr 192.168.1.0/24;ok
+ct original ip daddr 192.168.1.0/24;ok
+ct reply ip daddr 192.168.1.0/24;ok
+
+ct l3proto ipv4;ok
+ct l3proto foobar;fail
+
+ct protocol 6 ct original proto-dst 22;ok
+ct original protocol 17 ct reply proto-src 53;ok;ct protocol 17 ct reply proto-src 53
+
+# wrong address family
+ct reply ip daddr dead::beef;fail
+
+meta mark set ct original daddr map { 1.1.1.1 : 0x00000011 };fail
+meta mark set ct original ip daddr map { 1.1.1.1 : 0x00000011 };ok
+meta mark set ct original saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x0000001e };fail
+meta mark set ct original ip saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x0000001e };ok
+ct original saddr . meta mark { 1.1.1.1 . 0x00000014 };fail
+ct original ip saddr . meta mark { 1.1.1.1 . 0x00000014 };ok
+ct mark set ip dscp << 2 | 0x10;ok
+ct mark set ip dscp << 26 | 0x10;ok
+ct mark set ip dscp & 0x0f << 1;ok;ct mark set ip dscp & af33
+ct mark set ip dscp & 0x0f << 2;ok;ct mark set ip dscp & 0x3c
+ct mark set ip dscp | 0x04;ok
+ct mark set ip dscp | 1 << 20;ok;ct mark set ip dscp | 0x100000
diff --git a/tests/py/ip/ct.t.json b/tests/py/ip/ct.t.json
new file mode 100644
index 0000000..915632a
--- /dev/null
+++ b/tests/py/ip/ct.t.json
@@ -0,0 +1,481 @@
+# ct original ip saddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "ip saddr"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ct reply ip saddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "ip saddr"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ct original ip daddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "ip daddr"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ct reply ip daddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "ip daddr"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ct original ip saddr 192.168.1.0/24
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "ip saddr"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "192.168.1.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ct reply ip saddr 192.168.1.0/24
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "ip saddr"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "192.168.1.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ct original ip daddr 192.168.1.0/24
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "ip daddr"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "192.168.1.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ct reply ip daddr 192.168.1.0/24
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "ip daddr"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "192.168.1.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ct l3proto ipv4
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "l3proto"
+ }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ }
+]
+
+# ct protocol 6 ct original proto-dst 22
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "proto-dst"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ct original protocol 17 ct reply proto-src 53
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "original",
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "proto-src"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ }
+]
+
+# meta mark set ct original ip daddr map { 1.1.1.1 : 0x00000011 }
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "1.1.1.1",
+ 17
+ ]
+ ]
+ },
+ "key": {
+ "ct": {
+ "dir": "original",
+ "key": "ip daddr"
+ }
+ }
+ }
+ }
+ }
+ }
+]
+
+# meta mark set ct original ip saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x0000001e }
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "1.1.1.1",
+ 20
+ ]
+ },
+ 30
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "ct": {
+ "dir": "original",
+ "key": "ip saddr"
+ }
+ },
+ {
+ "meta": {
+ "key": "mark"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# ct original ip saddr . meta mark { 1.1.1.1 . 0x00000014 }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "dir": "original",
+ "key": "ip saddr"
+ }
+ },
+ {
+ "meta": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.1.1.1",
+ 20
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip dscp << 2 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ 2
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip dscp << 26 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ 26
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip dscp & 0x0f << 1
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "&": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ "af33"
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip dscp & 0x0f << 2
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "&": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ 60
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip dscp | 0x04
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip dscp | 1 << 20
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ 1048576
+ ]
+ }
+ }
+ }
+]
diff --git a/tests/py/ip/ct.t.json.output b/tests/py/ip/ct.t.json.output
new file mode 100644
index 0000000..cf4abae
--- /dev/null
+++ b/tests/py/ip/ct.t.json.output
@@ -0,0 +1,27 @@
+# ct original protocol 17 ct reply proto-src 53
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "dir": "reply",
+ "key": "proto-src"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ }
+]
+
diff --git a/tests/py/ip/ct.t.payload b/tests/py/ip/ct.t.payload
new file mode 100644
index 0000000..692011d
--- /dev/null
+++ b/tests/py/ip/ct.t.payload
@@ -0,0 +1,136 @@
+# ct original ip saddr 192.168.0.1
+ip test-ip4 output
+ [ ct load src_ip => reg 1 , dir original ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
+# ct reply ip saddr 192.168.0.1
+ip test-ip4 output
+ [ ct load src_ip => reg 1 , dir reply ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
+# ct original ip daddr 192.168.0.1
+ip test-ip4 output
+ [ ct load dst_ip => reg 1 , dir original ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
+# ct reply ip daddr 192.168.0.1
+ip test-ip4 output
+ [ ct load dst_ip => reg 1 , dir reply ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
+# ct original ip saddr 192.168.1.0/24
+ip test-ip4 output
+ [ ct load src_ip => reg 1 , dir original ]
+ [ cmp eq reg 1 0x0001a8c0 ]
+
+# ct reply ip saddr 192.168.1.0/24
+ip test-ip4 output
+ [ ct load src_ip => reg 1 , dir reply ]
+ [ cmp eq reg 1 0x0001a8c0 ]
+
+# ct original ip daddr 192.168.1.0/24
+ip test-ip4 output
+ [ ct load dst_ip => reg 1 , dir original ]
+ [ cmp eq reg 1 0x0001a8c0 ]
+
+# ct reply ip daddr 192.168.1.0/24
+ip test-ip4 output
+ [ ct load dst_ip => reg 1 , dir reply ]
+ [ cmp eq reg 1 0x0001a8c0 ]
+
+# ct l3proto ipv4
+ip test-ip4 output
+ [ ct load l3protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# ct protocol 6 ct original proto-dst 22
+ip test-ip4 output
+ [ ct load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ ct load proto_dst => reg 1 , dir original ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ct original protocol 17 ct reply proto-src 53
+ip test-ip4 output
+ [ ct load protocol => reg 1 , dir original ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ ct load proto_src => reg 1 , dir reply ]
+ [ cmp eq reg 1 0x00003500 ]
+
+# meta mark set ct original ip daddr map { 1.1.1.1 : 0x00000011 }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 01010101 : 00000011 0 [end]
+ip
+ [ ct load dst_ip => reg 1 , dir original ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ct original ip saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x0000001e }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 01010101 00000014 : 0000001e 0 [end]
+ip
+ [ ct load src_ip => reg 1 , dir original ]
+ [ meta load mark => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
+# ct original ip saddr . meta mark { 1.1.1.1 . 0x00000014 }
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 01010101 00000014 : 0 [end]
+ip
+ [ ct load src_ip => reg 1 , dir original ]
+ [ meta load mark => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# ct mark set ip dscp << 2 | 0x10
+ip test-ip4 output
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 << 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp << 26 | 0x10
+ip
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 << 0x0000001a ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp & 0x0f << 1
+ip test-ip4 output
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000001e ) ^ 0x00000000 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp & 0x0f << 2
+ip test-ip4 output
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000003c ) ^ 0x00000000 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp | 0x04
+ip test-ip4 output
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xfffffffb ) ^ 0x00000004 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp | 1 << 20
+ip test-ip4 output
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffefffff ) ^ 0x00100000 ]
+ [ ct set mark with reg 1 ]
diff --git a/tests/py/ip/dnat.t b/tests/py/ip/dnat.t
new file mode 100644
index 0000000..881571d
--- /dev/null
+++ b/tests/py/ip/dnat.t
@@ -0,0 +1,23 @@
+:prerouting;type nat hook prerouting priority 0
+
+*ip;test-ip4;prerouting
+
+iifname "eth0" tcp dport 80-90 dnat to 192.168.3.2;ok
+iifname "eth0" tcp dport != 80-90 dnat to 192.168.3.2;ok
+iifname "eth0" tcp dport {80, 90, 23} dnat to 192.168.3.2;ok
+iifname "eth0" tcp dport != {80, 90, 23} dnat to 192.168.3.2;ok
+iifname "eth0" tcp dport != 23-34 dnat to 192.168.3.2;ok
+iifname "eth0" tcp dport 81 dnat to 192.168.3.2:8080;ok
+iifname "eth0" tcp dport 81 dnat to 192.168.3.2:8080-8999;ok
+iifname "eth0" tcp dport 81 dnat to 192.168.3.2-192.168.3.4:8080;ok
+iifname "eth0" tcp dport 81 dnat to 192.168.3.2-192.168.3.4:8080-8999;ok
+
+dnat to ct mark map { 0x00000014 : 1.2.3.4};ok
+dnat to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4};ok
+
+dnat ip to ip saddr . tcp dport map { 192.168.1.2 . 80 : 10.141.10.0/24 . 8888 - 8999 };ok
+dnat ip to ip saddr . tcp dport map { 192.168.1.2 . 80 : 10.141.10.0/24 . 80 };ok
+dnat ip to ip saddr . tcp dport map { 192.168.1.2 . 80 : 10.141.10.2 . 8888 - 8999 };ok
+ip daddr 192.168.0.1 dnat ip to tcp dport map { 443 : 10.141.10.4 . 8443, 80 : 10.141.10.4 . 8080 };ok
+meta l4proto 6 dnat ip to iifname . ip saddr map { "enp2s0" . 10.1.1.136 : 1.1.2.69 . 22, "enp2s0" . 10.1.1.1-10.1.1.135 : 1.1.2.66-1.84.236.78 . 22 };ok
+dnat ip to iifname . ip saddr map { "enp2s0" . 10.1.1.136 : 1.1.2.69/32, "enp2s0" . 10.1.1.1-10.1.1.135 : 1.1.2.66-1.84.236.78 };ok
diff --git a/tests/py/ip/dnat.t.json b/tests/py/ip/dnat.t.json
new file mode 100644
index 0000000..fe15d07
--- /dev/null
+++ b/tests/py/ip/dnat.t.json
@@ -0,0 +1,743 @@
+# iifname "eth0" tcp dport 80-90 dnat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 81
+ }
+ },
+ {
+ "dnat": {
+ "addr": "192.168.3.2",
+ "port": 8080
+ }
+ }
+]
+
+# dnat to ct mark map { 0x00000014 : 1.2.3.4}
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "data": {
+ "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": {
+ "key": {
+ "concat": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "0x00000014",
+ "1.1.1.1"
+ ]
+ },
+ "1.2.3.4"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 81 dnat to 192.168.3.2:8080-8999
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 81
+ }
+ },
+ {
+ "dnat": {
+ "addr": "192.168.3.2",
+ "port": {
+ "range": [
+ 8080,
+ 8999
+ ]
+ }
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 81 dnat to 192.168.3.2-192.168.3.4:8080-8999
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 81
+ }
+ },
+ {
+ "dnat": {
+ "addr": {
+ "range": [
+ "192.168.3.2",
+ "192.168.3.4"
+ ]
+ },
+ "port": {
+ "range": [
+ 8080,
+ 8999
+ ]
+ }
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 81 dnat to 192.168.3.2-192.168.3.4:8080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 81
+ }
+ },
+ {
+ "dnat": {
+ "addr": {
+ "range": [
+ "192.168.3.2",
+ "192.168.3.4"
+ ]
+ },
+ "port": 8080
+ }
+ }
+]
+
+# dnat ip to ip saddr . tcp dport map { 192.168.1.2 . 80 : 10.141.10.2 . 8888 - 8999 }
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "192.168.1.2",
+ 80
+ ]
+ },
+ {
+ "concat": [
+ "10.141.10.2",
+ {
+ "range": [
+ 8888,
+ 8999
+ ]
+ }
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# dnat ip to ip saddr . tcp dport map { 192.168.1.2 . 80 : 10.141.10.0/24 . 8888 - 8999 }
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "192.168.1.2",
+ 80
+ ]
+ },
+ {
+ "concat": [
+ {
+ "prefix": {
+ "addr": "10.141.10.0",
+ "len": 24
+ }
+ },
+ {
+ "range": [
+ 8888,
+ 8999
+ ]
+ }
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# dnat ip to ip saddr . tcp dport map { 192.168.1.2 . 80 : 10.141.10.0/24 . 80 }
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "192.168.1.2",
+ 80
+ ]
+ },
+ {
+ "concat": [
+ {
+ "prefix": {
+ "addr": "10.141.10.0",
+ "len": 24
+ }
+ },
+ 80
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# ip daddr 192.168.0.1 dnat ip to tcp dport map { 443 : 10.141.10.4 . 8443, 80 : 10.141.10.4 . 8080 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ },
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ 80,
+ {
+ "concat": [
+ "10.141.10.4",
+ 8080
+ ]
+ }
+ ],
+ [
+ 443,
+ {
+ "concat": [
+ "10.141.10.4",
+ 8443
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# meta l4proto 6 dnat ip to iifname . ip saddr map { "enp2s0" . 10.1.1.136 : 1.1.2.69 . 22, "enp2s0" . 10.1.1.1-10.1.1.135 : 1.1.2.66-1.84.236.78 . 22 }
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "enp2s0",
+ "10.1.1.136"
+ ]
+ },
+ {
+ "concat": [
+ "1.1.2.69",
+ 22
+ ]
+ }
+ ],
+ [
+ {
+ "concat": [
+ "enp2s0",
+ {
+ "range": [
+ "10.1.1.1",
+ "10.1.1.135"
+ ]
+ }
+ ]
+ },
+ {
+ "concat": [
+ {
+ "range": [
+ "1.1.2.66",
+ "1.84.236.78"
+ ]
+ },
+ 22
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# dnat ip to iifname . ip saddr map { "enp2s0" . 10.1.1.136 : 1.1.2.69/32, "enp2s0" . 10.1.1.1-10.1.1.135 : 1.1.2.66-1.84.236.78 }
+[
+ {
+ "dnat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "enp2s0",
+ "10.1.1.136"
+ ]
+ },
+ {
+ "prefix": {
+ "addr": "1.1.2.69",
+ "len": 32
+ }
+ }
+ ],
+ [
+ {
+ "concat": [
+ "enp2s0",
+ {
+ "range": [
+ "10.1.1.1",
+ "10.1.1.135"
+ ]
+ }
+ ]
+ },
+ {
+ "range": [
+ "1.1.2.66",
+ "1.84.236.78"
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
diff --git a/tests/py/ip/dnat.t.json.output b/tests/py/ip/dnat.t.json.output
new file mode 100644
index 0000000..4f2c6df
--- /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": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "data": {
+ "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": {
+ "key": {
+ "concat": [
+ {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ 20,
+ "1.1.1.1"
+ ]
+ },
+ "1.2.3.4"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/dnat.t.payload.ip b/tests/py/ip/dnat.t.payload.ip
new file mode 100644
index 0000000..439c6ab
--- /dev/null
+++ b/tests/py/ip/dnat.t.payload.ip
@@ -0,0 +1,204 @@
+# iifname "eth0" tcp dport 80-90 dnat to 192.168.3.2
+ip test-ip4 prerouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00005000 ]
+ [ cmp lte reg 1 0x00005a00 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport != 80-90 dnat to 192.168.3.2
+ip test-ip4 prerouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00005000 0x00005a00 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport {80, 90, 23} dnat to 192.168.3.2
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00005000 : 0 [end] element 00005a00 : 0 [end] element 00001700 : 0 [end]
+ip test-ip4 prerouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport != {80, 90, 23} dnat to 192.168.3.2
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00005000 : 0 [end] element 00005a00 : 0 [end] element 00001700 : 0 [end]
+ip test-ip4 prerouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport != 23-34 dnat to 192.168.3.2
+ip test-ip4 prerouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00001700 0x00002200 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport 81 dnat to 192.168.3.2:8080
+ip test-ip4 prerouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005100 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ immediate reg 2 0x0000901f ]
+ [ nat dnat ip addr_min reg 1 proto_min reg 2 flags 0x2 ]
+
+# dnat to ct mark map { 0x00000014 : 1.2.3.4}
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00000014 : 04030201 0 [end]
+ip test-ip4 prerouting
+ [ ct load mark => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# dnat to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4}
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00000014 01010101 : 04030201 0 [end]
+ip test-ip4 output
+ [ ct load mark => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# dnat ip to ip saddr . tcp dport map { 192.168.1.2 . 80 : 10.141.10.0/24 . 8888 - 8999 }
+__map%d test-ip4 b size 1
+__map%d test-ip4 0
+ element 0201a8c0 00005000 : 000a8d0a 0000b822 ff0a8d0a 00002723 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 2b @ transport header + 2 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 addr_max reg 10 proto_min reg 9 proto_max reg 11 ]
+
+# dnat ip to ip saddr . tcp dport map { 192.168.1.2 . 80 : 10.141.10.0/24 . 80 }
+__map%d test-ip4 b size 1
+__map%d test-ip4 0
+ element 0201a8c0 00005000 : 000a8d0a 00005000 ff0a8d0a 00005000 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 2b @ transport header + 2 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 addr_max reg 10 proto_min reg 9 proto_max reg 11 ]
+
+# dnat ip to ip saddr . tcp dport map { 192.168.1.2 . 80 : 10.141.10.2 . 8888 - 8999 }
+__map%d test-ip4 b size 1
+__map%d test-ip4 0
+ element 0201a8c0 00005000 : 020a8d0a 0000b822 020a8d0a 00002723 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 2b @ transport header + 2 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 addr_max reg 10 proto_min reg 9 proto_max reg 11 ]
+
+# iifname "eth0" tcp dport 81 dnat to 192.168.3.2:8080-8999
+ip
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005100 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ immediate reg 2 0x0000901f ]
+ [ immediate reg 3 0x00002723 ]
+ [ nat dnat ip addr_min reg 1 proto_min reg 2 proto_max reg 3 flags 0x2 ]
+
+# iifname "eth0" tcp dport 81 dnat to 192.168.3.2-192.168.3.4:8080
+ip
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005100 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ immediate reg 2 0x0403a8c0 ]
+ [ immediate reg 3 0x0000901f ]
+ [ nat dnat ip addr_min reg 1 addr_max reg 2 proto_min reg 3 flags 0x2 ]
+
+# iifname "eth0" tcp dport 81 dnat to 192.168.3.2-192.168.3.4:8080-8999
+ip
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00005100 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ immediate reg 2 0x0403a8c0 ]
+ [ immediate reg 3 0x0000901f ]
+ [ immediate reg 4 0x00002723 ]
+ [ nat dnat ip addr_min reg 1 addr_max reg 2 proto_min reg 3 proto_max reg 4 flags 0x2 ]
+
+# ip daddr 192.168.0.1 dnat ip to tcp dport map { 443 : 10.141.10.4 . 8443, 80 : 10.141.10.4 . 8080 }
+__map%d test-ip4 b size 2
+__map%d test-ip4 0
+ element 0000bb01 : 040a8d0a 0000fb20 0 [end] element 00005000 : 040a8d0a 0000901f 0 [end]
+ip
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 proto_min reg 9 ]
+
+# meta l4proto 6 dnat ip to iifname . ip saddr map { "enp2s0" . 10.1.1.136 : 1.1.2.69 . 22, "enp2s0" . 10.1.1.1-10.1.1.135 : 1.1.2.66-1.84.236.78 . 22 }
+__map%d test-ip4 8f size 2
+__map%d test-ip4 0
+ element 32706e65 00003073 00000000 00000000 8801010a - 32706e65 00003073 00000000 00000000 8801010a : 45020101 00001600 45020101 00001600 0 [end] element 32706e65 00003073 00000000 00000000 0101010a - 32706e65 00003073 00000000 00000000 8701010a : 42020101 00001600 4eec5401 00001600 0 [end]
+ip test-ip4 prerouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ meta load iifname => reg 1 ]
+ [ payload load 4b @ network header + 12 => reg 2 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 addr_max reg 10 proto_min reg 9 proto_max reg 11 ]
+
+# dnat ip to iifname . ip saddr map { "enp2s0" . 10.1.1.136 : 1.1.2.69/32, "enp2s0" . 10.1.1.1-10.1.1.135 : 1.1.2.66-1.84.236.78 }
+__map%d test-ip4 8f size 2
+__map%d test-ip4 0
+ element 32706e65 00003073 00000000 00000000 8801010a - 32706e65 00003073 00000000 00000000 8801010a : 45020101 45020101 0 [end] element 32706e65 00003073 00000000 00000000 0101010a - 32706e65 00003073 00000000 00000000 8701010a : 42020101 4eec5401 0 [end]
+ip test-ip4 prerouting
+ [ meta load iifname => reg 1 ]
+ [ payload load 4b @ network header + 12 => reg 2 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 addr_max reg 9 ]
+
diff --git a/tests/py/ip/dup.t b/tests/py/ip/dup.t
new file mode 100644
index 0000000..700031c
--- /dev/null
+++ b/tests/py/ip/dup.t
@@ -0,0 +1,7 @@
+:input;type filter hook input priority 0
+
+*ip;test-ip4;input
+
+dup to 192.168.2.1;ok
+dup to 192.168.2.1 device "lo";ok
+dup to ip saddr map { 192.168.2.120 : 192.168.2.1 } device "lo";ok
diff --git a/tests/py/ip/dup.t.json b/tests/py/ip/dup.t.json
new file mode 100644
index 0000000..aa1e826
--- /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": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "192.168.2.120",
+ "192.168.2.1"
+ ]
+ ]
+ }
+ }
+ },
+ "dev": "lo"
+ }
+ }
+]
+
diff --git a/tests/py/ip/dup.t.payload b/tests/py/ip/dup.t.payload
new file mode 100644
index 0000000..347dc07
--- /dev/null
+++ b/tests/py/ip/dup.t.payload
@@ -0,0 +1,21 @@
+# dup to 192.168.2.1
+ip test-ip4 test
+ [ immediate reg 1 0x0102a8c0 ]
+ [ dup sreg_addr 1 ]
+
+# dup to 192.168.2.1 device "lo"
+ip test-ip4 test
+ [ immediate reg 1 0x0102a8c0 ]
+ [ immediate reg 2 0x00000001 ]
+ [ dup sreg_addr 1 sreg_dev 2 ]
+
+# dup to ip saddr map { 192.168.2.120 : 192.168.2.1 } device "lo"
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 7802a8c0 : 0102a8c0 0 [end]
+ip test-ip4 test
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ immediate reg 2 0x00000001 ]
+ [ dup sreg_addr 1 sreg_dev 2 ]
+
diff --git a/tests/py/ip/ether.t b/tests/py/ip/ether.t
new file mode 100644
index 0000000..e1d302c
--- /dev/null
+++ b/tests/py/ip/ether.t
@@ -0,0 +1,8 @@
+:input;type filter hook input priority 0
+
+*ip;test-ip;input
+
+tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept;ok;tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04 accept
+tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04;ok
+tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4;ok
+ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4 accept;ok
diff --git a/tests/py/ip/ether.t.json b/tests/py/ip/ether.t.json
new file mode 100644
index 0000000..355c7fc
--- /dev/null
+++ b/tests/py/ip/ether.t.json
@@ -0,0 +1,163 @@
+# 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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "==",
+ "right": "ether"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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 0000000..1e5dd50
--- /dev/null
+++ b/tests/py/ip/ether.t.json.output
@@ -0,0 +1,43 @@
+# 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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/ip/ether.t.payload b/tests/py/ip/ether.t.payload
new file mode 100644
index 0000000..bd7c8f1
--- /dev/null
+++ b/tests/py/ip/ether.t.payload
@@ -0,0 +1,50 @@
+# tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept
+ip test-ip input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4
+ip test-ip input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+
+# tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04
+ip test-ip input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+
+# ether saddr 00:0f:54:0c:11:04 ip daddr 1.2.3.4 accept
+ip test-ip input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ immediate reg 0 accept ]
+
diff --git a/tests/py/ip/flowtable.t b/tests/py/ip/flowtable.t
new file mode 100644
index 0000000..086c6cf
--- /dev/null
+++ b/tests/py/ip/flowtable.t
@@ -0,0 +1,5 @@
+:input;type filter hook input priority 0
+
+*ip;test-ip;input
+
+meter xyz size 8192 { ip saddr timeout 30s counter};ok
diff --git a/tests/py/ip/flowtable.t.json b/tests/py/ip/flowtable.t.json
new file mode 100644
index 0000000..a03cc9d
--- /dev/null
+++ b/tests/py/ip/flowtable.t.json
@@ -0,0 +1,24 @@
+# meter xyz size 8192 { ip saddr timeout 30s counter}
+[
+ {
+ "meter": {
+ "key": {
+ "elem": {
+ "timeout": 30,
+ "val": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "name": "xyz",
+ "size": 8192,
+ "stmt": {
+ "counter": null
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/flowtable.t.payload b/tests/py/ip/flowtable.t.payload
new file mode 100644
index 0000000..c0aad39
--- /dev/null
+++ b/tests/py/ip/flowtable.t.payload
@@ -0,0 +1,7 @@
+# meter xyz size 8192 { ip saddr timeout 30s counter}
+xyz test-ip 31
+xyz test-ip 0
+ip test-ip input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ dynset update reg_key 1 set xyz timeout 30000ms expr [ counter pkts 0 bytes 0 ] ]
+
diff --git a/tests/py/ip/hash.t b/tests/py/ip/hash.t
new file mode 100644
index 0000000..cbfc7ee
--- /dev/null
+++ b/tests/py/ip/hash.t
@@ -0,0 +1,10 @@
+:pre;type nat hook prerouting priority 0
+*ip;test-ip4;pre
+
+ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef;ok
+ct mark set jhash ip saddr . ip daddr mod 2;ok
+ct mark set jhash ip saddr . ip daddr mod 2 seed 0x0;ok
+ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef offset 100;ok
+ct mark set jhash ip saddr . ip daddr mod 2 offset 100;ok
+dnat to jhash ip saddr mod 2 seed 0xdeadbeef map { 0 : 192.168.20.100, 1 : 192.168.30.100 };ok
+ct mark set symhash mod 2 offset 100;ok
diff --git a/tests/py/ip/hash.t.json b/tests/py/ip/hash.t.json
new file mode 100644
index 0000000..a95cf22
--- /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": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "mod": 2,
+ "seed": 3735928559
+ }
+ }
+ }
+ }
+]
+
+# ct mark set jhash ip saddr . ip daddr mod 2
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "mod": 2
+ }
+ }
+ }
+ }
+]
+
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0x0
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "mod": 2,
+ "seed": 0
+ }
+ }
+ }
+ }
+]
+
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef offset 100
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "mod": 2,
+ "offset": 100,
+ "seed": 3735928559
+ }
+ }
+ }
+ }
+]
+
+# ct mark set jhash ip saddr . ip daddr mod 2 offset 100
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "jhash": {
+ "expr": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "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": {
+ "key": {
+ "jhash": {
+ "expr": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "mod": 2,
+ "seed": 3735928559
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 0,
+ "192.168.20.100"
+ ],
+ [
+ 1,
+ "192.168.30.100"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# ct mark set symhash mod 2 offset 100
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "symhash": {
+ "mod": 2,
+ "offset": 100
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/hash.t.payload b/tests/py/ip/hash.t.payload
new file mode 100644
index 0000000..fefe492
--- /dev/null
+++ b/tests/py/ip/hash.t.payload
@@ -0,0 +1,49 @@
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef
+ip test-ip4 pre
+ [ payload load 4b @ network header + 12 => reg 2 ]
+ [ payload load 4b @ network header + 16 => reg 13 ]
+ [ hash reg 1 = jhash(reg 2, 8, 0xdeadbeef) % mod 2 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set jhash ip saddr . ip daddr mod 2
+ip test-ip4 pre
+ [ payload load 4b @ network header + 12 => reg 2 ]
+ [ payload load 4b @ network header + 16 => reg 13 ]
+ [ hash reg 1 = jhash(reg 2, 8, 0x0) % mod 2 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0x0
+ip test-ip4 pre
+ [ payload load 4b @ network header + 12 => reg 2 ]
+ [ payload load 4b @ network header + 16 => reg 13 ]
+ [ hash reg 1 = jhash(reg 2, 8, 0x0) % mod 2 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef offset 100
+ip test-ip4 pre
+ [ payload load 4b @ network header + 12 => reg 2 ]
+ [ payload load 4b @ network header + 16 => reg 13 ]
+ [ hash reg 1 = jhash(reg 2, 8, 0xdeadbeef) % mod 2 offset 100 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set jhash ip saddr . ip daddr mod 2 offset 100
+ip test-ip4 pre
+ [ payload load 4b @ network header + 12 => reg 2 ]
+ [ payload load 4b @ network header + 16 => reg 13 ]
+ [ hash reg 1 = jhash(reg 2, 8, 0x0) % mod 2 offset 100 ]
+ [ ct set mark with reg 1 ]
+
+# dnat to jhash ip saddr mod 2 seed 0xdeadbeef map { 0 : 192.168.20.100, 1 : 192.168.30.100 }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00000000 : 6414a8c0 0 [end] element 00000001 : 641ea8c0 0 [end]
+ip test-ip4 pre
+ [ payload load 4b @ network header + 12 => reg 2 ]
+ [ hash reg 1 = jhash(reg 2, 4, 0xdeadbeef) % mod 2 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# ct mark set symhash mod 2 offset 100
+ip test-ip4 pre
+ [ hash reg 1 = symhash() % mod 2 offset 100 ]
+ [ ct set mark with reg 1 ]
diff --git a/tests/py/ip/icmp.t b/tests/py/ip/icmp.t
new file mode 100644
index 0000000..7ddf8b3
--- /dev/null
+++ b/tests/py/ip/icmp.t
@@ -0,0 +1,77 @@
+# BUG: There is a bug with icmp protocol and inet family.
+# *inet;test-inet
+:input;type filter hook input priority 0
+
+*ip;test-ip4;input
+
+icmp type echo-reply accept;ok
+icmp type destination-unreachable accept;ok
+icmp type source-quench accept;ok
+icmp type redirect accept;ok
+icmp type echo-request accept;ok
+icmp type time-exceeded accept;ok
+icmp type parameter-problem accept;ok
+icmp type timestamp-request accept;ok
+icmp type timestamp-reply accept;ok
+icmp type info-request accept;ok
+icmp type info-reply accept;ok
+icmp type address-mask-request accept;ok
+icmp type address-mask-reply accept;ok
+icmp type router-advertisement accept;ok
+icmp type router-solicitation accept;ok
+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;ok
+icmp type != {echo-reply, destination-unreachable, source-quench};ok
+
+icmp code 111 accept;ok
+icmp code != 111 accept;ok
+icmp code 33-55;ok
+icmp code != 33-55;ok
+icmp code { 2, 4, 54, 33, 56};ok;icmp code { prot-unreachable, frag-needed, 33, 54, 56}
+icmp code != { prot-unreachable, frag-needed, 33, 54, 56};ok
+
+icmp checksum 12343 accept;ok
+icmp checksum != 12343 accept;ok
+icmp checksum 11-343 accept;ok
+icmp checksum != 11-343 accept;ok
+icmp checksum { 1111, 222, 343} accept;ok
+icmp checksum != { 1111, 222, 343} accept;ok
+
+icmp id 1245 log;ok;icmp type { echo-reply, echo-request} icmp id 1245 log
+icmp id 22;ok;icmp type { echo-reply, echo-request} icmp id 22
+icmp id != 233;ok;icmp type { echo-reply, echo-request} icmp id != 233
+icmp id 33-45;ok;icmp type { echo-reply, echo-request} icmp id 33-45
+icmp id != 33-45;ok;icmp type { echo-reply, echo-request} icmp id != 33-45
+
+icmp id { 22, 34, 333};ok;icmp type { echo-request, echo-reply} icmp id { 22, 34, 333}
+icmp id != { 22, 34, 333};ok;icmp type { echo-request, echo-reply} icmp id != { 22, 34, 333}
+
+icmp sequence 22;ok;icmp type { echo-reply, echo-request} icmp sequence 22
+icmp sequence != 233;ok;icmp type { echo-reply, echo-request} icmp sequence != 233
+icmp sequence 33-45;ok;icmp type { echo-reply, echo-request} icmp sequence 33-45
+icmp sequence != 33-45;ok;icmp type { echo-reply, echo-request} icmp sequence != 33-45
+icmp sequence { 33, 55, 67, 88};ok;icmp type { echo-request, echo-reply} icmp sequence { 33, 55, 67, 88}
+icmp sequence != { 33, 55, 67, 88};ok;icmp type { echo-request, echo-reply} icmp sequence != { 33, 55, 67, 88}
+icmp id 1 icmp sequence 2;ok;icmp type { echo-reply, echo-request} icmp id 1 icmp sequence 2
+icmp type { echo-reply, echo-request} icmp id 1 icmp sequence 2;ok
+icmp type echo-reply icmp id 1;ok
+
+icmp mtu 33;ok
+icmp mtu 22-33;ok
+icmp mtu 22;ok
+icmp mtu != 233;ok
+icmp mtu 33-45;ok
+icmp mtu != 33-45;ok
+icmp mtu { 33, 55, 67, 88};ok
+icmp mtu != { 33, 55, 67, 88};ok
+
+icmp gateway 22;ok
+icmp gateway != 233;ok
+icmp gateway 33-45;ok
+icmp gateway != 33-45;ok
+icmp gateway { 33, 55, 67, 88};ok
+icmp gateway != { 33, 55, 67, 88};ok
+icmp gateway != 34;ok
+icmp gateway != { 333, 334};ok
+
+icmp code 1 icmp type 2;ok;icmp type 2 icmp code host-unreachable
+icmp code != 1 icmp type 2 icmp mtu 5;fail
diff --git a/tests/py/ip/icmp.t.json b/tests/py/ip/icmp.t.json
new file mode 100644
index 0000000..4f05250
--- /dev/null
+++ b/tests/py/ip/icmp.t.json
@@ -0,0 +1,1494 @@
+# icmp type echo-reply accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-reply"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type destination-unreachable accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "destination-unreachable"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type source-quench accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "source-quench"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type redirect accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "redirect"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type echo-request accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type time-exceeded accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "time-exceeded"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type parameter-problem accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "parameter-problem"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type timestamp-request accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "timestamp-request"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type timestamp-reply accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "timestamp-reply"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type info-request accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "info-request"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type info-reply accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "info-reply"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type address-mask-request accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "address-mask-request"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type address-mask-reply accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "address-mask-reply"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type router-advertisement accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "router-advertisement"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp type router-solicitation accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "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 type != {echo-reply, destination-unreachable, source-quench}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "echo-reply",
+ "destination-unreachable",
+ "source-quench"
+ ]
+ }
+ }
+ }
+]
+
+# icmp code 111 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 111
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp code != 111 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 111
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp code 33-55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 33,
+ 55
+ ]
+ }
+ }
+ }
+]
+
+# icmp code != 33-55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 33,
+ 55
+ ]
+ }
+ }
+ }
+]
+
+# icmp code { 2, 4, 54, 33, 56}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 2,
+ 4,
+ 33,
+ 54,
+ 56
+ ]
+ }
+ }
+ }
+]
+
+# icmp code != { prot-unreachable, frag-needed, 33, 54, 56}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "prot-unreachable",
+ "frag-needed",
+ 33,
+ 54,
+ 56
+ ]
+ }
+ }
+ }
+]
+
+# icmp checksum 12343 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 12343
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum != 12343 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 12343
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum 11-343 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 11,
+ 343
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum != 11-343 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 11,
+ 343
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum { 1111, 222, 343} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 222,
+ 343,
+ 1111
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp checksum != { 1111, 222, 343} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 222,
+ 343,
+ 1111
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmp id 1245 log
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 1245
+ }
+ },
+ {
+ "log": null
+ }
+]
+
+# icmp id 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# icmp id != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmp id 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmp id != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmp id { 22, 34, 333}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 22,
+ 34,
+ 333
+ ]
+ }
+ }
+ }
+]
+
+# icmp id != { 22, 34, 333}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 22,
+ 34,
+ 333
+ ]
+ }
+ }
+ }
+]
+
+# icmp sequence 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# icmp sequence != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmp sequence 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmp sequence != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmp sequence { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp sequence != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp id 1 icmp sequence 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# icmp type { echo-reply, echo-request} icmp id 1 icmp sequence 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# icmp type echo-reply icmp id 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-reply"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# icmp mtu 33
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 33
+ }
+ }
+]
+
+# icmp mtu 22-33
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 22,
+ 33
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# icmp mtu != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmp mtu 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp mtu != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# icmp gateway != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmp gateway 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmp gateway != 34
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 34
+ }
+ }
+]
+
+# icmp gateway != { 333, 334}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "gateway",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 333,
+ 334
+ ]
+ }
+ }
+ }
+]
+
+# icmp code 1 icmp type 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "host-unreachable"
+ }
+ }
+]
diff --git a/tests/py/ip/icmp.t.json.output b/tests/py/ip/icmp.t.json.output
new file mode 100644
index 0000000..5a07585
--- /dev/null
+++ b/tests/py/ip/icmp.t.json.output
@@ -0,0 +1,169 @@
+# icmp code { 2, 4, 54, 33, 56}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "prot-unreachable",
+ "frag-needed",
+ 33,
+ 54,
+ 56
+ ]
+ }
+ }
+ }
+]
+
+# icmp id 1245 log
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 1245
+ }
+ },
+ {
+ "log": null
+ }
+]
+
+# icmp id 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# icmp id != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmp id { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+
diff --git a/tests/py/ip/icmp.t.payload.ip b/tests/py/ip/icmp.t.payload.ip
new file mode 100644
index 0000000..3bc6de3
--- /dev/null
+++ b/tests/py/ip/icmp.t.payload.ip
@@ -0,0 +1,619 @@
+# icmp type echo-reply accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ immediate reg 0 accept ]
+
+# icmp type destination-unreachable accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ immediate reg 0 accept ]
+
+# icmp type source-quench accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000004 ]
+ [ immediate reg 0 accept ]
+
+# icmp type redirect accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+ [ immediate reg 0 accept ]
+
+# icmp type echo-request accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ immediate reg 0 accept ]
+
+# icmp type time-exceeded accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000000b ]
+ [ immediate reg 0 accept ]
+
+# icmp type parameter-problem accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000000c ]
+ [ immediate reg 0 accept ]
+
+# icmp type timestamp-request accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000000d ]
+ [ immediate reg 0 accept ]
+
+# icmp type timestamp-reply accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000000e ]
+ [ immediate reg 0 accept ]
+
+# icmp type info-request accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000000f ]
+ [ immediate reg 0 accept ]
+
+# icmp type info-reply accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000010 ]
+ [ immediate reg 0 accept ]
+
+# icmp type address-mask-request accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 0 accept ]
+
+# icmp type address-mask-reply accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000012 ]
+ [ immediate reg 0 accept ]
+
+# icmp type != {echo-reply, destination-unreachable, source-quench}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000000 : 0 [end] element 00000003 : 0 [end] element 00000004 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmp code 111 accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp eq reg 1 0x0000006f ]
+ [ immediate reg 0 accept ]
+
+# icmp code != 111 accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp neq reg 1 0x0000006f ]
+ [ immediate reg 0 accept ]
+
+# icmp code 33-55
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x00000037 ]
+
+# icmp code != 33-55
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x00000037 ]
+
+# icmp code { 2, 4, 54, 33, 56}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000036 : 0 [end] element 00000021 : 0 [end] element 00000038 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmp code != { prot-unreachable, frag-needed, 33, 54, 56}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000036 : 0 [end] element 00000021 : 0 [end] element 00000038 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmp checksum 12343 accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003730 ]
+ [ immediate reg 0 accept ]
+
+# icmp checksum != 12343 accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x00003730 ]
+ [ immediate reg 0 accept ]
+
+# icmp checksum 11-343 accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00000b00 ]
+ [ cmp lte reg 1 0x00005701 ]
+ [ immediate reg 0 accept ]
+
+# icmp checksum != 11-343 accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00000b00 0x00005701 ]
+ [ immediate reg 0 accept ]
+
+# icmp checksum { 1111, 222, 343} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00005704 : 0 [end] element 0000de00 : 0 [end] element 00005701 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# icmp checksum != { 1111, 222, 343} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00005704 : 0 [end] element 0000de00 : 0 [end] element 00005701 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# icmp id 1245 log
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x0000dd04 ]
+ [ log ]
+
+# icmp id 22
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# icmp id != 233
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# icmp id 33-45
+__set%d test-ip4 3
+__set%d test-ip4 input
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# icmp id != 33-45
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# icmp id { 22, 34, 333}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00001600 : 0 [end] element 00002200 : 0 [end] element 00004d01 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmp id != { 22, 34, 333}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00001600 : 0 [end] element 00002200 : 0 [end] element 00004d01 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmp sequence 22
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# icmp sequence != 233
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# icmp sequence 33-45
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# icmp sequence != 33-45
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# icmp sequence { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmp sequence != { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmp id 1 icmp sequence 2
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x02000100 ]
+
+# icmp type { echo-reply, echo-request} icmp id 1 icmp sequence 2
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000000 : 0 [end] element 00000008 : 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x02000100 ]
+
+# icmp type echo-reply icmp id 1
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# icmp mtu 33
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00002100 ]
+
+# icmp mtu 22-33
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00001600 ]
+ [ cmp lte reg 1 0x00002100 ]
+
+# icmp mtu 22
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# icmp mtu != 233
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# icmp mtu 33-45
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# icmp mtu != 33-45
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# icmp mtu { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmp mtu != { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmp gateway 22
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# icmp gateway != 233
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp neq reg 1 0xe9000000 ]
+
+# icmp gateway 33-45
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# icmp gateway != 33-45
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# icmp gateway { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmp gateway != { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmp gateway != 34
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x22000000 ]
+
+# icmp gateway != { 333, 334}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 4d010000 : 0 [end] element 4e010000 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmp type router-advertisement accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000009 ]
+ [ immediate reg 0 accept ]
+
+# icmp type router-solicitation accept
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ immediate reg 0 accept ]
+
+# 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
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000000 : 0 [end] element 00000003 : 0 [end] element 00000004 : 0 [end] element 00000005 : 0 [end] element 00000008 : 0 [end] element 0000000b : 0 [end] element 0000000c : 0 [end] element 0000000d : 0 [end] element 0000000e : 0 [end] element 0000000f : 0 [end] element 00000010 : 0 [end] element 00000011 : 0 [end] element 00000012 : 0 [end] element 00000009 : 0 [end] element 0000000a : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# icmp code 1 icmp type 2
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000102 ]
diff --git a/tests/py/ip/igmp.t b/tests/py/ip/igmp.t
new file mode 100644
index 0000000..a556e47
--- /dev/null
+++ b/tests/py/ip/igmp.t
@@ -0,0 +1,23 @@
+# *inet;test-inet
+:input;type filter hook input priority 0
+
+*ip;test-ip4;input
+
+igmp type membership-query;ok
+igmp type membership-report-v1;ok
+igmp type membership-report-v2;ok
+igmp type membership-report-v3;ok
+igmp type leave-group;ok
+
+igmp type { membership-report-v1, membership-report-v2, membership-report-v3};ok
+igmp type != { membership-report-v1, membership-report-v2, membership-report-v3};ok
+
+igmp checksum 12343;ok
+igmp checksum != 12343;ok
+igmp checksum 11-343;ok
+igmp checksum != 11-343;ok
+igmp checksum { 1111, 222, 343};ok
+igmp checksum != { 1111, 222, 343};ok
+
+igmp mrt 10;ok
+igmp mrt != 10;ok
diff --git a/tests/py/ip/igmp.t.json b/tests/py/ip/igmp.t.json
new file mode 100644
index 0000000..0e2a43f
--- /dev/null
+++ b/tests/py/ip/igmp.t.json
@@ -0,0 +1,273 @@
+# igmp type membership-query
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": "membership-query"
+ }
+ }
+]
+
+# igmp type membership-report-v1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": "membership-report-v1"
+ }
+ }
+]
+
+# igmp type membership-report-v2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": "membership-report-v2"
+ }
+ }
+]
+
+# igmp type membership-report-v3
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": "membership-report-v3"
+ }
+ }
+]
+
+# igmp type leave-group
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": "leave-group"
+ }
+ }
+]
+
+# igmp type { membership-report-v1, membership-report-v2, membership-report-v3}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "membership-report-v1",
+ "membership-report-v2",
+ "membership-report-v3"
+ ]
+ }
+ }
+ }
+]
+
+# igmp type != { membership-report-v1, membership-report-v2, membership-report-v3}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "igmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "membership-report-v1",
+ "membership-report-v2",
+ "membership-report-v3"
+ ]
+ }
+ }
+ }
+]
+
+# igmp checksum 12343
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": 12343
+ }
+ }
+]
+
+# igmp checksum != 12343
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "igmp"
+ }
+ },
+ "op": "!=",
+ "right": 12343
+ }
+ }
+]
+
+# igmp checksum 11-343
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 11,
+ 343
+ ]
+ }
+ }
+ }
+]
+
+# igmp checksum != 11-343
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "igmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 11,
+ 343
+ ]
+ }
+ }
+ }
+]
+
+# igmp checksum { 1111, 222, 343}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 222,
+ 343,
+ 1111
+ ]
+ }
+ }
+ }
+]
+
+# igmp checksum != { 1111, 222, 343}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "igmp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 222,
+ 343,
+ 1111
+ ]
+ }
+ }
+ }
+]
+
+# igmp mrt 10
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mrt",
+ "protocol": "igmp"
+ }
+ },
+ "op": "==",
+ "right": 10
+ }
+ }
+]
+
+# igmp mrt != 10
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mrt",
+ "protocol": "igmp"
+ }
+ },
+ "op": "!=",
+ "right": 10
+ }
+ }
+]
diff --git a/tests/py/ip/igmp.t.payload b/tests/py/ip/igmp.t.payload
new file mode 100644
index 0000000..940fe2c
--- /dev/null
+++ b/tests/py/ip/igmp.t.payload
@@ -0,0 +1,118 @@
+# igmp type membership-query
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+
+# igmp type membership-report-v1
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000012 ]
+
+# igmp type membership-report-v2
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# igmp type membership-report-v3
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000022 ]
+
+# igmp type leave-group
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000017 ]
+
+# igmp checksum 12343
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003730 ]
+
+# igmp checksum != 12343
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x00003730 ]
+
+# igmp checksum 11-343
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00000b00 ]
+ [ cmp lte reg 1 0x00005701 ]
+
+# igmp checksum != 11-343
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00000b00 0x00005701 ]
+
+# igmp checksum { 1111, 222, 343}
+__set%d test-ip4 3 size 3
+__set%d test-ip4 0
+ element 00005704 : 0 [end] element 0000de00 : 0 [end] element 00005701 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# igmp checksum != { 1111, 222, 343}
+__set%d test-ip4 3 size 3
+__set%d test-ip4 0
+ element 00005704 : 0 [end] element 0000de00 : 0 [end] element 00005701 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# igmp type { membership-report-v1, membership-report-v2, membership-report-v3}
+__set%d test-ip4 3 size 3
+__set%d test-ip4 0
+ element 00000012 : 0 [end] element 00000016 : 0 [end] element 00000022 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# igmp type != { membership-report-v1, membership-report-v2, membership-report-v3}
+__set%d test-ip4 3 size 3
+__set%d test-ip4 0
+ element 00000012 : 0 [end] element 00000016 : 0 [end] element 00000022 : 0 [end]
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# igmp mrt 10
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+
+# igmp mrt != 10
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp neq reg 1 0x0000000a ]
+
diff --git a/tests/py/ip/ip.t b/tests/py/ip/ip.t
new file mode 100644
index 0000000..720d9ae
--- /dev/null
+++ b/tests/py/ip/ip.t
@@ -0,0 +1,135 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*inet;test-inet;input
+*bridge;test-bridge;input
+*netdev;test-netdev;ingress,egress
+
+- ip version 2;ok
+
+# bug ip hdrlength
+- ip hdrlength 10;ok
+- ip hdrlength != 5;ok
+- ip hdrlength 5-8;ok
+- ip hdrlength != 3-13;ok
+- ip hdrlength {3, 5, 6, 8};ok
+- ip hdrlength != {3, 5, 7, 8};ok
+- ip hdrlength { 3-5};ok
+- ip hdrlength != { 3-59};ok
+# ip hdrlength 12
+# <cmdline>:1:1-38: Error: Could not process rule: Invalid argument
+# add rule ip test input ip hdrlength 12
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+# <cmdline>:1:37-38: Error: Value 22 exceeds valid range 0-15
+# add rule ip test input ip hdrlength 22
+
+ip dscp cs1;ok
+ip dscp != cs1;ok
+ip dscp 0x38;ok;ip dscp cs7
+ip dscp != 0x20;ok;ip dscp != cs4
+ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef};ok
+- ip dscp {0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x00, 0x0a, 0x0c, 0x0e, 0x12, 0x14, 0x16, 0x1a, 0x1c, 0x1e, 0x22, 0x24, 0x26, 0x2e};ok
+ip dscp != {cs0, cs3};ok
+ip dscp vmap { cs1 : continue , cs4 : accept } counter;ok
+
+ip length 232;ok
+ip length != 233;ok
+ip length 333-435;ok
+ip length != 333-453;ok
+ip length { 333, 553, 673, 838};ok
+ip length != { 333, 553, 673, 838};ok
+
+ip id 22;ok
+ip id != 233;ok
+ip id 33-45;ok
+ip id != 33-45;ok
+ip id { 33, 55, 67, 88};ok
+ip id != { 33, 55, 67, 88};ok
+
+ip frag-off 0xde accept;ok
+ip frag-off != 0xe9;ok
+ip frag-off 0x21-0x2d;ok
+ip frag-off != 0x21-0x2d;ok
+ip frag-off { 0x21, 0x37, 0x43, 0x58};ok
+ip frag-off != { 0x21, 0x37, 0x43, 0x58};ok
+ip frag-off & 0x1fff != 0x0;ok
+ip frag-off & 0x2000 != 0x0;ok
+ip frag-off & 0x4000 != 0x0;ok
+
+ip ttl 0 drop;ok
+ip ttl 233;ok
+ip ttl 33-55;ok
+ip ttl != 45-50;ok
+ip ttl {43, 53, 45 };ok
+ip ttl != {43, 53, 45 };ok
+
+ip protocol tcp;ok;ip protocol 6
+ip protocol != tcp;ok;ip protocol != 6
+ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept;ok;ip protocol { 33, 136, 17, 51, 50, 6, 132, 1, 108} accept
+ip protocol != { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept;ok;ip protocol != { 33, 136, 17, 51, 50, 6, 132, 1, 108} accept
+
+ip protocol 255;ok
+ip protocol 256;fail
+
+ip checksum 13172 drop;ok
+ip checksum 22;ok
+ip checksum != 233;ok
+ip checksum 33-45;ok
+ip checksum != 33-45;ok
+ip checksum { 33, 55, 67, 88};ok
+ip checksum != { 33, 55, 67, 88};ok
+
+ip saddr set {192.19.1.2, 191.1.22.1};fail
+
+ip saddr 192.168.2.0/24;ok
+ip saddr != 192.168.2.0/24;ok
+ip saddr 192.168.3.1 ip daddr 192.168.3.100;ok
+ip saddr != 1.1.1.1;ok
+ip saddr 1.1.1.1;ok
+ip daddr 192.168.0.1-192.168.0.250;ok
+ip daddr 10.0.0.0-10.255.255.255;ok
+ip daddr 172.16.0.0-172.31.255.255;ok
+ip daddr 192.168.3.1-192.168.4.250;ok
+ip daddr != 192.168.0.1-192.168.0.250;ok
+ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept;ok
+ip daddr != { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept;ok
+
+ip daddr 192.168.1.2-192.168.1.55;ok
+ip daddr != 192.168.1.2-192.168.1.55;ok
+ip saddr 192.168.1.3-192.168.33.55;ok
+ip saddr != 192.168.1.3-192.168.33.55;ok
+
+ip daddr 192.168.0.1;ok
+ip daddr 192.168.0.1 drop;ok
+ip daddr 192.168.0.2;ok
+
+ip saddr & 0xff == 1;ok;ip saddr & 0.0.0.255 == 0.0.0.1
+ip saddr & 0.0.0.255 < 0.0.0.127;ok
+
+ip saddr & 0xffff0000 == 0xffff0000;ok;ip saddr 255.255.0.0/16
+
+ip version 4 ip hdrlength 5;ok
+ip hdrlength 0;ok
+ip hdrlength 15;ok
+ip hdrlength vmap { 0-4 : drop, 5 : accept, 6 : continue } counter;ok
+ip hdrlength 16;fail
+
+# limit impact to lo
+iif "lo" ip daddr set 127.0.0.1;ok
+iif "lo" ip checksum set 0;ok
+iif "lo" ip id set 0;ok
+iif "lo" ip ecn set 1;ok;iif "lo" ip ecn set ect1
+iif "lo" ip ecn set ce;ok
+iif "lo" ip ttl set 23;ok
+iif "lo" ip protocol set 1;ok
+
+iif "lo" ip dscp set af23;ok
+iif "lo" ip dscp set cs0;ok
+
+ip saddr . ip daddr { 192.0.2.1 . 10.0.0.1-10.0.0.2 };ok
+ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept };ok
+
+ip saddr 1.2.3.4 ip daddr 3.4.5.6;ok
+ip saddr 1.2.3.4 counter ip daddr 3.4.5.6;ok
diff --git a/tests/py/ip/ip.t.json b/tests/py/ip/ip.t.json
new file mode 100644
index 0000000..882c94e
--- /dev/null
+++ b/tests/py/ip/ip.t.json
@@ -0,0 +1,1811 @@
+# ip dscp cs1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "cs1"
+ }
+ }
+]
+
+# ip dscp != cs1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "cs1"
+ }
+ }
+]
+
+# ip dscp 0x38
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "0x38"
+ }
+ }
+]
+
+# ip dscp != 0x20
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "cs0",
+ "cs3"
+ ]
+ }
+ }
+ }
+]
+
+# ip dscp vmap { cs1 : continue , cs4 : accept } counter
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "cs1",
+ {
+ "continue": null
+ }
+ ],
+ [
+ "cs4",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "counter": null
+ }
+]
+
+# ip length 232
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 232
+ }
+ }
+]
+
+# ip length != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip length 333-435
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 333, 435 ]
+ }
+ }
+ }
+]
+
+# ip length != 333-453
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 333, 453 ]
+ }
+ }
+ }
+]
+
+# ip length { 333, 553, 673, 838}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 333,
+ 553,
+ 673,
+ 838
+ ]
+ }
+ }
+ }
+]
+
+# ip length != { 333, 553, 673, 838}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 333,
+ 553,
+ 673,
+ 838
+ ]
+ }
+ }
+ }
+]
+
+# ip id 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip id != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip id 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip id != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip id { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip id != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip frag-off 0xde accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 222
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip frag-off != 0xe9
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip frag-off 0x21-0x2d
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip frag-off != 0x21-0x2d
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip frag-off { 0x21, 0x37, 0x43, 0x58}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip frag-off != { 0x21, 0x37, 0x43, 0x58}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip frag-off & 0x1fff != 0x0
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ 8191
+ ]
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# ip frag-off & 0x2000 != 0x0
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ 8192
+ ]
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# ip frag-off & 0x4000 != 0x0
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ 16384
+ ]
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# ip ttl 0 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip ttl 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 233
+ }
+ }
+]
+
+# ip ttl 33-55
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 55 ]
+ }
+ }
+ }
+]
+
+# ip ttl != 45-50
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 45, 50 ]
+ }
+ }
+ }
+]
+
+# ip ttl {43, 53, 45 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 43,
+ 45,
+ 53
+ ]
+ }
+ }
+ }
+]
+
+# ip ttl != {43, 53, 45 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "ttl",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 43,
+ 45,
+ 53
+ ]
+ }
+ }
+ }
+]
+
+# ip protocol tcp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ }
+]
+
+# ip protocol != tcp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "tcp"
+ }
+ }
+]
+
+# ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "icmp",
+ "esp",
+ "ah",
+ "comp",
+ "udp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip protocol 255
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 255
+ }
+ }
+]
+
+# ip checksum 13172 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 13172
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip checksum 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip checksum != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip checksum 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip checksum != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip checksum { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip checksum != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip saddr 192.168.2.0/24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "192.168.2.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# ip saddr != 192.168.2.0/24
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.3.1"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.3.100"
+ }
+ }
+]
+
+# ip saddr != 1.1.1.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "1.1.1.1"
+ }
+ }
+]
+
+# ip saddr 1.1.1.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.1.1.1"
+ }
+ }
+]
+
+# ip daddr 192.168.0.1-192.168.0.250
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "192.168.1.3", "192.168.33.55" ]
+ }
+ }
+ }
+]
+
+# ip daddr 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ }
+]
+
+# ip daddr 192.168.0.1 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip daddr 192.168.0.2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.2"
+ }
+ }
+]
+
+# ip saddr & 0xff == 1
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "0xff"
+ ]
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# ip saddr & 0.0.0.255 < 0.0.0.127
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "0.0.0.255"
+ ]
+ },
+ "op": "<",
+ "right": "0.0.0.127"
+ }
+ }
+]
+
+# ip saddr & 0xffff0000 == 0xffff0000
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "0xffff0000"
+ ]
+ },
+ "op": "==",
+ "right": "0xffff0000"
+ }
+ }
+]
+
+# ip version 4 ip hdrlength 5
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "version",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 4
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 5
+ }
+ }
+]
+
+# ip hdrlength 0
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# ip hdrlength 15
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 15
+ }
+ }
+]
+
+# ip hdrlength vmap { 0-4 : drop, 5 : accept, 6 : continue } counter
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "hdrlength",
+ "protocol": "ip"
+ }
+ },
+ "data": {
+ "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": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "value": "127.0.0.1"
+ }
+ }
+]
+
+# iif "lo" ip checksum set 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "ip"
+ }
+ },
+ "value": 0
+ }
+ }
+]
+
+# iif "lo" ip id set 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "id",
+ "protocol": "ip"
+ }
+ },
+ "value": 0
+ }
+ }
+]
+
+# iif "lo" ip ecn set 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "ecn",
+ "protocol": "ip"
+ }
+ },
+ "value": 1
+ }
+ }
+]
+
+# iif "lo" ip ecn set ce
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "ecn",
+ "protocol": "ip"
+ }
+ },
+ "value": "ce"
+ }
+ }
+]
+
+# iif "lo" ip ttl set 23
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "ttl",
+ "protocol": "ip"
+ }
+ },
+ "value": 23
+ }
+ }
+]
+
+# iif "lo" ip protocol set 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "value": 1
+ }
+ }
+]
+
+# iif "lo" ip dscp set af23
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ "value": "af23"
+ }
+ }
+]
+
+# iif "lo" ip dscp set cs0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ "value": "cs0"
+ }
+ }
+]
+
+# ip saddr . ip daddr { 192.0.2.1 . 10.0.0.1-10.0.0.2 }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "192.0.2.1",
+ {
+ "range": [
+ "10.0.0.1",
+ "10.0.0.2"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+[
+ {
+ "vmap": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ {
+ "range": [
+ "192.168.5.1",
+ "192.168.5.128"
+ ]
+ },
+ {
+ "range": [
+ "192.168.6.1",
+ "192.168.6.128"
+ ]
+ }
+ ]
+ },
+ {
+ "accept": null
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ip saddr 1.2.3.4 ip daddr 3.4.5.6
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "3.4.5.6"
+ }
+ }
+]
+
+# ip saddr 1.2.3.4 counter ip daddr 3.4.5.6
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "1.2.3.4"
+ }
+ },
+ {
+ "counter": {
+ "bytes": 0,
+ "packets": 0
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "3.4.5.6"
+ }
+ }
+]
diff --git a/tests/py/ip/ip.t.json.got b/tests/py/ip/ip.t.json.got
new file mode 100644
index 0000000..07ab4e3
--- /dev/null
+++ b/tests/py/ip/ip.t.json.got
@@ -0,0 +1,62 @@
+# ip frag-off & 0x1fff != 0x0
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ 8191
+ ]
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# ip frag-off & 0x2000 != 0x0
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ 8192
+ ]
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
+# ip frag-off & 0x4000 != 0x0
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "frag-off",
+ "protocol": "ip"
+ }
+ },
+ 16384
+ ]
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
diff --git a/tests/py/ip/ip.t.json.output b/tests/py/ip/ip.t.json.output
new file mode 100644
index 0000000..b201cda
--- /dev/null
+++ b/tests/py/ip/ip.t.json.output
@@ -0,0 +1,232 @@
+# ip dscp 0x38
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "cs7"
+ }
+ }
+]
+
+# ip dscp != 0x20
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ }
+]
+
+# ip protocol != tcp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 6
+ }
+ }
+]
+
+# ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 1,
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip saddr & 0xff == 1
+[
+ {
+ "match": {
+ "left": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "0.0.0.255"
+ ]
+ },
+ "op": "==",
+ "right": "0.0.0.1"
+ }
+ }
+]
+
+# ip saddr & 0xffff0000 == 0xffff0000
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "255.255.0.0",
+ "len": 16
+ }
+ }
+ }
+ }
+]
+
+# iif "lo" ip ecn set 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "ecn",
+ "protocol": "ip"
+ }
+ },
+ "value": "ect1"
+ }
+ }
+]
+
diff --git a/tests/py/ip/ip.t.payload b/tests/py/ip/ip.t.payload
new file mode 100644
index 0000000..43605a3
--- /dev/null
+++ b/tests/py/ip/ip.t.payload
@@ -0,0 +1,558 @@
+# ip dscp cs1
+ip test-ip4 input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000020 ]
+
+# ip dscp != cs1
+ip test-ip4 input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000020 ]
+
+# ip dscp 0x38
+ip test-ip4 input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x000000e0 ]
+
+# ip dscp != 0x20
+ip test-ip4 input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000080 ]
+
+# ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000020 : 0 [end] element 00000040 : 0 [end] element 00000060 : 0 [end] element 00000080 : 0 [end] element 000000a0 : 0 [end] element 000000c0 : 0 [end] element 000000e0 : 0 [end] element 00000000 : 0 [end] element 00000028 : 0 [end] element 00000030 : 0 [end] element 00000038 : 0 [end] element 00000048 : 0 [end] element 00000050 : 0 [end] element 00000058 : 0 [end] element 00000068 : 0 [end] element 00000070 : 0 [end] element 00000078 : 0 [end] element 00000088 : 0 [end] element 00000090 : 0 [end] element 00000098 : 0 [end] element 000000b8 : 0 [end]
+ip test-ip4 input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip dscp != {cs0, cs3}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000000 : 0 [end] element 00000060 : 0 [end]
+ip test-ip4 input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip dscp vmap { cs1 : continue , cs4 : accept } counter
+__map%d test-ip4 b size 2
+__map%d test-ip4 0
+ element 00000020 : continue 0 [end] element 00000080 : accept 0 [end]
+ip test-ip4 input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# ip length 232
+ip test-ip4 input
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000e800 ]
+
+# ip length != 233
+ip test-ip4 input
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip length 333-435
+ip test-ip4 input
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00004d01 ]
+ [ cmp lte reg 1 0x0000b301 ]
+
+# ip length != 333-453
+ip test-ip4 input
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ range neq reg 1 0x00004d01 0x0000c501 ]
+
+# ip length { 333, 553, 673, 838}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00004d01 : 0 [end] element 00002902 : 0 [end] element 0000a102 : 0 [end] element 00004603 : 0 [end]
+ip test-ip4 input
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip length != { 333, 553, 673, 838}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00004d01 : 0 [end] element 00002902 : 0 [end] element 0000a102 : 0 [end] element 00004603 : 0 [end]
+ip test-ip4 input
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip id 22
+ip test-ip4 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip id != 233
+ip test-ip4 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip id 33-45
+ip test-ip4 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip id != 33-45
+ip test-ip4 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip id { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip id != { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip frag-off 0xde accept
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0000de00 ]
+ [ immediate reg 0 accept ]
+
+# ip frag-off != 0xe9
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip frag-off 0x21-0x2d
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip frag-off != 0x21-0x2d
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip frag-off { 0x21, 0x37, 0x43, 0x58}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip frag-off != { 0x21, 0x37, 0x43, 0x58}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip frag-off & 0x1fff != 0x0
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff1f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x2000 != 0x0
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x4000 != 0x0
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000040 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip ttl 0 drop
+ip test-ip4 input
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ immediate reg 0 drop ]
+
+# ip ttl 233
+ip test-ip4 input
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x000000e9 ]
+
+# ip ttl 33-55
+ip test-ip4 input
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x00000037 ]
+
+# ip ttl != 45-50
+ip test-ip4 input
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ range neq reg 1 0x0000002d 0x00000032 ]
+
+# ip ttl {43, 53, 45 }
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 0000002b : 0 [end] element 00000035 : 0 [end] element 0000002d : 0 [end]
+ip test-ip4 input
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip ttl != {43, 53, 45 }
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 0000002b : 0 [end] element 00000035 : 0 [end] element 0000002d : 0 [end]
+ip test-ip4 input
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip protocol tcp
+ip test-ip4 input
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# ip protocol != tcp
+ip test-ip4 input
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp neq reg 1 0x00000006 ]
+
+# ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+ip test-ip4 input
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# ip protocol != { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000001 : 0 [end] element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+ip test-ip4 input
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip protocol 255
+ip test-ip4 input
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x000000ff ]
+
+# ip checksum 13172 drop
+ip test-ip4 input
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp eq reg 1 0x00007433 ]
+ [ immediate reg 0 drop ]
+
+# ip checksum 22
+ip test-ip4 input
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip checksum != 233
+ip test-ip4 input
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip checksum 33-45
+ip test-ip4 input
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip checksum != 33-45
+ip test-ip4 input
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip checksum { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip checksum != { 33, 55, 67, 88}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip test-ip4 input
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip saddr 192.168.2.0/24
+ip test-ip4 input
+ [ payload load 3b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0002a8c0 ]
+
+# ip saddr != 192.168.2.0/24
+ip test-ip4 input
+ [ payload load 3b @ network header + 12 => reg 1 ]
+ [ cmp neq reg 1 0x0002a8c0 ]
+
+# ip saddr 192.168.3.1 ip daddr 192.168.3.100
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0103a8c0 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x6403a8c0 ]
+
+# ip saddr != 1.1.1.1
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp neq reg 1 0x01010101 ]
+
+# ip saddr 1.1.1.1
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x01010101 ]
+
+# ip daddr 192.168.0.1-192.168.0.250
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0100a8c0 ]
+ [ cmp lte reg 1 0xfa00a8c0 ]
+
+# ip daddr 10.0.0.0-10.255.255.255
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0000000a ]
+ [ cmp lte reg 1 0xffffff0a ]
+
+# ip daddr 172.16.0.0-172.31.255.255
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x000010ac ]
+ [ cmp lte reg 1 0xffff1fac ]
+
+# ip daddr 192.168.3.1-192.168.4.250
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0103a8c0 ]
+ [ cmp lte reg 1 0xfa04a8c0 ]
+
+# ip daddr != 192.168.0.1-192.168.0.250
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ range neq reg 1 0x0100a8c0 0xfa00a8c0 ]
+
+# ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 0105a8c0 : 0 [end] element 0205a8c0 : 0 [end] element 0305a8c0 : 0 [end]
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# ip daddr != { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 0105a8c0 : 0 [end] element 0205a8c0 : 0 [end] element 0305a8c0 : 0 [end]
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip daddr 192.168.1.2-192.168.1.55
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0201a8c0 ]
+ [ cmp lte reg 1 0x3701a8c0 ]
+
+# ip daddr != 192.168.1.2-192.168.1.55
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ range neq reg 1 0x0201a8c0 0x3701a8c0 ]
+
+# ip saddr 192.168.1.3-192.168.33.55
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp gte reg 1 0x0301a8c0 ]
+ [ cmp lte reg 1 0x3721a8c0 ]
+
+# ip saddr != 192.168.1.3-192.168.33.55
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ range neq reg 1 0x0301a8c0 0x3721a8c0 ]
+
+# ip daddr 192.168.0.1
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
+# ip daddr 192.168.0.1 drop
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+ [ immediate reg 0 drop ]
+
+# ip daddr 192.168.0.2
+ip test-ip4 input
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0200a8c0 ]
+
+# ip saddr & 0xff == 1
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xff000000 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# ip saddr & 0.0.0.255 < 0.0.0.127
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xff000000 ) ^ 0x00000000 ]
+ [ cmp lt reg 1 0x7f000000 ]
+
+# ip saddr & 0xffff0000 == 0xffff0000
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000ffff ]
+
+# ip version 4 ip hdrlength 5
+ip test-ip4 input
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000040 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000005 ]
+
+# ip hdrlength 0
+ip test-ip4 input
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ip hdrlength 15
+ip test-ip4 input
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000f ]
+
+# ip hdrlength vmap { 0-4 : drop, 5 : accept, 6 : continue } counter
+__map%d test-ip4 f size 4
+__map%d test-ip4 0
+ element 00000000 : drop 0 [end] element 00000005 : accept 0 [end] element 00000006 : continue 0 [end] element 00000007 : 1 [end]
+ip test-ip4 input
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# iif "lo" ip daddr set 127.0.0.1
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 1 0x0100007f ]
+ [ payload write reg 1 => 4b @ network header + 16 csum_type 1 csum_off 10 csum_flags 0x1 ]
+
+# iif "lo" ip checksum set 0
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 1 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 10 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip id set 0
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 1 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 4 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ecn set 1
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000fcff ) ^ 0x00000100 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ecn set ce
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000fcff ) ^ 0x00000300 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip dscp set af23
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000003ff ) ^ 0x00005800 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip dscp set cs0
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000003ff ) ^ 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ttl set 23
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ network header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff00 ) ^ 0x00000017 ]
+ [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip protocol set 1
+ip test-ip4 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ network header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000ff ) ^ 0x00000100 ]
+ [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x1 ]
+
+# ip saddr . ip daddr { 192.0.2.1 . 10.0.0.1-10.0.0.2 }
+__set%d test-ip4 87 size 1
+__set%d test-ip4 0
+ element 010200c0 0100000a - 010200c0 0200000a : 0 [end]
+ip
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+__map%d test-ip4 8f size 1
+__map%d test-ip4 0
+ element 0105a8c0 0106a8c0 - 8005a8c0 8006a8c0 : accept 0 [end]
+ip
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip saddr 1.2.3.4 ip daddr 3.4.5.6
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x06050403 ]
+
+# ip saddr 1.2.3.4 counter ip daddr 3.4.5.6
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x06050403 ]
diff --git a/tests/py/ip/ip.t.payload.bridge b/tests/py/ip/ip.t.payload.bridge
new file mode 100644
index 0000000..e506f30
--- /dev/null
+++ b/tests/py/ip/ip.t.payload.bridge
@@ -0,0 +1,728 @@
+# ip dscp cs1
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000020 ]
+
+# ip dscp != cs1
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000020 ]
+
+# ip dscp 0x38
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x000000e0 ]
+
+# ip dscp != 0x20
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000080 ]
+
+# ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}
+__set%d test-bridge 3 size 21
+__set%d test-bridge 0
+ element 00000000 : 0 [end] element 00000020 : 0 [end] element 00000040 : 0 [end] element 00000060 : 0 [end] element 00000080 : 0 [end] element 000000a0 : 0 [end] element 000000c0 : 0 [end] element 000000e0 : 0 [end] element 00000028 : 0 [end] element 00000030 : 0 [end] element 00000038 : 0 [end] element 00000048 : 0 [end] element 00000050 : 0 [end] element 00000058 : 0 [end] element 00000068 : 0 [end] element 00000070 : 0 [end] element 00000078 : 0 [end] element 00000088 : 0 [end] element 00000090 : 0 [end] element 00000098 : 0 [end] element 000000b8 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip dscp != {cs0, cs3}
+__set%d test-bridge 3 size 2
+__set%d test-bridge 0
+ element 00000000 : 0 [end] element 00000060 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip dscp vmap { cs1 : continue , cs4 : accept } counter
+__map%d test-bridge b size 2
+__map%d test-bridge 0
+ element 00000020 : continue 0 [end] element 00000080 : accept 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# ip length 232
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000e800 ]
+
+# ip length != 233
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip length 333-435
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00004d01 ]
+ [ cmp lte reg 1 0x0000b301 ]
+
+# ip length != 333-453
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ range neq reg 1 0x00004d01 0x0000c501 ]
+
+# ip length { 333, 553, 673, 838}
+__set%d test-bridge 3 size 4
+__set%d test-bridge 0
+ element 00004d01 : 0 [end] element 00002902 : 0 [end] element 0000a102 : 0 [end] element 00004603 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip length != { 333, 553, 673, 838}
+__set%d test-bridge 3 size 4
+__set%d test-bridge 0
+ element 00004d01 : 0 [end] element 00002902 : 0 [end] element 0000a102 : 0 [end] element 00004603 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip id 22
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip id != 233
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip id 33-45
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip id != 33-45
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip id { 33, 55, 67, 88}
+__set%d test-bridge 3 size 4
+__set%d test-bridge 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip id != { 33, 55, 67, 88}
+__set%d test-bridge 3 size 4
+__set%d test-bridge 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip frag-off 0xde accept
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0000de00 ]
+ [ immediate reg 0 accept ]
+
+# ip frag-off != 0xe9
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip frag-off 0x21-0x2d
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip frag-off != 0x21-0x2d
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip frag-off { 0x21, 0x37, 0x43, 0x58}
+__set%d test-bridge 3 size 4
+__set%d test-bridge 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip frag-off != { 0x21, 0x37, 0x43, 0x58}
+__set%d test-bridge 3 size 4
+__set%d test-bridge 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip frag-off & 0x1fff != 0x0
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff1f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x2000 != 0x0
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x4000 != 0x0
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000040 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip ttl 0 drop
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ immediate reg 0 drop ]
+
+# ip ttl 233
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x000000e9 ]
+
+# ip ttl 33-55
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x00000037 ]
+
+# ip ttl != 45-50
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ range neq reg 1 0x0000002d 0x00000032 ]
+
+# ip ttl {43, 53, 45 }
+__set%d test-bridge 3 size 3
+__set%d test-bridge 0
+ element 0000002b : 0 [end] element 00000035 : 0 [end] element 0000002d : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip ttl != {43, 53, 45 }
+__set%d test-bridge 3 size 3
+__set%d test-bridge 0
+ element 0000002b : 0 [end] element 00000035 : 0 [end] element 0000002d : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip protocol tcp
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# ip protocol != tcp
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp neq reg 1 0x00000006 ]
+
+# ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+__set%d test-bridge 3 size 9
+__set%d test-bridge 0
+ element 00000001 : 0 [end] element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# ip protocol != { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+__set%d test-bridge 3 size 9
+__set%d test-bridge 0
+ element 00000001 : 0 [end] element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip protocol 255
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x000000ff ]
+
+# ip checksum 13172 drop
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp eq reg 1 0x00007433 ]
+ [ immediate reg 0 drop ]
+
+# ip checksum 22
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip checksum != 233
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip checksum 33-45
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip checksum != 33-45
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip checksum { 33, 55, 67, 88}
+__set%d test-bridge 3 size 4
+__set%d test-bridge 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip checksum != { 33, 55, 67, 88}
+__set%d test-bridge 3 size 4
+__set%d test-bridge 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip saddr 192.168.2.0/24
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0002a8c0 ]
+
+# ip saddr != 192.168.2.0/24
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
+ [ cmp neq reg 1 0x0002a8c0 ]
+
+# ip saddr 192.168.3.1 ip daddr 192.168.3.100
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0103a8c0 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x6403a8c0 ]
+
+# ip saddr != 1.1.1.1
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp neq reg 1 0x01010101 ]
+
+# ip saddr 1.1.1.1
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x01010101 ]
+
+# ip daddr 192.168.0.1-192.168.0.250
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0100a8c0 ]
+ [ cmp lte reg 1 0xfa00a8c0 ]
+
+# ip daddr 10.0.0.0-10.255.255.255
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0000000a ]
+ [ cmp lte reg 1 0xffffff0a ]
+
+# ip daddr 172.16.0.0-172.31.255.255
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x000010ac ]
+ [ cmp lte reg 1 0xffff1fac ]
+
+# ip daddr 192.168.3.1-192.168.4.250
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0103a8c0 ]
+ [ cmp lte reg 1 0xfa04a8c0 ]
+
+# ip daddr != 192.168.0.1-192.168.0.250
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ range neq reg 1 0x0100a8c0 0xfa00a8c0 ]
+
+# ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+__set%d test-bridge 3 size 3
+__set%d test-bridge 0
+ element 0105a8c0 : 0 [end] element 0205a8c0 : 0 [end] element 0305a8c0 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# ip daddr != { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+__set%d test-bridge 3 size 3
+__set%d test-bridge 0
+ element 0105a8c0 : 0 [end] element 0205a8c0 : 0 [end] element 0305a8c0 : 0 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip daddr 192.168.1.2-192.168.1.55
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0201a8c0 ]
+ [ cmp lte reg 1 0x3701a8c0 ]
+
+# ip daddr != 192.168.1.2-192.168.1.55
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ range neq reg 1 0x0201a8c0 0x3701a8c0 ]
+
+# ip saddr 192.168.1.3-192.168.33.55
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp gte reg 1 0x0301a8c0 ]
+ [ cmp lte reg 1 0x3721a8c0 ]
+
+# ip saddr != 192.168.1.3-192.168.33.55
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ range neq reg 1 0x0301a8c0 0x3721a8c0 ]
+
+# ip daddr 192.168.0.1
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
+# ip daddr 192.168.0.1 drop
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+ [ immediate reg 0 drop ]
+
+# ip daddr 192.168.0.2
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0200a8c0 ]
+
+# ip saddr & 0xff == 1
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xff000000 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# ip saddr & 0.0.0.255 < 0.0.0.127
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xff000000 ) ^ 0x00000000 ]
+ [ cmp lt reg 1 0x7f000000 ]
+
+# ip saddr & 0xffff0000 == 0xffff0000
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000ffff ]
+
+# ip version 4 ip hdrlength 5
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000040 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000005 ]
+
+# ip hdrlength 0
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ip hdrlength 15
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000f ]
+
+# ip hdrlength vmap { 0-4 : drop, 5 : accept, 6 : continue } counter
+__map%d test-bridge f size 4
+__map%d test-bridge 0
+ element 00000000 : drop 0 [end] element 00000005 : accept 0 [end] element 00000006 : continue 0 [end] element 00000007 : 1 [end]
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# iif "lo" ip daddr set 127.0.0.1
+bridge test-bridge input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ immediate reg 1 0x0100007f ]
+ [ payload write reg 1 => 4b @ network header + 16 csum_type 1 csum_off 10 csum_flags 0x1 ]
+
+# iif "lo" ip checksum set 0
+bridge test-bridge input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ immediate reg 1 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 10 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip id set 0
+bridge test-bridge input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ immediate reg 1 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 4 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ecn set 1
+bridge test-bridge input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000fcff ) ^ 0x00000100 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ecn set ce
+bridge test-bridge input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000fcff ) ^ 0x00000300 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ttl set 23
+bridge test-bridge input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff00 ) ^ 0x00000017 ]
+ [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip protocol set 1
+bridge test-bridge input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000ff ) ^ 0x00000100 ]
+ [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x1 ]
+
+# iif "lo" ip dscp set af23
+bridge test-bridge input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000003ff ) ^ 0x00005800 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip dscp set cs0
+bridge test-bridge input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000003ff ) ^ 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# ip saddr . ip daddr { 192.0.2.1 . 10.0.0.1-10.0.0.2 }
+__set%d test-bridge 87 size 1
+__set%d test-bridge 0
+ element 010200c0 0100000a - 010200c0 0200000a : 0 [end]
+bridge
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+__map%d test-bridge 8f size 1
+__map%d test-bridge 0
+ element 0105a8c0 0106a8c0 - 8005a8c0 8006a8c0 : accept 0 [end]
+bridge
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip saddr 1.2.3.4 ip daddr 3.4.5.6
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x06050403 ]
+
+# ip saddr 1.2.3.4 counter ip daddr 3.4.5.6
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x06050403 ]
diff --git a/tests/py/ip/ip.t.payload.bridge.got b/tests/py/ip/ip.t.payload.bridge.got
new file mode 100644
index 0000000..e728c23
--- /dev/null
+++ b/tests/py/ip/ip.t.payload.bridge.got
@@ -0,0 +1,24 @@
+# ip frag-off & 0x1fff != 0x0
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff1f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x2000 != 0x0
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x4000 != 0x0
+bridge test-bridge input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000040 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
diff --git a/tests/py/ip/ip.t.payload.got b/tests/py/ip/ip.t.payload.got
new file mode 100644
index 0000000..9a5c942
--- /dev/null
+++ b/tests/py/ip/ip.t.payload.got
@@ -0,0 +1,18 @@
+# ip frag-off & 0x1fff != 0x0
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff1f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x2000 != 0x0
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x4000 != 0x0
+ip test-ip4 input
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000040 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
diff --git a/tests/py/ip/ip.t.payload.inet b/tests/py/ip/ip.t.payload.inet
new file mode 100644
index 0000000..a7fa0fa
--- /dev/null
+++ b/tests/py/ip/ip.t.payload.inet
@@ -0,0 +1,728 @@
+# ip dscp cs1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000020 ]
+
+# ip dscp != cs1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000020 ]
+
+# ip dscp 0x38
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x000000e0 ]
+
+# ip dscp != 0x20
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000080 ]
+
+# ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000020 : 0 [end] element 00000040 : 0 [end] element 00000060 : 0 [end] element 00000080 : 0 [end] element 000000a0 : 0 [end] element 000000c0 : 0 [end] element 000000e0 : 0 [end] element 00000000 : 0 [end] element 00000028 : 0 [end] element 00000030 : 0 [end] element 00000038 : 0 [end] element 00000048 : 0 [end] element 00000050 : 0 [end] element 00000058 : 0 [end] element 00000068 : 0 [end] element 00000070 : 0 [end] element 00000078 : 0 [end] element 00000088 : 0 [end] element 00000090 : 0 [end] element 00000098 : 0 [end] element 000000b8 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip dscp != {cs0, cs3}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000000 : 0 [end] element 00000060 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip dscp vmap { cs1 : continue , cs4 : accept } counter
+__map%d test-inet b size 2
+__map%d test-inet 0
+ element 00000020 : continue 0 [end] element 00000080 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# ip length 232
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000e800 ]
+
+# ip length != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip length 333-435
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00004d01 ]
+ [ cmp lte reg 1 0x0000b301 ]
+
+# ip length != 333-453
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ range neq reg 1 0x00004d01 0x0000c501 ]
+
+# ip length { 333, 553, 673, 838}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00004d01 : 0 [end] element 00002902 : 0 [end] element 0000a102 : 0 [end] element 00004603 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip length != { 333, 553, 673, 838}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00004d01 : 0 [end] element 00002902 : 0 [end] element 0000a102 : 0 [end] element 00004603 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip id 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip id != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip id 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip id != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip id { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip id != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip frag-off 0xde accept
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0000de00 ]
+ [ immediate reg 0 accept ]
+
+# ip frag-off != 0xe9
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip frag-off 0x21-0x2d
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip frag-off != 0x21-0x2d
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip frag-off { 0x21, 0x37, 0x43, 0x58}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip frag-off != { 0x21, 0x37, 0x43, 0x58}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip frag-off & 0x1fff != 0x0
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff1f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x2000 != 0x0
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x4000 != 0x0
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000040 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip ttl 0 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ immediate reg 0 drop ]
+
+# ip ttl 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x000000e9 ]
+
+# ip ttl 33-55
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x00000037 ]
+
+# ip ttl != 45-50
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ range neq reg 1 0x0000002d 0x00000032 ]
+
+# ip ttl {43, 53, 45 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 0000002b : 0 [end] element 00000035 : 0 [end] element 0000002d : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip ttl != {43, 53, 45 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 0000002b : 0 [end] element 00000035 : 0 [end] element 0000002d : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip protocol tcp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# ip protocol != tcp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp neq reg 1 0x00000006 ]
+
+# ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000001 : 0 [end] element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# ip protocol != { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000001 : 0 [end] element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip protocol 255
+ip test-ip4 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x000000ff ]
+
+# ip checksum 13172 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp eq reg 1 0x00007433 ]
+ [ immediate reg 0 drop ]
+
+# ip checksum 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip checksum != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip checksum 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip checksum != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip checksum { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip checksum != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip saddr 192.168.2.0/24
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0002a8c0 ]
+
+# ip saddr != 192.168.2.0/24
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
+ [ cmp neq reg 1 0x0002a8c0 ]
+
+# ip saddr 192.168.3.1 ip daddr 192.168.3.100
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0103a8c0 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x6403a8c0 ]
+
+# ip saddr != 1.1.1.1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp neq reg 1 0x01010101 ]
+
+# ip saddr 1.1.1.1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x01010101 ]
+
+# ip daddr 192.168.0.1-192.168.0.250
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0100a8c0 ]
+ [ cmp lte reg 1 0xfa00a8c0 ]
+
+# ip daddr 10.0.0.0-10.255.255.255
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0000000a ]
+ [ cmp lte reg 1 0xffffff0a ]
+
+# ip daddr 172.16.0.0-172.31.255.255
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x000010ac ]
+ [ cmp lte reg 1 0xffff1fac ]
+
+# ip daddr 192.168.3.1-192.168.4.250
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0103a8c0 ]
+ [ cmp lte reg 1 0xfa04a8c0 ]
+
+# ip daddr != 192.168.0.1-192.168.0.250
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ range neq reg 1 0x0100a8c0 0xfa00a8c0 ]
+
+# ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 0105a8c0 : 0 [end] element 0205a8c0 : 0 [end] element 0305a8c0 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# ip daddr != { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+__set%d test-inet 3
+__set%d test-inet 0
+ element 0105a8c0 : 0 [end] element 0205a8c0 : 0 [end] element 0305a8c0 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip daddr 192.168.1.2-192.168.1.55
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0201a8c0 ]
+ [ cmp lte reg 1 0x3701a8c0 ]
+
+# ip daddr != 192.168.1.2-192.168.1.55
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ range neq reg 1 0x0201a8c0 0x3701a8c0 ]
+
+# ip saddr 192.168.1.3-192.168.33.55
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp gte reg 1 0x0301a8c0 ]
+ [ cmp lte reg 1 0x3721a8c0 ]
+
+# ip saddr != 192.168.1.3-192.168.33.55
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ range neq reg 1 0x0301a8c0 0x3721a8c0 ]
+
+# ip daddr 192.168.0.1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
+# ip daddr 192.168.0.1 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+ [ immediate reg 0 drop ]
+
+# ip daddr 192.168.0.2
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0200a8c0 ]
+
+# ip saddr & 0xff == 1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xff000000 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# ip saddr & 0.0.0.255 < 0.0.0.127
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xff000000 ) ^ 0x00000000 ]
+ [ cmp lt reg 1 0x7f000000 ]
+
+# ip saddr & 0xffff0000 == 0xffff0000
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000ffff ]
+
+# ip version 4 ip hdrlength 5
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000040 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000005 ]
+
+# ip hdrlength 0
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ip hdrlength 15
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000f ]
+
+# ip hdrlength vmap { 0-4 : drop, 5 : accept, 6 : continue } counter
+__map%d test-inet f size 4
+__map%d test-inet 0
+ element 00000000 : drop 0 [end] element 00000005 : accept 0 [end] element 00000006 : continue 0 [end] element 00000007 : 1 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# iif "lo" ip daddr set 127.0.0.1
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ immediate reg 1 0x0100007f ]
+ [ payload write reg 1 => 4b @ network header + 16 csum_type 1 csum_off 10 csum_flags 0x1 ]
+
+# iif "lo" ip checksum set 0
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ immediate reg 1 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 10 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip id set 0
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ immediate reg 1 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 4 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ecn set 1
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000fcff ) ^ 0x00000100 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ecn set ce
+inet test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000fcff ) ^ 0x00000300 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip dscp set af23
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000003ff ) ^ 0x00005800 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip dscp set cs0
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000003ff ) ^ 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ttl set 23
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff00 ) ^ 0x00000017 ]
+ [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip protocol set 1
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000ff ) ^ 0x00000100 ]
+ [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x1 ]
+
+# ip saddr . ip daddr { 192.0.2.1 . 10.0.0.1-10.0.0.2 }
+__set%d test-inet 87 size 1
+__set%d test-inet 0
+ element 010200c0 0100000a - 010200c0 0200000a : 0 [end]
+inet
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+__map%d test-inet 8f size 1
+__map%d test-inet 0
+ element 0105a8c0 0106a8c0 - 8005a8c0 8006a8c0 : accept 0 [end]
+inet
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip saddr 1.2.3.4 ip daddr 3.4.5.6
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x06050403 ]
+
+# ip saddr 1.2.3.4 counter ip daddr 3.4.5.6
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x06050403 ]
diff --git a/tests/py/ip/ip.t.payload.inet.got b/tests/py/ip/ip.t.payload.inet.got
new file mode 100644
index 0000000..ac52c78
--- /dev/null
+++ b/tests/py/ip/ip.t.payload.inet.got
@@ -0,0 +1,24 @@
+# ip frag-off & 0x1fff != 0x0
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff1f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x2000 != 0x0
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x4000 != 0x0
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000040 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
diff --git a/tests/py/ip/ip.t.payload.netdev b/tests/py/ip/ip.t.payload.netdev
new file mode 100644
index 0000000..aebd9d6
--- /dev/null
+++ b/tests/py/ip/ip.t.payload.netdev
@@ -0,0 +1,728 @@
+# ip length 232
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000e800 ]
+
+# ip length != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip length 333-435
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00004d01 ]
+ [ cmp lte reg 1 0x0000b301 ]
+
+# ip length != 333-453
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ range neq reg 1 0x00004d01 0x0000c501 ]
+
+# ip length { 333, 553, 673, 838}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00004d01 : 0 [end] element 00002902 : 0 [end] element 0000a102 : 0 [end] element 00004603 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip length != { 333, 553, 673, 838}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00004d01 : 0 [end] element 00002902 : 0 [end] element 0000a102 : 0 [end] element 00004603 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip id 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip id != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip id 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip id != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip id { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip id != { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip frag-off 0xde accept
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0000de00 ]
+ [ immediate reg 0 accept ]
+
+# ip frag-off != 0xe9
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip frag-off 0x21-0x2d
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip frag-off != 0x21-0x2d
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip frag-off { 0x21, 0x37, 0x43, 0x58}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip frag-off != { 0x21, 0x37, 0x43, 0x58}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip frag-off & 0x1fff != 0x0
+netdev x y
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff1f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x2000 != 0x0
+netdev x y
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x4000 != 0x0
+netdev x y
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000040 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip ttl 0 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+ [ immediate reg 0 drop ]
+
+# ip ttl 33-55
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x00000037 ]
+
+# ip ttl != 45-50
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ range neq reg 1 0x0000002d 0x00000032 ]
+
+# ip ttl {43, 53, 45 }
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 0000002b : 0 [end] element 00000035 : 0 [end] element 0000002d : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip ttl != {43, 53, 45 }
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 0000002b : 0 [end] element 00000035 : 0 [end] element 0000002d : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000001 : 0 [end] element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# ip protocol != { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000001 : 0 [end] element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip protocol 255
+ip test-ip4 input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x000000ff ]
+
+# ip checksum 13172 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp eq reg 1 0x00007433 ]
+ [ immediate reg 0 drop ]
+
+# ip checksum 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip checksum != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip checksum 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip checksum != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip checksum { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip checksum != { 33, 55, 67, 88}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 10 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip saddr 192.168.2.0/24
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0002a8c0 ]
+
+# ip saddr != 192.168.2.0/24
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 3b @ network header + 12 => reg 1 ]
+ [ cmp neq reg 1 0x0002a8c0 ]
+
+# ip saddr 192.168.3.1 ip daddr 192.168.3.100
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0103a8c0 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x6403a8c0 ]
+
+# ip saddr 1.1.1.1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x01010101 ]
+
+# ip daddr 192.168.0.1-192.168.0.250
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0100a8c0 ]
+ [ cmp lte reg 1 0xfa00a8c0 ]
+
+# ip daddr 10.0.0.0-10.255.255.255
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0000000a ]
+ [ cmp lte reg 1 0xffffff0a ]
+
+# ip daddr 172.16.0.0-172.31.255.255
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x000010ac ]
+ [ cmp lte reg 1 0xffff1fac ]
+
+# ip daddr 192.168.3.1-192.168.4.250
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0103a8c0 ]
+ [ cmp lte reg 1 0xfa04a8c0 ]
+
+# ip daddr != 192.168.0.1-192.168.0.250
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ range neq reg 1 0x0100a8c0 0xfa00a8c0 ]
+
+# ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 0105a8c0 : 0 [end] element 0205a8c0 : 0 [end] element 0305a8c0 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# ip daddr != { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 0105a8c0 : 0 [end] element 0205a8c0 : 0 [end] element 0305a8c0 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# ip daddr 192.168.1.2-192.168.1.55
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0201a8c0 ]
+ [ cmp lte reg 1 0x3701a8c0 ]
+
+# ip daddr != 192.168.1.2-192.168.1.55
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ range neq reg 1 0x0201a8c0 0x3701a8c0 ]
+
+# ip saddr 192.168.1.3-192.168.33.55
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp gte reg 1 0x0301a8c0 ]
+ [ cmp lte reg 1 0x3721a8c0 ]
+
+# ip saddr != 192.168.1.3-192.168.33.55
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ range neq reg 1 0x0301a8c0 0x3721a8c0 ]
+
+# ip daddr 192.168.0.1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
+# ip daddr 192.168.0.1 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr & 0xff == 1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xff000000 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# ip saddr & 0.0.0.255 < 0.0.0.127
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0xff000000 ) ^ 0x00000000 ]
+ [ cmp lt reg 1 0x7f000000 ]
+
+# ip saddr & 0xffff0000 == 0xffff0000
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ffff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000ffff ]
+
+# ip version 4 ip hdrlength 5
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000040 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000005 ]
+
+# ip hdrlength 0
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# ip hdrlength 15
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000f ]
+
+# ip hdrlength vmap { 0-4 : drop, 5 : accept, 6 : continue } counter
+__map%d test-netdev f size 4
+__map%d test-netdev 0
+ element 00000000 : drop 0 [end] element 00000005 : accept 0 [end] element 00000006 : continue 0 [end] element 00000007 : 1 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# ip ttl 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x000000e9 ]
+
+# ip protocol tcp
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# ip protocol != tcp
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp neq reg 1 0x00000006 ]
+
+# ip saddr != 1.1.1.1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp neq reg 1 0x01010101 ]
+
+# ip daddr 192.168.0.2
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0200a8c0 ]
+
+# ip dscp cs1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000020 ]
+
+# ip dscp != cs1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000020 ]
+
+# ip dscp 0x38
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x000000e0 ]
+
+# ip dscp != 0x20
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000080 ]
+
+# ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000000 : 0 [end] element 00000020 : 0 [end] element 00000040 : 0 [end] element 00000060 : 0 [end] element 00000080 : 0 [end] element 000000a0 : 0 [end] element 000000c0 : 0 [end] element 000000e0 : 0 [end] element 00000028 : 0 [end] element 00000030 : 0 [end] element 00000038 : 0 [end] element 00000048 : 0 [end] element 00000050 : 0 [end] element 00000058 : 0 [end] element 00000068 : 0 [end] element 00000070 : 0 [end] element 00000078 : 0 [end] element 00000088 : 0 [end] element 00000090 : 0 [end] element 00000098 : 0 [end] element 000000b8 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip dscp != {cs0, cs3}
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00000000 : 0 [end] element 00000060 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip dscp vmap { cs1 : continue , cs4 : accept } counter
+__map%d test-netdev b size 2
+__map%d test-netdev 0
+ element 00000020 : continue 0 [end] element 00000080 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# iif "lo" ip daddr set 127.0.0.1
+netdev test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ immediate reg 1 0x0100007f ]
+ [ payload write reg 1 => 4b @ network header + 16 csum_type 1 csum_off 10 csum_flags 0x1 ]
+
+# iif "lo" ip checksum set 0
+netdev test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ immediate reg 1 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 10 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip id set 0
+netdev test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ immediate reg 1 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 4 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ecn set 1
+netdev test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000fcff ) ^ 0x00000100 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ecn set ce
+netdev test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000fcff ) ^ 0x00000300 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip dscp set af23
+netdev test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000003ff ) ^ 0x00005800 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip dscp set cs0
+netdev test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000003ff ) ^ 0x00000000 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip ttl set 23
+netdev test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff00 ) ^ 0x00000017 ]
+ [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x0 ]
+
+# iif "lo" ip protocol set 1
+netdev test-netdev ingress
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000ff ) ^ 0x00000100 ]
+ [ payload write reg 1 => 2b @ network header + 8 csum_type 1 csum_off 10 csum_flags 0x1 ]
+
+# ip saddr . ip daddr { 192.0.2.1 . 10.0.0.1-10.0.0.2 }
+__set%d test-netdev 87 size 1
+__set%d test-netdev 0
+ element 010200c0 0100000a - 010200c0 0200000a : 0 [end]
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }
+__map%d test-netdev 8f size 1
+__map%d test-netdev 0
+ element 0105a8c0 0106a8c0 - 8005a8c0 8006a8c0 : accept 0 [end]
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip saddr 1.2.3.4 ip daddr 3.4.5.6
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x06050403 ]
+
+# ip saddr 1.2.3.4 counter ip daddr 3.4.5.6
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+ [ counter pkts 0 bytes 0 ]
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x06050403 ]
diff --git a/tests/py/ip/ip.t.payload.netdev.got b/tests/py/ip/ip.t.payload.netdev.got
new file mode 100644
index 0000000..b3e2e35
--- /dev/null
+++ b/tests/py/ip/ip.t.payload.netdev.got
@@ -0,0 +1,24 @@
+# ip frag-off & 0x1fff != 0x0
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000ff1f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x2000 != 0x0
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# ip frag-off & 0x4000 != 0x0
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 2b @ network header + 6 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000040 ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+
diff --git a/tests/py/ip/ip_tcp.t b/tests/py/ip/ip_tcp.t
new file mode 100644
index 0000000..ff398aa
--- /dev/null
+++ b/tests/py/ip/ip_tcp.t
@@ -0,0 +1,9 @@
+:input;type filter hook input priority 0
+
+*ip;test-ip;input
+
+# can remove ip dependency -- its redundant in ip family
+ip protocol tcp tcp dport 22;ok;tcp dport 22
+
+# but not here
+ip protocol tcp meta mark set 1 tcp dport 22;ok;ip protocol 6 meta mark set 0x00000001 tcp dport 22
diff --git a/tests/py/ip/ip_tcp.t.json b/tests/py/ip/ip_tcp.t.json
new file mode 100644
index 0000000..3757d6e
--- /dev/null
+++ b/tests/py/ip/ip_tcp.t.json
@@ -0,0 +1,64 @@
+# ip protocol tcp tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp meta mark set 1 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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 0000000..2d671df
--- /dev/null
+++ b/tests/py/ip/ip_tcp.t.json.output
@@ -0,0 +1,52 @@
+# ip protocol tcp tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip protocol tcp meta mark set 1 tcp dport 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
diff --git a/tests/py/ip/ip_tcp.t.payload b/tests/py/ip/ip_tcp.t.payload
new file mode 100644
index 0000000..f6f640d
--- /dev/null
+++ b/tests/py/ip/ip_tcp.t.payload
@@ -0,0 +1,16 @@
+# ip protocol tcp tcp dport 22
+ip test-ip input
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip protocol tcp meta mark set 1 tcp dport 22
+ip test-ip input
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x00000001 ]
+ [ meta set mark with reg 1 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
diff --git a/tests/py/ip/masquerade.t b/tests/py/ip/masquerade.t
new file mode 100644
index 0000000..384ac72
--- /dev/null
+++ b/tests/py/ip/masquerade.t
@@ -0,0 +1,30 @@
+:postrouting;type nat hook postrouting priority 0
+
+*ip;test-ip4;postrouting
+
+# nf_nat flags combination
+udp dport 53 masquerade;ok
+udp dport 53 masquerade random;ok
+udp dport 53 masquerade random,persistent;ok
+udp dport 53 masquerade random,persistent,fully-random;ok;udp dport 53 masquerade random,fully-random,persistent
+udp dport 53 masquerade random,fully-random;ok
+udp dport 53 masquerade random,fully-random,persistent;ok
+udp dport 53 masquerade persistent;ok
+udp dport 53 masquerade persistent,random;ok;udp dport 53 masquerade random,persistent
+udp dport 53 masquerade persistent,random,fully-random;ok;udp dport 53 masquerade random,fully-random,persistent
+udp dport 53 masquerade persistent,fully-random;ok;udp dport 53 masquerade fully-random,persistent
+udp dport 53 masquerade persistent,fully-random,random;ok;udp dport 53 masquerade random,fully-random,persistent
+
+# using ports
+ip protocol 6 masquerade to :1024;ok
+ip protocol 6 masquerade to :1024-2048;ok
+
+# masquerade is a terminal statement
+tcp dport 22 masquerade counter packets 0 bytes 0 accept;fail
+tcp sport 22 masquerade accept;fail
+ip saddr 10.1.1.1 masquerade drop;fail
+
+# masquerade with sets
+tcp dport { 1,2,3,4,5,6,7,8,101,202,303,1001,2002,3003} masquerade;ok
+ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter masquerade;ok
+iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } masquerade;ok
diff --git a/tests/py/ip/masquerade.t.json b/tests/py/ip/masquerade.t.json
new file mode 100644
index 0000000..4a90c70
--- /dev/null
+++ b/tests/py/ip/masquerade.t.json
@@ -0,0 +1,429 @@
+# udp dport 53 masquerade
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": null
+ }
+]
+
+# udp dport 53 masquerade random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": "random"
+ }
+ }
+]
+
+# udp dport 53 masquerade random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade random,fully-random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": "persistent"
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "fully-random",
+ "random"
+ ]
+ }
+ }
+]
+
+# ip protocol 6 masquerade to :1024
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "masquerade": {
+ "port": 1024
+ }
+ }
+]
+
+# ip protocol 6 masquerade to :1024-2048
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ "10.0.0.0", "10.2.3.4" ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "masquerade": null
+ }
+]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } masquerade
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "in",
+ "right": [
+ "established",
+ "new"
+ ]
+ }
+ },
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "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 0000000..58e7e29
--- /dev/null
+++ b/tests/py/ip/masquerade.t.json.output
@@ -0,0 +1,123 @@
+# udp dport 53 masquerade random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
diff --git a/tests/py/ip/masquerade.t.payload b/tests/py/ip/masquerade.t.payload
new file mode 100644
index 0000000..79e5285
--- /dev/null
+++ b/tests/py/ip/masquerade.t.payload
@@ -0,0 +1,142 @@
+# udp dport 53 masquerade
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq ]
+
+# udp dport 53 masquerade random
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x4 ]
+
+# udp dport 53 masquerade random,persistent
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0xc ]
+
+# udp dport 53 masquerade random,persistent,fully-random
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x1c ]
+
+# udp dport 53 masquerade random,fully-random
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x14 ]
+
+# udp dport 53 masquerade random,fully-random,persistent
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x1c ]
+
+# udp dport 53 masquerade persistent
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x8 ]
+
+# udp dport 53 masquerade persistent,random
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0xc ]
+
+# udp dport 53 masquerade persistent,random,fully-random
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x1c ]
+
+# udp dport 53 masquerade persistent,fully-random
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x18 ]
+
+# udp dport 53 masquerade persistent,fully-random,random
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x1c ]
+
+# tcp dport { 1,2,3,4,5,6,7,8,101,202,303,1001,2002,3003} masquerade
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000100 : 0 [end] element 00000200 : 0 [end] element 00000300 : 0 [end] element 00000400 : 0 [end] element 00000500 : 0 [end] element 00000600 : 0 [end] element 00000700 : 0 [end] element 00000800 : 0 [end] element 00006500 : 0 [end] element 0000ca00 : 0 [end] element 00002f01 : 0 [end] element 0000e903 : 0 [end] element 0000d207 : 0 [end] element 0000bb0b : 0 [end]
+ip test-ip4 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ masq ]
+
+# ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter masquerade
+ip test-ip4 postrouting
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0000000a ]
+ [ cmp lte reg 1 0x0403020a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ counter pkts 0 bytes 0 ]
+ [ masq ]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } masquerade
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00001600 : drop 0 [end] element 0000de00 : drop 0 [end]
+ip test-ip4 postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ ct load state => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000a ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ masq ]
+
+# ip protocol 6 masquerade to :1024
+ip test-ip4 postrouting
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x00000004 ]
+ [ masq proto_min reg 1 flags 0x2 ]
+
+# ip protocol 6 masquerade to :1024-2048
+ip test-ip4 postrouting
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x00000004 ]
+ [ immediate reg 2 0x00000008 ]
+ [ masq proto_min reg 1 proto_max reg 2 flags 0x2 ]
+
diff --git a/tests/py/ip/meta.t b/tests/py/ip/meta.t
new file mode 100644
index 0000000..a88a614
--- /dev/null
+++ b/tests/py/ip/meta.t
@@ -0,0 +1,22 @@
+:input;type filter hook input priority 0
+
+*ip;test-ip4;input
+
+icmp type echo-request;ok
+meta l4proto icmp icmp type echo-request;ok;icmp type echo-request
+meta l4proto ipv6-icmp icmpv6 type nd-router-advert;ok;icmpv6 type nd-router-advert
+meta l4proto 58 icmpv6 type nd-router-advert;ok;icmpv6 type nd-router-advert
+icmpv6 type nd-router-advert;ok
+
+meta protocol ip udp dport 67;ok;udp dport 67
+
+meta ibrname "br0";fail
+meta obrname "br0";fail
+
+meta sdif "lo" accept;ok
+meta sdifname != "vrf1" accept;ok
+
+meta mark set ip dscp;ok
+
+meta mark set ip dscp << 2 | 0x10;ok
+meta mark set ip dscp << 26 | 0x10;ok
diff --git a/tests/py/ip/meta.t.json b/tests/py/ip/meta.t.json
new file mode 100644
index 0000000..25936db
--- /dev/null
+++ b/tests/py/ip/meta.t.json
@@ -0,0 +1,236 @@
+# icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta l4proto icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": "icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta l4proto ipv6-icmp icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": "ipv6-icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# meta l4proto 58 icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": 58
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# meta sdif "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "sdif"
+ }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta sdifname != "vrf1" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "sdifname"
+ }
+ },
+ "op": "!=",
+ "right": "vrf1"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta protocol ip udp dport 67
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 67
+ }
+ }
+]
+
+# meta mark set ip dscp
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ }
+ }
+ }
+]
+
+# meta mark set ip dscp << 2 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ 2
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+
+# meta mark set ip dscp << 26 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip"
+ }
+ },
+ 26
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
diff --git a/tests/py/ip/meta.t.json.output b/tests/py/ip/meta.t.json.output
new file mode 100644
index 0000000..091282b
--- /dev/null
+++ b/tests/py/ip/meta.t.json.output
@@ -0,0 +1,48 @@
+# meta l4proto icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta l4proto ipv6-icmp icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# meta l4proto 58 icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-advert"
+ }
+ }
+]
+
diff --git a/tests/py/ip/meta.t.payload b/tests/py/ip/meta.t.payload
new file mode 100644
index 0000000..880ac5d
--- /dev/null
+++ b/tests/py/ip/meta.t.payload
@@ -0,0 +1,78 @@
+# icmp type echo-request
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# meta l4proto icmp icmp type echo-request
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# meta l4proto ipv6-icmp icmpv6 type nd-router-advert
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000086 ]
+
+# meta l4proto 58 icmpv6 type nd-router-advert
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000086 ]
+
+# icmpv6 type nd-router-advert
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000086 ]
+
+# meta sdif "lo" accept
+ip6 test-ip4 input
+ [ meta load sdif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 0 accept ]
+
+# meta sdifname != "vrf1" accept
+ip6 test-ip4 input
+ [ meta load sdifname => reg 1 ]
+ [ cmp neq reg 1 0x31667276 0x00000000 0x00000000 0x00000000 ]
+ [ immediate reg 0 accept ]
+
+# meta protocol ip udp dport 67
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00004300 ]
+
+# meta mark set ip dscp
+ip test-ip4 input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ip dscp << 2 | 0x10
+ip test-ip4 input
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 << 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ip dscp << 26 | 0x10
+ip
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 << 0x0000001a ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+ [ meta set mark with reg 1 ]
diff --git a/tests/py/ip/numgen.t b/tests/py/ip/numgen.t
new file mode 100644
index 0000000..2a88146
--- /dev/null
+++ b/tests/py/ip/numgen.t
@@ -0,0 +1,9 @@
+:pre;type nat hook prerouting priority 0
+*ip;test-ip4;pre
+
+ct mark set numgen inc mod 2;ok
+ct mark set numgen inc mod 2 offset 100;ok
+dnat to numgen inc mod 2 map { 0 : 192.168.10.100, 1 : 192.168.20.200 };ok
+dnat to numgen inc mod 10 map { 0-5 : 192.168.10.100, 6-9 : 192.168.20.200};ok
+dnat to numgen inc mod 7 offset 167772161;ok
+dnat to numgen inc mod 255 offset 167772161;ok
diff --git a/tests/py/ip/numgen.t.json b/tests/py/ip/numgen.t.json
new file mode 100644
index 0000000..6cf6604
--- /dev/null
+++ b/tests/py/ip/numgen.t.json
@@ -0,0 +1,129 @@
+# ct mark set numgen inc mod 2
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "numgen": {
+ "mod": 2,
+ "mode": "inc"
+ }
+ }
+ }
+ }
+]
+
+# ct mark set numgen inc mod 2 offset 100
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "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": {
+ "key": {
+ "numgen": {
+ "mod": 2,
+ "mode": "inc"
+ }
+ },
+ "data": {
+ "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": {
+ "key": {
+ "numgen": {
+ "mod": 10,
+ "mode": "inc"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ { "range": [ 0, 5 ] },
+ "192.168.10.100"
+ ],
+ [
+ { "range": [ 6, 9 ] },
+ "192.168.20.200"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# dnat to numgen inc mod 7 offset 167772161
+[
+ {
+ "dnat": {
+ "addr": {
+ "numgen": {
+ "mod": 7,
+ "mode": "inc",
+ "offset": 167772161
+ }
+ }
+ }
+ }
+]
+
+# dnat to numgen inc mod 255 offset 167772161
+[
+ {
+ "dnat": {
+ "addr": {
+ "numgen": {
+ "mod": 255,
+ "mode": "inc",
+ "offset": 167772161
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/numgen.t.json.output b/tests/py/ip/numgen.t.json.output
new file mode 100644
index 0000000..06ad1ec
--- /dev/null
+++ b/tests/py/ip/numgen.t.json.output
@@ -0,0 +1,112 @@
+# ct mark set numgen inc mod 2
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "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": {
+ "key": {
+ "numgen": {
+ "mod": 2,
+ "mode": "inc",
+ "offset": 0
+ }
+ },
+ "data": {
+ "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": {
+ "key": {
+ "numgen": {
+ "mod": 10,
+ "mode": "inc",
+ "offset": 0
+ }
+ },
+ "data": {
+ "set": [
+ [
+ { "range": [ 0, 5 ] },
+ "192.168.10.100"
+ ],
+ [
+ { "range": [ 6, 9 ] },
+ "192.168.20.200"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# dnat to numgen inc mod 7 offset 167772161
+[
+ {
+ "dnat": {
+ "addr": {
+ "numgen": {
+ "mod": 7,
+ "mode": "inc",
+ "offset": 167772161
+ }
+ }
+ }
+ }
+]
+
+# dnat to numgen inc mod 255 offset 167772161
+[
+ {
+ "dnat": {
+ "addr": {
+ "numgen": {
+ "mod": 255,
+ "mode": "inc",
+ "offset": 167772161
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/numgen.t.payload b/tests/py/ip/numgen.t.payload
new file mode 100644
index 0000000..b4eadf8
--- /dev/null
+++ b/tests/py/ip/numgen.t.payload
@@ -0,0 +1,40 @@
+# ct mark set numgen inc mod 2
+ip test-ip4 pre
+ [ numgen reg 1 = inc mod 2 ]
+ [ ct set mark with reg 1 ]
+
+# dnat to numgen inc mod 2 map { 0 : 192.168.10.100, 1 : 192.168.20.200 }
+__map%d x b
+__map%d x 0
+ element 00000000 : 640aa8c0 0 [end] element 00000001 : c814a8c0 0 [end]
+ip test-ip4 pre
+ [ numgen reg 1 = inc mod 2 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# dnat to numgen inc mod 10 map { 0-5 : 192.168.10.100, 6-9 : 192.168.20.200}
+__map%d test-ip4 f
+__map%d test-ip4 0
+ element 00000000 : 640aa8c0 0 [end] element 06000000 : c814a8c0 0 [end] element 0a000000 : 1 [end]
+ip test-ip4 pre
+ [ numgen reg 1 = inc mod 10 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# ct mark set numgen inc mod 2 offset 100
+ip test-ip4 pre
+ [ numgen reg 1 = inc mod 2 offset 100 ]
+ [ ct set mark with reg 1 ]
+
+# dnat to numgen inc mod 7 offset 167772161
+ip test-ip4 pre
+ [ numgen reg 1 = inc mod 7 offset 167772161 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ nat dnat ip addr_min reg 1 ]
+
+# dnat to numgen inc mod 255 offset 167772161
+ip test-ip4 pre
+ [ numgen reg 1 = inc mod 255 offset 167772161 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ nat dnat ip addr_min reg 1 ]
diff --git a/tests/py/ip/objects.t b/tests/py/ip/objects.t
new file mode 100644
index 0000000..4fcde7c
--- /dev/null
+++ b/tests/py/ip/objects.t
@@ -0,0 +1,58 @@
+:output;type filter hook output priority 0
+
+*ip;test-ip4;output
+
+# counter
+%cnt1 type counter;ok
+%cnt2 type counter;ok
+
+ip saddr 192.168.1.3 counter name "cnt2";ok
+ip saddr 192.168.1.3 counter name "cnt3";fail
+counter name tcp dport map {443 : "cnt1", 80 : "cnt2", 22 : "cnt1"};ok
+
+# quota
+%qt1 type quota 25 mbytes;ok
+%qt2 type quota over 1 kbytes;ok
+
+ip saddr 192.168.1.3 quota name "qt1";ok
+ip saddr 192.168.1.3 quota name "qt3";fail
+quota name tcp dport map {443 : "qt1", 80 : "qt2", 22 : "qt1"};ok
+
+# ct helper
+%cthelp1 type ct helper { type "ftp" protocol tcp; };ok
+%cthelp2 type ct helper { type "ftp" protocol tcp; l3proto ip6; };fail
+
+ct helper set "cthelp1";ok
+ct helper set tcp dport map {21 : "cthelp1", 2121 : "cthelp1" };ok
+
+# limit
+%lim1 type limit rate 400/minute;ok
+%lim2 type limit rate over 1024 bytes/second burst 512 bytes;ok
+
+ip saddr 192.168.1.3 limit name "lim1";ok
+ip saddr 192.168.1.3 limit name "lim3";fail
+limit name tcp dport map {443 : "lim1", 80 : "lim2", 22 : "lim1"};ok
+
+# ct timeout
+%cttime1 type ct timeout { protocol tcp; policy = { established:122 } ;};ok
+%cttime2 type ct timeout { protocol udp; policy = { syn_sent:122 } ;};fail
+%cttime3 type ct timeout { protocol tcp; policy = { established:132, close:16, close_wait:16 } ; l3proto ip ;};ok
+%cttime4 type ct timeout { protocol udp; policy = { replied:14, unreplied:19 } ;};ok
+%cttime5 type ct timeout {protocol tcp; policy = { estalbished:100 } ;};fail
+
+ct timeout set "cttime1";ok
+
+# ct expectation
+%ctexpect1 type ct expectation { protocol tcp; dport 1234; timeout 2m; size 12; };ok
+%ctexpect2 type ct expectation { protocol udp; };fail
+%ctexpect3 type ct expectation { protocol tcp; dport 4321; };fail
+%ctexpect4 type ct expectation { protocol tcp; dport 4321; timeout 2m; };fail
+%ctexpect5 type ct expectation { protocol udp; dport 9876; timeout 2m; size 12; l3proto ip; };ok
+
+ct expectation set "ctexpect1";ok
+
+# synproxy
+%synproxy1 type synproxy mss 1460 wscale 7;ok
+%synproxy2 type synproxy mss 1460 wscale 7 timestamp sack-perm;ok
+
+synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"};ok
diff --git a/tests/py/ip/objects.t.json b/tests/py/ip/objects.t.json
new file mode 100644
index 0000000..a70dd9e
--- /dev/null
+++ b/tests/py/ip/objects.t.json
@@ -0,0 +1,229 @@
+# ip saddr 192.168.1.3 counter name "cnt2"
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.3"
+ }
+ },
+ {
+ "counter": "cnt2"
+ }
+]
+
+# counter name tcp dport map {443 : "cnt1", 80 : "cnt2", 22 : "cnt1"}
+[
+ {
+ "counter": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 443,
+ "cnt1"
+ ],
+ [
+ 80,
+ "cnt2"
+ ],
+ [
+ 22,
+ "cnt1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
+# ip saddr 192.168.1.3 quota name "qt1"
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.3"
+ }
+ },
+ {
+ "quota": "qt1"
+ }
+]
+
+# quota name tcp dport map {443 : "qt1", 80 : "qt2", 22 : "qt1"}
+[
+ {
+ "quota": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 443,
+ "qt1"
+ ],
+ [
+ 80,
+ "qt2"
+ ],
+ [
+ 22,
+ "qt1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
+# ct helper set "cthelp1"
+[
+ {
+ "ct helper": "cthelp1"
+ }
+]
+
+# ct helper set tcp dport map {21 : "cthelp1", 2121 : "cthelp1" }
+[
+ {
+ "ct helper": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 21,
+ "cthelp1"
+ ],
+ [
+ 2121,
+ "cthelp1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
+# ip saddr 192.168.1.3 limit name "lim1"
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "192.168.1.3"
+ }
+ },
+ {
+ "limit": "lim1"
+ }
+]
+
+# limit name tcp dport map {443 : "lim1", 80 : "lim2", 22 : "lim1"}
+[
+ {
+ "limit": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 22,
+ "lim1"
+ ],
+ [
+ 80,
+ "lim2"
+ ],
+ [
+ 443,
+ "lim1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
+# ct timeout set "cttime1"
+[
+ {
+ "ct timeout": "cttime1"
+ }
+]
+
+# ct expectation set "ctexpect1"
+[
+ {
+ "ct expectation": "ctexpect1"
+ }
+]
+
+# synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"}
+[
+ {
+ "synproxy": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 80,
+ "synproxy2"
+ ],
+ [
+ 443,
+ "synproxy1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
diff --git a/tests/py/ip/objects.t.json.output b/tests/py/ip/objects.t.json.output
new file mode 100644
index 0000000..ade195d
--- /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": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 22,
+ "cnt1"
+ ],
+ [
+ 80,
+ "cnt2"
+ ],
+ [
+ 443,
+ "cnt1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
+# quota name tcp dport map {443 : "qt1", 80 : "qt2", 22 : "qt1"}
+[
+ {
+ "quota": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 22,
+ "qt1"
+ ],
+ [
+ 80,
+ "qt2"
+ ],
+ [
+ 443,
+ "qt1"
+ ]
+ ]
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/objects.t.payload b/tests/py/ip/objects.t.payload
new file mode 100644
index 0000000..5252724
--- /dev/null
+++ b/tests/py/ip/objects.t.payload
@@ -0,0 +1,79 @@
+# ip saddr 192.168.1.3 counter name "cnt2"
+ip test-ip4 output
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0301a8c0 ]
+ [ objref type 1 name cnt2 ]
+
+# counter name tcp dport map {443 : "cnt1", 80 : "cnt2", 22 : "cnt1"}
+__objmap%d test-ip4 43
+__objmap%d test-ip4 0
+ element 0000bb01 : 0 [end] element 00005000 : 0 [end] element 00001600 : 0 [end]
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ objref sreg 1 set __objmap%d ]
+
+# ip saddr 192.168.1.3 quota name "qt1"
+ip test-ip4 output
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0301a8c0 ]
+ [ objref type 2 name qt1 ]
+
+# quota name tcp dport map {443 : "qt1", 80 : "qt2", 22 : "qt1"}
+__objmap%d test-ip4 43
+__objmap%d test-ip4 0
+ element 0000bb01 : 0 [end] element 00005000 : 0 [end] element 00001600 : 0 [end]
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ objref sreg 1 set __objmap%d ]
+
+# ct helper set "cthelp1"
+ip test-ip4 output
+ [ objref type 3 name cthelp1 ]
+
+# ct helper set tcp dport map {21 : "cthelp1", 2121 : "cthelp1" }
+__objmap%d test-ip4 43
+__objmap%d test-ip4 0
+ element 00001500 : 0 [end] element 00004908 : 0 [end]
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ objref sreg 1 set __objmap%d ]
+
+# ip saddr 192.168.1.3 limit name "lim1"
+ip test-ip4 output
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ cmp eq reg 1 0x0301a8c0 ]
+ [ objref type 4 name lim1 ]
+
+# limit name tcp dport map {443 : "lim1", 80 : "lim2", 22 : "lim1"}
+__objmap%d test-ip4 43 size 3
+__objmap%d test-ip4 0
+ element 0000bb01 : 0 [end] element 00005000 : 0 [end] element 00001600 : 0 [end]
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ objref sreg 1 set __objmap%d ]
+
+# ct timeout set "cttime1"
+ip test-ip4 output
+ [ objref type 7 name cttime1 ]
+
+# ct expectation set "ctexpect1"
+ip test-ip4 output
+ [ objref type 9 name ctexpect1 ]
+
+# synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"}
+__objmap%d test-ip4 43 size 2
+__objmap%d test-ip4 0
+ element 0000bb01 : 0 [end] element 00005000 : 0 [end]
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ objref sreg 1 set __objmap%d ]
diff --git a/tests/py/ip/redirect.t b/tests/py/ip/redirect.t
new file mode 100644
index 0000000..8c2b52f
--- /dev/null
+++ b/tests/py/ip/redirect.t
@@ -0,0 +1,51 @@
+:output;type nat hook output priority 0
+
+*ip;test-ip4;output
+
+# without arguments
+udp dport 53 redirect;ok
+
+# nf_nat flags combination
+udp dport 53 redirect random;ok
+udp dport 53 redirect random,persistent;ok
+udp dport 53 redirect random,persistent,fully-random;ok;udp dport 53 redirect random,fully-random,persistent
+udp dport 53 redirect random,fully-random;ok
+udp dport 53 redirect random,fully-random,persistent;ok
+udp dport 53 redirect persistent;ok
+udp dport 53 redirect persistent,random;ok;udp dport 53 redirect random,persistent
+udp dport 53 redirect persistent,random,fully-random;ok;udp dport 53 redirect random,fully-random,persistent
+udp dport 53 redirect persistent,fully-random;ok;udp dport 53 redirect fully-random,persistent
+udp dport 53 redirect persistent,fully-random,random;ok;udp dport 53 redirect random,fully-random,persistent
+
+# port specification
+tcp dport 22 redirect to :22;ok
+udp dport 1234 redirect to :4321;ok
+ip daddr 172.16.0.1 udp dport 9998 redirect to :6515;ok
+tcp dport 39128 redirect to :993;ok
+ip protocol tcp redirect to :100-200;ok;ip protocol 6 redirect to :100-200
+redirect to :1234;fail
+redirect to :12341111;fail
+
+# both port and nf_nat flags
+tcp dport 9128 redirect to :993 random;ok
+tcp dport 9128 redirect to :993 fully-random;ok
+tcp dport 9128 redirect to :123 persistent;ok
+tcp dport 9128 redirect to :123 random,persistent;ok
+
+# nf_nat flags is the last argument
+udp dport 1234 redirect random to 123;fail
+udp dport 21234 redirect persistent,fully-random to 431;fail
+
+# redirect is a terminal statement
+tcp dport 22 redirect counter packets 0 bytes 0 accept;fail
+tcp sport 22 redirect accept;fail
+ip saddr 10.1.1.1 redirect drop;fail
+
+# redirect with sets
+tcp dport { 1, 2, 3, 4, 5, 6, 7, 8, 101, 202, 303, 1001, 2002, 3003} redirect;ok
+ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter redirect;ok
+iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } redirect;ok
+
+# redirect with maps
+redirect to :tcp dport map { 22 : 8000, 80 : 8080};ok
+
diff --git a/tests/py/ip/redirect.t.json b/tests/py/ip/redirect.t.json
new file mode 100644
index 0000000..2afdf9b
--- /dev/null
+++ b/tests/py/ip/redirect.t.json
@@ -0,0 +1,625 @@
+# udp dport 53 redirect
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": null
+ }
+]
+
+# udp dport 53 redirect random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": "random"
+ }
+ }
+]
+
+# udp dport 53 redirect random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect random,fully-random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": "persistent"
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "fully-random",
+ "random"
+ ]
+ }
+ }
+]
+
+# tcp dport 22 redirect to :22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "redirect": {
+ "port": 22
+ }
+ }
+]
+
+# udp dport 1234 redirect to :4321
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 1234
+ }
+ },
+ {
+ "redirect": {
+ "port": 4321
+ }
+ }
+]
+
+# ip daddr 172.16.0.1 udp dport 9998 redirect to :6515
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "172.16.0.1"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 9998
+ }
+ },
+ {
+ "redirect": {
+ "port": 6515
+ }
+ }
+]
+
+# tcp dport 39128 redirect to :993
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 39128
+ }
+ },
+ {
+ "redirect": {
+ "port": 993
+ }
+ }
+]
+
+# ip protocol tcp redirect to :100-200
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "redirect": {
+ "port": {
+ "range": [ 100, 200 ]
+ }
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :993 random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 9128
+ }
+ },
+ {
+ "redirect": {
+ "flags": "random",
+ "port": 993
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :993 fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 9128
+ }
+ },
+ {
+ "redirect": {
+ "flags": "fully-random",
+ "port": 993
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :123 persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 9128
+ }
+ },
+ {
+ "redirect": {
+ "flags": "persistent",
+ "port": 123
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :123 random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ "10.0.0.0", "10.2.3.4" ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "redirect": null
+ }
+]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } redirect
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "in",
+ "right": [
+ "established",
+ "new"
+ ]
+ }
+ },
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 22,
+ {
+ "drop": null
+ }
+ ],
+ [
+ 222,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "redirect": null
+ }
+]
+
+# redirect to :tcp dport map { 22 : 8000, 80 : 8080}
+[
+ {
+ "redirect": {
+ "port": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "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 0000000..4646c60
--- /dev/null
+++ b/tests/py/ip/redirect.t.json.output
@@ -0,0 +1,146 @@
+# udp dport 53 redirect random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# ip protocol tcp redirect to :100-200
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "redirect": {
+ "port": {
+ "range": [ 100, 200 ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip/redirect.t.payload b/tests/py/ip/redirect.t.payload
new file mode 100644
index 0000000..4bed47c
--- /dev/null
+++ b/tests/py/ip/redirect.t.payload
@@ -0,0 +1,220 @@
+# udp dport 53 redirect
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir ]
+
+# udp dport 53 redirect random
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x4 ]
+
+# udp dport 53 redirect random,persistent
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0xc ]
+
+# udp dport 53 redirect random,persistent,fully-random
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x1c ]
+
+# udp dport 53 redirect random,fully-random
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x14 ]
+
+# udp dport 53 redirect random,fully-random,persistent
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x1c ]
+
+# udp dport 53 redirect persistent
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x8 ]
+
+# udp dport 53 redirect persistent,random
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0xc ]
+
+# udp dport 53 redirect persistent,random,fully-random
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x1c ]
+
+# udp dport 53 redirect persistent,fully-random
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x18 ]
+
+# udp dport 53 redirect persistent,fully-random,random
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x1c ]
+
+# tcp dport 22 redirect to :22
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ immediate reg 1 0x00001600 ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
+# udp dport 1234 redirect to :4321
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000d204 ]
+ [ immediate reg 1 0x0000e110 ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
+# ip daddr 172.16.0.1 udp dport 9998 redirect to :6515
+ip test-ip4 output
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x010010ac ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000e27 ]
+ [ immediate reg 1 0x00007319 ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
+# tcp dport 39128 redirect to :993
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000d898 ]
+ [ immediate reg 1 0x0000e103 ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
+# ip protocol tcp redirect to :100-200
+ip test-ip4 output
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x00006400 ]
+ [ immediate reg 2 0x0000c800 ]
+ [ redir proto_min reg 1 proto_max reg 2 flags 0x2 ]
+
+# tcp dport 9128 redirect to :993 random
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000a823 ]
+ [ immediate reg 1 0x0000e103 ]
+ [ redir proto_min reg 1 flags 0x6 ]
+
+# tcp dport 9128 redirect to :993 fully-random
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000a823 ]
+ [ immediate reg 1 0x0000e103 ]
+ [ redir proto_min reg 1 flags 0x12 ]
+
+# tcp dport 9128 redirect to :123 persistent
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000a823 ]
+ [ immediate reg 1 0x00007b00 ]
+ [ redir proto_min reg 1 flags 0xa ]
+
+# tcp dport 9128 redirect to :123 random,persistent
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000a823 ]
+ [ immediate reg 1 0x00007b00 ]
+ [ redir proto_min reg 1 flags 0xe ]
+
+# tcp dport { 1, 2, 3, 4, 5, 6, 7, 8, 101, 202, 303, 1001, 2002, 3003} redirect
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000100 : 0 [end] element 00000200 : 0 [end] element 00000300 : 0 [end] element 00000400 : 0 [end] element 00000500 : 0 [end] element 00000600 : 0 [end] element 00000700 : 0 [end] element 00000800 : 0 [end] element 00006500 : 0 [end] element 0000ca00 : 0 [end] element 00002f01 : 0 [end] element 0000e903 : 0 [end] element 0000d207 : 0 [end] element 0000bb0b : 0 [end]
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ redir ]
+
+# ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter redirect
+ip test-ip4 output
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp gte reg 1 0x0000000a ]
+ [ cmp lte reg 1 0x0403020a ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ counter pkts 0 bytes 0 ]
+ [ redir ]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } redirect
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00001600 : drop 0 [end] element 0000de00 : drop 0 [end]
+ip test-ip4 output
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ ct load state => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000a ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ redir ]
+
+# redirect to :tcp dport map { 22 : 8000, 80 : 8080}
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 00001600 : 0000401f 0 [end] element 00005000 : 0000901f 0 [end]
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
diff --git a/tests/py/ip/reject.t b/tests/py/ip/reject.t
new file mode 100644
index 0000000..ad00994
--- /dev/null
+++ b/tests/py/ip/reject.t
@@ -0,0 +1,17 @@
+:output;type filter hook output priority 0
+
+*ip;test-ip4;output
+
+reject;ok
+reject with icmp host-unreachable;ok
+reject with icmp net-unreachable;ok
+reject with icmp prot-unreachable;ok
+reject with icmp port-unreachable;ok;reject
+reject with icmp net-prohibited;ok
+reject with icmp host-prohibited;ok
+reject with icmp admin-prohibited;ok
+reject with icmp 3;ok;reject
+mark 0x80000000 reject with tcp reset;ok;meta mark 0x80000000 reject with tcp reset
+
+reject with icmp no-route;fail
+reject with icmpv6 no-route;fail
diff --git a/tests/py/ip/reject.t.json b/tests/py/ip/reject.t.json
new file mode 100644
index 0000000..3e1d28d
--- /dev/null
+++ b/tests/py/ip/reject.t.json
@@ -0,0 +1,105 @@
+# reject
+[
+ {
+ "reject": null
+ }
+]
+
+# reject with icmp host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp net-unreachable
+[
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp prot-unreachable
+[
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp net-prohibited
+[
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp host-prohibited
+[
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp 3
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# mark 0x80000000 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "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 0000000..3917413
--- /dev/null
+++ b/tests/py/ip/reject.t.json.output
@@ -0,0 +1,28 @@
+# reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# mark 0x80000000 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": 2147483648
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
diff --git a/tests/py/ip/reject.t.payload b/tests/py/ip/reject.t.payload
new file mode 100644
index 0000000..5829065
--- /dev/null
+++ b/tests/py/ip/reject.t.payload
@@ -0,0 +1,44 @@
+# reject
+ip test-ip4 output
+ [ reject type 0 code 3 ]
+
+# reject with icmp host-unreachable
+ip test-ip4 output
+ [ reject type 0 code 1 ]
+
+# reject with icmp net-unreachable
+ip test-ip4 output
+ [ reject type 0 code 0 ]
+
+# reject with icmp prot-unreachable
+ip test-ip4 output
+ [ reject type 0 code 2 ]
+
+# reject with icmp port-unreachable
+ip test-ip4 output
+ [ reject type 0 code 3 ]
+
+# reject with icmp net-prohibited
+ip test-ip4 output
+ [ reject type 0 code 9 ]
+
+# reject with icmp host-prohibited
+ip test-ip4 output
+ [ reject type 0 code 10 ]
+
+# reject with icmp admin-prohibited
+ip test-ip4 output
+ [ reject type 0 code 13 ]
+
+# reject with icmp 3
+ip test-ip4 output
+ [ reject type 0 code 3 ]
+
+# mark 0x80000000 reject with tcp reset
+ip test-ip4 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x80000000 ]
+ [ reject type 1 code 0 ]
+
diff --git a/tests/py/ip/rt.t b/tests/py/ip/rt.t
new file mode 100644
index 0000000..986bf34
--- /dev/null
+++ b/tests/py/ip/rt.t
@@ -0,0 +1,7 @@
+:output;type filter hook input priority 0
+
+*ip;test-ip4;output
+
+rt nexthop 192.168.0.1;ok;rt ip nexthop 192.168.0.1
+rt nexthop fd00::1;fail
+rt ip6 nexthop fd00::1;fail
diff --git a/tests/py/ip/rt.t.json b/tests/py/ip/rt.t.json
new file mode 100644
index 0000000..41dbe34
--- /dev/null
+++ b/tests/py/ip/rt.t.json
@@ -0,0 +1,16 @@
+# rt nexthop 192.168.0.1
+[
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "family": "ip",
+ "key": "nexthop"
+ }
+ },
+ "op": "==",
+ "right": "192.168.0.1"
+ }
+ }
+]
+
diff --git a/tests/py/ip/rt.t.payload b/tests/py/ip/rt.t.payload
new file mode 100644
index 0000000..93eef4a
--- /dev/null
+++ b/tests/py/ip/rt.t.payload
@@ -0,0 +1,5 @@
+# rt nexthop 192.168.0.1
+ip test-ip4 output
+ [ rt load nexthop4 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+
diff --git a/tests/py/ip/sets.t b/tests/py/ip/sets.t
new file mode 100644
index 0000000..46d9686
--- /dev/null
+++ b/tests/py/ip/sets.t
@@ -0,0 +1,68 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip;test-ip4;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+!w type ipv4_addr;ok
+!x type inet_proto;ok
+!y type inet_service;ok
+!z type time;ok
+
+!set1 type ipv4_addr;ok
+?set1 192.168.3.4;ok
+
+?set1 192.168.3.4;ok
+?set1 192.168.3.5, 192.168.3.6;ok
+?set1 192.168.3.5, 192.168.3.6;ok
+?set1 192.168.3.8, 192.168.3.9;ok
+?set1 192.168.3.10, 192.168.3.11;ok
+?set1 1234:1234:1234:1234:1234:1234:1234:1234;fail
+?set2 192.168.3.4;fail
+
+!set2 type ipv4_addr;ok
+?set2 192.168.3.4;ok
+?set2 192.168.3.5, 192.168.3.6;ok
+?set2 192.168.3.5, 192.168.3.6;ok
+?set2 192.168.3.8, 192.168.3.9;ok
+?set2 192.168.3.10, 192.168.3.11;ok
+
+ip saddr @set1 drop;ok
+ip saddr != @set1 drop;ok
+ip saddr @set2 drop;ok
+ip saddr != @set2 drop;ok
+ip saddr @set33 drop;fail
+ip saddr != @set33 drop;fail
+
+!set3 type ipv4_addr flags interval;ok
+?set3 192.168.0.0/16;ok
+?set3 172.16.0.0/12;ok
+?set3 10.0.0.0/8;ok
+
+!set4 type ipv4_addr flags interval;ok
+?set4 192.168.1.0/24;ok
+?set4 192.168.0.0/24;ok
+?set4 192.168.2.0/24;ok
+?set4 192.168.1.1;fail
+?set4 192.168.3.0/24;ok
+
+!set5 type ipv4_addr . ipv4_addr;ok
+ip saddr . ip daddr @set5 drop;ok
+add @set5 { ip saddr . ip daddr };ok
+
+!map1 type ipv4_addr . ipv4_addr : mark;ok
+add @map1 { ip saddr . ip daddr : meta mark };ok
+
+# test nested anonymous sets
+ip saddr { { 1.1.1.0, 3.3.3.0 }, 2.2.2.0 };ok;ip saddr { 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 };ok;ip saddr { 1.1.1.0/24, 2.2.2.0/24, 3.3.3.0/24 }
+
+!set6 type ipv4_addr;ok
+?set6 192.168.3.5, *;ok
+ip saddr @set6 drop;ok
+
+ip saddr vmap { 1.1.1.1 : drop, * : accept };ok
+meta mark set ip saddr map { 1.1.1.1 : 0x00000001, * : 0x00000002 };ok
+
diff --git a/tests/py/ip/sets.t.json b/tests/py/ip/sets.t.json
new file mode 100644
index 0000000..44ca152
--- /dev/null
+++ b/tests/py/ip/sets.t.json
@@ -0,0 +1,305 @@
+# ip saddr @set1 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "@set1"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip saddr != @set1 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "@set1"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip saddr @set2 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "@set2"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip saddr != @set2 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "@set2"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip saddr . ip daddr @set5 drop
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": "@set5"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# add @set5 { ip saddr . ip daddr }
+[
+ {
+ "set": {
+ "elem": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "op": "add",
+ "set": "@set5"
+ }
+ }
+]
+
+# ip saddr { { 1.1.1.0, 3.3.3.0 }, 2.2.2.0 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "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
+ }
+ }
+ ]
+ }
+ }
+ }
+]
+
+# ip saddr @set6 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "@set6"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip saddr vmap { 1.1.1.1 : drop, * : accept }
+[
+ {
+ "vmap": {
+ "data": {
+ "set": [
+ [
+ "1.1.1.1",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "*",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ }
+]
+
+# meta mark set ip saddr map { 1.1.1.1 : 0x00000001, * : 0x00000002 }
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "1.1.1.1",
+ 1
+ ],
+ [
+ "*",
+ 2
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ }
+ }
+ }
+]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+[
+ {
+ "map": {
+ "data": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "elem": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "map": "@map1",
+ "op": "add"
+ }
+ }
+]
+
diff --git a/tests/py/ip/sets.t.json.got b/tests/py/ip/sets.t.json.got
new file mode 100644
index 0000000..8fae580
--- /dev/null
+++ b/tests/py/ip/sets.t.json.got
@@ -0,0 +1,62 @@
+# add @map1 { ip saddr . ip daddr : meta mark }
+[
+ {
+ "set": {
+ "data": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "elem": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "map": "@map1",
+ "op": "add"
+ }
+ }
+]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+[
+ {
+ "map": {
+ "data": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "elem": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ }
+ ]
+ },
+ "map": "@map1",
+ "op": "add"
+ }
+ }
+]
+
diff --git a/tests/py/ip/sets.t.json.payload.got b/tests/py/ip/sets.t.json.payload.got
new file mode 100644
index 0000000..daf27aa
--- /dev/null
+++ b/tests/py/ip/sets.t.json.payload.got
@@ -0,0 +1,157 @@
+# add @map1 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
diff --git a/tests/py/ip/sets.t.payload.inet b/tests/py/ip/sets.t.payload.inet
new file mode 100644
index 0000000..fd6517a
--- /dev/null
+++ b/tests/py/ip/sets.t.payload.inet
@@ -0,0 +1,106 @@
+# ip saddr @set1 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set1 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr != @set1 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set1 0x1 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr @set2 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set2 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr != @set2 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set2 0x1 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr . ip daddr @set5 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set set5 ]
+ [ immediate reg 0 drop ]
+
+# add @set5 { ip saddr . ip daddr }
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ dynset add reg_key 1 set set5 ]
+
+# ip saddr { { 1.1.1.0, 3.3.3.0 }, 2.2.2.0 }
+__set%d t 3
+__set%d t 0
+ element 00010101 : 0 [end] element 00030303 : 0 [end] element 00020202 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr { { 1.1.1.0/24, 3.3.3.0/24 }, 2.2.2.0/24 }
+__set%d t 7
+__set%d t 0
+ element 00000000 : 1 [end] element 00010101 : 0 [end] element 00020101 : 1 [end] element 00020202 : 0 [end] element 00030202 : 1 [end] element 00030303 : 0 [end] element 00040303 : 1 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr @set6 drop
+inet
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set6 ]
+ [ immediate reg 0 drop ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
+# ip saddr vmap { 1.1.1.1 : drop, * : accept }
+__map%d test-inet b
+__map%d test-inet 0
+ element 01010101 : drop 0 [end] element : accept 2 [end]
+inet
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# meta mark set ip saddr map { 1.1.1.1 : 0x00000001, * : 0x00000002 }
+__map%d test-inet b
+__map%d test-inet 0
+ element 01010101 : 00000001 0 [end] element : 00000002 2 [end]
+inet
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
diff --git a/tests/py/ip/sets.t.payload.ip b/tests/py/ip/sets.t.payload.ip
new file mode 100644
index 0000000..d9cc32b
--- /dev/null
+++ b/tests/py/ip/sets.t.payload.ip
@@ -0,0 +1,83 @@
+# ip saddr @set1 drop
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set1 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr != @set1 drop
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set1 0x1 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr @set2 drop
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set2 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr != @set2 drop
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set2 0x1 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr . ip daddr @set5 drop
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set set5 ]
+ [ immediate reg 0 drop ]
+
+# add @set5 { ip saddr . ip daddr }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ dynset add reg_key 1 set set5 ]
+
+# ip saddr { { 1.1.1.0, 3.3.3.0 }, 2.2.2.0 }
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00010101 : 0 [end] element 00030303 : 0 [end] element 00020202 : 0 [end]
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr { { 1.1.1.0/24, 3.3.3.0/24 }, 2.2.2.0/24 }
+__set%d test-ip4 7
+__set%d test-ip4 0
+ element 00000000 : 1 [end] element 00010101 : 0 [end] element 00020101 : 1 [end] element 00020202 : 0 [end] element 00030202 : 1 [end] element 00030303 : 0 [end] element 00040303 : 1 [end]
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr @set6 drop
+ip
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set6 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr vmap { 1.1.1.1 : drop, * : accept }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 01010101 : drop 0 [end] element : accept 2 [end]
+ip
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# meta mark set ip saddr map { 1.1.1.1 : 0x00000001, * : 0x00000002 }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 01010101 : 00000001 0 [end] element : 00000002 2 [end]
+ip
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
diff --git a/tests/py/ip/sets.t.payload.ip.got b/tests/py/ip/sets.t.payload.ip.got
new file mode 100644
index 0000000..c43a0c5
--- /dev/null
+++ b/tests/py/ip/sets.t.payload.ip.got
@@ -0,0 +1,14 @@
+# add @map5 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map5 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+ip test-ip4 input
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
diff --git a/tests/py/ip/sets.t.payload.netdev b/tests/py/ip/sets.t.payload.netdev
new file mode 100644
index 0000000..d41b9e8
--- /dev/null
+++ b/tests/py/ip/sets.t.payload.netdev
@@ -0,0 +1,107 @@
+# ip saddr @set1 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set1 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr != @set1 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set1 0x1 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr @set2 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set2 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr != @set2 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set2 0x1 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr . ip daddr @set5 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ lookup reg 1 set set5 ]
+ [ immediate reg 0 drop ]
+
+# add @set5 { ip saddr . ip daddr }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ dynset add reg_key 1 set set5 ]
+
+# ip saddr { { 1.1.1.0, 3.3.3.0 }, 2.2.2.0 }
+__set%d test-netdev 3
+__set%d test-netdev 0
+ element 00010101 : 0 [end] element 00030303 : 0 [end] element 00020202 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr { { 1.1.1.0/24, 3.3.3.0/24 }, 2.2.2.0/24 }
+__set%d test-netdev 7
+__set%d test-netdev 0
+ element 00000000 : 1 [end] element 00010101 : 0 [end] element 00020101 : 1 [end] element 00020202 : 0 [end] element 00030202 : 1 [end] element 00030303 : 0 [end] element 00040303 : 1 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip saddr @set6 drop
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set set6 ]
+ [ immediate reg 0 drop ]
+
+# ip saddr vmap { 1.1.1.1 : drop, * : accept }
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 01010101 : drop 0 [end] element : accept 2 [end]
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# meta mark set ip saddr map { 1.1.1.1 : 0x00000001, * : 0x00000002 }
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 01010101 : 00000001 0 [end] element : 00000002 2 [end]
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
diff --git a/tests/py/ip/sets.t.payload.netdev.got b/tests/py/ip/sets.t.payload.netdev.got
new file mode 100644
index 0000000..4c80527
--- /dev/null
+++ b/tests/py/ip/sets.t.payload.netdev.got
@@ -0,0 +1,18 @@
+# add @map5 { ip saddr . ip daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map5 sreg_data 10 ]
+
+# add @map1 { ip saddr . ip daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 4b @ network header + 16 => reg 9 ]
+ [ meta load mark => reg 10 ]
+ [ dynset add reg_key 1 set map1 sreg_data 10 ]
+
diff --git a/tests/py/ip/snat.t b/tests/py/ip/snat.t
new file mode 100644
index 0000000..d4b0d2c
--- /dev/null
+++ b/tests/py/ip/snat.t
@@ -0,0 +1,21 @@
+:postrouting;type nat hook postrouting priority 0
+
+*ip;test-ip4;postrouting
+
+iifname "eth0" tcp dport 80-90 snat to 192.168.3.2;ok
+iifname "eth0" tcp dport != 80-90 snat to 192.168.3.2;ok
+iifname "eth0" tcp dport {80, 90, 23} snat to 192.168.3.2;ok
+iifname "eth0" tcp dport != {80, 90, 23} snat to 192.168.3.2;ok
+iifname "eth0" tcp dport 80-90 snat to 192.168.3.0-192.168.3.255;ok;iifname "eth0" tcp dport 80-90 snat to 192.168.3.0/24
+iifname "eth0" tcp dport 80-90 snat to 192.168.3.15-192.168.3.240;ok
+
+iifname "eth0" tcp dport != 23-34 snat to 192.168.3.2;ok
+
+meta l4proto 17 snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 };ok
+snat ip to ip saddr map { 10.141.11.4 : 192.168.2.2-192.168.2.4 };ok
+snat ip to ip saddr map { 10.141.12.14 : 192.168.2.0/24 };ok
+snat ip prefix to ip saddr map { 10.141.11.0/24 : 192.168.2.0/24 };ok
+
+meta l4proto { 6, 17} snat ip to ip saddr . th dport map { 10.141.11.4 . 20 : 192.168.2.3 . 80};ok
+snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 };fail
+snat ip to ip saddr . th dport map { 10.141.11.4 . 20 : 192.168.2.3 . 80 };fail
diff --git a/tests/py/ip/snat.t.json b/tests/py/ip/snat.t.json
new file mode 100644
index 0000000..967560e
--- /dev/null
+++ b/tests/py/ip/snat.t.json
@@ -0,0 +1,530 @@
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 23, 34 ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.0-192.168.3.255
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 80,
+ 90
+ ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": {
+ "prefix": {
+ "addr": "192.168.3.0",
+ "len": 24
+ }
+ }
+ }
+ }
+]
+
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.15-192.168.3.240
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 80,
+ 90
+ ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": {
+ "range": [
+ "192.168.3.15",
+ "192.168.3.240"
+ ]
+ }
+ }
+ }
+]
+
+# snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "10.141.11.4",
+ {
+ "concat": [
+ "192.168.2.3",
+ 80
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip",
+ "type_flags": "concat"
+ }
+ }
+]
+
+# snat ip interval to ip saddr map { 10.141.11.4 : 192.168.2.2-192.168.2.4 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "10.141.11.4",
+ {
+ "range": [
+ "192.168.2.2",
+ "192.168.2.4"
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip",
+ "type_flags": "interval"
+ }
+ }
+]
+
+# snat ip prefix to ip saddr map { 10.141.11.0/24 : 192.168.2.0/24 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "prefix": {
+ "addr": "10.141.11.0",
+ "len": 24
+ }
+ },
+ {
+ "prefix": {
+ "addr": "192.168.2.0",
+ "len": 24
+ }
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip",
+ "flags": "netmap",
+ "type_flags": [
+ "interval",
+ "prefix"
+ ]
+ }
+ }
+]
+
+# meta l4proto 17 snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": "udp"
+ }
+ },
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "10.141.11.4",
+ {
+ "concat": [
+ "192.168.2.3",
+ 80
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# snat ip to ip saddr map { 10.141.11.4 : 192.168.2.2-192.168.2.4 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "10.141.11.4",
+ {
+ "range": [
+ "192.168.2.2",
+ "192.168.2.4"
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# snat ip to ip saddr map { 10.141.12.14 : 192.168.2.0/24 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "10.141.12.14",
+ {
+ "prefix": {
+ "addr": "192.168.2.0",
+ "len": 24
+ }
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# meta l4proto { 6, 17} snat ip to ip saddr . th dport map { 10.141.11.4 . 20 : 192.168.2.3 . 80}
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "tcp",
+ "udp"
+ ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "10.141.11.4",
+ 20
+ ]
+ },
+ {
+ "concat": [
+ "192.168.2.3",
+ 80
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "th"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
diff --git a/tests/py/ip/snat.t.json.output b/tests/py/ip/snat.t.json.output
new file mode 100644
index 0000000..2a99780
--- /dev/null
+++ b/tests/py/ip/snat.t.json.output
@@ -0,0 +1,249 @@
+# iifname "eth0" tcp dport {80, 90, 23} snat to 192.168.3.2
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "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": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 23,
+ 80,
+ 90
+ ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": "192.168.3.2"
+ }
+ }
+]
+
+# snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "10.141.11.4",
+ {
+ "concat": [
+ "192.168.2.3",
+ 80
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# meta l4proto 17 snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "10.141.11.4",
+ {
+ "concat": [
+ "192.168.2.3",
+ 80
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# meta l4proto { 6, 17} snat ip to ip saddr . th dport map { 10.141.11.4 . 20 : 192.168.2.3 . 80}
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 6,
+ 17
+ ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "10.141.11.4",
+ 20
+ ]
+ },
+ {
+ "concat": [
+ "192.168.2.3",
+ 80
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "th"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "family": "ip"
+ }
+ }
+]
+
+# snat ip prefix to ip saddr map { 10.141.11.0/24 : 192.168.2.0/24 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "prefix": {
+ "addr": "10.141.11.0",
+ "len": 24
+ }
+ },
+ {
+ "prefix": {
+ "addr": "192.168.2.0",
+ "len": 24
+ }
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip",
+ "flags": "netmap",
+ "type_flags": "prefix"
+ }
+ }
+]
+
diff --git a/tests/py/ip/snat.t.payload b/tests/py/ip/snat.t.payload
new file mode 100644
index 0000000..71a5e2f
--- /dev/null
+++ b/tests/py/ip/snat.t.payload
@@ -0,0 +1,154 @@
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.2
+ip test-ip4 postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00005000 ]
+ [ cmp lte reg 1 0x00005a00 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat snat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport != 80-90 snat to 192.168.3.2
+ip test-ip4 postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00005000 0x00005a00 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat snat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport {80, 90, 23} snat to 192.168.3.2
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00005000 : 0 [end] element 00005a00 : 0 [end] element 00001700 : 0 [end]
+ip test-ip4 postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat snat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport != {80, 90, 23} snat to 192.168.3.2
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00005000 : 0 [end] element 00005a00 : 0 [end] element 00001700 : 0 [end]
+ip test-ip4 postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat snat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport != 23-34 snat to 192.168.3.2
+ip test-ip4 postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x00001700 0x00002200 ]
+ [ immediate reg 1 0x0203a8c0 ]
+ [ nat snat ip addr_min reg 1 ]
+
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.0-192.168.3.255
+ip
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00005000 ]
+ [ cmp lte reg 1 0x00005a00 ]
+ [ immediate reg 1 0x0003a8c0 ]
+ [ immediate reg 2 0xff03a8c0 ]
+ [ nat snat ip addr_min reg 1 addr_max reg 2 ]
+
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.15-192.168.3.240
+ip
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00005000 ]
+ [ cmp lte reg 1 0x00005a00 ]
+ [ immediate reg 1 0x0f03a8c0 ]
+ [ immediate reg 2 0xf003a8c0 ]
+ [ nat snat ip addr_min reg 1 addr_max reg 2 ]
+
+# meta l4proto 17 snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
+__map%d test-ip4 b size 1
+__map%d test-ip4 0
+ element 040b8d0a : 0302a8c0 00005000 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat snat ip addr_min reg 1 proto_min reg 9 ]
+
+# snat ip to ip saddr map { 10.141.11.4 : 192.168.2.2-192.168.2.4 }
+__map%d test-ip4 b size 1
+__map%d test-ip4 0
+ element 040b8d0a : 0202a8c0 0402a8c0 0 [end]
+ip
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat snat ip addr_min reg 1 addr_max reg 9 ]
+
+# snat ip prefix to ip saddr map { 10.141.11.0/24 : 192.168.2.0/24 }
+__map%d test-ip4 f size 3
+__map%d test-ip4 0
+ element 00000000 : 1 [end] element 000b8d0a : 0002a8c0 ff02a8c0 0 [end] element 000c8d0a : 1 [end]
+ip
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat snat ip addr_min reg 1 addr_max reg 9 flags 0x40 ]
+
+# snat ip to ip saddr map { 10.141.12.14 : 192.168.2.0/24 }
+__map%d test-ip4 b size 1
+__map%d test-ip4 0
+ element 0e0c8d0a : 0002a8c0 ff02a8c0 0 [end]
+ip
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat snat ip addr_min reg 1 addr_max reg 9 ]
+
+# meta l4proto { 6, 17} snat ip to ip saddr . th dport map { 10.141.11.4 . 20 : 192.168.2.3 . 80}
+__set%d test-ip4 3 size 2
+__set%d test-ip4 0
+ element 00000006 : 0 [end] element 00000011 : 0 [end]
+__map%d test-ip4 b size 1
+__map%d test-ip4 0
+ element 040b8d0a 00001400 : 0302a8c0 00005000 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 4b @ network header + 12 => reg 1 ]
+ [ payload load 2b @ transport header + 2 => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat snat ip addr_min reg 1 proto_min reg 9 ]
+
+# ip daddr 192.168.0.1 dnat to tcp dport map { 443 : 10.141.10.4 . 8443, 80 : 10.141.10.4 . 8080 }
+__map%d x b size 2
+__map%d x 0
+ element 0000bb01 : 040a8d0a 0000fb20 0 [end] element 00005000 : 040a8d0a 0000901f 0 [end]
+ip
+ [ payload load 4b @ network header + 16 => reg 1 ]
+ [ cmp eq reg 1 0x0100a8c0 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ nat dnat ip addr_min reg 1 proto_min reg 9 ]
+
diff --git a/tests/py/ip/tcp.t b/tests/py/ip/tcp.t
new file mode 100644
index 0000000..4dcfcb6
--- /dev/null
+++ b/tests/py/ip/tcp.t
@@ -0,0 +1,6 @@
+:input;type filter hook input priority 0
+
+*ip;test-ip;input
+
+ip protocol tcp tcp dport ssh accept;ok;tcp dport 22 accept
+ip protocol ne tcp udp dport ssh accept;ok;ip protocol != 6 udp dport 22 accept
diff --git a/tests/py/ip/tcp.t.json b/tests/py/ip/tcp.t.json
new file mode 100644
index 0000000..d2c0915
--- /dev/null
+++ b/tests/py/ip/tcp.t.json
@@ -0,0 +1,62 @@
+# ip protocol tcp tcp dport ssh accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": "ssh"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip protocol ne tcp udp dport ssh accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": "tcp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "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 0000000..7e89854
--- /dev/null
+++ b/tests/py/ip/tcp.t.json.output
@@ -0,0 +1,50 @@
+# ip protocol tcp tcp dport ssh accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# ip protocol ne tcp udp dport ssh accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "!=",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/ip/tcp.t.payload b/tests/py/ip/tcp.t.payload
new file mode 100644
index 0000000..58956d9
--- /dev/null
+++ b/tests/py/ip/tcp.t.payload
@@ -0,0 +1,18 @@
+# ip protocol tcp tcp dport ssh accept
+ip test-ip input
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ immediate reg 0 accept ]
+
+# ip protocol ne tcp udp dport ssh accept
+ip test-ip input
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp neq reg 1 0x00000006 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ immediate reg 0 accept ]
+
diff --git a/tests/py/ip/tproxy.t b/tests/py/ip/tproxy.t
new file mode 100644
index 0000000..544c519
--- /dev/null
+++ b/tests/py/ip/tproxy.t
@@ -0,0 +1,14 @@
+:y;type filter hook prerouting priority -150
+
+*ip;x;y
+
+tproxy;fail
+tproxy to 192.0.2.1;fail
+tproxy to 192.0.2.1:50080;fail
+tproxy to :50080;fail
+meta l4proto 17 tproxy to 192.0.2.1;ok
+meta l4proto 6 tproxy to 192.0.2.1:50080;ok
+ip protocol 6 tproxy to :50080;ok
+meta l4proto 17 tproxy ip to 192.0.2.1;ok;meta l4proto 17 tproxy to 192.0.2.1
+meta l4proto 6 tproxy ip to 192.0.2.1:50080;ok;meta l4proto 6 tproxy to 192.0.2.1:50080
+ip protocol 6 tproxy ip to :50080;ok;ip protocol 6 tproxy to :50080
diff --git a/tests/py/ip/tproxy.t.json b/tests/py/ip/tproxy.t.json
new file mode 100644
index 0000000..4635fc1
--- /dev/null
+++ b/tests/py/ip/tproxy.t.json
@@ -0,0 +1,126 @@
+# meta l4proto 17 tproxy to 192.0.2.1
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "192.0.2.1"
+ }
+ }
+]
+
+# meta l4proto 6 tproxy to 192.0.2.1:50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "192.0.2.1",
+ "port": 50080
+ }
+ }
+]
+
+# ip protocol 6 tproxy to :50080
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "port": 50080
+ }
+ }
+]
+
+# meta l4proto 17 tproxy ip to 192.0.2.1
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "192.0.2.1",
+ "family": "ip"
+ }
+ }
+]
+
+# meta l4proto 6 tproxy ip to 192.0.2.1:50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "192.0.2.1",
+ "family": "ip",
+ "port": 50080
+ }
+ }
+]
+
+# ip protocol 6 tproxy ip to :50080
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "family": "ip",
+ "port": 50080
+ }
+ }
+]
diff --git a/tests/py/ip/tproxy.t.json.output b/tests/py/ip/tproxy.t.json.output
new file mode 100644
index 0000000..2690f22
--- /dev/null
+++ b/tests/py/ip/tproxy.t.json.output
@@ -0,0 +1,61 @@
+# meta l4proto 17 tproxy ip to 192.0.2.1
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "192.0.2.1"
+ }
+ }
+]
+
+# meta l4proto 6 tproxy ip to 192.0.2.1:50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "192.0.2.1",
+ "port": 50080
+ }
+ }
+]
+
+# ip protocol 6 tproxy ip to :50080
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "protocol",
+ "protocol": "ip"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "port": 50080
+ }
+ }
+]
diff --git a/tests/py/ip/tproxy.t.payload b/tests/py/ip/tproxy.t.payload
new file mode 100644
index 0000000..dfe830e
--- /dev/null
+++ b/tests/py/ip/tproxy.t.payload
@@ -0,0 +1,44 @@
+# meta l4proto 17 tproxy to 192.0.2.1
+ip x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0x010200c0 ]
+ [ tproxy ip addr reg 1 ]
+
+# meta l4proto 6 tproxy to 192.0.2.1:50080
+ip x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x010200c0 ]
+ [ immediate reg 2 0x0000a0c3 ]
+ [ tproxy ip addr reg 1 port reg 2 ]
+
+# ip protocol 6 tproxy to :50080
+ip x y
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x0000a0c3 ]
+ [ tproxy ip port reg 1 ]
+
+# meta l4proto 17 tproxy ip to 192.0.2.1
+ip x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0x010200c0 ]
+ [ tproxy ip addr reg 1 ]
+
+# meta l4proto 6 tproxy ip to 192.0.2.1:50080
+ip x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x010200c0 ]
+ [ immediate reg 2 0x0000a0c3 ]
+ [ tproxy ip addr reg 1 port reg 2 ]
+
+# ip protocol 6 tproxy ip to :50080
+ip x y
+ [ payload load 1b @ network header + 9 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x0000a0c3 ]
+ [ tproxy ip port reg 1 ]
+
diff --git a/tests/py/ip6/chains.t b/tests/py/ip6/chains.t
new file mode 100644
index 0000000..e78f9e0
--- /dev/null
+++ b/tests/py/ip6/chains.t
@@ -0,0 +1,17 @@
+# filter chains available are: input, output, forward, forward, prerouting and postrouting.
+:filter-input;type filter hook input priority 0
+:filter-prer;type filter hook prerouting priority 0
+:filter-forw-t;type filter hook forward priority 0
+:filter-out-t;type filter hook output priority 0
+:filter-post-t;type filter hook postrouting priority 0
+
+# nat chains available are: input, output, forward, prerouting and postrouting.
+:nat-input;type nat hook input priority 0
+:nat-prerouting;type nat hook prerouting priority 0
+:nat-output;type nat hook output priority 0
+:nat-postrou;type nat hook postrouting priority 0
+
+# route chain available is output.
+:route-out;type route hook output priority 0
+
+*ip6;test-ip6;filter-input,filter-prer,filter-forw-t,filter-out-t,filter-post-t,nat-input,nat-prerouting,nat-output,nat-postrou,route-out
diff --git a/tests/py/ip6/ct.t b/tests/py/ip6/ct.t
new file mode 100644
index 0000000..c06fd6a
--- /dev/null
+++ b/tests/py/ip6/ct.t
@@ -0,0 +1,9 @@
+:output;type filter hook output priority 0
+
+*ip6;test-ip6;output
+
+ct mark set ip6 dscp << 2 | 0x10;ok
+ct mark set ip6 dscp << 26 | 0x10;ok
+ct mark set ip6 dscp | 0x04;ok
+ct mark set ip6 dscp | 0xff000000;ok
+ct mark set ip6 dscp & 0x0f << 2;ok;ct mark set ip6 dscp & 0x3c
diff --git a/tests/py/ip6/ct.t.json b/tests/py/ip6/ct.t.json
new file mode 100644
index 0000000..7d8c88b
--- /dev/null
+++ b/tests/py/ip6/ct.t.json
@@ -0,0 +1,293 @@
+# ct mark set ip6 dscp lshift 2 or 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 2
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp lshift 26 or 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 26
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp << 2 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 2
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp << 26 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 26
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp | 0x04
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp | 0xff000000
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 4278190080
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp << 2 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 2
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp << 26 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 26
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp | 0x04
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp | 0xff000000
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 4278190080
+ ]
+ }
+ }
+ }
+]
+
+# ct mark set ip6 dscp & 0x0f << 2
+[
+ {
+ "mangle": {
+ "key": {
+ "ct": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "&": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 60
+ ]
+ }
+ }
+ }
+]
diff --git a/tests/py/ip6/ct.t.payload b/tests/py/ip6/ct.t.payload
new file mode 100644
index 0000000..944208f
--- /dev/null
+++ b/tests/py/ip6/ct.t.payload
@@ -0,0 +1,46 @@
+# ct mark set ip6 dscp << 2 | 0x10
+ip6 test-ip6 output
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ bitwise reg 1 = ( reg 1 << 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set ip6 dscp << 26 | 0x10
+ip6 test-ip6 output
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ bitwise reg 1 = ( reg 1 << 0x0000001a ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set ip6 dscp | 0x04
+ip6 test-ip6 output
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xfffffffb ) ^ 0x00000004 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set ip6 dscp | 0xff000000
+ip6 test-ip6 output
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffffff ) ^ 0xff000000 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set ip6 dscp & 0x0f << 2
+ip6 test-ip6 output
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000003c ) ^ 0x00000000 ]
+ [ ct set mark with reg 1 ]
diff --git a/tests/py/ip6/dnat.t b/tests/py/ip6/dnat.t
new file mode 100644
index 0000000..89d5a5f
--- /dev/null
+++ b/tests/py/ip6/dnat.t
@@ -0,0 +1,9 @@
+:prerouting;type nat hook prerouting priority 0
+
+*ip6;test-ip6;prerouting
+
+tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100;ok
+tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:100;ok
+tcp dport 80-90 dnat to [2001:838:35f:1::]:80;ok
+dnat to [2001:838:35f:1::]/64;ok;dnat to 2001:838:35f:1::/64
+dnat to 2001:838:35f:1::-2001:838:35f:1:ffff:ffff:ffff:ffff;ok;dnat to 2001:838:35f:1::/64
diff --git a/tests/py/ip6/dnat.t.json b/tests/py/ip6/dnat.t.json
new file mode 100644
index 0000000..cbfdb68
--- /dev/null
+++ b/tests/py/ip6/dnat.t.json
@@ -0,0 +1,106 @@
+# tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 80, 90 ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": {
+ "range": [ "2001:838:35f:1::", "2001:838:35f:2::" ]
+ },
+ "port": {
+ "range": [ 80, 100 ]
+ }
+ }
+ }
+]
+
+# tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:100
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 80, 90 ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": {
+ "range": [ "2001:838:35f:1::", "2001:838:35f:2::" ]
+ },
+ "port": 100
+ }
+ }
+]
+
+# tcp dport 80-90 dnat to [2001:838:35f:1::]:80
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 80, 90 ]
+ }
+ }
+ },
+ {
+ "dnat": {
+ "addr": "2001:838:35f:1::",
+ "port": 80
+ }
+ }
+]
+
+# dnat to [2001:838:35f:1::]/64
+[
+ {
+ "dnat": {
+ "addr": {
+ "prefix": {
+ "addr": "2001:838:35f:1::",
+ "len": 64
+ }
+ }
+ }
+ }
+]
+
+# dnat to 2001:838:35f:1::-2001:838:35f:1:ffff:ffff:ffff:ffff
+[
+ {
+ "dnat": {
+ "addr": {
+ "prefix": {
+ "addr": "2001:838:35f:1::",
+ "len": 64
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/dnat.t.payload.ip6 b/tests/py/ip6/dnat.t.payload.ip6
new file mode 100644
index 0000000..004ffde
--- /dev/null
+++ b/tests/py/ip6/dnat.t.payload.ip6
@@ -0,0 +1,47 @@
+# tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100
+ip6 test-ip6 prerouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00005000 ]
+ [ cmp lte reg 1 0x00005a00 ]
+ [ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
+ [ immediate reg 2 0x38080120 0x02005f03 0x00000000 0x00000000 ]
+ [ immediate reg 3 0x00005000 ]
+ [ immediate reg 4 0x00006400 ]
+ [ nat dnat ip6 addr_min reg 1 addr_max reg 2 proto_min reg 3 proto_max reg 4 flags 0x2 ]
+
+# tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:100
+ip6 test-ip6 prerouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00005000 ]
+ [ cmp lte reg 1 0x00005a00 ]
+ [ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
+ [ immediate reg 2 0x38080120 0x02005f03 0x00000000 0x00000000 ]
+ [ immediate reg 3 0x00006400 ]
+ [ nat dnat ip6 addr_min reg 1 addr_max reg 2 proto_min reg 3 flags 0x2 ]
+
+# tcp dport 80-90 dnat to [2001:838:35f:1::]:80
+ip6 test-ip6 prerouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00005000 ]
+ [ cmp lte reg 1 0x00005a00 ]
+ [ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
+ [ immediate reg 2 0x00005000 ]
+ [ nat dnat ip6 addr_min reg 1 proto_min reg 2 flags 0x2 ]
+
+# dnat to [2001:838:35f:1::]/64
+ip6 test-ip6 prerouting
+ [ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
+ [ immediate reg 2 0x38080120 0x01005f03 0xffffffff 0xffffffff ]
+ [ nat dnat ip6 addr_min reg 1 addr_max reg 2 ]
+
+# dnat to 2001:838:35f:1::-2001:838:35f:1:ffff:ffff:ffff:ffff
+ip6 test-ip6 prerouting
+ [ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
+ [ immediate reg 2 0x38080120 0x01005f03 0xffffffff 0xffffffff ]
+ [ nat dnat ip6 addr_min reg 1 addr_max reg 2 ]
diff --git a/tests/py/ip6/dst.t b/tests/py/ip6/dst.t
new file mode 100644
index 0000000..cd1fd3b
--- /dev/null
+++ b/tests/py/ip6/dst.t
@@ -0,0 +1,21 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+*inet;test-inet;input
+
+dst nexthdr 22;ok
+dst nexthdr != 233;ok
+dst nexthdr 33-45;ok
+dst nexthdr != 33-45;ok
+dst nexthdr { 33, 55, 67, 88};ok
+dst nexthdr != { 33, 55, 67, 88};ok
+dst nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp};ok;dst nexthdr { 51, 50, 17, 136, 58, 6, 33, 132, 108}
+dst nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp};ok;dst nexthdr != { 51, 50, 17, 136, 58, 6, 33, 132, 108}
+dst nexthdr icmp;ok;dst nexthdr 1
+dst nexthdr != icmp;ok;dst nexthdr != 1
+
+dst hdrlength 22;ok
+dst hdrlength != 233;ok
+dst hdrlength 33-45;ok
+dst hdrlength != 33-45;ok
+dst hdrlength { 33, 55, 67, 88};ok
diff --git a/tests/py/ip6/dst.t.json b/tests/py/ip6/dst.t.json
new file mode 100644
index 0000000..e947a76
--- /dev/null
+++ b/tests/py/ip6/dst.t.json
@@ -0,0 +1,315 @@
+# dst nexthdr 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# dst nexthdr != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# dst nexthdr 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# dst nexthdr != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# dst nexthdr { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# dst nexthdr != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# dst nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "udplite",
+ "ipcomp",
+ "udp",
+ "ah",
+ "sctp",
+ "esp",
+ "dccp",
+ "tcp",
+ "ipv6-icmp"
+ ]
+ }
+ }
+ }
+]
+
+# dst nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "udplite",
+ "ipcomp",
+ "udp",
+ "ah",
+ "sctp",
+ "esp",
+ "dccp",
+ "tcp",
+ "ipv6-icmp"
+ ]
+ }
+ }
+ }
+]
+
+# dst nexthdr icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": "icmp"
+ }
+ }
+]
+
+# dst nexthdr != icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": "icmp"
+ }
+ }
+]
+
+# dst hdrlength 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# dst hdrlength != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# dst hdrlength 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# dst hdrlength != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# dst hdrlength { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# dst hdrlength != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
diff --git a/tests/py/ip6/dst.t.json.output b/tests/py/ip6/dst.t.json.output
new file mode 100644
index 0000000..69d8f68
--- /dev/null
+++ b/tests/py/ip6/dst.t.json.output
@@ -0,0 +1,88 @@
+# dst nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 58,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# dst nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 58,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# dst nexthdr icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# dst nexthdr != icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "dst"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
diff --git a/tests/py/ip6/dst.t.payload.inet b/tests/py/ip6/dst.t.payload.inet
new file mode 100644
index 0000000..90d6bda
--- /dev/null
+++ b/tests/py/ip6/dst.t.payload.inet
@@ -0,0 +1,131 @@
+# dst nexthdr 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# dst nexthdr != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# dst nexthdr 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# dst nexthdr != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# dst nexthdr { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# dst nexthdr != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# dst nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# dst nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# dst nexthdr icmp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# dst nexthdr != icmp
+ip6 test-ip6 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# dst hdrlength 22
+ip6 test-ip6 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# dst hdrlength != 233
+ip6 test-ip6 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# dst hdrlength 33-45
+ip6 test-ip6 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# dst hdrlength != 33-45
+ip6 test-ip6 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# dst hdrlength { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# dst hdrlength != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
diff --git a/tests/py/ip6/dst.t.payload.ip6 b/tests/py/ip6/dst.t.payload.ip6
new file mode 100644
index 0000000..941140d
--- /dev/null
+++ b/tests/py/ip6/dst.t.payload.ip6
@@ -0,0 +1,99 @@
+# dst nexthdr 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# dst nexthdr != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# dst nexthdr 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# dst nexthdr != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# dst nexthdr { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# dst nexthdr != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# dst nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# dst nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# dst nexthdr icmp
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# dst nexthdr != icmp
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# dst hdrlength 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# dst hdrlength != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# dst hdrlength 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# dst hdrlength != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# dst hdrlength { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# dst hdrlength != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
diff --git a/tests/py/ip6/dup.t b/tests/py/ip6/dup.t
new file mode 100644
index 0000000..72cc5d5
--- /dev/null
+++ b/tests/py/ip6/dup.t
@@ -0,0 +1,7 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+
+dup to abcd::1;ok
+dup to abcd::1 device "lo";ok
+dup to ip6 saddr map { abcd::1 : cafe::cafe } device "lo";ok
diff --git a/tests/py/ip6/dup.t.json b/tests/py/ip6/dup.t.json
new file mode 100644
index 0000000..8a9493b
--- /dev/null
+++ b/tests/py/ip6/dup.t.json
@@ -0,0 +1,46 @@
+# dup to abcd::1
+[
+ {
+ "dup": {
+ "addr": "abcd::1"
+ }
+ }
+]
+
+# dup to abcd::1 device "lo"
+[
+ {
+ "dup": {
+ "addr": "abcd::1",
+ "dev": "lo"
+ }
+ }
+]
+
+# dup to ip6 saddr map { abcd::1 : cafe::cafe } device "lo"
+[
+ {
+ "dup": {
+ "addr": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "abcd::1",
+ "cafe::cafe"
+ ]
+ ]
+ }
+ }
+ },
+ "dev": "lo"
+ }
+ }
+]
+
diff --git a/tests/py/ip6/dup.t.payload b/tests/py/ip6/dup.t.payload
new file mode 100644
index 0000000..c441d4b
--- /dev/null
+++ b/tests/py/ip6/dup.t.payload
@@ -0,0 +1,21 @@
+# dup to abcd::1
+ip6 test test
+ [ immediate reg 1 0x0000cdab 0x00000000 0x00000000 0x01000000 ]
+ [ dup sreg_addr 1 ]
+
+# dup to abcd::1 device "lo"
+ip6 test test
+ [ immediate reg 1 0x0000cdab 0x00000000 0x00000000 0x01000000 ]
+ [ immediate reg 2 0x00000001 ]
+ [ dup sreg_addr 1 sreg_dev 2 ]
+
+# dup to ip6 saddr map { abcd::1 : cafe::cafe } device "lo"
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 0000cdab 00000000 00000000 01000000 : 0000feca 00000000 00000000 feca0000 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ immediate reg 2 0x00000001 ]
+ [ dup sreg_addr 1 sreg_dev 2 ]
+
diff --git a/tests/py/ip6/ether.t b/tests/py/ip6/ether.t
new file mode 100644
index 0000000..49d7d06
--- /dev/null
+++ b/tests/py/ip6/ether.t
@@ -0,0 +1,8 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+
+tcp dport 22 iiftype ether ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:4 accept;ok;tcp dport 22 ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04 accept
+tcp dport 22 ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04;ok
+tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip6 daddr 1::2;ok
+ether saddr 00:0f:54:0c:11:04 ip6 daddr 1::2 accept;ok
diff --git a/tests/py/ip6/ether.t.json b/tests/py/ip6/ether.t.json
new file mode 100644
index 0000000..5e4b43b
--- /dev/null
+++ b/tests/py/ip6/ether.t.json
@@ -0,0 +1,163 @@
+# tcp dport 22 iiftype ether ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iiftype" }
+ },
+ "op": "==",
+ "right": "ether"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1::2"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# tcp dport 22 ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1::2"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ }
+]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip6 daddr 1::2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1::2"
+ }
+ }
+]
+
+# ether saddr 00:0f:54:0c:11:04 ip6 daddr 1::2 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1::2"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/ip6/ether.t.json.output b/tests/py/ip6/ether.t.json.output
new file mode 100644
index 0000000..7ace627
--- /dev/null
+++ b/tests/py/ip6/ether.t.json.output
@@ -0,0 +1,43 @@
+# tcp dport 22 iiftype ether ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:4 accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1::2"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "00:0f:54:0c:11:04"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
diff --git a/tests/py/ip6/ether.t.payload b/tests/py/ip6/ether.t.payload
new file mode 100644
index 0000000..592b4ea
--- /dev/null
+++ b/tests/py/ip6/ether.t.payload
@@ -0,0 +1,49 @@
+# tcp dport 22 iiftype ether ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:4 accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 0x00000000 0x00000000 0x02000000 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ immediate reg 0 accept ]
+
+# tcp dport 22 ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 0x00000000 0x00000000 0x02000000 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+
+# tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip6 daddr 1::2
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 0x00000000 0x00000000 0x02000000 ]
+
+# ether saddr 00:0f:54:0c:11:04 ip6 daddr 1::2 accept
+ip6 test-ip6 input
+ [ meta load iiftype => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 6b @ link header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x0c540f00 0x00000411 ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 0x00000000 0x00000000 0x02000000 ]
+ [ immediate reg 0 accept ]
diff --git a/tests/py/ip6/exthdr.t b/tests/py/ip6/exthdr.t
new file mode 100644
index 0000000..a6c2d2b
--- /dev/null
+++ b/tests/py/ip6/exthdr.t
@@ -0,0 +1,19 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+
+exthdr hbh exists;ok
+exthdr rt exists;ok
+exthdr frag exists;ok
+exthdr dst exists;ok
+exthdr mh exists;ok
+
+exthdr hbh missing;ok
+
+exthdr hbh == exists;ok;exthdr hbh exists
+exthdr hbh == missing;ok;exthdr hbh missing
+exthdr hbh != exists;ok
+exthdr hbh != missing;ok
+
+exthdr hbh 1;ok;exthdr hbh exists
+exthdr hbh 0;ok;exthdr hbh missing
diff --git a/tests/py/ip6/exthdr.t.json b/tests/py/ip6/exthdr.t.json
new file mode 100644
index 0000000..4ca77d6
--- /dev/null
+++ b/tests/py/ip6/exthdr.t.json
@@ -0,0 +1,180 @@
+# exthdr hbh exists
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# exthdr rt exists
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# exthdr frag exists
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# exthdr dst exists
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "dst"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# exthdr mh exists
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# exthdr hbh missing
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
+# exthdr hbh == exists
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# exthdr hbh == missing
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
+# exthdr hbh != exists
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": true
+ }
+ }
+]
+
+# exthdr hbh != missing
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": false
+ }
+ }
+]
+
+# exthdr hbh 1
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# exthdr hbh 0
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
diff --git a/tests/py/ip6/exthdr.t.json.output b/tests/py/ip6/exthdr.t.json.output
new file mode 100644
index 0000000..c9f5b49
--- /dev/null
+++ b/tests/py/ip6/exthdr.t.json.output
@@ -0,0 +1,60 @@
+# exthdr hbh == exists
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# exthdr hbh == missing
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
+# exthdr hbh 1
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": true
+ }
+ }
+]
+
+# exthdr hbh 0
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": false
+ }
+ }
+]
+
diff --git a/tests/py/ip6/exthdr.t.payload.ip6 b/tests/py/ip6/exthdr.t.payload.ip6
new file mode 100644
index 0000000..be10d61
--- /dev/null
+++ b/tests/py/ip6/exthdr.t.payload.ip6
@@ -0,0 +1,60 @@
+# exthdr hbh exists
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 0 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# exthdr rt exists
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# exthdr frag exists
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 44 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# exthdr dst exists
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 60 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# exthdr mh exists
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# exthdr hbh missing
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 0 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# exthdr hbh == exists
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 0 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# exthdr hbh == missing
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 0 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# exthdr hbh != exists
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 0 + 0 present => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# exthdr hbh != missing
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 0 + 0 present => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
+# exthdr hbh 1
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 0 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# exthdr hbh 0
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 0 + 0 present => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
diff --git a/tests/py/ip6/flowtable.t b/tests/py/ip6/flowtable.t
new file mode 100644
index 0000000..e58d51b
--- /dev/null
+++ b/tests/py/ip6/flowtable.t
@@ -0,0 +1,6 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+
+meter acct_out size 4096 { meta iif . ip6 saddr timeout 600s counter };ok;meter acct_out size 4096 { iif . ip6 saddr timeout 10m counter }
+meter acct_out size 12345 { ip6 saddr . meta iif timeout 600s counter };ok;meter acct_out size 12345 { ip6 saddr . iif timeout 10m counter }
diff --git a/tests/py/ip6/flowtable.t.json b/tests/py/ip6/flowtable.t.json
new file mode 100644
index 0000000..d0b3a95
--- /dev/null
+++ b/tests/py/ip6/flowtable.t.json
@@ -0,0 +1,62 @@
+# meter acct_out size 4096 { meta iif . ip6 saddr timeout 600s counter }
+[
+ {
+ "meter": {
+ "key": {
+ "elem": {
+ "timeout": 600,
+ "val": {
+ "concat": [
+ {
+ "meta": { "key": "iif" }
+ },
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "name": "acct_out",
+ "size": 4096,
+ "stmt": {
+ "counter": null
+ }
+ }
+ }
+]
+
+# meter acct_out size 12345 { ip6 saddr . meta iif timeout 600s counter }
+[
+ {
+ "meter": {
+ "key": {
+ "elem": {
+ "timeout": 600,
+ "val": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ {
+ "meta": { "key": "iif" }
+ }
+ ]
+ }
+ }
+ },
+ "name": "acct_out",
+ "size": 12345,
+ "stmt": {
+ "counter": null
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/flowtable.t.json.output b/tests/py/ip6/flowtable.t.json.output
new file mode 100644
index 0000000..d0b3a95
--- /dev/null
+++ b/tests/py/ip6/flowtable.t.json.output
@@ -0,0 +1,62 @@
+# meter acct_out size 4096 { meta iif . ip6 saddr timeout 600s counter }
+[
+ {
+ "meter": {
+ "key": {
+ "elem": {
+ "timeout": 600,
+ "val": {
+ "concat": [
+ {
+ "meta": { "key": "iif" }
+ },
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "name": "acct_out",
+ "size": 4096,
+ "stmt": {
+ "counter": null
+ }
+ }
+ }
+]
+
+# meter acct_out size 12345 { ip6 saddr . meta iif timeout 600s counter }
+[
+ {
+ "meter": {
+ "key": {
+ "elem": {
+ "timeout": 600,
+ "val": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ {
+ "meta": { "key": "iif" }
+ }
+ ]
+ }
+ }
+ },
+ "name": "acct_out",
+ "size": 12345,
+ "stmt": {
+ "counter": null
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/flowtable.t.payload b/tests/py/ip6/flowtable.t.payload
new file mode 100644
index 0000000..559475f
--- /dev/null
+++ b/tests/py/ip6/flowtable.t.payload
@@ -0,0 +1,16 @@
+# meter acct_out size 4096 { meta iif . ip6 saddr timeout 600s counter }
+acct_out test-ip6 31
+acct_out test-ip6 0
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ payload load 16b @ network header + 8 => reg 9 ]
+ [ dynset update reg_key 1 set acct_out timeout 600000ms expr [ counter pkts 0 bytes 0 ] ]
+
+# meter acct_out size 12345 { ip6 saddr . meta iif timeout 600s counter }
+acct_out test-ip6 31
+acct_out test-ip6 0
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ meta load iif => reg 2 ]
+ [ dynset update reg_key 1 set acct_out timeout 600000ms expr [ counter pkts 0 bytes 0 ] ]
+
diff --git a/tests/py/ip6/frag.t b/tests/py/ip6/frag.t
new file mode 100644
index 0000000..6bbd6ac
--- /dev/null
+++ b/tests/py/ip6/frag.t
@@ -0,0 +1,40 @@
+:output;type filter hook output priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip6;test-ip6;output
+*inet;test-inet;output
+*netdev;test-netdev;ingress,egress
+
+frag nexthdr tcp;ok;frag nexthdr 6
+frag nexthdr != icmp;ok;frag nexthdr != 1
+frag nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp};ok;frag nexthdr { 51, 136, 132, 6, 108, 50, 17, 33}
+frag nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp};ok;frag nexthdr != { 51, 136, 132, 6, 108, 50, 17, 33}
+frag nexthdr esp;ok;frag nexthdr 50
+frag nexthdr ah;ok;frag nexthdr 51
+
+frag reserved 22;ok
+frag reserved != 233;ok
+frag reserved 33-45;ok
+frag reserved != 33-45;ok
+frag reserved { 33, 55, 67, 88};ok
+frag reserved != { 33, 55, 67, 88};ok
+
+frag frag-off 22;ok
+frag frag-off != 233;ok
+frag frag-off 33-45;ok
+frag frag-off != 33-45;ok
+frag frag-off { 33, 55, 67, 88};ok
+frag frag-off != { 33, 55, 67, 88};ok
+
+frag reserved2 1;ok
+frag more-fragments 0;ok
+frag more-fragments 1;ok
+
+frag id 1;ok
+frag id 22;ok
+frag id != 33;ok
+frag id 33-45;ok
+frag id != 33-45;ok
+frag id { 33, 55, 67, 88};ok
+frag id != { 33, 55, 67, 88};ok
diff --git a/tests/py/ip6/frag.t.json b/tests/py/ip6/frag.t.json
new file mode 100644
index 0000000..b8c06df
--- /dev/null
+++ b/tests/py/ip6/frag.t.json
@@ -0,0 +1,644 @@
+# frag nexthdr tcp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ }
+]
+
+# frag nexthdr != icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": "icmp"
+ }
+ }
+]
+
+# frag nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "esp",
+ "ah",
+ "comp",
+ "udp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp"
+ ]
+ }
+ }
+ }
+]
+
+# frag nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "esp",
+ "ah",
+ "comp",
+ "udp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp"
+ ]
+ }
+ }
+ }
+]
+
+# frag nexthdr esp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": "esp"
+ }
+ }
+]
+
+# frag nexthdr ah
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": "ah"
+ }
+ }
+]
+
+# frag reserved 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# frag reserved != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# frag reserved 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# frag reserved != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# frag reserved { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# frag reserved != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# frag reserved { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# frag reserved != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# frag frag-off 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "frag-off",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# frag frag-off != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "frag-off",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# frag frag-off 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "frag-off",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# frag frag-off != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "frag-off",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# frag frag-off { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "frag-off",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# frag frag-off != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "frag-off",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# frag frag-off { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "frag-off",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# frag frag-off != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "frag-off",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# frag reserved2 1
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved2",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# frag more-fragments 0
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "more-fragments",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# frag more-fragments 1
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "more-fragments",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# frag id 1
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "id",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# frag id 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "id",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# frag id != 33
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "id",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": 33
+ }
+ }
+]
+
+# frag id 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "id",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# frag id != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "id",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# frag id { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "id",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# frag id != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "id",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# frag id { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "id",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
+# frag id != { 33-55}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "id",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 55 ] }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/frag.t.json.output b/tests/py/ip6/frag.t.json.output
new file mode 100644
index 0000000..68d382b
--- /dev/null
+++ b/tests/py/ip6/frag.t.json.output
@@ -0,0 +1,118 @@
+# frag nexthdr tcp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ }
+]
+
+# frag nexthdr != icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# frag nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# frag nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# frag nexthdr esp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 50
+ }
+ }
+]
+
+# frag nexthdr ah
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "frag"
+ }
+ },
+ "op": "==",
+ "right": 51
+ }
+ }
+]
+
diff --git a/tests/py/ip6/frag.t.payload.inet b/tests/py/ip6/frag.t.payload.inet
new file mode 100644
index 0000000..20334f4
--- /dev/null
+++ b/tests/py/ip6/frag.t.payload.inet
@@ -0,0 +1,232 @@
+# frag nexthdr tcp
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# frag nexthdr != icmp
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# frag nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag nexthdr esp
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+
+# frag nexthdr ah
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+
+# frag reserved 22
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# frag reserved != 233
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# frag reserved 33-45
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# frag reserved != 33-45
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# frag reserved { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag reserved != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag frag-off 22
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000b000 ]
+
+# frag frag-off != 233
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00004807 ]
+
+# frag frag-off 33-45
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp gte reg 1 0x00000801 ]
+ [ cmp lte reg 1 0x00006801 ]
+
+# frag frag-off != 33-45
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ range neq reg 1 0x00000801 0x00006801 ]
+
+# frag frag-off { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag frag-off != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag id 1
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# frag id 22
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# frag id != 33
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp neq reg 1 0x21000000 ]
+
+# frag id 33-45
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# frag id != 33-45
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# frag id { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag id != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag reserved2 1
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000006 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# frag more-fragments 0
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# frag more-fragments 1
+inet test-inet output
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000001 ]
+
diff --git a/tests/py/ip6/frag.t.payload.ip6 b/tests/py/ip6/frag.t.payload.ip6
new file mode 100644
index 0000000..7c3e7a4
--- /dev/null
+++ b/tests/py/ip6/frag.t.payload.ip6
@@ -0,0 +1,176 @@
+# frag nexthdr tcp
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# frag nexthdr != icmp
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# frag nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag nexthdr esp
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+
+# frag nexthdr ah
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+
+# frag reserved 22
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# frag reserved != 233
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# frag reserved 33-45
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# frag reserved != 33-45
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# frag reserved { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag reserved != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag frag-off 22
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000b000 ]
+
+# frag frag-off != 233
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00004807 ]
+
+# frag frag-off 33-45
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp gte reg 1 0x00000801 ]
+ [ cmp lte reg 1 0x00006801 ]
+
+# frag frag-off != 33-45
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ range neq reg 1 0x00000801 0x00006801 ]
+
+# frag frag-off { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag frag-off != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag id 1
+ip6 test-ip6 output
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# frag id 22
+ip6 test-ip6 output
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# frag id != 33
+ip6 test-ip6 output
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp neq reg 1 0x21000000 ]
+
+# frag id 33-45
+ip6 test-ip6 output
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# frag id != 33-45
+ip6 test-ip6 output
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# frag id { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag id != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag reserved2 1
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000006 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# frag more-fragments 0
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# frag more-fragments 1
+ip6 test-ip6 output
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000001 ]
+
diff --git a/tests/py/ip6/frag.t.payload.ip6.got b/tests/py/ip6/frag.t.payload.ip6.got
new file mode 100644
index 0000000..db439da
--- /dev/null
+++ b/tests/py/ip6/frag.t.payload.ip6.got
@@ -0,0 +1,43 @@
+# frag frag-off 0x16
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000b000 ]
+
+# frag frag-off != 0xe9
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00004807 ]
+
+# frag frag-off 0x21-0x2d
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp gte reg 1 0x00000801 ]
+ [ cmp lte reg 1 0x00006801 ]
+
+# frag frag-off != 0x21-0x2d
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ range neq reg 1 0x00000801 0x00006801 ]
+
+# frag frag-off { 0x21, 0x37, 0x43, 0x58}
+__set%d test-ip6 3 size 4
+__set%d test-ip6 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag frag-off != { 0x21, 0x37, 0x43, 0x58}
+__set%d test-ip6 3 size 4
+__set%d test-ip6 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+ip6 test-ip6 output
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
diff --git a/tests/py/ip6/frag.t.payload.netdev b/tests/py/ip6/frag.t.payload.netdev
new file mode 100644
index 0000000..0562075
--- /dev/null
+++ b/tests/py/ip6/frag.t.payload.netdev
@@ -0,0 +1,232 @@
+# frag nexthdr tcp
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# frag nexthdr != icmp
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# frag nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+__set%d test-netdev 3 size 8
+__set%d test-netdev 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+__set%d test-netdev 3 size 8
+__set%d test-netdev 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag nexthdr esp
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+
+# frag nexthdr ah
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+
+# frag reserved 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# frag reserved != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# frag reserved 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# frag reserved != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# frag reserved { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag reserved != { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag frag-off 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000b000 ]
+
+# frag frag-off != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00004807 ]
+
+# frag frag-off 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp gte reg 1 0x00000801 ]
+ [ cmp lte reg 1 0x00006801 ]
+
+# frag frag-off != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ range neq reg 1 0x00000801 0x00006801 ]
+
+# frag frag-off { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag frag-off != { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag reserved2 1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000006 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# frag more-fragments 0
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# frag more-fragments 1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# frag id 1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# frag id 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# frag id != 33
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp neq reg 1 0x21000000 ]
+
+# frag id 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# frag id != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# frag id { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag id != { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
diff --git a/tests/py/ip6/frag.t.payload.netdev.got b/tests/py/ip6/frag.t.payload.netdev.got
new file mode 100644
index 0000000..0562075
--- /dev/null
+++ b/tests/py/ip6/frag.t.payload.netdev.got
@@ -0,0 +1,232 @@
+# frag nexthdr tcp
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+
+# frag nexthdr != icmp
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# frag nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+__set%d test-netdev 3 size 8
+__set%d test-netdev 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp}
+__set%d test-netdev 3 size 8
+__set%d test-netdev 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag nexthdr esp
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+
+# frag nexthdr ah
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000033 ]
+
+# frag reserved 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# frag reserved != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# frag reserved 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# frag reserved != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# frag reserved { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag reserved != { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag frag-off 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000b000 ]
+
+# frag frag-off != 233
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00004807 ]
+
+# frag frag-off 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ cmp gte reg 1 0x00000801 ]
+ [ cmp lte reg 1 0x00006801 ]
+
+# frag frag-off != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ range neq reg 1 0x00000801 0x00006801 ]
+
+# frag frag-off { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag frag-off != { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 00000801 : 0 [end] element 0000b801 : 0 [end] element 00001802 : 0 [end] element 0000c002 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 2b @ 44 + 2 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# frag reserved2 1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000006 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# frag more-fragments 0
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# frag more-fragments 1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# frag id 1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# frag id 22
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# frag id != 33
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp neq reg 1 0x21000000 ]
+
+# frag id 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# frag id != 33-45
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# frag id { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# frag id != { 33, 55, 67, 88}
+__set%d test-netdev 3 size 4
+__set%d test-netdev 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
diff --git a/tests/py/ip6/hbh.t b/tests/py/ip6/hbh.t
new file mode 100644
index 0000000..fce5fea
--- /dev/null
+++ b/tests/py/ip6/hbh.t
@@ -0,0 +1,22 @@
+:filter-input;type filter hook input priority 0
+
+*ip6;test-ip6;filter-input
+*inet;test-inet;filter-input
+
+hbh hdrlength 22;ok
+hbh hdrlength != 233;ok
+hbh hdrlength 33-45;ok
+hbh hdrlength != 33-45;ok
+hbh hdrlength {33, 55, 67, 88};ok
+hbh hdrlength != {33, 55, 67, 88};ok
+
+hbh nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6};ok;hbh nexthdr { 58, 136, 51, 50, 6, 17, 132, 33, 108}
+hbh nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6};ok;hbh nexthdr != { 58, 136, 51, 50, 6, 17, 132, 33, 108}
+hbh nexthdr 22;ok
+hbh nexthdr != 233;ok
+hbh nexthdr 33-45;ok
+hbh nexthdr != 33-45;ok
+hbh nexthdr {33, 55, 67, 88};ok
+hbh nexthdr != {33, 55, 67, 88};ok
+hbh nexthdr ip;ok;hbh nexthdr 0
+hbh nexthdr != ip;ok;hbh nexthdr != 0
diff --git a/tests/py/ip6/hbh.t.json b/tests/py/ip6/hbh.t.json
new file mode 100644
index 0000000..68670a3
--- /dev/null
+++ b/tests/py/ip6/hbh.t.json
@@ -0,0 +1,316 @@
+# hbh hdrlength 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# hbh hdrlength != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# hbh hdrlength 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# hbh hdrlength != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# hbh hdrlength {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# hbh hdrlength != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# hbh nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "esp",
+ "ah",
+ "comp",
+ "udp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp",
+ "icmpv6"
+ ]
+ }
+ }
+ }
+]
+
+# hbh nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "esp",
+ "ah",
+ "comp",
+ "udp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp",
+ "icmpv6"
+ ]
+ }
+ }
+ }
+]
+
+# hbh nexthdr 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# hbh nexthdr != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# hbh nexthdr 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# hbh nexthdr != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# hbh nexthdr {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# hbh nexthdr != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# hbh nexthdr ip
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ }
+]
+
+# hbh nexthdr != ip
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": "ip"
+ }
+ }
+]
+
diff --git a/tests/py/ip6/hbh.t.json.output b/tests/py/ip6/hbh.t.json.output
new file mode 100644
index 0000000..190f0fc
--- /dev/null
+++ b/tests/py/ip6/hbh.t.json.output
@@ -0,0 +1,68 @@
+# hbh nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [ 6, 17, 33, 50, 51, 58, 108, 132, 136 ]
+ }
+ }
+ }
+]
+
+# hbh nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [ 6, 17, 33, 50, 51, 58, 108, 132, 136 ]
+ }
+ }
+ }
+]
+
+# hbh nexthdr ip
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# hbh nexthdr != ip
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "hbh"
+ }
+ },
+ "op": "!=",
+ "right": 0
+ }
+ }
+]
+
diff --git a/tests/py/ip6/hbh.t.payload.inet b/tests/py/ip6/hbh.t.payload.inet
new file mode 100644
index 0000000..63afd83
--- /dev/null
+++ b/tests/py/ip6/hbh.t.payload.inet
@@ -0,0 +1,132 @@
+# hbh hdrlength 22
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# hbh hdrlength != 233
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# hbh hdrlength 33-45
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# hbh hdrlength != 33-45
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# hbh hdrlength {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# hbh hdrlength != {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# hbh nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end] element 0000003a : 0 [end]
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# hbh nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end] element 0000003a : 0 [end]
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# hbh nexthdr 22
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# hbh nexthdr != 233
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# hbh nexthdr 33-45
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# hbh nexthdr != 33-45
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# hbh nexthdr {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# hbh nexthdr != {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# hbh nexthdr ip
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# hbh nexthdr != ip
+inet test-inet filter-input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
diff --git a/tests/py/ip6/hbh.t.payload.ip6 b/tests/py/ip6/hbh.t.payload.ip6
new file mode 100644
index 0000000..913505a
--- /dev/null
+++ b/tests/py/ip6/hbh.t.payload.ip6
@@ -0,0 +1,100 @@
+# hbh hdrlength 22
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# hbh hdrlength != 233
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# hbh hdrlength 33-45
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# hbh hdrlength != 33-45
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# hbh hdrlength {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# hbh hdrlength != {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# hbh nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# hbh nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# hbh nexthdr 22
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# hbh nexthdr != 233
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# hbh nexthdr 33-45
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# hbh nexthdr != 33-45
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# hbh nexthdr {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# hbh nexthdr != {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# hbh nexthdr ip
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# hbh nexthdr != ip
+ip6 test-ip6 filter-input
+ [ exthdr load ipv6 1b @ 0 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000000 ]
+
diff --git a/tests/py/ip6/icmpv6.t b/tests/py/ip6/icmpv6.t
new file mode 100644
index 0000000..35dad2b
--- /dev/null
+++ b/tests/py/ip6/icmpv6.t
@@ -0,0 +1,99 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+# BUG: There is a bug with icmpv6 and inet tables
+# *inet;test-inet;input
+
+icmpv6 type destination-unreachable accept;ok
+icmpv6 type packet-too-big accept;ok
+icmpv6 type time-exceeded accept;ok
+icmpv6 type echo-request accept;ok
+icmpv6 type echo-reply accept;ok
+icmpv6 type mld-listener-query accept;ok
+icmpv6 type mld-listener-report accept;ok
+icmpv6 type mld-listener-done accept;ok
+icmpv6 type mld-listener-reduction accept;ok;icmpv6 type mld-listener-done accept
+icmpv6 type nd-router-solicit accept;ok
+icmpv6 type nd-router-advert accept;ok
+icmpv6 type nd-neighbor-solicit accept;ok
+icmpv6 type nd-neighbor-advert accept;ok
+icmpv6 type nd-redirect accept;ok
+icmpv6 type parameter-problem accept;ok
+icmpv6 type router-renumbering accept;ok
+icmpv6 type ind-neighbor-solicit accept;ok
+icmpv6 type ind-neighbor-advert accept;ok
+icmpv6 type mld2-listener-report accept;ok
+icmpv6 type {destination-unreachable, time-exceeded, nd-router-solicit} accept;ok
+icmpv6 type {router-renumbering, mld-listener-done, time-exceeded, nd-router-solicit} accept;ok
+icmpv6 type {mld-listener-query, time-exceeded, nd-router-advert} accept;ok
+icmpv6 type != {mld-listener-query, time-exceeded, nd-router-advert} accept;ok
+
+icmpv6 code 4;ok;icmpv6 code port-unreachable
+icmpv6 code 3-66;ok
+icmpv6 code {5, 6, 7} accept;ok;icmpv6 code {policy-fail, reject-route, 7} accept
+icmpv6 code != {policy-fail, reject-route, 7} accept;ok
+
+icmpv6 checksum 2222 log;ok
+icmpv6 checksum != 2222 log;ok
+icmpv6 checksum 222-226;ok
+icmpv6 checksum != 222-226;ok
+icmpv6 checksum { 222, 226};ok
+icmpv6 checksum != { 222, 226};ok
+
+# BUG: icmpv6 parameter-problem, pptr
+# [ICMP6HDR_PPTR] = ICMP6HDR_FIELD("parameter-problem", icmp6_pptr),
+# $ sudo nft add rule ip6 test6 input icmpv6 parameter-problem 35
+# <cmdline>:1:53-53: Error: syntax error, unexpected end of file
+# add rule ip6 test6 input icmpv6 parameter-problem 35
+# ^
+# $ sudo nft add rule ip6 test6 input icmpv6 parameter-problem
+# <cmdline>:1:26-31: Error: Value 58 exceeds valid range 0-0
+# add rule ip6 test6 input icmpv6 parameter-problem
+# ^^^^^^
+# $ sudo nft add rule ip6 test6 input icmpv6 parameter-problem 2-4
+# <cmdline>:1:54-54: Error: syntax error, unexpected end of file
+# add rule ip6 test6 input icmpv6 parameter-problem 2-4
+
+icmpv6 mtu 22;ok
+icmpv6 mtu != 233;ok
+icmpv6 mtu 33-45;ok
+icmpv6 mtu != 33-45;ok
+icmpv6 mtu {33, 55, 67, 88};ok
+icmpv6 mtu != {33, 55, 67, 88};ok
+icmpv6 type packet-too-big icmpv6 mtu 1280;ok;icmpv6 mtu 1280
+
+icmpv6 id 33-45;ok;icmpv6 type { echo-request, echo-reply} icmpv6 id 33-45
+icmpv6 id != 33-45;ok;icmpv6 type { echo-request, echo-reply} icmpv6 id != 33-45
+icmpv6 id {33, 55, 67, 88};ok;icmpv6 type { echo-request, echo-reply} icmpv6 id { 33, 55, 67, 88}
+icmpv6 id != {33, 55, 67, 88};ok;icmpv6 type { echo-request, echo-reply} icmpv6 id != { 33, 55, 67, 88}
+
+icmpv6 id 1;ok;icmpv6 type { echo-request, echo-reply} icmpv6 id 1
+icmpv6 type echo-reply icmpv6 id 65534;ok
+
+icmpv6 sequence 2;ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence 2
+icmpv6 sequence {3, 4, 5, 6, 7} accept;ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence { 3, 4, 5, 6, 7} accept
+
+
+icmpv6 sequence {2, 4};ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence { 2, 4}
+icmpv6 sequence != {2, 4};ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence != { 2, 4}
+icmpv6 sequence 2-4;ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence 2-4
+icmpv6 sequence != 2-4;ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence != 2-4
+
+icmpv6 max-delay 33-45;ok
+icmpv6 max-delay != 33-45;ok
+icmpv6 max-delay {33, 55, 67, 88};ok
+icmpv6 max-delay != {33, 55, 67, 88};ok
+
+icmpv6 type parameter-problem icmpv6 code no-route;ok
+
+icmpv6 type mld-listener-query icmpv6 taddr 2001:db8::133;ok
+icmpv6 type nd-neighbor-solicit icmpv6 taddr 2001:db8::133;ok
+icmpv6 type nd-neighbor-advert icmpv6 taddr 2001:db8::133;ok
+icmpv6 taddr 2001:db8::133;ok;icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-done, nd-neighbor-solicit, nd-neighbor-advert, nd-redirect} icmpv6 taddr 2001:db8::133
+
+icmpv6 taddr 2001:db8::133;ok;icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-done, nd-neighbor-solicit, nd-neighbor-advert, nd-redirect} icmpv6 taddr 2001:db8::133
+
+icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-done, nd-neighbor-solicit, nd-neighbor-advert, nd-redirect} icmpv6 taddr 2001:db8::133;ok
+icmpv6 type { nd-neighbor-solicit, nd-neighbor-advert } icmpv6 taddr 2001:db8::133;ok
+icmpv6 daddr 2001:db8::133;ok
+icmpv6 type nd-redirect icmpv6 daddr 2001:db8::133;ok;icmpv6 daddr 2001:db8::133
diff --git a/tests/py/ip6/icmpv6.t.json b/tests/py/ip6/icmpv6.t.json
new file mode 100644
index 0000000..224a8e8
--- /dev/null
+++ b/tests/py/ip6/icmpv6.t.json
@@ -0,0 +1,1425 @@
+# icmpv6 type destination-unreachable accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "destination-unreachable"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type packet-too-big accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "packet-too-big"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type time-exceeded accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "time-exceeded"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type echo-request accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type echo-reply accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-reply"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type mld-listener-query accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "mld-listener-query"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type mld-listener-report accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "mld-listener-report"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type mld-listener-done accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "mld-listener-done"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type mld-listener-reduction accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "mld-listener-reduction"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type nd-router-solicit accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-solicit"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type nd-router-advert accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-advert"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type nd-neighbor-solicit accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-neighbor-solicit"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type nd-neighbor-advert accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-neighbor-advert"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type nd-redirect accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-redirect"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type parameter-problem accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "parameter-problem"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type router-renumbering accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "router-renumbering"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type ind-neighbor-solicit accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "ind-neighbor-solicit"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type ind-neighbor-advert accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "ind-neighbor-advert"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type mld2-listener-report accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "mld2-listener-report"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type {destination-unreachable, time-exceeded, nd-router-solicit} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "destination-unreachable",
+ "time-exceeded",
+ "nd-router-solicit"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type {router-renumbering, mld-listener-done, time-exceeded, nd-router-solicit} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "router-renumbering",
+ "mld-listener-done",
+ "time-exceeded",
+ "nd-router-solicit"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type {mld-listener-query, time-exceeded, nd-router-advert} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "mld-listener-query",
+ "time-exceeded",
+ "nd-router-advert"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type != {mld-listener-query, time-exceeded, nd-router-advert} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "mld-listener-query",
+ "time-exceeded",
+ "nd-router-advert"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 code 4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 4
+ }
+ }
+]
+
+# icmpv6 code 3-66
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 3, 66 ]
+ }
+ }
+ }
+]
+
+# icmpv6 code {5, 6, 7} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 5,
+ 6,
+ 7
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 code != {policy-fail, reject-route, 7} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "policy-fail",
+ "reject-route",
+ 7
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 checksum 2222 log
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 2222
+ }
+ },
+ {
+ "log": null
+ }
+]
+
+# icmpv6 checksum != 2222 log
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": 2222
+ }
+ },
+ {
+ "log": null
+ }
+]
+
+# icmpv6 checksum 222-226
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 222, 226 ]
+ }
+ }
+ }
+]
+
+# icmpv6 checksum != 222-226
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 222, 226 ]
+ }
+ }
+ }
+]
+
+# icmpv6 checksum { 222, 226}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 222,
+ 226
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 checksum != { 222, 226}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "checksum",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 222,
+ 226
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 mtu 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# icmpv6 mtu != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# icmpv6 mtu 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmpv6 mtu != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmpv6 mtu {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 mtu != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmpv6 id != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmpv6 id {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# icmpv6 type echo-reply icmpv6 id 65534
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "echo-reply"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 65534
+ }
+ }
+]
+
+# icmpv6 sequence 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# icmpv6 sequence {3, 4, 5, 6, 7} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 3,
+ 4,
+ 5,
+ 6,
+ 7
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 sequence {2, 4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence != {2, 4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence 2-4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 2, 4 ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence != 2-4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 2, 4 ]
+ }
+ }
+ }
+]
+
+# icmpv6 max-delay 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "max-delay",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmpv6 max-delay != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "max-delay",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# icmpv6 max-delay {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "max-delay",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 max-delay != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "max-delay",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 type packet-too-big icmpv6 mtu 1280
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 1280
+ }
+ }
+]
+
+# icmpv6 type parameter-problem icmpv6 code no-route
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "parameter-problem"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "no-route"
+ }
+ }
+]
+
+# icmpv6 type mld-listener-query icmpv6 taddr 2001:db8::133
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "mld-listener-query"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "taddr",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "2001:db8::133"
+ }
+ }
+]
+
+# icmpv6 type nd-neighbor-solicit icmpv6 taddr 2001:db8::133
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-neighbor-solicit"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "taddr",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "2001:db8::133"
+ }
+ }
+]
+
+# icmpv6 type nd-neighbor-advert icmpv6 taddr 2001:db8::133
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-neighbor-advert"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "taddr",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "2001:db8::133"
+ }
+ }
+]
+
+# icmpv6 taddr 2001:db8::133
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "mld-listener-query",
+ "mld-listener-report",
+ "mld-listener-done",
+ "nd-neighbor-solicit",
+ "nd-neighbor-advert",
+ "nd-redirect"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "taddr",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "2001:db8::133"
+ }
+ }
+]
+
+# icmpv6 taddr 2001:db8::133
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "mld-listener-query",
+ "mld-listener-report",
+ "mld-listener-done",
+ "nd-neighbor-solicit",
+ "nd-neighbor-advert",
+ "nd-redirect"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "taddr",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "2001:db8::133"
+ }
+ }
+]
+
+# icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-done, nd-neighbor-solicit, nd-neighbor-advert, nd-redirect} icmpv6 taddr 2001:db8::133
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "mld-listener-query",
+ "mld-listener-report",
+ "mld-listener-done",
+ "nd-neighbor-solicit",
+ "nd-neighbor-advert",
+ "nd-redirect"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "taddr",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "2001:db8::133"
+ }
+ }
+]
+
+# icmpv6 type { nd-neighbor-solicit, nd-neighbor-advert } icmpv6 taddr 2001:db8::133
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "nd-neighbor-solicit",
+ "nd-neighbor-advert"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "taddr",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "2001:db8::133"
+ }
+ }
+]
+
+# icmpv6 daddr 2001:db8::133
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "2001:db8::133"
+ }
+ }
+]
+
+# icmpv6 type nd-redirect icmpv6 daddr 2001:db8::133
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "2001:db8::133"
+ }
+ }
+]
diff --git a/tests/py/ip6/icmpv6.t.json.output b/tests/py/ip6/icmpv6.t.json.output
new file mode 100644
index 0000000..7b8f5c1
--- /dev/null
+++ b/tests/py/ip6/icmpv6.t.json.output
@@ -0,0 +1,760 @@
+# icmpv6 type mld-listener-reduction accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "mld-listener-done"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type {router-renumbering, mld-listener-done, time-exceeded, nd-router-solicit} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "time-exceeded",
+ "mld-listener-done",
+ "nd-router-solicit",
+ "router-renumbering"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type {mld-listener-query, time-exceeded, nd-router-advert} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "time-exceeded",
+ "mld-listener-query",
+ "nd-router-advert"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 type != {mld-listener-query, time-exceeded, nd-router-advert} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "time-exceeded",
+ "mld-listener-query",
+ "nd-router-advert"
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 code 4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "port-unreachable"
+ }
+ }
+]
+
+# icmpv6 code 3-66
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ "addr-unreachable",
+ 66
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 code {5, 6, 7} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "policy-fail",
+ "reject-route",
+ 7
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 code { 3-66}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [
+ "addr-unreachable",
+ 66
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 code != { 3-66}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ {
+ "range": [
+ "addr-unreachable",
+ 66
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id {33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id != {33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# icmpv6 sequence {3, 4, 5, 6, 7} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 3,
+ 4,
+ 5,
+ 6,
+ 7
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 sequence {2, 4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence != {2, 4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence 2-4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence != 2-4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence { 2-4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 2,
+ 4
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence != { 2-4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 2,
+ 4
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/icmpv6.t.payload.ip6 b/tests/py/ip6/icmpv6.t.payload.ip6
new file mode 100644
index 0000000..fcaf481
--- /dev/null
+++ b/tests/py/ip6/icmpv6.t.payload.ip6
@@ -0,0 +1,643 @@
+# icmpv6 type destination-unreachable accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type packet-too-big accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type time-exceeded accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type echo-request accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000080 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type echo-reply accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type mld-listener-query accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type mld-listener-report accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000083 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type mld-listener-done accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type mld-listener-reduction accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000084 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type nd-router-solicit accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000085 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type nd-router-advert accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000086 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type nd-neighbor-solicit accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000087 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type nd-neighbor-advert accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type nd-redirect accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000089 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type parameter-problem accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000004 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type router-renumbering accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000008a ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type ind-neighbor-solicit accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000008d ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type ind-neighbor-advert accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000008e ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type mld2-listener-report accept
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x0000008f ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type {destination-unreachable, time-exceeded, nd-router-solicit} accept
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000001 : 0 [end] element 00000003 : 0 [end] element 00000085 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type {router-renumbering, mld-listener-done, time-exceeded, nd-router-solicit} accept
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 0000008a : 0 [end] element 00000084 : 0 [end] element 00000003 : 0 [end] element 00000085 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type {mld-listener-query, time-exceeded, nd-router-advert} accept
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000082 : 0 [end] element 00000003 : 0 [end] element 00000086 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 type != {mld-listener-query, time-exceeded, nd-router-advert} accept
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000082 : 0 [end] element 00000003 : 0 [end] element 00000086 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 code 4
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000004 ]
+
+# icmpv6 code 3-66
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000003 ]
+ [ cmp lte reg 1 0x00000042 ]
+
+# icmpv6 code {5, 6, 7} accept
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000005 : 0 [end] element 00000006 : 0 [end] element 00000007 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 code != {policy-fail, reject-route, 7} accept
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000005 : 0 [end] element 00000006 : 0 [end] element 00000007 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 checksum 2222 log
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000ae08 ]
+ [ log ]
+
+# icmpv6 checksum != 2222 log
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000ae08 ]
+ [ log ]
+
+# icmpv6 checksum 222-226
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x0000de00 ]
+ [ cmp lte reg 1 0x0000e200 ]
+
+# icmpv6 checksum != 222-226
+ip6
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ range neq reg 1 0x0000de00 0x0000e200 ]
+
+# icmpv6 checksum { 222, 226}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 0000de00 : 0 [end] element 0000e200 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmpv6 checksum != { 222, 226}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 0000de00 : 0 [end] element 0000e200 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmpv6 mtu 22
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x16000000 ]
+
+# icmpv6 mtu != 233
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp neq reg 1 0xe9000000 ]
+
+# icmpv6 mtu 33-45
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x21000000 ]
+ [ cmp lte reg 1 0x2d000000 ]
+
+# icmpv6 mtu != 33-45
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x21000000 0x2d000000 ]
+
+# icmpv6 mtu {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmpv6 mtu != {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 21000000 : 0 [end] element 37000000 : 0 [end] element 43000000 : 0 [end] element 58000000 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmpv6 type packet-too-big icmpv6 mtu 1280
+ip6
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00050000 ]
+
+# icmpv6 id 33-45
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# icmpv6 id != 33-45
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# icmpv6 id {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmpv6 id != {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmpv6 id 1
+__set%d test-ip6 3 size 2
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+ip6
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# icmpv6 type echo-reply icmpv6 id 65534
+ip6
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000081 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x0000feff ]
+
+# icmpv6 sequence 2
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000200 ]
+
+# icmpv6 sequence {3, 4, 5, 6, 7} accept
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000300 : 0 [end] element 00000400 : 0 [end] element 00000500 : 0 [end] element 00000600 : 0 [end] element 00000700 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ immediate reg 0 accept ]
+
+# icmpv6 sequence {2, 4}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000200 : 0 [end] element 00000400 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmpv6 sequence != {2, 4}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000200 : 0 [end] element 00000400 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmpv6 sequence 2-4
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00000200 ]
+ [ cmp lte reg 1 0x00000400 ]
+
+# icmpv6 sequence != 2-4
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 2b @ transport header + 6 => reg 1 ]
+ [ range neq reg 1 0x00000200 0x00000400 ]
+
+# icmpv6 max-delay 33-45
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# icmpv6 max-delay != 33-45
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# icmpv6 max-delay {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# icmpv6 max-delay != {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
+ [ payload load 2b @ transport header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# icmpv6 type parameter-problem icmpv6 code no-route
+ip6
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000004 ]
+
+# icmpv6 type mld-listener-query icmpv6 taddr 2001:db8::133
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
+ [ payload load 16b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xb80d0120 0x00000000 0x00000000 0x33010000 ]
+
+# icmpv6 type nd-neighbor-solicit icmpv6 taddr 2001:db8::133
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000087 ]
+ [ payload load 16b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xb80d0120 0x00000000 0x00000000 0x33010000 ]
+
+# icmpv6 type nd-neighbor-advert icmpv6 taddr 2001:db8::133
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000088 ]
+ [ payload load 16b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xb80d0120 0x00000000 0x00000000 0x33010000 ]
+
+# icmpv6 taddr 2001:db8::133
+__set%d test-ip6 3 size 6
+__set%d test-ip6 0
+ element 00000082 : 0 [end] element 00000083 : 0 [end] element 00000084 : 0 [end] element 00000087 : 0 [end] element 00000088 : 0 [end] element 00000089 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 16b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xb80d0120 0x00000000 0x00000000 0x33010000 ]
+
+# icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-done, nd-neighbor-solicit, nd-neighbor-advert, nd-redirect} icmpv6 taddr 2001:db8::133
+__set%d test-ip6 3 size 6
+__set%d test-ip6 0
+ element 00000082 : 0 [end] element 00000083 : 0 [end] element 00000084 : 0 [end] element 00000087 : 0 [end] element 00000088 : 0 [end] element 00000089 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 16b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xb80d0120 0x00000000 0x00000000 0x33010000 ]
+
+# icmpv6 type { nd-neighbor-solicit, nd-neighbor-advert } icmpv6 taddr 2001:db8::133
+__set%d test-ip6 3 size 2
+__set%d test-ip6 0
+ element 00000087 : 0 [end] element 00000088 : 0 [end]
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 16b @ transport header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xb80d0120 0x00000000 0x00000000 0x33010000 ]
+
+# icmpv6 daddr 2001:db8::133
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000089 ]
+ [ payload load 16b @ transport header + 24 => reg 1 ]
+ [ cmp eq reg 1 0xb80d0120 0x00000000 0x00000000 0x33010000 ]
+
+# icmpv6 type nd-redirect icmpv6 daddr 2001:db8::133
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000089 ]
+ [ payload load 16b @ transport header + 24 => reg 1 ]
+ [ cmp eq reg 1 0xb80d0120 0x00000000 0x00000000 0x33010000 ]
diff --git a/tests/py/ip6/ip6.t b/tests/py/ip6/ip6.t
new file mode 100644
index 0000000..2ffe318
--- /dev/null
+++ b/tests/py/ip6/ip6.t
@@ -0,0 +1,153 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+*inet;test-inet;input
+
+# BUG: Problem with version, priority
+# <cmdline>:1:1-38: Error: Could not process rule: Invalid argument
+# add rule ip6 test6 input ip6 version 1
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- ip6 version 6;ok
+
+ip6 dscp cs1;ok
+ip6 dscp != cs1;ok
+ip6 dscp 0x38;ok;ip6 dscp cs7
+ip6 dscp != 0x20;ok;ip6 dscp != cs4
+ip6 dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef};ok
+ip6 dscp vmap { 0x04 : accept, 0x3f : continue } counter;ok
+
+ip6 flowlabel 22;ok
+ip6 flowlabel != 233;ok
+- ip6 flowlabel 33-45;ok
+- ip6 flowlabel != 33-45;ok
+ip6 flowlabel { 33, 55, 67, 88};ok
+# BUG ip6 flowlabel { 5046528, 2883584, 13522432 }
+ip6 flowlabel != { 33, 55, 67, 88};ok
+ip6 flowlabel vmap { 0 : accept, 2 : continue };ok
+
+ip6 length 22;ok
+ip6 length != 233;ok
+ip6 length 33-45;ok
+ip6 length != 33-45;ok
+ip6 length { 33, 55, 67, 88};ok
+ip6 length != {33, 55, 67, 88};ok
+
+ip6 nexthdr {udp, ah, comp, udplite, tcp, dccp, sctp};ok;ip6 nexthdr { 132, 51, 108, 136, 17, 33, 6}
+ip6 nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6};ok;ip6 nexthdr { 6, 136, 108, 33, 50, 17, 132, 58, 51}
+ip6 nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6};ok;ip6 nexthdr != { 6, 136, 108, 33, 50, 17, 132, 58, 51}
+ip6 nexthdr esp;ok;ip6 nexthdr 50
+ip6 nexthdr != esp;ok;ip6 nexthdr != 50
+ip6 nexthdr 33-44;ok
+ip6 nexthdr != 33-44;ok
+
+ip6 hoplimit 1;ok
+ip6 hoplimit != 233;ok
+ip6 hoplimit 33-45;ok
+ip6 hoplimit != 33-45;ok
+ip6 hoplimit {33, 55, 67, 88};ok
+ip6 hoplimit != {33, 55, 67, 88};ok
+
+# from src/scanner.l
+# v680 (({hex4}:){7}{hex4})
+ip6 saddr 1234:1234:1234:1234:1234:1234:1234:1234;ok
+# v670 ((:)(:{hex4}{7}))
+ip6 saddr ::1234:1234:1234:1234:1234:1234:1234;ok;ip6 saddr 0:1234:1234:1234:1234:1234:1234:1234
+# v671 ((({hex4}:){1})(:{hex4}{6}))
+ip6 saddr 1234::1234:1234:1234:1234:1234:1234;ok;ip6 saddr 1234:0:1234:1234:1234:1234:1234:1234
+# v672 ((({hex4}:){2})(:{hex4}{5}))
+ip6 saddr 1234:1234::1234:1234:1234:1234:1234;ok;ip6 saddr 1234:1234:0:1234:1234:1234:1234:1234
+ip6 saddr 1234:1234:0:1234:1234:1234:1234:1234;ok
+# v673 ((({hex4}:){3})(:{hex4}{4}))
+ip6 saddr 1234:1234:1234::1234:1234:1234:1234;ok;ip6 saddr 1234:1234:1234:0:1234:1234:1234:1234
+# v674 ((({hex4}:){4})(:{hex4}{3}))
+ip6 saddr 1234:1234:1234:1234:0:1234:1234:1234;ok
+# v675 ((({hex4}:){5})(:{hex4}{2}))
+ip6 saddr 1234:1234:1234:1234:1234::1234:1234;ok;ip6 saddr 1234:1234:1234:1234:1234:0:1234:1234
+# v676 ((({hex4}:){6})(:{hex4}{1}))
+ip6 saddr 1234:1234:1234:1234:1234:1234:0:1234;ok
+# v677 ((({hex4}:){7})(:))
+ip6 saddr 1234:1234:1234:1234:1234:1234:1234::;ok;ip6 saddr 1234:1234:1234:1234:1234:1234:1234:0
+# v67 ({v670}|{v671}|{v672}|{v673}|{v674}|{v675}|{v676}|{v677})
+# v660 ((:)(:{hex4}{6}))
+ip6 saddr ::1234:1234:1234:1234:1234:1234;ok
+# v661 ((({hex4}:){1})(:{hex4}{5}))
+ip6 saddr 1234::1234:1234:1234:1234:1234;ok
+# v662 ((({hex4}:){2})(:{hex4}{4}))
+ip6 saddr 1234:1234::1234:1234:1234:1234;ok
+# v663 ((({hex4}:){3})(:{hex4}{3}))
+ip6 saddr 1234:1234:1234::1234:1234:1234;ok
+# v664 ((({hex4}:){4})(:{hex4}{2}))
+ip6 saddr 1234:1234:1234:1234::1234:1234;ok
+# v665 ((({hex4}:){5})(:{hex4}{1}))
+ip6 saddr 1234:1234:1234:1234:1234::1234;ok
+# v666 ((({hex4}:){6})(:))
+ip6 saddr 1234:1234:1234:1234:1234:1234::;ok
+# v66 ({v660}|{v661}|{v662}|{v663}|{v664}|{v665}|{v666})
+# v650 ((:)(:{hex4}{5}))
+ip6 saddr ::1234:1234:1234:1234:1234;ok
+# v651 ((({hex4}:){1})(:{hex4}{4}))
+ip6 saddr 1234::1234:1234:1234:1234;ok
+# v652 ((({hex4}:){2})(:{hex4}{3}))
+ip6 saddr 1234:1234::1234:1234:1234;ok
+# v653 ((({hex4}:){3})(:{hex4}{2}))
+ip6 saddr 1234:1234:1234::1234:1234;ok
+# v654 ((({hex4}:){4})(:{hex4}{1}))
+ip6 saddr 1234:1234:1234:1234::1234;ok
+# v655 ((({hex4}:){5})(:))
+ip6 saddr 1234:1234:1234:1234:1234::;ok
+# v65 ({v650}|{v651}|{v652}|{v653}|{v654}|{v655})
+# v640 ((:)(:{hex4}{4}))
+ip6 saddr ::1234:1234:1234:1234;ok
+# v641 ((({hex4}:){1})(:{hex4}{3}))
+ip6 saddr 1234::1234:1234:1234;ok
+# v642 ((({hex4}:){2})(:{hex4}{2}))
+ip6 saddr 1234:1234::1234:1234;ok
+# v643 ((({hex4}:){3})(:{hex4}{1}))
+ip6 saddr 1234:1234:1234::1234;ok
+# v644 ((({hex4}:){4})(:))
+ip6 saddr 1234:1234:1234:1234::;ok
+# v64 ({v640}|{v641}|{v642}|{v643}|{v644})
+# v630 ((:)(:{hex4}{3}))
+ip6 saddr ::1234:1234:1234;ok
+# v631 ((({hex4}:){1})(:{hex4}{2}))
+ip6 saddr 1234::1234:1234;ok
+# v632 ((({hex4}:){2})(:{hex4}{1}))
+ip6 saddr 1234:1234::1234;ok
+# v633 ((({hex4}:){3})(:))
+ip6 saddr 1234:1234:1234::;ok
+# v63 ({v630}|{v631}|{v632}|{v633})
+# v620 ((:)(:{hex4}{2}))
+ip6 saddr ::1234:1234;ok;ip6 saddr ::18.52.18.52
+# v621 ((({hex4}:){1})(:{hex4}{1}))
+ip6 saddr 1234::1234;ok
+# v622 ((({hex4}:){2})(:))
+ip6 saddr 1234:1234::;ok
+# v62 ({v620}|{v621}|{v622})
+# v610 ((:)(:{hex4}{1}))
+ip6 saddr ::1234;ok
+# v611 ((({hex4}:){1})(:))
+ip6 saddr 1234::;ok
+# v61 ({v610}|{v611})
+# v60 (::)
+ip6 saddr ::/64;ok
+ip6 saddr ::1 ip6 daddr ::2;ok
+
+ip6 daddr != {::1234:1234:1234:1234:1234:1234:1234, 1234:1234::1234:1234:1234:1234:1234 };ok;ip6 daddr != {0:1234:1234:1234:1234:1234:1234:1234, 1234:1234:0:1234:1234:1234:1234:1234}
+ip6 daddr != ::1234:1234:1234:1234:1234:1234:1234-1234:1234::1234:1234:1234:1234:1234;ok;ip6 daddr != 0:1234:1234:1234:1234:1234:1234:1234-1234:1234:0:1234:1234:1234:1234:1234
+
+# limit impact to lo
+iif "lo" ip6 daddr set ::1;ok
+iif "lo" ip6 hoplimit set 1;ok
+iif "lo" ip6 dscp set af42;ok
+iif "lo" ip6 dscp set 63;ok;iif "lo" ip6 dscp set 0x3f
+iif "lo" ip6 ecn set ect0;ok
+iif "lo" ip6 ecn set ce;ok
+
+iif "lo" ip6 flowlabel set 0;ok
+iif "lo" ip6 flowlabel set 12345;ok
+iif "lo" ip6 flowlabel set 0xfffff;ok;iif "lo" ip6 flowlabel set 1048575
+
+iif "lo" ip6 ecn set 4;fail
+iif "lo" ip6 dscp set 64;fail
+iif "lo" ip6 flowlabel set 1048576;fail
diff --git a/tests/py/ip6/ip6.t.json b/tests/py/ip6/ip6.t.json
new file mode 100644
index 0000000..cf80217
--- /dev/null
+++ b/tests/py/ip6/ip6.t.json
@@ -0,0 +1,1559 @@
+# ip6 dscp cs1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "cs1"
+ }
+ }
+]
+
+# ip6 dscp != cs1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": "cs1"
+ }
+ }
+]
+
+# ip6 dscp 0x38
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "0x38"
+ }
+ }
+]
+
+# ip6 dscp != 0x20
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": "0x20"
+ }
+ }
+]
+
+# ip6 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",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "cs0",
+ "cs1",
+ "cs2",
+ "cs3",
+ "cs4",
+ "cs5",
+ "cs6",
+ "cs7",
+ "af11",
+ "af12",
+ "af13",
+ "af21",
+ "af22",
+ "af23",
+ "af31",
+ "af32",
+ "af33",
+ "af41",
+ "af42",
+ "af43",
+ "ef"
+ ]
+ }
+ }
+ }
+]
+
+# ip6 dscp vmap { 0x04 : accept, 0x3f : continue } counter
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "0x04",
+ {
+ "accept": null
+ }
+ ],
+ [
+ "0x3f",
+ {
+ "continue": null
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "counter": null
+ }
+]
+
+# ip6 flowlabel 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flowlabel",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip6 flowlabel != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flowlabel",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip6 flowlabel { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flowlabel",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip6 flowlabel != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "flowlabel",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip6 flowlabel vmap { 0 : accept, 2 : continue }
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "flowlabel",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 0,
+ {
+ "accept": null
+ }
+ ],
+ [
+ 2,
+ {
+ "continue": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 length 22
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# ip6 length != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip6 length 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip6 length != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip6 length { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip6 length != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "length",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr {udp, ah, comp, udplite, tcp, dccp, sctp}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "udp",
+ "ah",
+ "comp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp"
+ ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "esp",
+ "ah",
+ "comp",
+ "udp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp",
+ "icmpv6"
+ ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "esp",
+ "ah",
+ "comp",
+ "udp",
+ "udplite",
+ "tcp",
+ "dccp",
+ "sctp",
+ "icmpv6"
+ ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr esp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "esp"
+ }
+ }
+]
+
+# ip6 nexthdr != esp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": "esp"
+ }
+ }
+]
+
+# ip6 nexthdr { 33-44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ { "range": [ 33, 44 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr != { 33-44}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 33, 44 ] }
+ ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr 33-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 44 ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr != 33-44
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 44 ]
+ }
+ }
+ }
+]
+
+# ip6 hoplimit 1
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hoplimit",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# ip6 hoplimit != 233
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hoplimit",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# ip6 hoplimit 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hoplimit",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip6 hoplimit != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hoplimit",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# ip6 hoplimit {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hoplimit",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip6 hoplimit != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "hoplimit",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr ::1234:1234:1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::1234:1234:1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234::1234:1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234::1234:1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234::1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234::1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:0:1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:0:1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234::1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234::1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:0:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:0:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:1234::1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:1234::1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:0:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:1234:1234:0:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:1234::
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:1234:1234:1234::"
+ }
+ }
+]
+
+# ip6 saddr ::1234:1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::1234:1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234::1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234::1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234::1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234::1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234::1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234::1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234::1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234::1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:1234::1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:1234::1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234::
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:1234:1234::"
+ }
+ }
+]
+
+# ip6 saddr ::1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234::1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234::1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234::1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234::1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234::1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234::1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234::1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234::1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:1234::
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:1234::"
+ }
+ }
+]
+
+# ip6 saddr ::1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234::1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234::1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234::1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234::1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234::1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234::1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234::
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234::"
+ }
+ }
+]
+
+# ip6 saddr ::1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234::1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234::1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234::1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234::1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234::
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234::"
+ }
+ }
+]
+
+# ip6 saddr ::1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234::1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234::1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234::
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234::"
+ }
+ }
+]
+
+# ip6 saddr ::1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::1234"
+ }
+ }
+]
+
+# ip6 saddr 1234::
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234::"
+ }
+ }
+]
+
+# ip6 saddr ::/64
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "prefix": {
+ "addr": "::",
+ "len": 64
+ }
+ }
+ }
+ }
+]
+
+# ip6 saddr ::1 ip6 daddr ::2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::1"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::2"
+ }
+ }
+]
+
+# ip6 daddr != {::1234:1234:1234:1234:1234:1234:1234, 1234:1234::1234:1234:1234:1234:1234 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "::1234:1234:1234:1234:1234:1234:1234",
+ "1234:1234::1234:1234:1234:1234:1234"
+ ]
+ }
+ }
+ }
+]
+
+# ip6 daddr != ::1234:1234:1234:1234:1234:1234:1234-1234:1234::1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "::1234:1234:1234:1234:1234:1234:1234", "1234:1234::1234:1234:1234:1234:1234" ]
+ }
+ }
+ }
+]
+
+# iif "lo" ip6 daddr set ::1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "value": "::1"
+ }
+ }
+]
+
+# iif "lo" ip6 hoplimit set 1
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "hoplimit",
+ "protocol": "ip6"
+ }
+ },
+ "value": 1
+ }
+ }
+]
+
+# iif "lo" ip6 dscp set af42
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "value": "af42"
+ }
+ }
+]
+
+# iif "lo" ip6 dscp set 63
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "value": 63
+ }
+ }
+]
+
+# iif "lo" ip6 ecn set ect0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "ecn",
+ "protocol": "ip6"
+ }
+ },
+ "value": "ect0"
+ }
+ }
+]
+
+# iif "lo" ip6 ecn set ce
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "ecn",
+ "protocol": "ip6"
+ }
+ },
+ "value": "ce"
+ }
+ }
+]
+
+# iif "lo" ip6 flowlabel set 0
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "flowlabel",
+ "protocol": "ip6"
+ }
+ },
+ "value": 0
+ }
+ }
+]
+
+# iif "lo" ip6 flowlabel set 12345
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "flowlabel",
+ "protocol": "ip6"
+ }
+ },
+ "value": 12345
+ }
+ }
+]
+
+# iif "lo" ip6 flowlabel set 0xfffff
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "flowlabel",
+ "protocol": "ip6"
+ }
+ },
+ "value": "0xfffff"
+ }
+ }
+]
+
diff --git a/tests/py/ip6/ip6.t.json.output b/tests/py/ip6/ip6.t.json.output
new file mode 100644
index 0000000..6c20939
--- /dev/null
+++ b/tests/py/ip6/ip6.t.json.output
@@ -0,0 +1,374 @@
+# ip6 dscp 0x38
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "cs7"
+ }
+ }
+]
+
+# ip6 dscp != 0x20
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": "cs4"
+ }
+ }
+]
+
+# ip6 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",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "cs0",
+ "cs1",
+ "af11",
+ "af12",
+ "af13",
+ "cs2",
+ "af21",
+ "af22",
+ "af23",
+ "cs3",
+ "af31",
+ "af32",
+ "af33",
+ "cs4",
+ "af41",
+ "af42",
+ "af43",
+ "cs5",
+ "ef",
+ "cs6",
+ "cs7"
+ ]
+ }
+ }
+ }
+]
+
+# ip6 dscp vmap { 0x04 : accept, 0x3f : continue } counter
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 4,
+ {
+ "accept": null
+ }
+ ],
+ [
+ 63,
+ {
+ "continue": null
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "counter": null
+ }
+]
+
+# ip6 nexthdr {udp, ah, comp, udplite, tcp, dccp, sctp}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 33,
+ 51,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [ 6, 17, 33, 50, 51, 58, 108, 132, 136 ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [ 6, 17, 33, 50, 51, 58, 108, 132, 136 ]
+ }
+ }
+ }
+]
+
+# ip6 nexthdr esp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": 50
+ }
+ }
+]
+
+# ip6 nexthdr != esp
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": 50
+ }
+ }
+]
+
+# ip6 saddr ::1234:1234:1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "0:1234:1234:1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234::1234:1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:0:1234:1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234::1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:0:1234:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234::1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:0:1234:1234:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:1234::1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:1234:0:1234:1234"
+ }
+ }
+]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:1234::
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "1234:1234:1234:1234:1234:1234:1234:0"
+ }
+ }
+]
+
+# ip6 saddr ::1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "::18.52.18.52"
+ }
+ }
+]
+
+# ip6 daddr != {::1234:1234:1234:1234:1234:1234:1234, 1234:1234::1234:1234:1234:1234:1234 }
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "0:1234:1234:1234:1234:1234:1234:1234",
+ "1234:1234:0:1234:1234:1234:1234:1234"
+ ]
+ }
+ }
+ }
+]
+
+# ip6 daddr != ::1234:1234:1234:1234:1234:1234:1234-1234:1234::1234:1234:1234:1234:1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ "0:1234:1234:1234:1234:1234:1234:1234", "1234:1234:0:1234:1234:1234:1234:1234" ]
+ }
+ }
+ }
+]
+
+# iif "lo" ip6 flowlabel set 0xfffff
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iif" }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "mangle": {
+ "key": {
+ "payload": {
+ "field": "flowlabel",
+ "protocol": "ip6"
+ }
+ },
+ "value": 1048575
+ }
+ }
+]
+
diff --git a/tests/py/ip6/ip6.t.payload.inet b/tests/py/ip6/ip6.t.payload.inet
new file mode 100644
index 0000000..20dfe54
--- /dev/null
+++ b/tests/py/ip6/ip6.t.payload.inet
@@ -0,0 +1,641 @@
+# ip6 dscp cs1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# ip6 dscp != cs1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000002 ]
+
+# ip6 dscp 0x38
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000e ]
+
+# ip6 dscp != 0x20
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000008 ]
+
+# ip6 dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000000 : 0 [end] element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000006 : 0 [end] element 00000008 : 0 [end] element 0000000a : 0 [end] element 0000000c : 0 [end] element 0000000e : 0 [end] element 00008002 : 0 [end] element 00000003 : 0 [end] element 00008003 : 0 [end] element 00008004 : 0 [end] element 00000005 : 0 [end] element 00008005 : 0 [end] element 00008006 : 0 [end] element 00000007 : 0 [end] element 00008007 : 0 [end] element 00008008 : 0 [end] element 00000009 : 0 [end] element 00008009 : 0 [end] element 0000800b : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 dscp vmap { 0x04 : accept, 0x3f : continue } counter
+__map%d test-inet b size 2
+__map%d test-inet 0
+ element 00000001 : accept 0 [end] element 0000c00f : continue 0 [end]
+ip6 test-ip6 input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# ip6 flowlabel 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00160000 ]
+
+# ip6 flowlabel != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00e90000 ]
+
+# ip6 flowlabel { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00210000 : 0 [end] element 00370000 : 0 [end] element 00430000 : 0 [end] element 00580000 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 flowlabel != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00210000 : 0 [end] element 00370000 : 0 [end] element 00430000 : 0 [end] element 00580000 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 flowlabel vmap { 0 : accept, 2 : continue }
+__map%d test-inet b size 2
+__map%d test-inet 0
+ element 00000000 : accept 0 [end] element 00020000 : continue 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 length 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip6 length != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip6 length 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip6 length != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip6 length { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 length != {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 nexthdr {udp, ah, comp, udplite, tcp, dccp, sctp}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000011 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end] element 0000003a : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end] element 0000003a : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 nexthdr esp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+
+# ip6 nexthdr != esp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000032 ]
+
+# ip6 nexthdr 33-44
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002c ]
+
+# ip6 nexthdr != 33-44
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002c ]
+
+# ip6 hoplimit 1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip6 hoplimit != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# ip6 hoplimit 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# ip6 hoplimit != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# ip6 hoplimit {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 hoplimit != {33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34123412 0x34123412 ]
+
+# ip6 saddr ::1234:1234:1234:1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34120000 0x34123412 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234:1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x34123412 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234:1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34120000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234:0:1234:1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34120000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234::1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234:0:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234::1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00003412 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:0:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34123412 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:1234::
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34123412 0x00003412 ]
+
+# ip6 saddr ::1234:1234:1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x34123412 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x34120000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234::1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234::1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234::1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00003412 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234::
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34123412 0x00000000 ]
+
+# ip6 saddr ::1234:1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x34120000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234::1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234::1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234::
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00003412 0x00000000 ]
+
+# ip6 saddr ::1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234::1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234:1234::
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00000000 0x00000000 ]
+
+# ip6 saddr ::1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234::
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x00000000 0x00000000 ]
+
+# ip6 saddr ::1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234::1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234:1234::
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x00000000 0x00000000 ]
+
+# ip6 saddr ::1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234::
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x00000000 0x00000000 ]
+
+# ip6 saddr ::/64
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 8b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 ]
+
+# ip6 saddr ::1 ip6 daddr ::2
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x01000000 ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x02000000 ]
+
+# ip6 daddr != {::1234:1234:1234:1234:1234:1234:1234, 1234:1234::1234:1234:1234:1234:1234 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 34120000 34123412 34123412 34123412 : 0 [end] element 34123412 34120000 34123412 34123412 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 daddr != ::1234:1234:1234:1234:1234:1234:1234-1234:1234::1234:1234:1234:1234:1234
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ range neq reg 1 0x34120000 0x34123412 0x34123412 0x34123412 0x34123412 0x34120000 0x34123412 0x34123412 ]
+
+# iif "lo" ip6 daddr set ::1
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ immediate reg 1 0x00000000 0x00000000 0x00000000 0x01000000 ]
+ [ payload write reg 1 => 16b @ network header + 24 csum_type 0 csum_off 0 csum_flags 0x1 ]
+
+# iif "lo" ip6 hoplimit set 1
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ immediate reg 1 0x00000001 ]
+ [ payload write reg 1 => 1b @ network header + 7 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 dscp set af42
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00003ff0 ) ^ 0x00000009 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 dscp set 63
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00003ff0 ) ^ 0x0000c00f ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 ecn set ect0
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000cf ) ^ 0x00000020 ]
+ [ payload write reg 1 => 1b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 ecn set ce
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000cf ) ^ 0x00000030 ]
+ [ payload write reg 1 => 1b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 flowlabel set 0
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ payload write reg 1 => 3b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 flowlabel set 12345
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00393000 ]
+ [ payload write reg 1 => 3b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 flowlabel set 0xfffff
+inet test-inet input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00ffff0f ]
+ [ payload write reg 1 => 3b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
diff --git a/tests/py/ip6/ip6.t.payload.ip6 b/tests/py/ip6/ip6.t.payload.ip6
new file mode 100644
index 0000000..f8e3ca3
--- /dev/null
+++ b/tests/py/ip6/ip6.t.payload.ip6
@@ -0,0 +1,481 @@
+# ip6 dscp cs1
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000002 ]
+
+# ip6 dscp != cs1
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000002 ]
+
+# ip6 dscp 0x38
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x0000000e ]
+
+# ip6 dscp != 0x20
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000008 ]
+
+# ip6 dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000006 : 0 [end] element 00000008 : 0 [end] element 0000000a : 0 [end] element 0000000c : 0 [end] element 0000000e : 0 [end] element 00000000 : 0 [end] element 00008002 : 0 [end] element 00000003 : 0 [end] element 00008003 : 0 [end] element 00008004 : 0 [end] element 00000005 : 0 [end] element 00008005 : 0 [end] element 00008006 : 0 [end] element 00000007 : 0 [end] element 00008007 : 0 [end] element 00008008 : 0 [end] element 00000009 : 0 [end] element 00008009 : 0 [end] element 0000800b : 0 [end]
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 dscp vmap { 0x04 : accept, 0x3f : continue } counter
+__map%d test-ip6 b size 2
+__map%d test-ip6 0
+ element 00000001 : accept 0 [end] element 0000c00f : continue 0 [end]
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ counter pkts 0 bytes 0 ]
+
+# ip6 flowlabel 22
+ip6 test-ip6 input
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00160000 ]
+
+# ip6 flowlabel != 233
+ip6 test-ip6 input
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00e90000 ]
+
+# ip6 flowlabel { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00210000 : 0 [end] element 00370000 : 0 [end] element 00430000 : 0 [end] element 00580000 : 0 [end]
+ip6 test-ip6 input
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 flowlabel != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00210000 : 0 [end] element 00370000 : 0 [end] element 00430000 : 0 [end] element 00580000 : 0 [end]
+ip6 test-ip6 input
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 flowlabel vmap { 0 : accept, 2 : continue }
+__map%d test-ip6 b size 2
+__map%d test-ip6 0
+ element 00000000 : accept 0 [end] element 00020000 : continue 0 [end]
+ip6 test-ip6 input
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 length 22
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# ip6 length != 233
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# ip6 length 33-45
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# ip6 length != 33-45
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# ip6 length { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 length != {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 nexthdr {udp, ah, comp, udplite, tcp, dccp, sctp}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000011 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end]
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000032 : 0 [end] element 00000033 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000088 : 0 [end] element 00000006 : 0 [end] element 00000021 : 0 [end] element 00000084 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 nexthdr esp
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000032 ]
+
+# ip6 nexthdr != esp
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp neq reg 1 0x00000032 ]
+
+# ip6 nexthdr 33-44
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002c ]
+
+# ip6 nexthdr != 33-44
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002c ]
+
+# ip6 hoplimit 1
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip6 hoplimit != 233
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# ip6 hoplimit 33-45
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# ip6 hoplimit != 33-45
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# ip6 hoplimit {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# ip6 hoplimit != {33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ payload load 1b @ network header + 7 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34123412 0x34123412 ]
+
+# ip6 saddr ::1234:1234:1234:1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34120000 0x34123412 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234:1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x34123412 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234:1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34120000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234:0:1234:1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34120000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234::1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234:0:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234::1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00003412 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:0:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34123412 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234:1234::
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34123412 0x00003412 ]
+
+# ip6 saddr ::1234:1234:1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x34123412 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x34120000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234::1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234::1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234::1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00003412 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234:1234::
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x34123412 0x00000000 ]
+
+# ip6 saddr ::1234:1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x34120000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234::1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234:1234::1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234:1234:1234::
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00003412 0x00000000 ]
+
+# ip6 saddr ::1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x34123412 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234:1234:1234::1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234:1234::
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x34123412 0x00000000 0x00000000 ]
+
+# ip6 saddr ::1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x34120000 0x34123412 ]
+
+# ip6 saddr 1234::1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234:1234::1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234:1234:1234::
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00003412 0x00000000 0x00000000 ]
+
+# ip6 saddr ::1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x34123412 ]
+
+# ip6 saddr 1234::1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234:1234::
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x34123412 0x00000000 0x00000000 0x00000000 ]
+
+# ip6 saddr ::1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x34120000 ]
+
+# ip6 saddr 1234::
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00003412 0x00000000 0x00000000 0x00000000 ]
+
+# ip6 saddr ::/64
+ip6 test-ip6 input
+ [ payload load 8b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 ]
+
+# ip6 saddr ::1 ip6 daddr ::2
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x01000000 ]
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x02000000 ]
+
+# ip6 daddr != {::1234:1234:1234:1234:1234:1234:1234, 1234:1234::1234:1234:1234:1234:1234 }
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 34120000 34123412 34123412 34123412 : 0 [end] element 34123412 34120000 34123412 34123412 : 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# ip6 daddr != ::1234:1234:1234:1234:1234:1234:1234-1234:1234::1234:1234:1234:1234:1234
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ range neq reg 1 0x34120000 0x34123412 0x34123412 0x34123412 0x34123412 0x34120000 0x34123412 0x34123412 ]
+
+# iif "lo" ip6 daddr set ::1
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 1 0x00000000 0x00000000 0x00000000 0x01000000 ]
+ [ payload write reg 1 => 16b @ network header + 24 csum_type 0 csum_off 0 csum_flags 0x1 ]
+
+# iif "lo" ip6 hoplimit set 1
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 1 0x00000001 ]
+ [ payload write reg 1 => 1b @ network header + 7 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 dscp set af42
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00003ff0 ) ^ 0x00000009 ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 dscp set 63
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00003ff0 ) ^ 0x0000c00f ]
+ [ payload write reg 1 => 2b @ network header + 0 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 ecn set ect0
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000cf ) ^ 0x00000020 ]
+ [ payload write reg 1 => 1b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 ecn set ce
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000cf ) ^ 0x00000030 ]
+ [ payload write reg 1 => 1b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 flowlabel set 0
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ payload write reg 1 => 3b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 flowlabel set 12345
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00393000 ]
+ [ payload write reg 1 => 3b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# iif "lo" ip6 flowlabel set 0xfffff
+ip6 test-ip6 input
+ [ meta load iif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 3b @ network header + 1 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00ffff0f ]
+ [ payload write reg 1 => 3b @ network header + 1 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
diff --git a/tests/py/ip6/map.t b/tests/py/ip6/map.t
new file mode 100644
index 0000000..4d06e87
--- /dev/null
+++ b/tests/py/ip6/map.t
@@ -0,0 +1,5 @@
+:input;type filter hook input priority 0
+*ip6;test-ip6;input
+
+mark set ip6 saddr and ::ffff map { ::2 : 0x0000002a, ::ffff : 0x00000017};ok;meta mark set ip6 saddr & ::ffff map { ::2 : 0x0000002a, ::ffff : 0x00000017}
+
diff --git a/tests/py/ip6/map.t.json b/tests/py/ip6/map.t.json
new file mode 100644
index 0000000..78a01c6
--- /dev/null
+++ b/tests/py/ip6/map.t.json
@@ -0,0 +1,38 @@
+# mark set ip6 saddr and ::ffff map { ::2 : 0x0000002a, ::ffff : 0x00000017}
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": {
+ "map": {
+ "key": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "::ffff"
+ ]
+ },
+ "data": {
+ "set": [
+ [
+ "::2",
+ "0x0000002a"
+ ],
+ [
+ "::ffff",
+ "0x00000017"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/map.t.json.output b/tests/py/ip6/map.t.json.output
new file mode 100644
index 0000000..9280d55
--- /dev/null
+++ b/tests/py/ip6/map.t.json.output
@@ -0,0 +1,38 @@
+# mark set ip6 saddr and ::ffff map { ::2 : 0x0000002a, ::ffff : 0x00000017}
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "value": {
+ "map": {
+ "key": {
+ "&": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "::ffff"
+ ]
+ },
+ "data": {
+ "set": [
+ [
+ "::2",
+ 42
+ ],
+ [
+ "::ffff",
+ 23
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/map.t.payload b/tests/py/ip6/map.t.payload
new file mode 100644
index 0000000..8e900c1
--- /dev/null
+++ b/tests/py/ip6/map.t.payload
@@ -0,0 +1,10 @@
+# mark set ip6 saddr and ::ffff map { ::2 : 0x0000002a, ::ffff : 0x00000017}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00000000 00000000 00000000 02000000 : 0000002a 0 [end] element 00000000 00000000 00000000 ffff0000 : 00000017 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000000 0x00000000 0x00000000 0xffff0000 ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
diff --git a/tests/py/ip6/masquerade.t b/tests/py/ip6/masquerade.t
new file mode 100644
index 0000000..4eb0467
--- /dev/null
+++ b/tests/py/ip6/masquerade.t
@@ -0,0 +1,30 @@
+:postrouting;type nat hook postrouting priority 0
+
+*ip6;test-ip6;postrouting
+
+# nf_nat flags combination
+udp dport 53 masquerade;ok
+udp dport 53 masquerade random;ok
+udp dport 53 masquerade random,persistent;ok
+udp dport 53 masquerade random,persistent,fully-random;ok;udp dport 53 masquerade random,fully-random,persistent
+udp dport 53 masquerade random,fully-random;ok
+udp dport 53 masquerade random,fully-random,persistent;ok
+udp dport 53 masquerade persistent;ok
+udp dport 53 masquerade persistent,random;ok;udp dport 53 masquerade random,persistent
+udp dport 53 masquerade persistent,random,fully-random;ok;udp dport 53 masquerade random,fully-random,persistent
+udp dport 53 masquerade persistent,fully-random;ok;udp dport 53 masquerade fully-random,persistent
+udp dport 53 masquerade persistent,fully-random,random;ok;udp dport 53 masquerade random,fully-random,persistent
+
+# using ports
+meta l4proto 6 masquerade to :1024;ok
+meta l4proto 6 masquerade to :1024-2048;ok
+
+# masquerade is a terminal statement
+tcp dport 22 masquerade counter packets 0 bytes 0 accept;fail
+tcp sport 22 masquerade accept;fail
+ip6 saddr ::1 masquerade drop;fail
+
+# masquerade with sets
+tcp dport { 1,2,3,4,5,6,7,8,101,202,303,1001,2002,3003} masquerade;ok
+ip6 daddr fe00::1-fe00::200 udp dport 53 counter masquerade;ok
+iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } masquerade;ok
diff --git a/tests/py/ip6/masquerade.t.json b/tests/py/ip6/masquerade.t.json
new file mode 100644
index 0000000..824b44f
--- /dev/null
+++ b/tests/py/ip6/masquerade.t.json
@@ -0,0 +1,423 @@
+# udp dport 53 masquerade
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": null
+ }
+]
+
+# udp dport 53 masquerade random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": "random"
+ }
+ }
+]
+
+# udp dport 53 masquerade random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade random,fully-random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": "persistent"
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "persistent",
+ "fully-random",
+ "random"
+ ]
+ }
+ }
+]
+
+# meta l4proto 6 masquerade to :1024
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "masquerade": {
+ "port": 1024
+ }
+ }
+]
+
+# meta l4proto 6 masquerade to :1024-2048
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "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",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 101,
+ 202,
+ 303,
+ 1001,
+ 2002,
+ 3003
+ ]
+ }
+ }
+ },
+ {
+ "masquerade": null
+ }
+]
+
+# ip6 daddr fe00::1-fe00::200 udp dport 53 counter masquerade
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ "fe00::1", "fe00::200" ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "masquerade": null
+ }
+]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } masquerade
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "in",
+ "right": [
+ "established",
+ "new"
+ ]
+ }
+ },
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 22,
+ {
+ "drop": null
+ }
+ ],
+ [
+ 222,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "masquerade": null
+ }
+]
+
diff --git a/tests/py/ip6/masquerade.t.json.output b/tests/py/ip6/masquerade.t.json.output
new file mode 100644
index 0000000..31d0cd9
--- /dev/null
+++ b/tests/py/ip6/masquerade.t.json.output
@@ -0,0 +1,98 @@
+# udp dport 53 masquerade persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 masquerade persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "masquerade": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
diff --git a/tests/py/ip6/masquerade.t.payload.ip6 b/tests/py/ip6/masquerade.t.payload.ip6
new file mode 100644
index 0000000..43ae2ae
--- /dev/null
+++ b/tests/py/ip6/masquerade.t.payload.ip6
@@ -0,0 +1,142 @@
+# udp dport 53 masquerade
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq ]
+
+# udp dport 53 masquerade random
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x4 ]
+
+# udp dport 53 masquerade random,persistent
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0xc ]
+
+# udp dport 53 masquerade random,persistent,fully-random
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x1c ]
+
+# udp dport 53 masquerade random,fully-random
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x14 ]
+
+# udp dport 53 masquerade random,fully-random,persistent
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x1c ]
+
+# udp dport 53 masquerade persistent
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x8 ]
+
+# udp dport 53 masquerade persistent,random
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0xc ]
+
+# udp dport 53 masquerade persistent,random,fully-random
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x1c ]
+
+# udp dport 53 masquerade persistent,fully-random
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x18 ]
+
+# udp dport 53 masquerade persistent,fully-random,random
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ masq flags 0x1c ]
+
+# tcp dport { 1,2,3,4,5,6,7,8,101,202,303,1001,2002,3003} masquerade
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000100 : 0 [end] element 00000200 : 0 [end] element 00000300 : 0 [end] element 00000400 : 0 [end] element 00000500 : 0 [end] element 00000600 : 0 [end] element 00000700 : 0 [end] element 00000800 : 0 [end] element 00006500 : 0 [end] element 0000ca00 : 0 [end] element 00002f01 : 0 [end] element 0000e903 : 0 [end] element 0000d207 : 0 [end] element 0000bb0b : 0 [end]
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ masq ]
+
+# ip6 daddr fe00::1-fe00::200 udp dport 53 counter masquerade
+ip6 test-ip6 postrouting
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ cmp gte reg 1 0x000000fe 0x00000000 0x00000000 0x01000000 ]
+ [ cmp lte reg 1 0x000000fe 0x00000000 0x00000000 0x00020000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ counter pkts 0 bytes 0 ]
+ [ masq ]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } masquerade
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00001600 : drop 0 [end] element 0000de00 : drop 0 [end]
+ip6 test-ip6 postrouting
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ ct load state => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000a ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ masq ]
+
+# meta l4proto 6 masquerade to :1024
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x00000004 ]
+ [ masq proto_min reg 1 flags 0x2 ]
+
+# meta l4proto 6 masquerade to :1024-2048
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x00000004 ]
+ [ immediate reg 2 0x00000008 ]
+ [ masq proto_min reg 1 proto_max reg 2 flags 0x2 ]
+
diff --git a/tests/py/ip6/meta.t b/tests/py/ip6/meta.t
new file mode 100644
index 0000000..c177b08
--- /dev/null
+++ b/tests/py/ip6/meta.t
@@ -0,0 +1,19 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+
+icmpv6 type nd-router-advert;ok
+meta l4proto ipv6-icmp icmpv6 type nd-router-advert;ok;icmpv6 type nd-router-advert
+
+meta l4proto icmp icmp type echo-request;ok;icmp type echo-request
+meta l4proto 1 icmp type echo-request;ok;icmp type echo-request
+icmp type echo-request;ok
+
+meta protocol ip udp dport 67;ok
+meta protocol ip6 udp dport 67;ok;udp dport 67
+
+meta sdif "lo" accept;ok
+meta sdifname != "vrf1" accept;ok
+
+meta mark set ip6 dscp << 2 | 0x10;ok
+meta mark set ip6 dscp << 26 | 0x10;ok
diff --git a/tests/py/ip6/meta.t.json b/tests/py/ip6/meta.t.json
new file mode 100644
index 0000000..1a2394d
--- /dev/null
+++ b/tests/py/ip6/meta.t.json
@@ -0,0 +1,313 @@
+# icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# meta l4proto ipv6-icmp icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": "ipv6-icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# meta l4proto icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": "icmp"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta l4proto 1 icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "l4proto" }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta sdif "lo" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "sdif"
+ }
+ },
+ "op": "==",
+ "right": "lo"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta sdifname != "vrf1" accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "sdifname"
+ }
+ },
+ "op": "!=",
+ "right": "vrf1"
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# meta protocol ip udp dport 67
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 67
+ }
+ }
+]
+
+# meta protocol ip6 udp dport 67
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip6"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 67
+ }
+ }
+]
+
+# meta mark set ip6 dscp lshift 2 or 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 2
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# meta mark set ip6 dscp lshift 26 or 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 26
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# meta mark set ip6 dscp << 2 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 2
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
+# meta mark set ip6 dscp << 26 | 0x10
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "|": [
+ {
+ "<<": [
+ {
+ "payload": {
+ "field": "dscp",
+ "protocol": "ip6"
+ }
+ },
+ 26
+ ]
+ },
+ 16
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/meta.t.json.output b/tests/py/ip6/meta.t.json.output
new file mode 100644
index 0000000..61adf18
--- /dev/null
+++ b/tests/py/ip6/meta.t.json.output
@@ -0,0 +1,64 @@
+# meta l4proto ipv6-icmp icmpv6 type nd-router-advert
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "nd-router-advert"
+ }
+ }
+]
+
+# meta l4proto icmp icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta l4proto 1 icmp type echo-request
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "echo-request"
+ }
+ }
+]
+
+# meta protocol ip6 udp dport 67
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 67
+ }
+ }
+]
+
diff --git a/tests/py/ip6/meta.t.payload b/tests/py/ip6/meta.t.payload
new file mode 100644
index 0000000..6a37f1d
--- /dev/null
+++ b/tests/py/ip6/meta.t.payload
@@ -0,0 +1,82 @@
+# icmpv6 type nd-router-advert
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000086 ]
+
+# meta l4proto ipv6-icmp icmpv6 type nd-router-advert
+ip test-ip4 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000086 ]
+
+# meta l4proto icmp icmp type echo-request
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# meta l4proto 1 icmp type echo-request
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# icmp type echo-request
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+
+# meta sdif "lo" accept
+ip6 test-ip6 input
+ [ meta load sdif => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ immediate reg 0 accept ]
+
+# meta sdifname != "vrf1" accept
+ip6 test-ip6 input
+ [ meta load sdifname => reg 1 ]
+ [ cmp neq reg 1 0x31667276 0x00000000 0x00000000 0x00000000 ]
+ [ immediate reg 0 accept ]
+
+# meta protocol ip udp dport 67
+ip6 test-ip6 input
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00004300 ]
+
+# meta protocol ip6 udp dport 67
+ip6 test-ip6 input
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00004300 ]
+
+# meta mark set ip6 dscp << 2 | 0x10
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ bitwise reg 1 = ( reg 1 << 0x00000002 ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ip6 dscp << 26 | 0x10
+ip6 test-ip6 input
+ [ payload load 2b @ network header + 0 => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+ [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+ [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+ [ bitwise reg 1 = ( reg 1 << 0x0000001a ) ]
+ [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+ [ meta set mark with reg 1 ]
diff --git a/tests/py/ip6/mh.t b/tests/py/ip6/mh.t
new file mode 100644
index 0000000..46f4ba0
--- /dev/null
+++ b/tests/py/ip6/mh.t
@@ -0,0 +1,42 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+*inet;test-inet;input
+
+mh nexthdr 1;ok
+mh nexthdr != 1;ok
+mh nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp };ok;mh nexthdr { 58, 17, 108, 6, 51, 136, 50, 132, 33}
+mh nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp };ok;mh nexthdr != { 58, 17, 108, 6, 51, 136, 50, 132, 33}
+mh nexthdr icmp;ok;mh nexthdr 1
+mh nexthdr != icmp;ok;mh nexthdr != 1
+mh nexthdr 22;ok
+mh nexthdr != 233;ok
+mh nexthdr 33-45;ok
+mh nexthdr != 33-45;ok
+mh nexthdr { 33, 55, 67, 88 };ok
+mh nexthdr != { 33, 55, 67, 88 };ok
+
+mh hdrlength 22;ok
+mh hdrlength != 233;ok
+mh hdrlength 33-45;ok
+mh hdrlength != 33-45;ok
+mh hdrlength { 33, 55, 67, 88 };ok
+mh hdrlength != { 33, 55, 67, 88 };ok
+
+mh type {binding-refresh-request, home-test-init, careof-test-init, home-test, careof-test, binding-update, binding-acknowledgement, binding-error, fast-binding-update, fast-binding-acknowledgement, fast-binding-advertisement, experimental-mobility-header, home-agent-switch-message};ok
+mh type home-agent-switch-message;ok
+mh type != home-agent-switch-message;ok
+
+mh reserved 22;ok
+mh reserved != 233;ok
+mh reserved 33-45;ok
+mh reserved != 33-45;ok
+mh reserved { 33, 55, 67, 88};ok
+mh reserved != { 33, 55, 67, 88};ok
+
+mh checksum 22;ok
+mh checksum != 233;ok
+mh checksum 33-45;ok
+mh checksum != 33-45;ok
+mh checksum { 33, 55, 67, 88};ok
+mh checksum != { 33, 55, 67, 88};ok
diff --git a/tests/py/ip6/mh.t.json b/tests/py/ip6/mh.t.json
new file mode 100644
index 0000000..3159b14
--- /dev/null
+++ b/tests/py/ip6/mh.t.json
@@ -0,0 +1,640 @@
+# mh nexthdr 1
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# mh nexthdr != 1
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# mh nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "udplite",
+ "ipcomp",
+ "udp",
+ "ah",
+ "sctp",
+ "esp",
+ "dccp",
+ "tcp",
+ "ipv6-icmp"
+ ]
+ }
+ }
+ }
+]
+
+# mh nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "udplite",
+ "ipcomp",
+ "udp",
+ "ah",
+ "sctp",
+ "esp",
+ "dccp",
+ "tcp",
+ "ipv6-icmp"
+ ]
+ }
+ }
+ }
+]
+
+# mh nexthdr icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": "icmp"
+ }
+ }
+]
+
+# mh nexthdr != icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": "icmp"
+ }
+ }
+]
+
+# mh nexthdr 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# mh nexthdr != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# mh nexthdr 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# mh nexthdr != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# mh nexthdr { 33, 55, 67, 88 }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# mh nexthdr != { 33, 55, 67, 88 }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# mh hdrlength 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# mh hdrlength != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# mh hdrlength 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# mh hdrlength != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# mh hdrlength { 33, 55, 67, 88 }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# mh hdrlength != { 33, 55, 67, 88 }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# mh type {binding-refresh-request, home-test-init, careof-test-init, home-test, careof-test, binding-update, binding-acknowledgement, binding-error, fast-binding-update, fast-binding-acknowledgement, fast-binding-advertisement, experimental-mobility-header, home-agent-switch-message}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "type",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "binding-refresh-request",
+ "home-test-init",
+ "careof-test-init",
+ "home-test",
+ "careof-test",
+ "binding-update",
+ "binding-acknowledgement",
+ "binding-error",
+ "fast-binding-update",
+ "fast-binding-acknowledgement",
+ "fast-binding-advertisement",
+ "experimental-mobility-header",
+ "home-agent-switch-message"
+ ]
+ }
+ }
+ }
+]
+
+# mh type home-agent-switch-message
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "type",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": "home-agent-switch-message"
+ }
+ }
+]
+
+# mh type != home-agent-switch-message
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "type",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": "home-agent-switch-message"
+ }
+ }
+]
+
+# mh reserved 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# mh reserved != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# mh reserved 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# mh reserved != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# mh reserved { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# mh reserved != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "reserved",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# mh checksum 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "checksum",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# mh checksum != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "checksum",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# mh checksum 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "checksum",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# mh checksum != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "checksum",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# mh checksum { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "checksum",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# mh checksum != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "checksum",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/mh.t.json.output b/tests/py/ip6/mh.t.json.output
new file mode 100644
index 0000000..a851804
--- /dev/null
+++ b/tests/py/ip6/mh.t.json.output
@@ -0,0 +1,88 @@
+# mh nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 58,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# mh nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 58,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# mh nexthdr icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# mh nexthdr != icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "mh"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
diff --git a/tests/py/ip6/mh.t.payload.inet b/tests/py/ip6/mh.t.payload.inet
new file mode 100644
index 0000000..54eaa70
--- /dev/null
+++ b/tests/py/ip6/mh.t.payload.inet
@@ -0,0 +1,267 @@
+# mh nexthdr 1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# mh nexthdr != 1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# mh nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# mh nexthdr icmp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# mh nexthdr != icmp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# mh nexthdr 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# mh nexthdr != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# mh nexthdr 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# mh nexthdr != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# mh nexthdr { 33, 55, 67, 88 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh nexthdr != { 33, 55, 67, 88 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# mh hdrlength 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# mh hdrlength != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# mh hdrlength 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# mh hdrlength != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# mh hdrlength { 33, 55, 67, 88 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh hdrlength != { 33, 55, 67, 88 }
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# mh type {binding-refresh-request, home-test-init, careof-test-init, home-test, careof-test, binding-update, binding-acknowledgement, binding-error, fast-binding-update, fast-binding-acknowledgement, fast-binding-advertisement, experimental-mobility-header, home-agent-switch-message}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000000 : 0 [end] element 00000001 : 0 [end] element 00000002 : 0 [end] element 00000003 : 0 [end] element 00000004 : 0 [end] element 00000005 : 0 [end] element 00000006 : 0 [end] element 00000007 : 0 [end] element 00000008 : 0 [end] element 00000009 : 0 [end] element 0000000a : 0 [end] element 0000000b : 0 [end] element 0000000c : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh type home-agent-switch-message
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000000c ]
+
+# mh type != home-agent-switch-message
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000000c ]
+
+# mh reserved 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# mh reserved != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# mh reserved 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# mh reserved != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# mh reserved { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh reserved != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# mh checksum 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# mh checksum != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# mh checksum 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# mh checksum != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# mh checksum { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh checksum != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
diff --git a/tests/py/ip6/mh.t.payload.ip6 b/tests/py/ip6/mh.t.payload.ip6
new file mode 100644
index 0000000..73bd422
--- /dev/null
+++ b/tests/py/ip6/mh.t.payload.ip6
@@ -0,0 +1,201 @@
+# mh nexthdr 1
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# mh nexthdr != 1
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# mh nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh nexthdr != { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# mh nexthdr icmp
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# mh nexthdr != icmp
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# mh nexthdr 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# mh nexthdr != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# mh nexthdr 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# mh nexthdr != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# mh nexthdr { 33, 55, 67, 88 }
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh nexthdr != { 33, 55, 67, 88 }
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# mh hdrlength 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# mh hdrlength != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# mh hdrlength 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# mh hdrlength != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# mh hdrlength { 33, 55, 67, 88 }
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh hdrlength != { 33, 55, 67, 88 }
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# mh type {binding-refresh-request, home-test-init, careof-test-init, home-test, careof-test, binding-update, binding-acknowledgement, binding-error, fast-binding-update, fast-binding-acknowledgement, fast-binding-advertisement, experimental-mobility-header, home-agent-switch-message}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000000 : 0 [end] element 00000001 : 0 [end] element 00000002 : 0 [end] element 00000003 : 0 [end] element 00000004 : 0 [end] element 00000005 : 0 [end] element 00000006 : 0 [end] element 00000007 : 0 [end] element 00000008 : 0 [end] element 00000009 : 0 [end] element 0000000a : 0 [end] element 0000000b : 0 [end] element 0000000c : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh type home-agent-switch-message
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000000c ]
+
+# mh type != home-agent-switch-message
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 2 => reg 1 ]
+ [ cmp neq reg 1 0x0000000c ]
+
+# mh reserved 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# mh reserved != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# mh reserved 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# mh reserved != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# mh reserved { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh reserved != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 135 + 3 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# mh checksum 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00001600 ]
+
+# mh checksum != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ cmp neq reg 1 0x0000e900 ]
+
+# mh checksum 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ cmp gte reg 1 0x00002100 ]
+ [ cmp lte reg 1 0x00002d00 ]
+
+# mh checksum != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ range neq reg 1 0x00002100 0x00002d00 ]
+
+# mh checksum { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# mh checksum != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 2b @ 135 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
diff --git a/tests/py/ip6/redirect.t b/tests/py/ip6/redirect.t
new file mode 100644
index 0000000..70ef7f9
--- /dev/null
+++ b/tests/py/ip6/redirect.t
@@ -0,0 +1,49 @@
+:output;type nat hook output priority 0
+
+*ip6;test-ip6;output
+
+# with no arguments
+redirect;ok
+udp dport 954 redirect;ok
+ip6 saddr fe00::cafe counter redirect;ok
+
+# nf_nat flags combination
+udp dport 53 redirect random;ok
+udp dport 53 redirect random,persistent;ok
+udp dport 53 redirect random,persistent,fully-random;ok;udp dport 53 redirect random,fully-random,persistent
+udp dport 53 redirect random,fully-random;ok
+udp dport 53 redirect random,fully-random,persistent;ok
+udp dport 53 redirect persistent;ok
+udp dport 53 redirect persistent,random;ok;udp dport 53 redirect random,persistent
+udp dport 53 redirect persistent,random,fully-random;ok;udp dport 53 redirect random,fully-random,persistent
+udp dport 53 redirect persistent,fully-random;ok;udp dport 53 redirect fully-random,persistent
+udp dport 53 redirect persistent,fully-random,random;ok;udp dport 53 redirect random,fully-random,persistent
+
+# port specification
+udp dport 1234 redirect to :1234;ok
+ip6 daddr fe00::cafe udp dport 9998 redirect to :6515;ok
+ip6 nexthdr tcp redirect to :100-200;ok;ip6 nexthdr 6 redirect to :100-200
+tcp dport 39128 redirect to :993;ok
+redirect to :1234;fail
+redirect to :12341111;fail
+
+# both port and nf_nat flags
+tcp dport 9128 redirect to :993 random;ok
+tcp dport 9128 redirect to :993 fully-random,persistent;ok
+
+# nf_nat flags are the last argument
+tcp dport 9128 redirect persistent to 123;fail
+tcp dport 9128 redirect random,persistent to 123;fail
+
+# redirect is a terminal statement
+tcp dport 22 redirect counter packets 0 bytes 0 accept;fail
+tcp sport 22 redirect accept;fail
+ip6 saddr ::1 redirect drop;fail
+
+# redirect with sets
+tcp dport { 1, 2, 3, 4, 5, 6, 7, 8, 101, 202, 303, 1001, 2002, 3003} redirect;ok
+ip6 daddr fe00::1-fe00::200 udp dport 53 counter redirect;ok
+iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } redirect;ok
+
+# redirect with maps
+redirect to :tcp dport map { 22 : 8000, 80 : 8080};ok
diff --git a/tests/py/ip6/redirect.t.json b/tests/py/ip6/redirect.t.json
new file mode 100644
index 0000000..c18223f
--- /dev/null
+++ b/tests/py/ip6/redirect.t.json
@@ -0,0 +1,589 @@
+# redirect
+[
+ {
+ "redirect": null
+ }
+]
+
+# udp dport 954 redirect
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 954
+ }
+ },
+ {
+ "redirect": null
+ }
+]
+
+# ip6 saddr fe00::cafe counter redirect
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "fe00::cafe"
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "redirect": null
+ }
+]
+
+# udp dport 53 redirect random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": "random"
+ }
+ }
+]
+
+# udp dport 53 redirect random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect random,fully-random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": "persistent"
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "random",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "fully-random"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "persistent",
+ "fully-random",
+ "random"
+ ]
+ }
+ }
+]
+
+# udp dport 1234 redirect to :1234
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 1234
+ }
+ },
+ {
+ "redirect": {
+ "port": 1234
+ }
+ }
+]
+
+# ip6 daddr fe00::cafe udp dport 9998 redirect to :6515
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "fe00::cafe"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 9998
+ }
+ },
+ {
+ "redirect": {
+ "port": 6515
+ }
+ }
+]
+
+# ip6 nexthdr tcp redirect to :100-200
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "tcp"
+ }
+ },
+ {
+ "redirect": {
+ "port": {
+ "range": [ 100, 200 ]
+ }
+ }
+ }
+]
+
+# tcp dport 39128 redirect to :993
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 39128
+ }
+ },
+ {
+ "redirect": {
+ "port": 993
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :993 random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 9128
+ }
+ },
+ {
+ "redirect": {
+ "flags": "random",
+ "port": 993
+ }
+ }
+]
+
+# tcp dport 9128 redirect to :993 fully-random,persistent
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": 9128
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "fully-random",
+ "persistent"
+ ],
+ "port": 993
+ }
+ }
+]
+
+# tcp dport { 1, 2, 3, 4, 5, 6, 7, 8, 101, 202, 303, 1001, 2002, 3003} redirect
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 101,
+ 202,
+ 303,
+ 1001,
+ 2002,
+ 3003
+ ]
+ }
+ }
+ },
+ {
+ "redirect": null
+ }
+]
+
+# ip6 daddr fe00::1-fe00::200 udp dport 53 counter redirect
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ "fe00::1", "fe00::200" ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "counter": null
+ },
+ {
+ "redirect": null
+ }
+]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } redirect
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "iifname" }
+ },
+ "op": "==",
+ "right": "eth0"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "state"
+ }
+ },
+ "op": "in",
+ "right": [
+ "established",
+ "new"
+ ]
+ }
+ },
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 22,
+ {
+ "drop": null
+ }
+ ],
+ [
+ 222,
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ "redirect": null
+ }
+]
+
+# redirect to :tcp dport map { 22 : 8000, 80 : 8080}
+[
+ {
+ "redirect": {
+ "port": {
+ "map": {
+ "key": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ 22,
+ 8000
+ ],
+ [
+ 80,
+ 8080
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/redirect.t.json.output b/tests/py/ip6/redirect.t.json.output
new file mode 100644
index 0000000..0174cc7
--- /dev/null
+++ b/tests/py/ip6/redirect.t.json.output
@@ -0,0 +1,146 @@
+# udp dport 53 redirect random,persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,random,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# udp dport 53 redirect persistent,fully-random,random
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "udp"
+ }
+ },
+ "op": "==",
+ "right": 53
+ }
+ },
+ {
+ "redirect": {
+ "flags": [
+ "random",
+ "fully-random",
+ "persistent"
+ ]
+ }
+ }
+]
+
+# ip6 nexthdr tcp redirect to :100-200
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "nexthdr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "redirect": {
+ "port": {
+ "range": [ 100, 200 ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/redirect.t.payload.ip6 b/tests/py/ip6/redirect.t.payload.ip6
new file mode 100644
index 0000000..cfc2901
--- /dev/null
+++ b/tests/py/ip6/redirect.t.payload.ip6
@@ -0,0 +1,204 @@
+# redirect
+ip6 test-ip6 output
+ [ redir ]
+
+# udp dport 954 redirect
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000ba03 ]
+ [ redir ]
+
+# ip6 saddr fe00::cafe counter redirect
+ip6 test-ip6 output
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0x000000fe 0x00000000 0x00000000 0xfeca0000 ]
+ [ counter pkts 0 bytes 0 ]
+ [ redir ]
+
+# udp dport 53 redirect random
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x4 ]
+
+# udp dport 53 redirect random,persistent
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0xc ]
+
+# udp dport 53 redirect random,persistent,fully-random
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x1c ]
+
+# udp dport 53 redirect random,fully-random
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x14 ]
+
+# udp dport 53 redirect random,fully-random,persistent
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x1c ]
+
+# udp dport 53 redirect persistent
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x8 ]
+
+# udp dport 53 redirect persistent,random
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0xc ]
+
+# udp dport 53 redirect persistent,random,fully-random
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x1c ]
+
+# udp dport 53 redirect persistent,fully-random
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x18 ]
+
+# udp dport 53 redirect persistent,fully-random,random
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ redir flags 0x1c ]
+
+# udp dport 1234 redirect to :1234
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000d204 ]
+ [ immediate reg 1 0x0000d204 ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
+# ip6 daddr fe00::cafe udp dport 9998 redirect to :6515
+ip6 test-ip6 output
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x000000fe 0x00000000 0x00000000 0xfeca0000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000e27 ]
+ [ immediate reg 1 0x00007319 ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
+# ip6 nexthdr tcp redirect to :100-200
+ip6 test-ip6 output
+ [ payload load 1b @ network header + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x00006400 ]
+ [ immediate reg 2 0x0000c800 ]
+ [ redir proto_min reg 1 proto_max reg 2 flags 0x2 ]
+
+# tcp dport 39128 redirect to :993
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000d898 ]
+ [ immediate reg 1 0x0000e103 ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
+# tcp dport 9128 redirect to :993 random
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000a823 ]
+ [ immediate reg 1 0x0000e103 ]
+ [ redir proto_min reg 1 flags 0x6 ]
+
+# tcp dport 9128 redirect to :993 fully-random,persistent
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x0000a823 ]
+ [ immediate reg 1 0x0000e103 ]
+ [ redir proto_min reg 1 flags 0x1a ]
+
+# tcp dport { 1, 2, 3, 4, 5, 6, 7, 8, 101, 202, 303, 1001, 2002, 3003} redirect
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000100 : 0 [end] element 00000200 : 0 [end] element 00000300 : 0 [end] element 00000400 : 0 [end] element 00000500 : 0 [end] element 00000600 : 0 [end] element 00000700 : 0 [end] element 00000800 : 0 [end] element 00006500 : 0 [end] element 0000ca00 : 0 [end] element 00002f01 : 0 [end] element 0000e903 : 0 [end] element 0000d207 : 0 [end] element 0000bb0b : 0 [end]
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ redir ]
+
+# ip6 daddr fe00::1-fe00::200 udp dport 53 counter redirect
+ip6 test-ip6 output
+ [ payload load 16b @ network header + 24 => reg 1 ]
+ [ cmp gte reg 1 0x000000fe 0x00000000 0x00000000 0x01000000 ]
+ [ cmp lte reg 1 0x000000fe 0x00000000 0x00000000 0x00020000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00003500 ]
+ [ counter pkts 0 bytes 0 ]
+ [ redir ]
+
+# iifname "eth0" ct state established,new tcp dport vmap {22 : drop, 222 : drop } redirect
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00001600 : drop 0 [end] element 0000de00 : drop 0 [end]
+ip6 test-ip6 output
+ [ meta load iifname => reg 1 ]
+ [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+ [ ct load state => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x0000000a ) ^ 0x00000000 ]
+ [ cmp neq reg 1 0x00000000 ]
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+ [ redir ]
+
+# redirect to :tcp dport map { 22 : 8000, 80 : 8080}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00001600 : 0000401f 0 [end] element 00005000 : 0000901f 0 [end]
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ redir proto_min reg 1 flags 0x2 ]
+
diff --git a/tests/py/ip6/reject.t b/tests/py/ip6/reject.t
new file mode 100644
index 0000000..bfdd094
--- /dev/null
+++ b/tests/py/ip6/reject.t
@@ -0,0 +1,16 @@
+:output;type filter hook output priority 0
+
+*ip6;test-ip6;output
+
+reject;ok
+reject with icmpv6 no-route;ok
+reject with icmpv6 admin-prohibited;ok
+reject with icmpv6 addr-unreachable;ok
+reject with icmpv6 port-unreachable;ok;reject
+reject with icmpv6 policy-fail;ok
+reject with icmpv6 reject-route;ok
+reject with icmpv6 3;ok;reject with icmpv6 addr-unreachable
+mark 0x80000000 reject with tcp reset;ok;meta mark 0x80000000 reject with tcp reset
+
+reject with icmpv6 host-unreachable;fail
+reject with icmp host-unreachable;fail
diff --git a/tests/py/ip6/reject.t.json b/tests/py/ip6/reject.t.json
new file mode 100644
index 0000000..312a7da
--- /dev/null
+++ b/tests/py/ip6/reject.t.json
@@ -0,0 +1,95 @@
+# reject
+[
+ {
+ "reject": null
+ }
+]
+
+# reject with icmpv6 no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 addr-unreachable
+[
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 policy-fail
+[
+ {
+ "reject": {
+ "expr": "policy-fail",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 reject-route
+[
+ {
+ "reject": {
+ "expr": "reject-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 3
+[
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# mark 0x80000000 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": "0x80000000"
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
diff --git a/tests/py/ip6/reject.t.json.output b/tests/py/ip6/reject.t.json.output
new file mode 100644
index 0000000..04f12f5
--- /dev/null
+++ b/tests/py/ip6/reject.t.json.output
@@ -0,0 +1,28 @@
+# reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# mark 0x80000000 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": { "key": "mark" }
+ },
+ "op": "==",
+ "right": 2147483648
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
diff --git a/tests/py/ip6/reject.t.payload.ip6 b/tests/py/ip6/reject.t.payload.ip6
new file mode 100644
index 0000000..3d4321b
--- /dev/null
+++ b/tests/py/ip6/reject.t.payload.ip6
@@ -0,0 +1,40 @@
+# reject
+ip6 test-ip6 output
+ [ reject type 0 code 4 ]
+
+# reject with icmpv6 no-route
+ip6 test-ip6 output
+ [ reject type 0 code 0 ]
+
+# reject with icmpv6 admin-prohibited
+ip6 test-ip6 output
+ [ reject type 0 code 1 ]
+
+# reject with icmpv6 addr-unreachable
+ip6 test-ip6 output
+ [ reject type 0 code 3 ]
+
+# reject with icmpv6 port-unreachable
+ip6 test-ip6 output
+ [ reject type 0 code 4 ]
+
+# reject with icmpv6 policy-fail
+ip6 test-ip6 output
+ [ reject type 0 code 5 ]
+
+# reject with icmpv6 reject-route
+ip6 test-ip6 output
+ [ reject type 0 code 6 ]
+
+# reject with icmpv6 3
+ip6 test-ip6 output
+ [ reject type 0 code 3 ]
+
+# mark 0x80000000 reject with tcp reset
+ip6 test-ip6 output
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x80000000 ]
+ [ reject type 1 code 0 ]
+
diff --git a/tests/py/ip6/rt.t b/tests/py/ip6/rt.t
new file mode 100644
index 0000000..c33d38a
--- /dev/null
+++ b/tests/py/ip6/rt.t
@@ -0,0 +1,38 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+*inet;test-inet;input
+
+rt nexthdr 1;ok
+rt nexthdr != 1;ok
+rt nexthdr {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp};ok;rt nexthdr { 33, 136, 50, 132, 51, 17, 108, 6, 58}
+rt nexthdr != {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp};ok;rt nexthdr != { 33, 136, 50, 132, 51, 17, 108, 6, 58}
+rt nexthdr icmp;ok;rt nexthdr 1
+rt nexthdr != icmp;ok;rt nexthdr != 1
+rt nexthdr 22;ok
+rt nexthdr != 233;ok
+rt nexthdr 33-45;ok
+rt nexthdr != 33-45;ok
+rt nexthdr { 33, 55, 67, 88};ok
+rt nexthdr != { 33, 55, 67, 88};ok
+
+rt hdrlength 22;ok
+rt hdrlength != 233;ok
+rt hdrlength 33-45;ok
+rt hdrlength != 33-45;ok
+rt hdrlength { 33, 55, 67, 88};ok
+rt hdrlength != { 33, 55, 67, 88};ok
+
+rt type 22;ok
+rt type != 233;ok
+rt type 33-45;ok
+rt type != 33-45;ok
+rt type { 33, 55, 67, 88};ok
+rt type != { 33, 55, 67, 88};ok
+
+rt seg-left 22;ok
+rt seg-left != 233;ok
+rt seg-left 33-45;ok
+rt seg-left != 33-45;ok
+rt seg-left { 33, 55, 67, 88};ok
+rt seg-left != { 33, 55, 67, 88};ok
diff --git a/tests/py/ip6/rt.t.json b/tests/py/ip6/rt.t.json
new file mode 100644
index 0000000..b12873d
--- /dev/null
+++ b/tests/py/ip6/rt.t.json
@@ -0,0 +1,576 @@
+# rt nexthdr 1
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# rt nexthdr != 1
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
+# rt nexthdr {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "udplite",
+ "ipcomp",
+ "udp",
+ "ah",
+ "sctp",
+ "esp",
+ "dccp",
+ "tcp",
+ "ipv6-icmp"
+ ]
+ }
+ }
+ }
+]
+
+# rt nexthdr != {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "udplite",
+ "ipcomp",
+ "udp",
+ "ah",
+ "sctp",
+ "esp",
+ "dccp",
+ "tcp",
+ "ipv6-icmp"
+ ]
+ }
+ }
+ }
+]
+
+# rt nexthdr icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": "icmp"
+ }
+ }
+]
+
+# rt nexthdr != icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": "icmp"
+ }
+ }
+]
+
+# rt nexthdr 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# rt nexthdr != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# rt nexthdr 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# rt nexthdr != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# rt nexthdr { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# rt nexthdr != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# rt hdrlength 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# rt hdrlength != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# rt hdrlength 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# rt hdrlength != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# rt hdrlength { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# rt hdrlength != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "hdrlength",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# rt type 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "type",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# rt type != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "type",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# rt type 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "type",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# rt type != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "type",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# rt type { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "type",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# rt type != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "type",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# rt seg-left 22
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "seg-left",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
+ }
+]
+
+# rt seg-left != 233
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "seg-left",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
+ }
+]
+
+# rt seg-left 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "seg-left",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# rt seg-left != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "seg-left",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [ 33, 45 ]
+ }
+ }
+ }
+]
+
+# rt seg-left { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "seg-left",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# rt seg-left != { 33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "seg-left",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/rt.t.json.output b/tests/py/ip6/rt.t.json.output
new file mode 100644
index 0000000..be5db0e
--- /dev/null
+++ b/tests/py/ip6/rt.t.json.output
@@ -0,0 +1,88 @@
+# rt nexthdr {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 58,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# rt nexthdr != {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 6,
+ 17,
+ 33,
+ 50,
+ 51,
+ 58,
+ 108,
+ 132,
+ 136
+ ]
+ }
+ }
+ }
+]
+
+# rt nexthdr icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ }
+]
+
+# rt nexthdr != icmp
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "nexthdr",
+ "name": "rt"
+ }
+ },
+ "op": "!=",
+ "right": 1
+ }
+ }
+]
+
diff --git a/tests/py/ip6/rt.t.payload.inet b/tests/py/ip6/rt.t.payload.inet
new file mode 100644
index 0000000..864d311
--- /dev/null
+++ b/tests/py/ip6/rt.t.payload.inet
@@ -0,0 +1,244 @@
+# rt nexthdr 1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# rt nexthdr != 1
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# rt nexthdr {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt nexthdr != {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# rt nexthdr icmp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# rt nexthdr != icmp
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# rt nexthdr 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# rt nexthdr != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# rt nexthdr 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# rt nexthdr != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# rt nexthdr { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt nexthdr != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# rt hdrlength 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# rt hdrlength != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# rt hdrlength 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# rt hdrlength != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# rt hdrlength { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt hdrlength != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# rt type 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# rt type != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# rt type 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# rt type != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# rt type { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt type != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# rt seg-left 22
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# rt seg-left != 233
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# rt seg-left 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# rt seg-left != 33-45
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# rt seg-left { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt seg-left != { 33, 55, 67, 88}
+__set%d test-inet 3
+__set%d test-inet 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
diff --git a/tests/py/ip6/rt.t.payload.ip6 b/tests/py/ip6/rt.t.payload.ip6
new file mode 100644
index 0000000..c7b52f8
--- /dev/null
+++ b/tests/py/ip6/rt.t.payload.ip6
@@ -0,0 +1,184 @@
+# rt nexthdr 1
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# rt nexthdr != 1
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# rt nexthdr {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt nexthdr != {udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000088 : 0 [end] element 0000006c : 0 [end] element 00000011 : 0 [end] element 00000033 : 0 [end] element 00000084 : 0 [end] element 00000032 : 0 [end] element 00000021 : 0 [end] element 00000006 : 0 [end] element 0000003a : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# rt nexthdr icmp
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# rt nexthdr != icmp
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x00000001 ]
+
+# rt nexthdr 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# rt nexthdr != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# rt nexthdr 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# rt nexthdr != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# rt nexthdr { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt nexthdr != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# rt hdrlength 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# rt hdrlength != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# rt hdrlength 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# rt hdrlength != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# rt hdrlength { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt hdrlength != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 1 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# rt type 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# rt type != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# rt type 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# rt type != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# rt type { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt type != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 2 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
+# rt seg-left 22
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ cmp eq reg 1 0x00000016 ]
+
+# rt seg-left != 233
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ cmp neq reg 1 0x000000e9 ]
+
+# rt seg-left 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ cmp gte reg 1 0x00000021 ]
+ [ cmp lte reg 1 0x0000002d ]
+
+# rt seg-left != 33-45
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ range neq reg 1 0x00000021 0x0000002d ]
+
+# rt seg-left { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# rt seg-left != { 33, 55, 67, 88}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000021 : 0 [end] element 00000037 : 0 [end] element 00000043 : 0 [end] element 00000058 : 0 [end]
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 3 => reg 1 ]
+ [ lookup reg 1 set __set%d 0x1 ]
+
diff --git a/tests/py/ip6/rt0.t b/tests/py/ip6/rt0.t
new file mode 100644
index 0000000..1d50a89
--- /dev/null
+++ b/tests/py/ip6/rt0.t
@@ -0,0 +1,6 @@
+:output;type filter hook input priority 0
+
+*ip6;test-ip6;output
+
+rt nexthop 192.168.0.1;fail
+rt nexthop fd00::1;ok;rt ip6 nexthop fd00::1
diff --git a/tests/py/ip6/rt0.t.json b/tests/py/ip6/rt0.t.json
new file mode 100644
index 0000000..75ff923
--- /dev/null
+++ b/tests/py/ip6/rt0.t.json
@@ -0,0 +1,16 @@
+# rt nexthop fd00::1
+[
+ {
+ "match": {
+ "left": {
+ "rt": {
+ "family": "ip6",
+ "key": "nexthop"
+ }
+ },
+ "op": "==",
+ "right": "fd00::1"
+ }
+ }
+]
+
diff --git a/tests/py/ip6/rt0.t.payload b/tests/py/ip6/rt0.t.payload
new file mode 100644
index 0000000..464b7f2
--- /dev/null
+++ b/tests/py/ip6/rt0.t.payload
@@ -0,0 +1,5 @@
+# rt nexthop fd00::1
+ip6 test-ip6 output
+ [ rt load nexthop6 => reg 1 ]
+ [ cmp eq reg 1 0x000000fd 0x00000000 0x00000000 0x01000000 ]
+
diff --git a/tests/py/ip6/sets.t b/tests/py/ip6/sets.t
new file mode 100644
index 0000000..17fd62f
--- /dev/null
+++ b/tests/py/ip6/sets.t
@@ -0,0 +1,48 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+!w type ipv6_addr;ok
+!x type inet_proto;ok
+!y type inet_service;ok
+!z type time;ok
+
+?set2 192.168.3.4;fail
+!set2 type ipv6_addr;ok
+?set2 1234:1234::1234:1234:1234:1234:1234;ok
+?set2 1234:1234::1234:1234:1234:1234:1234;ok
+?set2 1234::1234:1234:1234;ok
+?set2 1234:1234:1234:1234:1234::1234:1234, 1234:1234::123;ok
+?set2 192.168.3.8, 192.168.3.9;fail
+?set2 1234:1234::1234:1234:1234:1234;ok
+?set2 1234:1234::1234:1234:1234:1234;ok
+?set2 1234:1234:1234::1234;ok
+
+ip6 saddr @set2 drop;ok
+ip6 saddr != @set2 drop;ok
+ip6 saddr @set33 drop;fail
+ip6 saddr != @set33 drop;fail
+
+!set3 type ipv6_addr flags interval;ok
+?set3 1234:1234:1234:1234::/64;ok
+?set3 1324:1234:1234:1235::/64;ok
+?set3 1324:1234:1234:1233::/64;ok
+?set3 1234:1234:1234:1234:1234:1234:/96;fail
+?set3 1324:1234:1234:1236::/64;ok
+
+!set4 type ipv6_addr flags interval;ok
+?set4 1234:1234:1234:1234::/64,4321:1234:1234:1234::/64;ok
+?set4 4321:1234:1234:1234:1234:1234::/96;fail
+
+!set5 type ipv6_addr . ipv6_addr;ok
+ip6 saddr . ip6 daddr @set5 drop;ok
+add @set5 { ip6 saddr . ip6 daddr };ok
+
+!map1 type ipv6_addr . ipv6_addr : mark;ok
+add @map1 { ip6 saddr . ip6 daddr : meta mark };ok
+
+delete @set5 { ip6 saddr . ip6 daddr };ok
diff --git a/tests/py/ip6/sets.t.json b/tests/py/ip6/sets.t.json
new file mode 100644
index 0000000..2029d2b
--- /dev/null
+++ b/tests/py/ip6/sets.t.json
@@ -0,0 +1,150 @@
+# ip6 saddr @set2 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "==",
+ "right": "@set2"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip6 saddr != @set2 drop
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "op": "!=",
+ "right": "@set2"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# ip6 saddr . ip6 daddr @set5 drop
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": "@set5"
+ }
+ },
+ {
+ "drop": null
+ }
+]
+
+# add @set5 { ip6 saddr . ip6 daddr }
+[
+ {
+ "set": {
+ "elem": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ }
+ ]
+ },
+ "op": "add",
+ "set": "@set5"
+ }
+ }
+]
+
+# delete @set5 { ip6 saddr . ip6 daddr }
+[
+ {
+ "set": {
+ "elem": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ }
+ ]
+ },
+ "op": "delete",
+ "set": "@set5"
+ }
+ }
+]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+[
+ {
+ "map": {
+ "data": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "elem": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ }
+ ]
+ },
+ "map": "@map1",
+ "op": "add"
+ }
+ }
+]
+
diff --git a/tests/py/ip6/sets.t.json.got b/tests/py/ip6/sets.t.json.got
new file mode 100644
index 0000000..114b17c
--- /dev/null
+++ b/tests/py/ip6/sets.t.json.got
@@ -0,0 +1,31 @@
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+[
+ {
+ "map": {
+ "data": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "elem": {
+ "concat": [
+ {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip6"
+ }
+ }
+ ]
+ },
+ "map": "@map1",
+ "op": "add"
+ }
+ }
+]
+
diff --git a/tests/py/ip6/sets.t.json.payload.got b/tests/py/ip6/sets.t.json.payload.got
new file mode 100644
index 0000000..18ac33b
--- /dev/null
+++ b/tests/py/ip6/sets.t.json.payload.got
@@ -0,0 +1,107 @@
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev egress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
diff --git a/tests/py/ip6/sets.t.payload b/tests/py/ip6/sets.t.payload
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/py/ip6/sets.t.payload
diff --git a/tests/py/ip6/sets.t.payload.inet b/tests/py/ip6/sets.t.payload.inet
new file mode 100644
index 0000000..2bbd557
--- /dev/null
+++ b/tests/py/ip6/sets.t.payload.inet
@@ -0,0 +1,49 @@
+# ip6 saddr @set2 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set set2 ]
+ [ immediate reg 0 drop ]
+
+# ip6 saddr != @set2 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set set2 0x1 ]
+ [ immediate reg 0 drop ]
+
+# ip6 saddr . ip6 daddr @set5 drop
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ lookup reg 1 set set5 ]
+ [ immediate reg 0 drop ]
+
+# add @set5 { ip6 saddr . ip6 daddr }
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ dynset add reg_key 1 set set5 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
+# delete @set5 { ip6 saddr . ip6 daddr }
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ dynset delete reg_key 1 set set5 ]
diff --git a/tests/py/ip6/sets.t.payload.inet.got b/tests/py/ip6/sets.t.payload.inet.got
new file mode 100644
index 0000000..4cfa6a4
--- /dev/null
+++ b/tests/py/ip6/sets.t.payload.inet.got
@@ -0,0 +1,9 @@
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
diff --git a/tests/py/ip6/sets.t.payload.ip6 b/tests/py/ip6/sets.t.payload.ip6
new file mode 100644
index 0000000..c59f7b5
--- /dev/null
+++ b/tests/py/ip6/sets.t.payload.ip6
@@ -0,0 +1,38 @@
+# ip6 saddr @set2 drop
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set set2 ]
+ [ immediate reg 0 drop ]
+
+# ip6 saddr != @set2 drop
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set set2 0x1 ]
+ [ immediate reg 0 drop ]
+
+# ip6 saddr . ip6 daddr @set5 drop
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ lookup reg 1 set set5 ]
+ [ immediate reg 0 drop ]
+
+# add @set5 { ip6 saddr . ip6 daddr }
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ dynset add reg_key 1 set set5 ]
+
+# delete @set5 { ip6 saddr . ip6 daddr }
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ dynset delete reg_key 1 set set5 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
diff --git a/tests/py/ip6/sets.t.payload.ip6.got b/tests/py/ip6/sets.t.payload.ip6.got
new file mode 100644
index 0000000..8c0ee0d
--- /dev/null
+++ b/tests/py/ip6/sets.t.payload.ip6.got
@@ -0,0 +1,7 @@
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
diff --git a/tests/py/ip6/sets.t.payload.netdev b/tests/py/ip6/sets.t.payload.netdev
new file mode 100644
index 0000000..1866d26
--- /dev/null
+++ b/tests/py/ip6/sets.t.payload.netdev
@@ -0,0 +1,50 @@
+# ip6 saddr @set2 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set set2 ]
+ [ immediate reg 0 drop ]
+
+# ip6 saddr != @set2 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set set2 0x1 ]
+ [ immediate reg 0 drop ]
+
+# ip6 saddr . ip6 daddr @set5 drop
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ lookup reg 1 set set5 ]
+ [ immediate reg 0 drop ]
+
+# add @set5 { ip6 saddr . ip6 daddr }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ dynset add reg_key 1 set set5 ]
+
+# delete @set5 { ip6 saddr . ip6 daddr }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ dynset delete reg_key 1 set set5 ]
+
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
diff --git a/tests/py/ip6/sets.t.payload.netdev.got b/tests/py/ip6/sets.t.payload.netdev.got
new file mode 100644
index 0000000..792d841
--- /dev/null
+++ b/tests/py/ip6/sets.t.payload.netdev.got
@@ -0,0 +1,9 @@
+# add @map1 { ip6 saddr . ip6 daddr : meta mark }
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ payload load 16b @ network header + 24 => reg 2 ]
+ [ meta load mark => reg 3 ]
+ [ dynset add reg_key 1 set map1 sreg_data 3 ]
+
diff --git a/tests/py/ip6/snat.t b/tests/py/ip6/snat.t
new file mode 100644
index 0000000..564f089
--- /dev/null
+++ b/tests/py/ip6/snat.t
@@ -0,0 +1,6 @@
+:postrouting;type nat hook postrouting priority 0
+
+*ip6;test-ip6;postrouting
+
+tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100;ok
+tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:100;ok
diff --git a/tests/py/ip6/snat.t.json b/tests/py/ip6/snat.t.json
new file mode 100644
index 0000000..58b0980
--- /dev/null
+++ b/tests/py/ip6/snat.t.json
@@ -0,0 +1,54 @@
+# tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 80, 90 ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": {
+ "range": [ "2001:838:35f:1::", "2001:838:35f:2::" ]
+ },
+ "port": {
+ "range": [ 80, 100 ]
+ }
+ }
+ }
+]
+
+# tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:100
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [ 80, 90 ]
+ }
+ }
+ },
+ {
+ "snat": {
+ "addr": {
+ "range": [ "2001:838:35f:1::", "2001:838:35f:2::" ]
+ },
+ "port": 100
+ }
+ }
+]
+
diff --git a/tests/py/ip6/snat.t.payload.ip6 b/tests/py/ip6/snat.t.payload.ip6
new file mode 100644
index 0000000..66a2967
--- /dev/null
+++ b/tests/py/ip6/snat.t.payload.ip6
@@ -0,0 +1,25 @@
+# tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00005000 ]
+ [ cmp lte reg 1 0x00005a00 ]
+ [ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
+ [ immediate reg 2 0x38080120 0x02005f03 0x00000000 0x00000000 ]
+ [ immediate reg 3 0x00005000 ]
+ [ immediate reg 4 0x00006400 ]
+ [ nat snat ip6 addr_min reg 1 addr_max reg 2 proto_min reg 3 proto_max reg 4 flags 0x2 ]
+
+# tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:100
+ip6 test-ip6 postrouting
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ payload load 2b @ transport header + 2 => reg 1 ]
+ [ cmp gte reg 1 0x00005000 ]
+ [ cmp lte reg 1 0x00005a00 ]
+ [ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
+ [ immediate reg 2 0x38080120 0x02005f03 0x00000000 0x00000000 ]
+ [ immediate reg 3 0x00006400 ]
+ [ nat snat ip6 addr_min reg 1 addr_max reg 2 proto_min reg 3 flags 0x2 ]
+
diff --git a/tests/py/ip6/srh.t b/tests/py/ip6/srh.t
new file mode 100644
index 0000000..fbaff41
--- /dev/null
+++ b/tests/py/ip6/srh.t
@@ -0,0 +1,22 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+
+srh last-entry 0;ok
+srh last-entry 127;ok
+srh last-entry { 0, 4-127, 255 };ok
+
+srh flags 0;ok
+srh flags 127;ok
+srh flags { 0, 4-127, 255 };ok
+
+srh tag 0;ok
+srh tag 127;ok
+srh tag { 0, 4-127, 0xffff };ok;srh tag { 0, 4-127, 65535 }
+
+srh sid[1] dead::beef;ok
+srh sid[2] dead::beef;ok
+
+srh last-entry { 0, 4-127, 256 };fail
+srh flags { 0, 4-127, 256 };fail
+srh tag { 0, 4-127, 0x10000 };fail
diff --git a/tests/py/ip6/srh.t.json b/tests/py/ip6/srh.t.json
new file mode 100644
index 0000000..2d16f1c
--- /dev/null
+++ b/tests/py/ip6/srh.t.json
@@ -0,0 +1,194 @@
+# srh last-entry 0
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "last-entry",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# srh last-entry 127
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "last-entry",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": 127
+ }
+ }
+]
+
+# srh last-entry { 0, 4-127, 255 }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "last-entry",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 0,
+ { "range": [ 4, 127 ] },
+ 255
+ ]
+ }
+ }
+ }
+]
+
+# srh flags 0
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "flags",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# srh flags 127
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "flags",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": 127
+ }
+ }
+]
+
+# srh flags { 0, 4-127, 255 }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "flags",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 0,
+ { "range": [ 4, 127 ] },
+ 255
+ ]
+ }
+ }
+ }
+]
+
+# srh tag 0
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "tag",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": 0
+ }
+ }
+]
+
+# srh tag 127
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "tag",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": 127
+ }
+ }
+]
+
+# srh tag { 0, 4-127, 0xffff }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "tag",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 0,
+ { "range": [ 4, 127 ] },
+ "0xffff"
+ ]
+ }
+ }
+ }
+]
+
+# srh sid[1] dead::beef
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "sid[1]",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": "dead::beef"
+ }
+ }
+]
+
+# srh sid[2] dead::beef
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "sid[2]",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": "dead::beef"
+ }
+ }
+]
+
diff --git a/tests/py/ip6/srh.t.json.output b/tests/py/ip6/srh.t.json.output
new file mode 100644
index 0000000..f801b81
--- /dev/null
+++ b/tests/py/ip6/srh.t.json.output
@@ -0,0 +1,22 @@
+# srh tag { 0, 4-127, 0xffff }
+[
+ {
+ "match": {
+ "left": {
+ "exthdr": {
+ "field": "tag",
+ "name": "srh"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 0,
+ { "range": [ 4, 127 ] },
+ 65535
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/srh.t.payload b/tests/py/ip6/srh.t.payload
new file mode 100644
index 0000000..364940a
--- /dev/null
+++ b/tests/py/ip6/srh.t.payload
@@ -0,0 +1,64 @@
+# srh last-entry 0
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# srh last-entry 127
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x0000007f ]
+
+# srh last-entry { 0, 4-127, 255 }
+__set%d test-ip6 7 size 5
+__set%d test-ip6 0
+ element 00000000 : 0 [end] element 00000001 : 1 [end] element 00000004 : 0 [end] element 00000080 : 1 [end] element 000000ff : 0 [end] userdata = { \x01\x04\x01\x00\x00\x00 }
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 4 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# srh flags 0
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 5 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# srh flags 127
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 5 => reg 1 ]
+ [ cmp eq reg 1 0x0000007f ]
+
+# srh flags { 0, 4-127, 255 }
+__set%d test-ip6 7 size 5
+__set%d test-ip6 0
+ element 00000000 : 0 [end] element 00000001 : 1 [end] element 00000004 : 0 [end] element 00000080 : 1 [end] element 000000ff : 0 [end] userdata = { \x01\x04\x01\x00\x00\x00 }
+ip6 test-ip6 input
+ [ exthdr load ipv6 1b @ 43 + 5 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# srh tag 0
+ip6 test-ip6 input
+ [ exthdr load ipv6 2b @ 43 + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# srh tag 127
+ip6 test-ip6 input
+ [ exthdr load ipv6 2b @ 43 + 6 => reg 1 ]
+ [ cmp eq reg 1 0x00007f00 ]
+
+# srh tag { 0, 4-127, 0xffff }
+__set%d test-ip6 7 size 5
+__set%d test-ip6 0
+ element 00000000 : 0 [end] element 00000100 : 1 [end] element 00000400 : 0 [end] element 00008000 : 1 [end] element 0000ffff : 0 [end] userdata = { \x01\x04\x01\x00\x00\x00 }
+ip6 test-ip6 input
+ [ exthdr load ipv6 2b @ 43 + 6 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# srh sid[1] dead::beef
+ip6 test-ip6 input
+ [ exthdr load ipv6 16b @ 43 + 8 => reg 1 ]
+ [ cmp eq reg 1 0x0000adde 0x00000000 0x00000000 0xefbe0000 ]
+
+# srh sid[2] dead::beef
+ip6 test-ip6 input
+ [ exthdr load ipv6 16b @ 43 + 24 => reg 1 ]
+ [ cmp eq reg 1 0x0000adde 0x00000000 0x00000000 0xefbe0000 ]
+
diff --git a/tests/py/ip6/tproxy.t b/tests/py/ip6/tproxy.t
new file mode 100644
index 0000000..d4c6bff
--- /dev/null
+++ b/tests/py/ip6/tproxy.t
@@ -0,0 +1,14 @@
+:y;type filter hook prerouting priority -150
+
+*ip6;x;y
+
+tproxy;fail
+tproxy to [2001:db8::1];fail
+tproxy to [2001:db8::1]:50080;fail
+tproxy to :50080;fail
+meta l4proto 6 tproxy to [2001:db8::1];ok
+meta l4proto 17 tproxy to [2001:db8::1]:50080;ok
+meta l4proto 6 tproxy to :50080;ok
+meta l4proto 6 tproxy ip6 to [2001:db8::1];ok;meta l4proto 6 tproxy to [2001:db8::1]
+meta l4proto 17 tproxy ip6 to [2001:db8::1]:50080;ok;meta l4proto 17 tproxy to [2001:db8::1]:50080
+meta l4proto 6 tproxy ip6 to :50080;ok;meta l4proto 6 tproxy to :50080
diff --git a/tests/py/ip6/tproxy.t.json b/tests/py/ip6/tproxy.t.json
new file mode 100644
index 0000000..0e02d49
--- /dev/null
+++ b/tests/py/ip6/tproxy.t.json
@@ -0,0 +1,125 @@
+# meta l4proto 6 tproxy to [2001:db8::1]
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "2001:db8::1"
+ }
+ }
+]
+
+# meta l4proto 17 tproxy to [2001:db8::1]:50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "2001:db8::1",
+ "port": 50080
+ }
+ }
+]
+
+# meta l4proto 6 tproxy to :50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "port": 50080
+ }
+ }
+]
+
+# meta l4proto 6 tproxy ip6 to [2001:db8::1]
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "2001:db8::1",
+ "family": "ip6"
+ }
+ }
+]
+
+# meta l4proto 17 tproxy ip6 to [2001:db8::1]:50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "2001:db8::1",
+ "family": "ip6",
+ "port": 50080
+ }
+ }
+]
+
+# meta l4proto 6 tproxy ip6 to :50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "family": "ip6",
+ "port": 50080
+ }
+ }
+]
+
diff --git a/tests/py/ip6/tproxy.t.json.output b/tests/py/ip6/tproxy.t.json.output
new file mode 100644
index 0000000..461738b
--- /dev/null
+++ b/tests/py/ip6/tproxy.t.json.output
@@ -0,0 +1,60 @@
+# meta l4proto 6 tproxy ip6 to [2001:db8::1]
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "2001:db8::1"
+ }
+ }
+]
+
+# meta l4proto 17 tproxy ip6 to [2001:db8::1]:50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 17
+ }
+ },
+ {
+ "tproxy": {
+ "addr": "2001:db8::1",
+ "port": 50080
+ }
+ }
+]
+
+# meta l4proto 6 tproxy ip6 to :50080
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "tproxy": {
+ "port": 50080
+ }
+ }
+]
diff --git a/tests/py/ip6/tproxy.t.payload b/tests/py/ip6/tproxy.t.payload
new file mode 100644
index 0000000..9f28e80
--- /dev/null
+++ b/tests/py/ip6/tproxy.t.payload
@@ -0,0 +1,44 @@
+# meta l4proto 6 tproxy to [2001:db8::1]
+ip6 x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0xb80d0120 0x00000000 0x00000000 0x01000000 ]
+ [ tproxy ip6 addr reg 1 ]
+
+# meta l4proto 17 tproxy to [2001:db8::1]:50080
+ip6 x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0xb80d0120 0x00000000 0x00000000 0x01000000 ]
+ [ immediate reg 2 0x0000a0c3 ]
+ [ tproxy ip6 addr reg 1 port reg 2 ]
+
+# meta l4proto 6 tproxy to :50080
+ip6 x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x0000a0c3 ]
+ [ tproxy ip6 port reg 1 ]
+
+# meta l4proto 6 tproxy ip6 to [2001:db8::1]
+ip6 x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0xb80d0120 0x00000000 0x00000000 0x01000000 ]
+ [ tproxy ip6 addr reg 1 ]
+
+# meta l4proto 17 tproxy ip6 to [2001:db8::1]:50080
+ip6 x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000011 ]
+ [ immediate reg 1 0xb80d0120 0x00000000 0x00000000 0x01000000 ]
+ [ immediate reg 2 0x0000a0c3 ]
+ [ tproxy ip6 addr reg 1 port reg 2 ]
+
+# meta l4proto 6 tproxy ip6 to :50080
+ip6 x y
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ immediate reg 1 0x0000a0c3 ]
+ [ tproxy ip6 port reg 1 ]
+
diff --git a/tests/py/ip6/vmap.t b/tests/py/ip6/vmap.t
new file mode 100644
index 0000000..2d54b82
--- /dev/null
+++ b/tests/py/ip6/vmap.t
@@ -0,0 +1,58 @@
+:input;type filter hook input priority 0
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*ip6;test-ip6;input
+*inet;test-inet;input
+*netdev;test-netdev;ingress,egress
+
+ip6 saddr vmap { abcd::3 : accept };ok
+ip6 saddr 1234:1234:1234:1234:1234:1234:1234:1234:1234;fail
+
+# Ipv6 address combinations
+# from src/scanner.l
+ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:1234 : accept};ok
+ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234:1234 : accept};ok;ip6 saddr vmap { 0:1234:1234:1234:1234:1234:1234:1234 : accept}
+ip6 saddr vmap { 1234::1234:1234:1234:1234:1234:1234 : accept};ok;ip6 saddr vmap { 1234:0:1234:1234:1234:1234:1234:1234 : accept}
+ip6 saddr vmap { 1234:1234::1234:1234:1234:1234:1234 : accept};ok;ip6 saddr vmap { 1234:1234:0:1234:1234:1234:1234:1234 : accept}
+ip6 saddr vmap { 1234:1234:1234::1234:1234:1234:1234 : accept};ok;ip6 saddr vmap { 1234:1234:1234:0:1234:1234:1234:1234 : accept}
+ip6 saddr vmap { 1234:1234:1234:1234::1234:1234:1234 : accept};ok;ip6 saddr vmap { 1234:1234:1234:1234:0:1234:1234:1234 : accept}
+ip6 saddr vmap { 1234:1234:1234:1234:1234::1234:1234 : accept};ok;ip6 saddr vmap { 1234:1234:1234:1234:1234:0:1234:1234 : accept}
+ip6 saddr vmap { 1234:1234:1234:1234:1234:1234::1234 : accept};ok;ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:0:1234 : accept}
+ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:: : accept};ok;ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:0 : accept}
+ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234::1234:1234:1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234::1234:1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234::1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234:1234::1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234:1234:1234::1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:: : accept};ok
+ip6 saddr vmap { ::1234:1234:1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234::1234:1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234::1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234::1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234:1234::1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234:1234:1234:: : accept};ok
+ip6 saddr vmap { ::1234:1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234::1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234::1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234::1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234:1234:: : accept};ok
+ip6 saddr vmap { ::1234:1234:1234 : accept};ok
+ip6 saddr vmap { 1234::1234:1234 : accept};ok
+ip6 saddr vmap { 1234:1234::1234 : accept};ok
+ip6 saddr vmap { 1234:1234:1234:: : accept};ok
+ip6 saddr vmap { ::1234:1234 : accept};ok;ip6 saddr vmap { ::18.52.18.52 : accept}
+ip6 saddr vmap { 1234::1234 : accept};ok
+ip6 saddr vmap { 1234:1234:: : accept};ok
+ip6 saddr vmap { ::1234 : accept};ok
+ip6 saddr vmap { 1234:: : accept};ok
+ip6 saddr vmap { ::/64 : accept};ok
+
+ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:: : accept, ::aaaa : drop};ok;ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:0 : accept, ::aaaa : drop}
+ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept, ::bbbb : drop};ok;ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:0 : accept, ::bbbb : drop}
+ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::cccc : drop};ok;ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:0 : accept, ::cccc : drop}
+ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::dddd: drop};ok;ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:0 : accept, ::dddd: drop}
+
+# rule without comma:
+filter-input ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:bbbb:::accept::adda : drop};fail
diff --git a/tests/py/ip6/vmap.t.json b/tests/py/ip6/vmap.t.json
new file mode 100644
index 0000000..1b867ff
--- /dev/null
+++ b/tests/py/ip6/vmap.t.json
@@ -0,0 +1,1037 @@
+# ip6 saddr vmap { abcd::3 : accept }
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "abcd::3",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::1234:1234:1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234::1234:1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234::1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234::1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234::1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234::1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234::1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234::1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234::1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:: : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234:1234::",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::1234:1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234::1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234::1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234::1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234::1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234::1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234::1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:: : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234::",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234::1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234::1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234::1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234::1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:: : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234::",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234::1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234::1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234::1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234::1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234::1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234::1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:: : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234::",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { ::1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234::1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234::1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234::1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234::1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:: : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234::",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { ::1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234::1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234::1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:: : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234::",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { ::1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:: : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234::",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { ::/64 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ {
+ "prefix": {
+ "addr": "::",
+ "len": 64
+ }
+ },
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:: : accept, ::aaaa : drop}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234:aaaa::",
+ {
+ "accept": null
+ }
+ ],
+ [
+ "::aaaa",
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept, ::bbbb : drop}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234:aaaa::",
+ {
+ "accept": null
+ }
+ ],
+ [
+ "::bbbb",
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::cccc : drop}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234:aaaa::",
+ {
+ "accept": null
+ }
+ ],
+ [
+ "::cccc",
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::dddd: drop}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234:aaaa::",
+ {
+ "accept": null
+ }
+ ],
+ [
+ "::dddd",
+ {
+ "drop": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/vmap.t.json.output b/tests/py/ip6/vmap.t.json.output
new file mode 100644
index 0000000..affe383
--- /dev/null
+++ b/tests/py/ip6/vmap.t.json.output
@@ -0,0 +1,336 @@
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "0:1234:1234:1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:0:1234:1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:0:1234:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:0:1234:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234:1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:0:1234:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234::1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:0:1234:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234::1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234:0:1234",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:: : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "1234:1234:1234:1234:1234:1234:1234:0",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap { ::1234:1234 : accept}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::18.52.18.52",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:: : accept, ::aaaa : drop}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::aaaa",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "1234:1234:1234:1234:1234:1234:aaaa:0",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept, ::bbbb : drop}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::bbbb",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "1234:1234:1234:1234:1234:1234:aaaa:0",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::cccc : drop}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::cccc",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "1234:1234:1234:1234:1234:1234:aaaa:0",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::dddd: drop}
+[
+ {
+ "vmap": {
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip6"
+ }
+ },
+ "data": {
+ "set": [
+ [
+ "::dddd",
+ {
+ "drop": null
+ }
+ ],
+ [
+ "1234:1234:1234:1234:1234:1234:aaaa:0",
+ {
+ "accept": null
+ }
+ ]
+ ]
+ }
+ }
+ }
+]
+
diff --git a/tests/py/ip6/vmap.t.payload.inet b/tests/py/ip6/vmap.t.payload.inet
new file mode 100644
index 0000000..931cc6b
--- /dev/null
+++ b/tests/py/ip6/vmap.t.payload.inet
@@ -0,0 +1,420 @@
+# ip6 saddr vmap { abcd::3 : accept }
+__map%d test-inet b
+__map%d test-inet 0
+ element 0000cdab 00000000 00000000 03000000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34120000 34123412 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00003412 34123412 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34120000 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00003412 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 34120000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234::1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 00003412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234::1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 34123412 34120000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:: : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 34123412 00003412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00000000 34123412 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00003412 34120000 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00000000 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00003412 34120000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 00000000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234::1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 00003412 34120000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:: : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 34123412 00000000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00000000 34120000 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00003412 00000000 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00000000 34120000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00003412 00000000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 00000000 34120000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:: : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 00003412 00000000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00000000 00000000 34123412 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00003412 00000000 34120000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00000000 00000000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00003412 00000000 34120000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:: : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 00000000 00000000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00000000 00000000 34120000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00003412 00000000 00000000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00000000 00000000 34120000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:: : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00003412 00000000 00000000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00000000 00000000 00000000 34123412 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00003412 00000000 00000000 34120000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:: : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 00000000 00000000 00000000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234 : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00000000 00000000 00000000 34120000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:: : accept}
+__map%d test-inet b
+__map%d test-inet 0
+ element 00003412 00000000 00000000 00000000 : accept 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::/64 : accept}
+__map%d test-inet f
+__map%d test-inet 0
+ element 00000000 00000000 00000000 00000000 : accept 0 [end] element 00000000 01000000 00000000 00000000 : 1 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:: : accept, ::aaaa : drop}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 aaaa0000 : drop 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept, ::bbbb : drop}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 bbbb0000 : drop 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::cccc : drop}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 cccc0000 : drop 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::dddd: drop}
+__map%d test-inet b
+__map%d test-inet 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 dddd0000 : drop 0 [end]
+inet test-inet input
+ [ meta load nfproto => reg 1 ]
+ [ cmp eq reg 1 0x0000000a ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
diff --git a/tests/py/ip6/vmap.t.payload.ip6 b/tests/py/ip6/vmap.t.payload.ip6
new file mode 100644
index 0000000..6e077b2
--- /dev/null
+++ b/tests/py/ip6/vmap.t.payload.ip6
@@ -0,0 +1,336 @@
+# ip6 saddr vmap { abcd::3 : accept }
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 0000cdab 00000000 00000000 03000000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34120000 34123412 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00003412 34123412 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34120000 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00003412 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 34120000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234::1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 00003412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234::1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 34123412 34120000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:: : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 34123412 00003412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00000000 34123412 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00003412 34120000 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00000000 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00003412 34120000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 00000000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234::1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 00003412 34120000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:: : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 34123412 00000000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00000000 34120000 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00003412 00000000 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00000000 34120000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00003412 00000000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 00000000 34120000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:: : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 00003412 00000000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00000000 00000000 34123412 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00003412 00000000 34120000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00000000 00000000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00003412 00000000 34120000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:: : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 00000000 00000000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00000000 00000000 34120000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00003412 00000000 00000000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00000000 00000000 34120000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:: : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00003412 00000000 00000000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00000000 00000000 00000000 34123412 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00003412 00000000 00000000 34120000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:: : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 00000000 00000000 00000000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234 : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00000000 00000000 00000000 34120000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:: : accept}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 00003412 00000000 00000000 00000000 : accept 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::/64 : accept}
+__map%d test-ip6 f
+__map%d test-ip6 0
+ element 00000000 00000000 00000000 00000000 : accept 0 [end] element 00000000 01000000 00000000 00000000 : 1 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:: : accept, ::aaaa : drop}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 aaaa0000 : drop 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept, ::bbbb : drop}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 bbbb0000 : drop 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::cccc : drop}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 cccc0000 : drop 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::dddd: drop}
+__map%d test-ip6 b
+__map%d test-ip6 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 dddd0000 : drop 0 [end]
+ip6 test-ip6 input
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
diff --git a/tests/py/ip6/vmap.t.payload.netdev b/tests/py/ip6/vmap.t.payload.netdev
new file mode 100644
index 0000000..45f2c0b
--- /dev/null
+++ b/tests/py/ip6/vmap.t.payload.netdev
@@ -0,0 +1,420 @@
+# ip6 saddr vmap { abcd::3 : accept }
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 0000cdab 00000000 00000000 03000000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34120000 34123412 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00003412 34123412 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34120000 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00003412 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 34120000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234::1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 00003412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234::1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 34123412 34120000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:: : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 34123412 00003412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00000000 34123412 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00003412 34120000 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00000000 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00003412 34120000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 00000000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234::1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 00003412 34120000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:: : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 34123412 00000000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00000000 34120000 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00003412 00000000 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00000000 34120000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00003412 00000000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234::1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 00000000 34120000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:1234:: : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 00003412 00000000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00000000 00000000 34123412 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00003412 00000000 34120000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00000000 00000000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234::1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00003412 00000000 34120000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:1234:: : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 00000000 00000000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00000000 00000000 34120000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00003412 00000000 00000000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234::1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00000000 00000000 34120000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:1234:: : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00003412 00000000 00000000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234:1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00000000 00000000 00000000 34123412 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234::1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00003412 00000000 00000000 34120000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:1234:: : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 00000000 00000000 00000000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::1234 : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00000000 00000000 00000000 34120000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { 1234:: : accept}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00003412 00000000 00000000 00000000 : accept 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap { ::/64 : accept}
+__map%d test-netdev f
+__map%d test-netdev 0
+ element 00000000 00000000 00000000 00000000 : accept 0 [end] element 00000000 01000000 00000000 00000000 : 1 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:: : accept, ::aaaa : drop}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 aaaa0000 : drop 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept, ::bbbb : drop}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 bbbb0000 : drop 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::cccc : drop}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 cccc0000 : drop 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
+# ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::dddd: drop}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 34123412 34123412 34123412 0000aaaa : accept 0 [end] element 00000000 00000000 00000000 dddd0000 : drop 0 [end]
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ payload load 16b @ network header + 8 => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 0 ]
+
diff --git a/tests/py/log b/tests/py/log
new file mode 100644
index 0000000..aba5a15
--- /dev/null
+++ b/tests/py/log
@@ -0,0 +1,1004 @@
+INFO: Log will be available at /tmp/nftables-test.log
+any/last.t: ERROR: line 11: add rule ip test-ip4 input last: This rule should not have failed.
+any/last.t: ERROR: line 12: add rule ip test-ip4 input last used 300s: This rule should not have failed.
+any/meta.t: ERROR: line 3: I cannot create the chain 'egress'
+any/meta.t: ERROR: line 12: add rule netdev test-netdev egress meta length 1000: This rule should not have failed.
+any/meta.t: ERROR: line 13: add rule netdev test-netdev egress meta length 22: This rule should not have failed.
+any/meta.t: ERROR: line 14: add rule netdev test-netdev egress meta length != 233: This rule should not have failed.
+any/meta.t: ERROR: line 15: add rule netdev test-netdev egress meta length 33-45: This rule should not have failed.
+any/meta.t: ERROR: line 16: add rule netdev test-netdev egress meta length != 33-45: This rule should not have failed.
+any/meta.t: ERROR: line 17: add rule netdev test-netdev egress meta length { 33, 55, 67, 88}: This rule should not have failed.
+any/meta.t: ERROR: line 18: add rule netdev test-netdev egress meta length { 33-55, 67-88}: This rule should not have failed.
+any/meta.t: ERROR: line 19: add rule netdev test-netdev egress meta length { 33-55, 56-88, 100-120}: This rule should not have failed.
+any/meta.t: ERROR: line 20: add rule netdev test-netdev egress meta length != { 33, 55, 67, 88}: This rule should not have failed.
+any/meta.t: ERROR: line 21: add rule netdev test-netdev egress meta length { 33-55, 66-88}: This rule should not have failed.
+any/meta.t: ERROR: line 22: add rule netdev test-netdev egress meta length != { 33-55, 66-88}: This rule should not have failed.
+any/meta.t: ERROR: line 24: add rule netdev test-netdev egress meta protocol { ip, arp, ip6, vlan }: This rule should not have failed.
+any/meta.t: ERROR: line 25: add rule netdev test-netdev egress meta protocol != {ip, arp, ip6, 8021q}: This rule should not have failed.
+any/meta.t: ERROR: line 26: add rule netdev test-netdev egress meta protocol ip: This rule should not have failed.
+any/meta.t: ERROR: line 27: add rule netdev test-netdev egress meta protocol != ip: This rule should not have failed.
+any/meta.t: ERROR: line 29: add rule netdev test-netdev egress meta l4proto 22: This rule should not have failed.
+any/meta.t: ERROR: line 30: add rule netdev test-netdev egress meta l4proto != 233: This rule should not have failed.
+any/meta.t: ERROR: line 31: add rule netdev test-netdev egress meta l4proto 33-45: This rule should not have failed.
+any/meta.t: ERROR: line 32: add rule netdev test-netdev egress meta l4proto != 33-45: This rule should not have failed.
+any/meta.t: ERROR: line 33: add rule netdev test-netdev egress meta l4proto { 33, 55, 67, 88}: This rule should not have failed.
+any/meta.t: ERROR: line 34: add rule netdev test-netdev egress meta l4proto != { 33, 55, 67, 88}: This rule should not have failed.
+any/meta.t: ERROR: line 35: add rule netdev test-netdev egress meta l4proto { 33-55, 66-88}: This rule should not have failed.
+any/meta.t: ERROR: line 36: add rule netdev test-netdev egress meta l4proto != { 33-55, 66-88}: This rule should not have failed.
+any/meta.t: ERROR: line 38: add rule netdev test-netdev egress meta priority root: This rule should not have failed.
+any/meta.t: ERROR: line 39: add rule netdev test-netdev egress meta priority none: This rule should not have failed.
+any/meta.t: ERROR: line 40: add rule netdev test-netdev egress meta priority 0x87654321: This rule should not have failed.
+any/meta.t: ERROR: line 41: add rule netdev test-netdev egress meta priority 2271560481: This rule should not have failed.
+any/meta.t: ERROR: line 42: add rule netdev test-netdev egress meta priority 1:1234: This rule should not have failed.
+any/meta.t: ERROR: line 43: add rule netdev test-netdev egress meta priority bcad:dadc: This rule should not have failed.
+any/meta.t: ERROR: line 44: add rule netdev test-netdev egress meta priority aabb:0: This rule should not have failed.
+any/meta.t: ERROR: line 45: add rule netdev test-netdev egress meta priority != bcad:dadc: This rule should not have failed.
+any/meta.t: ERROR: line 46: add rule netdev test-netdev egress meta priority != aabb:0: This rule should not have failed.
+any/meta.t: ERROR: line 47: add rule netdev test-netdev egress meta priority bcad:dada-bcad:dadc: This rule should not have failed.
+any/meta.t: ERROR: line 48: add rule netdev test-netdev egress meta priority != bcad:dada-bcad:dadc: This rule should not have failed.
+any/meta.t: ERROR: line 49: add rule netdev test-netdev egress meta priority {bcad:dada, bcad:dadc, aaaa:bbbb}: This rule should not have failed.
+any/meta.t: ERROR: line 50: add rule netdev test-netdev egress meta priority set cafe:beef: This rule should not have failed.
+any/meta.t: ERROR: line 51: add rule netdev test-netdev egress meta priority != {bcad:dada, bcad:dadc, aaaa:bbbb}: This rule should not have failed.
+any/meta.t: ERROR: line 53: add rule netdev test-netdev egress meta mark 0x4: This rule should not have failed.
+any/meta.t: ERROR: line 54: add rule netdev test-netdev egress meta mark 0x32: This rule should not have failed.
+any/meta.t: ERROR: line 55: add rule netdev test-netdev egress meta mark and 0x03 == 0x01: This rule should not have failed.
+any/meta.t: ERROR: line 56: add rule netdev test-netdev egress meta mark and 0x03 != 0x01: This rule should not have failed.
+any/meta.t: ERROR: line 57: add rule netdev test-netdev egress meta mark 0x10: This rule should not have failed.
+any/meta.t: ERROR: line 58: add rule netdev test-netdev egress meta mark != 0x10: This rule should not have failed.
+any/meta.t: ERROR: line 59: add rule netdev test-netdev egress meta mark 0xffffff00/24: This rule should not have failed.
+any/meta.t: ERROR: line 61: add rule netdev test-netdev egress meta mark or 0x03 == 0x01: This rule should not have failed.
+any/meta.t: ERROR: line 62: add rule netdev test-netdev egress meta mark or 0x03 != 0x01: This rule should not have failed.
+any/meta.t: ERROR: line 63: add rule netdev test-netdev egress meta mark xor 0x03 == 0x01: This rule should not have failed.
+any/meta.t: ERROR: line 64: add rule netdev test-netdev egress meta mark xor 0x03 != 0x01: This rule should not have failed.
+any/meta.t: ERROR: line 66: add rule netdev test-netdev egress meta iif "lo" accept: This rule should not have failed.
+any/meta.t: ERROR: line 67: add rule netdev test-netdev egress meta iif != "lo" accept: This rule should not have failed.
+any/meta.t: ERROR: line 69: add rule netdev test-netdev egress meta iifname "dummy0": This rule should not have failed.
+any/meta.t: ERROR: line 70: add rule netdev test-netdev egress meta iifname != "dummy0": This rule should not have failed.
+any/meta.t: ERROR: line 71: add rule netdev test-netdev egress meta iifname {"dummy0", "lo"}: This rule should not have failed.
+any/meta.t: ERROR: line 72: add rule netdev test-netdev egress meta iifname != {"dummy0", "lo"}: This rule should not have failed.
+any/meta.t: ERROR: line 73: add rule netdev test-netdev egress meta iifname "dummy*": This rule should not have failed.
+any/meta.t: ERROR: line 74: add rule netdev test-netdev egress meta iifname "dummy\*": This rule should not have failed.
+any/meta.t: ERROR: line 77: add rule netdev test-netdev egress meta iiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}: This rule should not have failed.
+any/meta.t: ERROR: line 78: add rule netdev test-netdev egress meta iiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre}: This rule should not have failed.
+any/meta.t: ERROR: line 79: add rule netdev test-netdev egress meta iiftype != ether: This rule should not have failed.
+any/meta.t: ERROR: line 80: add rule netdev test-netdev egress meta iiftype ether: This rule should not have failed.
+any/meta.t: ERROR: line 81: add rule netdev test-netdev egress meta iiftype != ppp: This rule should not have failed.
+any/meta.t: ERROR: line 82: add rule netdev test-netdev egress meta iiftype ppp: This rule should not have failed.
+any/meta.t: ERROR: line 84: add rule netdev test-netdev egress meta oif "lo" accept: This rule should not have failed.
+any/meta.t: ERROR: line 85: add rule netdev test-netdev egress meta oif != "lo" accept: This rule should not have failed.
+any/meta.t: ERROR: line 87: add rule netdev test-netdev egress meta oifname "dummy0": This rule should not have failed.
+any/meta.t: ERROR: line 88: add rule netdev test-netdev egress meta oifname != "dummy0": This rule should not have failed.
+any/meta.t: ERROR: line 89: add rule netdev test-netdev egress meta oifname { "dummy0", "lo"}: This rule should not have failed.
+any/meta.t: ERROR: line 90: add rule netdev test-netdev egress meta oifname "dummy*": This rule should not have failed.
+any/meta.t: ERROR: line 91: add rule netdev test-netdev egress meta oifname "dummy\*": This rule should not have failed.
+any/meta.t: ERROR: line 94: add rule netdev test-netdev egress meta oiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}: This rule should not have failed.
+any/meta.t: ERROR: line 95: add rule netdev test-netdev egress meta oiftype != {ether, ppp, ipip, ipip6, loopback, sit, ipgre}: This rule should not have failed.
+any/meta.t: ERROR: line 96: add rule netdev test-netdev egress meta oiftype != ether: This rule should not have failed.
+any/meta.t: ERROR: line 97: add rule netdev test-netdev egress meta oiftype ether: This rule should not have failed.
+any/meta.t: ERROR: line 99: add rule netdev test-netdev egress meta skuid {"bin", "root", "daemon"} accept: This rule should not have failed.
+any/meta.t: ERROR: line 100: add rule netdev test-netdev egress meta skuid != {"bin", "root", "daemon"} accept: This rule should not have failed.
+any/meta.t: ERROR: line 101: add rule netdev test-netdev egress meta skuid "root": This rule should not have failed.
+any/meta.t: ERROR: line 102: add rule netdev test-netdev egress meta skuid != "root": This rule should not have failed.
+any/meta.t: ERROR: line 103: add rule netdev test-netdev egress meta skuid lt 3000 accept: This rule should not have failed.
+any/meta.t: ERROR: line 104: add rule netdev test-netdev egress meta skuid gt 3000 accept: This rule should not have failed.
+any/meta.t: ERROR: line 105: add rule netdev test-netdev egress meta skuid eq 3000 accept: This rule should not have failed.
+any/meta.t: ERROR: line 106: add rule netdev test-netdev egress meta skuid 3001-3005 accept: This rule should not have failed.
+any/meta.t: ERROR: line 107: add rule netdev test-netdev egress meta skuid != 2001-2005 accept: This rule should not have failed.
+any/meta.t: ERROR: line 108: add rule netdev test-netdev egress meta skuid { 2001-2005, 3001-3005} accept: This rule should not have failed.
+any/meta.t: ERROR: line 109: add rule netdev test-netdev egress meta skuid != { 2001-2005, 3001-3005} accept: This rule should not have failed.
+any/meta.t: ERROR: line 111: add rule netdev test-netdev egress meta skgid {"bin", "root", "daemon"} accept: This rule should not have failed.
+any/meta.t: ERROR: line 112: add rule netdev test-netdev egress meta skgid != {"bin", "root", "daemon"} accept: This rule should not have failed.
+any/meta.t: ERROR: line 113: add rule netdev test-netdev egress meta skgid "root": This rule should not have failed.
+any/meta.t: ERROR: line 114: add rule netdev test-netdev egress meta skgid != "root": This rule should not have failed.
+any/meta.t: ERROR: line 115: add rule netdev test-netdev egress meta skgid lt 3000 accept: This rule should not have failed.
+any/meta.t: ERROR: line 116: add rule netdev test-netdev egress meta skgid gt 3000 accept: This rule should not have failed.
+any/meta.t: ERROR: line 117: add rule netdev test-netdev egress meta skgid eq 3000 accept: This rule should not have failed.
+any/meta.t: ERROR: line 118: add rule netdev test-netdev egress meta skgid 2001-2005 accept: This rule should not have failed.
+any/meta.t: ERROR: line 119: add rule netdev test-netdev egress meta skgid != 2001-2005 accept: This rule should not have failed.
+any/meta.t: ERROR: line 131: add rule netdev test-netdev egress meta mark set 0xffffffc8 xor 0x16: This rule should not have failed.
+any/meta.t: ERROR: line 132: add rule netdev test-netdev egress meta mark set 0x16 and 0x16: This rule should not have failed.
+any/meta.t: ERROR: line 133: add rule netdev test-netdev egress meta mark set 0xffffffe9 or 0x16: This rule should not have failed.
+any/meta.t: ERROR: line 134: add rule netdev test-netdev egress meta mark set 0xffffffde and 0x16: This rule should not have failed.
+any/meta.t: ERROR: line 135: add rule netdev test-netdev egress meta mark set 0xf045ffde or 0x10: This rule should not have failed.
+any/meta.t: ERROR: line 136: add rule netdev test-netdev egress meta mark set 0xffffffde or 0x16: This rule should not have failed.
+any/meta.t: ERROR: line 137: add rule netdev test-netdev egress meta mark set 0x32 or 0xfffff: This rule should not have failed.
+any/meta.t: ERROR: line 138: add rule netdev test-netdev egress meta mark set 0xfffe xor 0x16: This rule should not have failed.
+any/meta.t: ERROR: line 143: add rule netdev test-netdev egress meta iif "lo": This rule should not have failed.
+any/meta.t: ERROR: line 144: add rule netdev test-netdev egress meta oif "lo": This rule should not have failed.
+any/meta.t: ERROR: line 145: add rule netdev test-netdev egress meta oifname "dummy2" accept: This rule should not have failed.
+any/meta.t: ERROR: line 146: add rule netdev test-netdev egress meta skuid 3000: This rule should not have failed.
+any/meta.t: ERROR: line 147: add rule netdev test-netdev egress meta skgid 3000: This rule should not have failed.
+any/meta.t: ERROR: line 151: add rule netdev test-netdev egress meta rtclassid "cosmos": This rule should not have failed.
+any/meta.t: ERROR: line 153: add rule netdev test-netdev egress meta pkttype broadcast: This rule should not have failed.
+any/meta.t: ERROR: line 154: add rule netdev test-netdev egress meta pkttype host: This rule should not have failed.
+any/meta.t: ERROR: line 155: add rule netdev test-netdev egress meta pkttype multicast: This rule should not have failed.
+any/meta.t: ERROR: line 156: add rule netdev test-netdev egress meta pkttype != broadcast: This rule should not have failed.
+any/meta.t: ERROR: line 157: add rule netdev test-netdev egress meta pkttype != host: This rule should not have failed.
+any/meta.t: ERROR: line 158: add rule netdev test-netdev egress meta pkttype != multicast: This rule should not have failed.
+any/meta.t: ERROR: line 160: add rule netdev test-netdev egress pkttype { broadcast, multicast} accept: This rule should not have failed.
+any/meta.t: ERROR: line 162: add rule netdev test-netdev egress meta cpu 1: This rule should not have failed.
+any/meta.t: ERROR: line 163: add rule netdev test-netdev egress meta cpu != 1: This rule should not have failed.
+any/meta.t: ERROR: line 164: add rule netdev test-netdev egress meta cpu 1-3: This rule should not have failed.
+any/meta.t: ERROR: line 165: add rule netdev test-netdev egress meta cpu != 1-2: This rule should not have failed.
+any/meta.t: ERROR: line 166: add rule netdev test-netdev egress meta cpu { 2,3}: This rule should not have failed.
+any/meta.t: ERROR: line 167: add rule netdev test-netdev egress meta cpu { 2-3, 5-7}: This rule should not have failed.
+any/meta.t: ERROR: line 168: add rule netdev test-netdev egress meta cpu != { 2,3}: This rule should not have failed.
+any/meta.t: ERROR: line 170: add rule netdev test-netdev egress meta iifgroup 0: This rule should not have failed.
+any/meta.t: ERROR: line 171: add rule netdev test-netdev egress meta iifgroup != 0: This rule should not have failed.
+any/meta.t: ERROR: line 172: add rule netdev test-netdev egress meta iifgroup "default": This rule should not have failed.
+any/meta.t: ERROR: line 173: add rule netdev test-netdev egress meta iifgroup != "default": This rule should not have failed.
+any/meta.t: ERROR: line 174: add rule netdev test-netdev egress meta iifgroup {"default", 11}: This rule should not have failed.
+any/meta.t: ERROR: line 175: add rule netdev test-netdev egress meta iifgroup != {"default", 11}: This rule should not have failed.
+any/meta.t: ERROR: line 176: add rule netdev test-netdev egress meta iifgroup { 11,33}: This rule should not have failed.
+any/meta.t: ERROR: line 177: add rule netdev test-netdev egress meta iifgroup {11-33, 44-55}: This rule should not have failed.
+any/meta.t: ERROR: line 178: add rule netdev test-netdev egress meta iifgroup != { 11,33}: This rule should not have failed.
+any/meta.t: ERROR: line 179: add rule netdev test-netdev egress meta iifgroup != {11-33, 44-55}: This rule should not have failed.
+any/meta.t: ERROR: line 180: add rule netdev test-netdev egress meta oifgroup 0: This rule should not have failed.
+any/meta.t: ERROR: line 181: add rule netdev test-netdev egress meta oifgroup != 0: This rule should not have failed.
+any/meta.t: ERROR: line 182: add rule netdev test-netdev egress meta oifgroup "default": This rule should not have failed.
+any/meta.t: ERROR: line 183: add rule netdev test-netdev egress meta oifgroup != "default": This rule should not have failed.
+any/meta.t: ERROR: line 184: add rule netdev test-netdev egress meta oifgroup {"default", 11}: This rule should not have failed.
+any/meta.t: ERROR: line 185: add rule netdev test-netdev egress meta oifgroup != {"default", 11}: This rule should not have failed.
+any/meta.t: ERROR: line 186: add rule netdev test-netdev egress meta oifgroup { 11,33}: This rule should not have failed.
+any/meta.t: ERROR: line 187: add rule netdev test-netdev egress meta oifgroup {11-33, 44-55}: This rule should not have failed.
+any/meta.t: ERROR: line 188: add rule netdev test-netdev egress meta oifgroup != { 11,33}: This rule should not have failed.
+any/meta.t: ERROR: line 189: add rule netdev test-netdev egress meta oifgroup != {11-33, 44-55}: This rule should not have failed.
+any/meta.t: ERROR: line 191: add rule netdev test-netdev egress meta cgroup 1048577: This rule should not have failed.
+any/meta.t: ERROR: line 192: add rule netdev test-netdev egress meta cgroup != 1048577: This rule should not have failed.
+any/meta.t: ERROR: line 193: add rule netdev test-netdev egress meta cgroup { 1048577, 1048578 }: This rule should not have failed.
+any/meta.t: ERROR: line 194: add rule netdev test-netdev egress meta cgroup != { 1048577, 1048578}: This rule should not have failed.
+any/meta.t: ERROR: line 195: add rule netdev test-netdev egress meta cgroup 1048577-1048578: This rule should not have failed.
+any/meta.t: ERROR: line 196: add rule netdev test-netdev egress meta cgroup != 1048577-1048578: This rule should not have failed.
+any/meta.t: ERROR: line 198: add rule netdev test-netdev egress meta iif . meta oif { "lo" . "lo" }: This rule should not have failed.
+any/meta.t: ERROR: line 199: add rule netdev test-netdev egress meta iif . meta oif . meta mark { "lo" . "lo" . 0x0000000a }: This rule should not have failed.
+any/meta.t: ERROR: line 200: add rule netdev test-netdev egress meta iif . meta oif vmap { "lo" . "lo" : drop }: This rule should not have failed.
+any/meta.t: ERROR: line 202: add rule netdev test-netdev egress meta random eq 1: This rule should not have failed.
+any/meta.t: ERROR: line 203: add rule netdev test-netdev egress meta random gt 1000000: This rule should not have failed.
+any/meta.t: ERROR: line 205: add rule netdev test-netdev egress meta time "1970-05-23 21:07:14" drop: This rule should not have failed.
+any/meta.t: ERROR: line 206: add rule netdev test-netdev egress meta time 12341234 drop: This rule should not have failed.
+any/meta.t: ERROR: line 207: add rule netdev test-netdev egress meta time "2019-06-21 17:00:00" drop: This rule should not have failed.
+any/meta.t: ERROR: line 208: add rule netdev test-netdev egress meta time "2019-07-01 00:00:00" drop: This rule should not have failed.
+any/meta.t: ERROR: line 209: add rule netdev test-netdev egress meta time "2019-07-01 00:01:00" drop: This rule should not have failed.
+any/meta.t: ERROR: line 210: add rule netdev test-netdev egress meta time "2019-07-01 00:00:01" drop: This rule should not have failed.
+any/meta.t: ERROR: line 211: add rule netdev test-netdev egress meta time < "2022-07-01 11:00:00" accept: This rule should not have failed.
+any/meta.t: ERROR: line 212: add rule netdev test-netdev egress meta time > "2022-07-01 11:00:00" accept: This rule should not have failed.
+any/meta.t: ERROR: line 213: add rule netdev test-netdev egress meta day "Saturday" drop: This rule should not have failed.
+any/meta.t: ERROR: line 214: add rule netdev test-netdev egress meta day 6 drop: This rule should not have failed.
+any/meta.t: ERROR: line 216: add rule netdev test-netdev egress meta hour "17:00" drop: This rule should not have failed.
+any/meta.t: ERROR: line 217: add rule netdev test-netdev egress meta hour "17:00:00" drop: This rule should not have failed.
+any/meta.t: ERROR: line 218: add rule netdev test-netdev egress meta hour "17:00:01" drop: This rule should not have failed.
+any/meta.t: ERROR: line 219: add rule netdev test-netdev egress meta hour "00:00" drop: This rule should not have failed.
+any/meta.t: ERROR: line 220: add rule netdev test-netdev egress meta hour "00:01" drop: This rule should not have failed.
+any/meta.t: ERROR: line 221: add rule netdev test-netdev egress time < "2022-07-01 11:00:00" accept: This rule should not have failed.
+any/meta.t: ERROR: line 222: add rule netdev test-netdev egress time > "2022-07-01 11:00:00" accept: This rule should not have failed.
+any/meta.t: ERROR: line 226: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+any/rawpayload.t: ERROR: line 3: I cannot create the chain 'egress'
+any/rawpayload.t: ERROR: line 8: add rule netdev test-netdev egress meta l4proto { tcp, udp, sctp} @th,16,16 { 22, 23, 80 }: This rule should not have failed.
+any/rawpayload.t: ERROR: line 9: add rule netdev test-netdev egress meta l4proto tcp @th,16,16 { 22, 23, 80}: This rule should not have failed.
+any/rawpayload.t: ERROR: line 10: add rule netdev test-netdev egress @nh,8,8 0xff: This rule should not have failed.
+any/rawpayload.t: ERROR: line 11: add rule netdev test-netdev egress @nh,8,16 0x0: This rule should not have failed.
+any/rawpayload.t: ERROR: line 18: add rule netdev test-netdev egress @ll,0,1 1: This rule should not have failed.
+any/rawpayload.t: ERROR: line 19: add rule netdev test-netdev egress @ll,0,8 & 0x80 == 0x80: This rule should not have failed.
+any/rawpayload.t: ERROR: line 20: add rule netdev test-netdev egress @ll,0,128 0xfedcba987654321001234567890abcde: This rule should not have failed.
+any/rawpayload.t: ERROR: line 22: add rule netdev test-netdev egress meta l4proto 91 @th,400,16 0x0 accept: This rule should not have failed.
+any/rawpayload.t: ERROR: line 24: add rule inet test-inet input @ih,32,32 0x14000000: This rule should not have failed.
+any/rawpayload.t: ERROR: line 24: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+any/rt.t: OK
+any/ct.t: OK
+any/log.t: OK
+any/queue.t: OK
+any/objects.t: ERROR: line 3: I cannot create the chain 'egress'
+any/objects.t: ERROR: line 16: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+any/objects.t: OK
+any/counter.t: OK
+any/quota.t: ERROR: line 3: I cannot create the chain 'egress'
+any/quota.t: ERROR: line 12: add rule netdev test-netdev egress quota 1025 bytes: This rule should not have failed.
+any/quota.t: ERROR: line 13: add rule netdev test-netdev egress quota 1 kbytes: This rule should not have failed.
+any/quota.t: ERROR: line 14: add rule netdev test-netdev egress quota 2 kbytes: This rule should not have failed.
+any/quota.t: ERROR: line 15: add rule netdev test-netdev egress quota 1025 kbytes: This rule should not have failed.
+any/quota.t: ERROR: line 16: add rule netdev test-netdev egress quota 1023 mbytes: This rule should not have failed.
+any/quota.t: ERROR: line 17: add rule netdev test-netdev egress quota 10230 mbytes: This rule should not have failed.
+any/quota.t: ERROR: line 18: add rule netdev test-netdev egress quota 1023000 mbytes: This rule should not have failed.
+any/quota.t: ERROR: line 20: add rule netdev test-netdev egress quota over 1 kbytes: This rule should not have failed.
+any/quota.t: ERROR: line 21: add rule netdev test-netdev egress quota over 2 kbytes: This rule should not have failed.
+any/quota.t: ERROR: line 22: add rule netdev test-netdev egress quota over 1025 kbytes: This rule should not have failed.
+any/quota.t: ERROR: line 23: add rule netdev test-netdev egress quota over 1023 mbytes: This rule should not have failed.
+any/quota.t: ERROR: line 24: add rule netdev test-netdev egress quota over 10230 mbytes: This rule should not have failed.
+any/quota.t: ERROR: line 25: add rule netdev test-netdev egress quota over 1023000 mbytes: This rule should not have failed.
+any/quota.t: ERROR: line 25: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+any/limit.t: ERROR: line 3: I cannot create the chain 'egress'
+any/limit.t: ERROR: line 12: add rule netdev test-netdev egress limit rate 400/minute: This rule should not have failed.
+any/limit.t: ERROR: line 13: add rule netdev test-netdev egress limit rate 20/second: This rule should not have failed.
+any/limit.t: ERROR: line 14: add rule netdev test-netdev egress limit rate 400/hour: This rule should not have failed.
+any/limit.t: ERROR: line 15: add rule netdev test-netdev egress limit rate 40/day: This rule should not have failed.
+any/limit.t: ERROR: line 16: add rule netdev test-netdev egress limit rate 400/week: This rule should not have failed.
+any/limit.t: ERROR: line 17: add rule netdev test-netdev egress limit rate 1023/second burst 10 packets: This rule should not have failed.
+any/limit.t: ERROR: line 20: add rule netdev test-netdev egress limit rate 1 kbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 21: add rule netdev test-netdev egress limit rate 2 kbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 22: add rule netdev test-netdev egress limit rate 1025 kbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 23: add rule netdev test-netdev egress limit rate 1023 mbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 24: add rule netdev test-netdev egress limit rate 10230 mbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 25: add rule netdev test-netdev egress limit rate 1023000 mbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 28: add rule netdev test-netdev egress limit rate 1 bytes / second: This rule should not have failed.
+any/limit.t: ERROR: line 29: add rule netdev test-netdev egress limit rate 1 kbytes / second: This rule should not have failed.
+any/limit.t: ERROR: line 30: add rule netdev test-netdev egress limit rate 1 mbytes / second: This rule should not have failed.
+any/limit.t: ERROR: line 33: add rule netdev test-netdev egress limit rate 1025 bytes/second burst 512 bytes: This rule should not have failed.
+any/limit.t: ERROR: line 34: add rule netdev test-netdev egress limit rate 1025 kbytes/second burst 1023 kbytes: This rule should not have failed.
+any/limit.t: ERROR: line 35: add rule netdev test-netdev egress limit rate 1025 mbytes/second burst 1025 kbytes: This rule should not have failed.
+any/limit.t: ERROR: line 36: add rule netdev test-netdev egress limit rate 1025000 mbytes/second burst 1023 mbytes: This rule should not have failed.
+any/limit.t: ERROR: line 38: add rule netdev test-netdev egress limit rate over 400/minute: This rule should not have failed.
+any/limit.t: ERROR: line 39: add rule netdev test-netdev egress limit rate over 20/second: This rule should not have failed.
+any/limit.t: ERROR: line 40: add rule netdev test-netdev egress limit rate over 400/hour: This rule should not have failed.
+any/limit.t: ERROR: line 41: add rule netdev test-netdev egress limit rate over 40/day: This rule should not have failed.
+any/limit.t: ERROR: line 42: add rule netdev test-netdev egress limit rate over 400/week: This rule should not have failed.
+any/limit.t: ERROR: line 43: add rule netdev test-netdev egress limit rate over 1023/second burst 10 packets: This rule should not have failed.
+any/limit.t: ERROR: line 45: add rule netdev test-netdev egress limit rate over 1 kbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 46: add rule netdev test-netdev egress limit rate over 2 kbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 47: add rule netdev test-netdev egress limit rate over 1025 kbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 48: add rule netdev test-netdev egress limit rate over 1023 mbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 49: add rule netdev test-netdev egress limit rate over 10230 mbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 50: add rule netdev test-netdev egress limit rate over 1023000 mbytes/second: This rule should not have failed.
+any/limit.t: ERROR: line 52: add rule netdev test-netdev egress limit rate over 1025 bytes/second burst 512 bytes: This rule should not have failed.
+any/limit.t: ERROR: line 53: add rule netdev test-netdev egress limit rate over 1025 kbytes/second burst 1023 kbytes: This rule should not have failed.
+any/limit.t: ERROR: line 54: add rule netdev test-netdev egress limit rate over 1025 mbytes/second burst 1025 kbytes: This rule should not have failed.
+any/limit.t: ERROR: line 55: add rule netdev test-netdev egress limit rate over 1025000 mbytes/second burst 1023 mbytes: This rule should not have failed.
+any/limit.t: ERROR: line 55: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+any/tcpopt.t: ERROR: line 58: add rule ip test-ip4 input reset tcp option mptcp: This rule should not have failed.
+any/tcpopt.t: ERROR: line 59: add rule ip test-ip4 input reset tcp option 2: This rule should not have failed.
+any/tcpopt.t: ERROR: line 60: add rule ip test-ip4 input reset tcp option 123: This rule should not have failed.
+arp/arp.t: ERROR: line 4: I cannot create the chain 'egress'
+arp/arp.t: ERROR: line 9: add rule netdev test-netdev egress arp htype 1: This rule should not have failed.
+arp/arp.t: ERROR: line 10: add rule netdev test-netdev egress arp htype != 1: This rule should not have failed.
+arp/arp.t: ERROR: line 11: add rule netdev test-netdev egress arp htype 22: This rule should not have failed.
+arp/arp.t: ERROR: line 12: add rule netdev test-netdev egress arp htype != 233: This rule should not have failed.
+arp/arp.t: ERROR: line 13: add rule netdev test-netdev egress arp htype 33-45: This rule should not have failed.
+arp/arp.t: ERROR: line 14: add rule netdev test-netdev egress arp htype != 33-45: This rule should not have failed.
+arp/arp.t: ERROR: line 15: add rule netdev test-netdev egress arp htype { 33, 55, 67, 88}: This rule should not have failed.
+arp/arp.t: ERROR: line 16: add rule netdev test-netdev egress arp htype != { 33, 55, 67, 88}: This rule should not have failed.
+arp/arp.t: ERROR: line 18: add rule netdev test-netdev egress arp ptype 0x0800: This rule should not have failed.
+arp/arp.t: ERROR: line 20: add rule netdev test-netdev egress arp hlen 22: This rule should not have failed.
+arp/arp.t: ERROR: line 21: add rule netdev test-netdev egress arp hlen != 233: This rule should not have failed.
+arp/arp.t: ERROR: line 22: add rule netdev test-netdev egress arp hlen 33-45: This rule should not have failed.
+arp/arp.t: ERROR: line 23: add rule netdev test-netdev egress arp hlen != 33-45: This rule should not have failed.
+arp/arp.t: ERROR: line 24: add rule netdev test-netdev egress arp hlen { 33, 55, 67, 88}: This rule should not have failed.
+arp/arp.t: ERROR: line 25: add rule netdev test-netdev egress arp hlen != { 33, 55, 67, 88}: This rule should not have failed.
+arp/arp.t: ERROR: line 27: add rule netdev test-netdev egress arp plen 22: This rule should not have failed.
+arp/arp.t: ERROR: line 28: add rule netdev test-netdev egress arp plen != 233: This rule should not have failed.
+arp/arp.t: ERROR: line 29: add rule netdev test-netdev egress arp plen 33-45: This rule should not have failed.
+arp/arp.t: ERROR: line 30: add rule netdev test-netdev egress arp plen != 33-45: This rule should not have failed.
+arp/arp.t: ERROR: line 31: add rule netdev test-netdev egress arp plen { 33, 55, 67, 88}: This rule should not have failed.
+arp/arp.t: ERROR: line 32: add rule netdev test-netdev egress arp plen != { 33, 55, 67, 88}: This rule should not have failed.
+arp/arp.t: ERROR: line 34: add rule netdev test-netdev egress arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request}: This rule should not have failed.
+arp/arp.t: ERROR: line 35: add rule netdev test-netdev egress arp operation != {nak, inreply, inrequest, rreply, rrequest, reply, request}: This rule should not have failed.
+arp/arp.t: ERROR: line 36: add rule netdev test-netdev egress arp operation 1-2: This rule should not have failed.
+arp/arp.t: ERROR: line 37: add rule netdev test-netdev egress arp operation request: This rule should not have failed.
+arp/arp.t: ERROR: line 38: add rule netdev test-netdev egress arp operation reply: This rule should not have failed.
+arp/arp.t: ERROR: line 39: add rule netdev test-netdev egress arp operation rrequest: This rule should not have failed.
+arp/arp.t: ERROR: line 40: add rule netdev test-netdev egress arp operation rreply: This rule should not have failed.
+arp/arp.t: ERROR: line 41: add rule netdev test-netdev egress arp operation inrequest: This rule should not have failed.
+arp/arp.t: ERROR: line 42: add rule netdev test-netdev egress arp operation inreply: This rule should not have failed.
+arp/arp.t: ERROR: line 43: add rule netdev test-netdev egress arp operation nak: This rule should not have failed.
+arp/arp.t: ERROR: line 44: add rule netdev test-netdev egress arp operation != request: This rule should not have failed.
+arp/arp.t: ERROR: line 45: add rule netdev test-netdev egress arp operation != reply: This rule should not have failed.
+arp/arp.t: ERROR: line 46: add rule netdev test-netdev egress arp operation != rrequest: This rule should not have failed.
+arp/arp.t: ERROR: line 47: add rule netdev test-netdev egress arp operation != rreply: This rule should not have failed.
+arp/arp.t: ERROR: line 48: add rule netdev test-netdev egress arp operation != inrequest: This rule should not have failed.
+arp/arp.t: ERROR: line 49: add rule netdev test-netdev egress arp operation != inreply: This rule should not have failed.
+arp/arp.t: ERROR: line 50: add rule netdev test-netdev egress arp operation != nak: This rule should not have failed.
+arp/arp.t: ERROR: line 52: add rule netdev test-netdev egress arp saddr ip 1.2.3.4: This rule should not have failed.
+arp/arp.t: ERROR: line 53: add rule netdev test-netdev egress arp daddr ip 4.3.2.1: This rule should not have failed.
+arp/arp.t: ERROR: line 54: add rule netdev test-netdev egress arp saddr ether aa:bb:cc:aa:bb:cc: This rule should not have failed.
+arp/arp.t: ERROR: line 55: add rule netdev test-netdev egress arp daddr ether aa:bb:cc:aa:bb:cc: This rule should not have failed.
+arp/arp.t: ERROR: line 57: add rule netdev test-netdev egress arp saddr ip 192.168.1.1 arp daddr ether fe:ed:00:c0:ff:ee: This rule should not have failed.
+arp/arp.t: ERROR: line 58: add rule netdev test-netdev egress arp daddr ether fe:ed:00:c0:ff:ee arp saddr ip 192.168.1.1: This rule should not have failed.
+arp/arp.t: ERROR: line 60: add rule netdev test-netdev egress meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566: This rule should not have failed.
+arp/arp.t: ERROR: line 60: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+bridge/meta.t: OK
+bridge/redirect.t: ERROR: line 5: add rule bridge test-bridge prerouting meta broute set 1: This rule should not have failed.
+bridge/icmpX.t: OK
+bridge/vlan.t: ERROR: line 3: I cannot create the chain 'egress'
+bridge/vlan.t: ERROR: line 8: add rule netdev test-netdev egress vlan id 4094: This rule should not have failed.
+bridge/vlan.t: ERROR: line 9: add rule netdev test-netdev egress vlan id 0: This rule should not have failed.
+bridge/vlan.t: ERROR: line 12: add rule netdev test-netdev egress vlan id 4094 vlan dei 0: This rule should not have failed.
+bridge/vlan.t: ERROR: line 13: add rule netdev test-netdev egress vlan id 4094 vlan dei 1: This rule should not have failed.
+bridge/vlan.t: ERROR: line 14: add rule netdev test-netdev egress vlan id 4094 vlan dei != 1: This rule should not have failed.
+bridge/vlan.t: ERROR: line 15: add rule netdev test-netdev egress vlan id 4094 vlan cfi 1: This rule should not have failed.
+bridge/vlan.t: ERROR: line 19: add rule netdev test-netdev egress vlan id 4094 vlan dei 1 vlan pcp 7: This rule should not have failed.
+bridge/vlan.t: ERROR: line 20: add rule netdev test-netdev egress vlan id 4094 vlan dei 1 vlan pcp 3: This rule should not have failed.
+bridge/vlan.t: ERROR: line 22: add rule netdev test-netdev egress ether type vlan vlan id 4094: This rule should not have failed.
+bridge/vlan.t: ERROR: line 23: add rule netdev test-netdev egress ether type vlan vlan id 0: This rule should not have failed.
+bridge/vlan.t: ERROR: line 24: add rule netdev test-netdev egress ether type vlan vlan id 4094 vlan dei 0: This rule should not have failed.
+bridge/vlan.t: ERROR: line 25: add rule netdev test-netdev egress ether type vlan vlan id 4094 vlan dei 1: This rule should not have failed.
+bridge/vlan.t: ERROR: line 28: add rule netdev test-netdev egress vlan id 4094 tcp dport 22: This rule should not have failed.
+bridge/vlan.t: ERROR: line 29: add rule netdev test-netdev egress vlan id 1 ip saddr 10.0.0.1: This rule should not have failed.
+bridge/vlan.t: ERROR: line 30: add rule netdev test-netdev egress vlan id 1 ip saddr 10.0.0.0/23: This rule should not have failed.
+bridge/vlan.t: ERROR: line 31: add rule netdev test-netdev egress vlan id 1 ip saddr 10.0.0.0/23 udp dport 53: This rule should not have failed.
+bridge/vlan.t: ERROR: line 32: add rule netdev test-netdev egress ether type vlan vlan id 1 ip saddr 10.0.0.0/23 udp dport 53: This rule should not have failed.
+bridge/vlan.t: ERROR: line 34: add rule netdev test-netdev egress vlan id { 1, 2, 4, 100, 4095 } vlan pcp 1-3: This rule should not have failed.
+bridge/vlan.t: ERROR: line 37: add rule netdev test-netdev egress ether type vlan ip protocol 1 accept: This rule should not have failed.
+bridge/vlan.t: ERROR: line 40: add rule netdev test-netdev egress ether type 8021ad vlan id 1 ip protocol 6 accept: This rule should not have failed.
+bridge/vlan.t: ERROR: line 41: add rule netdev test-netdev egress ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip counter: This rule should not have failed.
+bridge/vlan.t: ERROR: line 42: add rule netdev test-netdev egress ether type 8021ad vlan id 1 vlan type 8021q vlan id 2 vlan type ip ip protocol 6: This rule should not have failed.
+bridge/vlan.t: ERROR: line 49: add rule netdev test-netdev egress vlan id 1 vlan id set 2: This rule should not have failed.
+bridge/vlan.t: ERROR: line 51: add rule netdev test-netdev egress ether saddr 00:01:02:03:04:05 vlan id 1: This rule should not have failed.
+bridge/vlan.t: ERROR: line 52: add rule netdev test-netdev egress vlan id 2 ether saddr 0:1:2:3:4:6: This rule should not have failed.
+bridge/vlan.t: ERROR: line 54: add rule netdev test-netdev egress ether saddr . vlan id { 0a:0b:0c:0d:0e:0f . 42, 0a:0b:0c:0d:0e:0f . 4095 }: This rule should not have failed.
+bridge/vlan.t: ERROR: line 54: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+bridge/ether.t: OK
+bridge/reject.t: OK
+inet/ipsec.t: OK
+inet/vmap.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/vmap.t: ERROR: line 8: add rule netdev test-netdev egress iifname . ip protocol . th dport vmap { "eth0" . tcp . 22 : accept, "eth1" . udp . 67 : drop }: This rule should not have failed.
+inet/vmap.t: ERROR: line 9: add rule inet test-inet input ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e }: This rule should not have failed.
+inet/vmap.t: ERROR: line 10: add rule netdev test-netdev egress udp length . @th,160,128 vmap { 47-63 . 0xe373135363130333131303735353203 : accept }: This rule should not have failed.
+inet/vmap.t: ERROR: line 10: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/meta.t: OK
+inet/snat.t: OK
+inet/ether-ip.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/ether-ip.t: ERROR: line 8: add rule netdev test-netdev egress tcp dport 22 iiftype ether ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:4 accept: This rule should not have failed.
+inet/ether-ip.t: ERROR: line 9: add rule netdev test-netdev egress tcp dport 22 ip daddr 1.2.3.4 ether saddr 00:0f:54:0c:11:04: This rule should not have failed.
+inet/ether-ip.t: ERROR: line 9: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/rt.t: OK
+inet/ct.t: OK
+inet/ip.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/ip.t: ERROR: line 10: add rule netdev test-netdev egress ip saddr . ip daddr . ether saddr { 1.1.1.1 . 2.2.2.2 . ca:fe:ca:fe:ca:fe }: This rule should not have failed.
+inet/ip.t: ERROR: line 12: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/icmpX.t: OK
+inet/tcp.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/tcp.t: ERROR: line 12: add rule netdev test-netdev egress tcp dport 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 13: add rule netdev test-netdev egress tcp dport != 233: This rule should not have failed.
+inet/tcp.t: ERROR: line 14: add rule netdev test-netdev egress tcp dport 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 15: add rule netdev test-netdev egress tcp dport != 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 16: add rule netdev test-netdev egress tcp dport { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 17: add rule netdev test-netdev egress tcp dport != { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 18: add rule netdev test-netdev egress tcp dport {telnet, http, https} accept: This rule should not have failed.
+inet/tcp.t: ERROR: line 19: add rule netdev test-netdev egress tcp dport vmap { 22 : accept, 23 : drop }: This rule should not have failed.
+inet/tcp.t: ERROR: line 20: add rule netdev test-netdev egress tcp dport vmap { 25:accept, 28:drop }: This rule should not have failed.
+inet/tcp.t: ERROR: line 21: add rule netdev test-netdev egress tcp dport { 22, 53, 80, 110 }: This rule should not have failed.
+inet/tcp.t: ERROR: line 22: add rule netdev test-netdev egress tcp dport != { 22, 53, 80, 110 }: This rule should not have failed.
+inet/tcp.t: ERROR: line 26: add rule netdev test-netdev egress tcp sport 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 27: add rule netdev test-netdev egress tcp sport != 233: This rule should not have failed.
+inet/tcp.t: ERROR: line 28: add rule netdev test-netdev egress tcp sport 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 29: add rule netdev test-netdev egress tcp sport != 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 30: add rule netdev test-netdev egress tcp sport { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 31: add rule netdev test-netdev egress tcp sport != { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 32: add rule netdev test-netdev egress tcp sport vmap { 25:accept, 28:drop }: This rule should not have failed.
+inet/tcp.t: ERROR: line 34: add rule netdev test-netdev egress tcp sport 8080 drop: This rule should not have failed.
+inet/tcp.t: ERROR: line 35: add rule netdev test-netdev egress tcp sport 1024 tcp dport 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 36: add rule netdev test-netdev egress tcp sport 1024 tcp dport 22 tcp sequence 0: This rule should not have failed.
+inet/tcp.t: ERROR: line 38: add rule netdev test-netdev egress tcp sequence 0 tcp sport 1024 tcp dport 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 39: add rule netdev test-netdev egress tcp sequence 0 tcp sport { 1024, 1022} tcp dport 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 41: add rule netdev test-netdev egress tcp sequence 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 42: add rule netdev test-netdev egress tcp sequence != 233: This rule should not have failed.
+inet/tcp.t: ERROR: line 43: add rule netdev test-netdev egress tcp sequence 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 44: add rule netdev test-netdev egress tcp sequence != 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 45: add rule netdev test-netdev egress tcp sequence { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 46: add rule netdev test-netdev egress tcp sequence != { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 48: add rule netdev test-netdev egress tcp ackseq 42949672 drop: This rule should not have failed.
+inet/tcp.t: ERROR: line 49: add rule netdev test-netdev egress tcp ackseq 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 50: add rule netdev test-netdev egress tcp ackseq != 233: This rule should not have failed.
+inet/tcp.t: ERROR: line 51: add rule netdev test-netdev egress tcp ackseq 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 52: add rule netdev test-netdev egress tcp ackseq != 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 53: add rule netdev test-netdev egress tcp ackseq { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 54: add rule netdev test-netdev egress tcp ackseq != { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 66: add rule netdev test-netdev egress tcp flags { fin, syn, rst, psh, ack, urg, ecn, cwr} drop: This rule should not have failed.
+inet/tcp.t: ERROR: line 67: add rule netdev test-netdev egress tcp flags != { fin, urg, ecn, cwr} drop: This rule should not have failed.
+inet/tcp.t: ERROR: line 68: add rule netdev test-netdev egress tcp flags cwr: This rule should not have failed.
+inet/tcp.t: ERROR: line 69: add rule netdev test-netdev egress tcp flags != cwr: This rule should not have failed.
+inet/tcp.t: ERROR: line 70: add rule netdev test-netdev egress tcp flags == syn: This rule should not have failed.
+inet/tcp.t: ERROR: line 71: add rule netdev test-netdev egress tcp flags fin,syn / fin,syn: This rule should not have failed.
+inet/tcp.t: ERROR: line 72: add rule netdev test-netdev egress tcp flags != syn / fin,syn: This rule should not have failed.
+inet/tcp.t: ERROR: line 73: add rule netdev test-netdev egress tcp flags & syn != 0: This rule should not have failed.
+inet/tcp.t: ERROR: line 74: add rule netdev test-netdev egress tcp flags & syn == 0: This rule should not have failed.
+inet/tcp.t: ERROR: line 75: add rule netdev test-netdev egress tcp flags & (syn | ack) != 0: This rule should not have failed.
+inet/tcp.t: ERROR: line 76: add rule netdev test-netdev egress tcp flags & (syn | ack) == 0: This rule should not have failed.
+inet/tcp.t: ERROR: line 78: add rule netdev test-netdev egress tcp flags & syn == syn: This rule should not have failed.
+inet/tcp.t: ERROR: line 79: add rule netdev test-netdev egress tcp flags & syn != syn: This rule should not have failed.
+inet/tcp.t: ERROR: line 80: add rule netdev test-netdev egress tcp flags & (fin | syn | rst | ack) syn: This rule should not have failed.
+inet/tcp.t: ERROR: line 81: add rule netdev test-netdev egress tcp flags & (fin | syn | rst | ack) == syn: This rule should not have failed.
+inet/tcp.t: ERROR: line 82: add rule netdev test-netdev egress tcp flags & (fin | syn | rst | ack) != syn: This rule should not have failed.
+inet/tcp.t: ERROR: line 83: add rule netdev test-netdev egress tcp flags & (fin | syn | rst | ack) == (syn | ack): This rule should not have failed.
+inet/tcp.t: ERROR: line 84: add rule netdev test-netdev egress tcp flags & (fin | syn | rst | ack) != (syn | ack): This rule should not have failed.
+inet/tcp.t: ERROR: line 85: add rule netdev test-netdev egress tcp flags & (syn | ack) == (syn | ack): This rule should not have failed.
+inet/tcp.t: ERROR: line 86: add rule netdev test-netdev egress tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr: This rule should not have failed.
+inet/tcp.t: ERROR: line 87: add rule netdev test-netdev egress tcp flags { syn, syn | ack }: This rule should not have failed.
+inet/tcp.t: ERROR: line 88: add rule netdev test-netdev egress tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack }: This rule should not have failed.
+inet/tcp.t: ERROR: line 89: add rule netdev test-netdev egress tcp flags ! fin,rst: This rule should not have failed.
+inet/tcp.t: ERROR: line 92: add rule netdev test-netdev egress tcp window 22222: This rule should not have failed.
+inet/tcp.t: ERROR: line 93: add rule netdev test-netdev egress tcp window 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 94: add rule netdev test-netdev egress tcp window != 233: This rule should not have failed.
+inet/tcp.t: ERROR: line 95: add rule netdev test-netdev egress tcp window 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 96: add rule netdev test-netdev egress tcp window != 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 97: add rule netdev test-netdev egress tcp window { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 98: add rule netdev test-netdev egress tcp window != { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 100: add rule netdev test-netdev egress tcp checksum 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 101: add rule netdev test-netdev egress tcp checksum != 233: This rule should not have failed.
+inet/tcp.t: ERROR: line 102: add rule netdev test-netdev egress tcp checksum 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 103: add rule netdev test-netdev egress tcp checksum != 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 104: add rule netdev test-netdev egress tcp checksum { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 105: add rule netdev test-netdev egress tcp checksum != { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 107: add rule netdev test-netdev egress tcp urgptr 1234 accept: This rule should not have failed.
+inet/tcp.t: ERROR: line 108: add rule netdev test-netdev egress tcp urgptr 22: This rule should not have failed.
+inet/tcp.t: ERROR: line 109: add rule netdev test-netdev egress tcp urgptr != 233: This rule should not have failed.
+inet/tcp.t: ERROR: line 110: add rule netdev test-netdev egress tcp urgptr 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 111: add rule netdev test-netdev egress tcp urgptr != 33-45: This rule should not have failed.
+inet/tcp.t: ERROR: line 112: add rule netdev test-netdev egress tcp urgptr { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 113: add rule netdev test-netdev egress tcp urgptr != { 33, 55, 67, 88}: This rule should not have failed.
+inet/tcp.t: ERROR: line 115: add rule netdev test-netdev egress tcp doff 8: This rule should not have failed.
+inet/tcp.t: ERROR: line 115: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/icmp.t: OK
+inet/socket.t: OK
+inet/udplite.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/udplite.t: ERROR: line 10: add rule netdev test-netdev egress udplite sport 80 accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 11: add rule netdev test-netdev egress udplite sport != 60 accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 12: add rule netdev test-netdev egress udplite sport 50-70 accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 13: add rule netdev test-netdev egress udplite sport != 50-60 accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 14: add rule netdev test-netdev egress udplite sport { 49, 50} drop: This rule should not have failed.
+inet/udplite.t: ERROR: line 15: add rule netdev test-netdev egress udplite sport != { 49, 50} accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 17: add rule netdev test-netdev egress udplite dport 80 accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 18: add rule netdev test-netdev egress udplite dport != 60 accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 19: add rule netdev test-netdev egress udplite dport 70-75 accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 20: add rule netdev test-netdev egress udplite dport != 50-60 accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 21: add rule netdev test-netdev egress udplite dport { 49, 50} drop: This rule should not have failed.
+inet/udplite.t: ERROR: line 22: add rule netdev test-netdev egress udplite dport != { 49, 50} accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 31: add rule netdev test-netdev egress udplite checksum 6666 drop: This rule should not have failed.
+inet/udplite.t: ERROR: line 32: add rule netdev test-netdev egress udplite checksum != { 444, 555} accept: This rule should not have failed.
+inet/udplite.t: ERROR: line 33: add rule netdev test-netdev egress udplite checksum 22: This rule should not have failed.
+inet/udplite.t: ERROR: line 34: add rule netdev test-netdev egress udplite checksum != 233: This rule should not have failed.
+inet/udplite.t: ERROR: line 35: add rule netdev test-netdev egress udplite checksum 33-45: This rule should not have failed.
+inet/udplite.t: ERROR: line 36: add rule netdev test-netdev egress udplite checksum != 33-45: This rule should not have failed.
+inet/udplite.t: ERROR: line 37: add rule netdev test-netdev egress udplite checksum { 33, 55, 67, 88}: This rule should not have failed.
+inet/udplite.t: ERROR: line 38: add rule netdev test-netdev egress udplite checksum != { 33, 55, 67, 88}: This rule should not have failed.
+inet/udplite.t: ERROR: line 38: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/dccp.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/dccp.t: ERROR: line 10: add rule netdev test-netdev egress dccp sport 21-35: This rule should not have failed.
+inet/dccp.t: ERROR: line 11: add rule netdev test-netdev egress dccp sport != 21-35: This rule should not have failed.
+inet/dccp.t: ERROR: line 12: add rule netdev test-netdev egress dccp sport {23, 24, 25}: This rule should not have failed.
+inet/dccp.t: ERROR: line 13: add rule netdev test-netdev egress dccp sport != {23, 24, 25}: This rule should not have failed.
+inet/dccp.t: ERROR: line 15: add rule netdev test-netdev egress dccp sport 20-50: This rule should not have failed.
+inet/dccp.t: ERROR: line 19: add rule netdev test-netdev egress dccp dport {23, 24, 25}: This rule should not have failed.
+inet/dccp.t: ERROR: line 20: add rule netdev test-netdev egress dccp dport != {23, 24, 25}: This rule should not have failed.
+inet/dccp.t: ERROR: line 22: add rule netdev test-netdev egress dccp type {request, response, data, ack, dataack, closereq, close, reset, sync, syncack}: This rule should not have failed.
+inet/dccp.t: ERROR: line 23: add rule netdev test-netdev egress dccp type != {request, response, data, ack, dataack, closereq, close, reset, sync, syncack}: This rule should not have failed.
+inet/dccp.t: ERROR: line 24: add rule netdev test-netdev egress dccp type request: This rule should not have failed.
+inet/dccp.t: ERROR: line 25: add rule netdev test-netdev egress dccp type != request: This rule should not have failed.
+inet/dccp.t: ERROR: line 27: add rule ip test-ip4 input dccp option 0 exists: This rule should not have failed.
+inet/dccp.t: ERROR: line 28: add rule ip test-ip4 input dccp option 43 missing: This rule should not have failed.
+inet/dccp.t: ERROR: line 29: add rule ip test-ip4 input dccp option 255 exists: This rule should not have failed.
+inet/dccp.t: ERROR: line 30: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/tproxy.t: OK
+inet/ether.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/ether.t: ERROR: line 11: add rule netdev test-netdev egress tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept: This rule should not have failed.
+inet/ether.t: ERROR: line 12: add rule netdev test-netdev egress tcp dport 22 ether saddr 00:0f:54:0c:11:04 accept: This rule should not have failed.
+inet/ether.t: ERROR: line 14: add rule netdev test-netdev egress ether saddr 00:0f:54:0c:11:04 accept: This rule should not have failed.
+inet/ether.t: ERROR: line 16: add rule netdev test-netdev egress vlan id 1: This rule should not have failed.
+inet/ether.t: ERROR: line 17: add rule netdev test-netdev egress ether type vlan vlan id 2: This rule should not have failed.
+inet/ether.t: ERROR: line 20: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/synproxy.t: OK
+inet/sctp.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/sctp.t: ERROR: line 10: add rule netdev test-netdev egress sctp sport 23: This rule should not have failed.
+inet/sctp.t: ERROR: line 11: add rule netdev test-netdev egress sctp sport != 23: This rule should not have failed.
+inet/sctp.t: ERROR: line 12: add rule netdev test-netdev egress sctp sport 23-44: This rule should not have failed.
+inet/sctp.t: ERROR: line 13: add rule netdev test-netdev egress sctp sport != 23-44: This rule should not have failed.
+inet/sctp.t: ERROR: line 14: add rule netdev test-netdev egress sctp sport { 23, 24, 25}: This rule should not have failed.
+inet/sctp.t: ERROR: line 15: add rule netdev test-netdev egress sctp sport != { 23, 24, 25}: This rule should not have failed.
+inet/sctp.t: ERROR: line 17: add rule netdev test-netdev egress sctp dport 23: This rule should not have failed.
+inet/sctp.t: ERROR: line 18: add rule netdev test-netdev egress sctp dport != 23: This rule should not have failed.
+inet/sctp.t: ERROR: line 19: add rule netdev test-netdev egress sctp dport 23-44: This rule should not have failed.
+inet/sctp.t: ERROR: line 20: add rule netdev test-netdev egress sctp dport != 23-44: This rule should not have failed.
+inet/sctp.t: ERROR: line 21: add rule netdev test-netdev egress sctp dport { 23, 24, 25}: This rule should not have failed.
+inet/sctp.t: ERROR: line 22: add rule netdev test-netdev egress sctp dport != { 23, 24, 25}: This rule should not have failed.
+inet/sctp.t: ERROR: line 24: add rule netdev test-netdev egress sctp checksum 1111: This rule should not have failed.
+inet/sctp.t: ERROR: line 25: add rule netdev test-netdev egress sctp checksum != 11: This rule should not have failed.
+inet/sctp.t: ERROR: line 26: add rule netdev test-netdev egress sctp checksum 21-333: This rule should not have failed.
+inet/sctp.t: ERROR: line 27: add rule netdev test-netdev egress sctp checksum != 32-111: This rule should not have failed.
+inet/sctp.t: ERROR: line 28: add rule netdev test-netdev egress sctp checksum { 22, 33, 44}: This rule should not have failed.
+inet/sctp.t: ERROR: line 29: add rule netdev test-netdev egress sctp checksum != { 22, 33, 44}: This rule should not have failed.
+inet/sctp.t: ERROR: line 31: add rule netdev test-netdev egress sctp vtag 22: This rule should not have failed.
+inet/sctp.t: ERROR: line 32: add rule netdev test-netdev egress sctp vtag != 233: This rule should not have failed.
+inet/sctp.t: ERROR: line 33: add rule netdev test-netdev egress sctp vtag 33-45: This rule should not have failed.
+inet/sctp.t: ERROR: line 34: add rule netdev test-netdev egress sctp vtag != 33-45: This rule should not have failed.
+inet/sctp.t: ERROR: line 35: add rule netdev test-netdev egress sctp vtag {33, 55, 67, 88}: This rule should not have failed.
+inet/sctp.t: ERROR: line 36: add rule netdev test-netdev egress sctp vtag != {33, 55, 67, 88}: This rule should not have failed.
+inet/sctp.t: ERROR: line 39: add rule ip test-ip4 input sctp chunk data exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 40: add rule ip test-ip4 input sctp chunk init exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 41: add rule ip test-ip4 input sctp chunk init-ack exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 42: add rule ip test-ip4 input sctp chunk sack exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 43: add rule ip test-ip4 input sctp chunk heartbeat exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 44: add rule ip test-ip4 input sctp chunk heartbeat-ack exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 45: add rule ip test-ip4 input sctp chunk abort exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 46: add rule ip test-ip4 input sctp chunk shutdown exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 47: add rule ip test-ip4 input sctp chunk shutdown-ack exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 48: add rule ip test-ip4 input sctp chunk error exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 49: add rule ip test-ip4 input sctp chunk cookie-echo exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 50: add rule ip test-ip4 input sctp chunk cookie-ack exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 51: add rule ip test-ip4 input sctp chunk ecne exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 52: add rule ip test-ip4 input sctp chunk cwr exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 53: add rule ip test-ip4 input sctp chunk shutdown-complete exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 54: add rule ip test-ip4 input sctp chunk asconf-ack exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 55: add rule ip test-ip4 input sctp chunk forward-tsn exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 56: add rule ip test-ip4 input sctp chunk asconf exists: This rule should not have failed.
+inet/sctp.t: ERROR: line 59: add rule ip test-ip4 input sctp chunk data type 0: This rule should not have failed.
+inet/sctp.t: ERROR: line 60: add rule ip test-ip4 input sctp chunk init flags 23: This rule should not have failed.
+inet/sctp.t: ERROR: line 61: add rule ip test-ip4 input sctp chunk init-ack length 42: This rule should not have failed.
+inet/sctp.t: ERROR: line 64: add rule ip test-ip4 input sctp chunk data stream 1337: This rule should not have failed.
+inet/sctp.t: ERROR: line 65: add rule ip test-ip4 input sctp chunk init initial-tsn 5: This rule should not have failed.
+inet/sctp.t: ERROR: line 66: add rule ip test-ip4 input sctp chunk init-ack num-outbound-streams 3: This rule should not have failed.
+inet/sctp.t: ERROR: line 67: add rule ip test-ip4 input sctp chunk sack a-rwnd 1: This rule should not have failed.
+inet/sctp.t: ERROR: line 68: add rule ip test-ip4 input sctp chunk shutdown cum-tsn-ack 65535: This rule should not have failed.
+inet/sctp.t: ERROR: line 69: add rule ip test-ip4 input sctp chunk ecne lowest-tsn 5: This rule should not have failed.
+inet/sctp.t: ERROR: line 70: add rule ip test-ip4 input sctp chunk cwr lowest-tsn 8: This rule should not have failed.
+inet/sctp.t: ERROR: line 71: add rule ip test-ip4 input sctp chunk asconf-ack seqno 12345: This rule should not have failed.
+inet/sctp.t: ERROR: line 72: add rule ip test-ip4 input sctp chunk forward-tsn new-cum-tsn 31337: This rule should not have failed.
+inet/sctp.t: ERROR: line 73: add rule ip test-ip4 input sctp chunk asconf seqno 12345: This rule should not have failed.
+inet/sctp.t: ERROR: line 73: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/map.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/map.t: ERROR: line 9: add rule netdev test-netdev egress mark set ip saddr map { 10.2.3.2 : 0x0000002a, 10.2.3.1 : 0x00000017}: This rule should not have failed.
+inet/map.t: ERROR: line 10: add rule netdev test-netdev egress mark set ip hdrlength map { 5 : 0x00000017, 4 : 0x00000001}: This rule should not have failed.
+inet/map.t: ERROR: line 10: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/ip_tcp.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/ip_tcp.t: ERROR: line 10: add rule netdev test-netdev egress ip protocol tcp tcp dport 22: This rule should not have failed.
+inet/ip_tcp.t: ERROR: line 13: add rule netdev test-netdev egress ip protocol tcp ip saddr 1.2.3.4 tcp dport 22: This rule should not have failed.
+inet/ip_tcp.t: ERROR: line 16: add rule netdev test-netdev egress ip protocol tcp counter ip saddr 1.2.3.4 tcp dport 22: This rule should not have failed.
+inet/ip_tcp.t: ERROR: line 19: add rule netdev test-netdev egress ip protocol tcp counter tcp dport 22: This rule should not have failed.
+inet/ip_tcp.t: ERROR: line 21: add rule netdev test-netdev egress ether type ip tcp dport 22: This rule should not have failed.
+inet/ip_tcp.t: ERROR: line 21: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/fib.t: OK
+inet/vxlan.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/vxlan.t: ERROR: line 11: add rule ip test-ip4 input udp dport 4789 vxlan vni 10: This rule should not have failed.
+inet/vxlan.t: ERROR: line 12: add rule ip test-ip4 input udp dport 4789 vxlan ip saddr 10.141.11.2: This rule should not have failed.
+inet/vxlan.t: ERROR: line 13: add rule ip test-ip4 input udp dport 4789 vxlan ip saddr 10.141.11.0/24: This rule should not have failed.
+inet/vxlan.t: ERROR: line 14: add rule ip test-ip4 input udp dport 4789 vxlan ip protocol 1: This rule should not have failed.
+inet/vxlan.t: ERROR: line 15: add rule ip test-ip4 input udp dport 4789 vxlan udp sport 8888: This rule should not have failed.
+inet/vxlan.t: ERROR: line 16: add rule ip test-ip4 input udp dport 4789 vxlan icmp type echo-reply: This rule should not have failed.
+inet/vxlan.t: ERROR: line 17: add rule ip test-ip4 input udp dport 4789 vxlan ether saddr 62:87:4d:d6:19:05: This rule should not have failed.
+inet/vxlan.t: ERROR: line 18: add rule ip test-ip4 input udp dport 4789 vxlan vlan id 10: This rule should not have failed.
+inet/vxlan.t: ERROR: line 19: add rule ip test-ip4 input udp dport 4789 vxlan ip dscp 0x02: This rule should not have failed.
+inet/vxlan.t: ERROR: line 20: add rule ip test-ip4 input udp dport 4789 vxlan ip dscp 0x02: This rule should not have failed.
+inet/vxlan.t: ERROR: line 21: add rule ip test-ip4 input udp dport 4789 vxlan ip saddr . vxlan ip daddr { 1.2.3.4 . 4.3.2.1 }: This rule should not have failed.
+inet/vxlan.t: ERROR: line 23: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/ah.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/ah.t: ERROR: line 22: add rule netdev test-netdev egress ah hdrlength 11-23: This rule should not have failed.
+inet/ah.t: ERROR: line 23: add rule netdev test-netdev egress ah hdrlength != 11-23: This rule should not have failed.
+inet/ah.t: ERROR: line 24: add rule netdev test-netdev egress ah hdrlength {11, 23, 44 }: This rule should not have failed.
+inet/ah.t: ERROR: line 25: add rule netdev test-netdev egress ah hdrlength != {11, 23, 44 }: This rule should not have failed.
+inet/ah.t: ERROR: line 27: add rule netdev test-netdev egress ah reserved 22: This rule should not have failed.
+inet/ah.t: ERROR: line 28: add rule netdev test-netdev egress ah reserved != 233: This rule should not have failed.
+inet/ah.t: ERROR: line 29: add rule netdev test-netdev egress ah reserved 33-45: This rule should not have failed.
+inet/ah.t: ERROR: line 30: add rule netdev test-netdev egress ah reserved != 33-45: This rule should not have failed.
+inet/ah.t: ERROR: line 31: add rule netdev test-netdev egress ah reserved {23, 100}: This rule should not have failed.
+inet/ah.t: ERROR: line 32: add rule netdev test-netdev egress ah reserved != {23, 100}: This rule should not have failed.
+inet/ah.t: ERROR: line 34: add rule netdev test-netdev egress ah spi 111: This rule should not have failed.
+inet/ah.t: ERROR: line 35: add rule netdev test-netdev egress ah spi != 111: This rule should not have failed.
+inet/ah.t: ERROR: line 36: add rule netdev test-netdev egress ah spi 111-222: This rule should not have failed.
+inet/ah.t: ERROR: line 37: add rule netdev test-netdev egress ah spi != 111-222: This rule should not have failed.
+inet/ah.t: ERROR: line 38: add rule netdev test-netdev egress ah spi {111, 122}: This rule should not have failed.
+inet/ah.t: ERROR: line 39: add rule netdev test-netdev egress ah spi != {111, 122}: This rule should not have failed.
+inet/ah.t: ERROR: line 42: add rule netdev test-netdev egress ah sequence 123: This rule should not have failed.
+inet/ah.t: ERROR: line 43: add rule netdev test-netdev egress ah sequence != 123: This rule should not have failed.
+inet/ah.t: ERROR: line 44: add rule netdev test-netdev egress ah sequence {23, 25, 33}: This rule should not have failed.
+inet/ah.t: ERROR: line 45: add rule netdev test-netdev egress ah sequence != {23, 25, 33}: This rule should not have failed.
+inet/ah.t: ERROR: line 46: add rule netdev test-netdev egress ah sequence 23-33: This rule should not have failed.
+inet/ah.t: ERROR: line 47: add rule netdev test-netdev egress ah sequence != 23-33: This rule should not have failed.
+inet/ah.t: ERROR: line 47: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/dnat.t: OK
+inet/esp.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/esp.t: ERROR: line 10: add rule netdev test-netdev egress esp spi 100: This rule should not have failed.
+inet/esp.t: ERROR: line 11: add rule netdev test-netdev egress esp spi != 100: This rule should not have failed.
+inet/esp.t: ERROR: line 12: add rule netdev test-netdev egress esp spi 111-222: This rule should not have failed.
+inet/esp.t: ERROR: line 13: add rule netdev test-netdev egress esp spi != 111-222: This rule should not have failed.
+inet/esp.t: ERROR: line 14: add rule netdev test-netdev egress esp spi { 100, 102}: This rule should not have failed.
+inet/esp.t: ERROR: line 15: add rule netdev test-netdev egress esp spi != { 100, 102}: This rule should not have failed.
+inet/esp.t: ERROR: line 17: add rule netdev test-netdev egress esp sequence 22: This rule should not have failed.
+inet/esp.t: ERROR: line 18: add rule netdev test-netdev egress esp sequence 22-24: This rule should not have failed.
+inet/esp.t: ERROR: line 19: add rule netdev test-netdev egress esp sequence != 22-24: This rule should not have failed.
+inet/esp.t: ERROR: line 20: add rule netdev test-netdev egress esp sequence { 22, 24}: This rule should not have failed.
+inet/esp.t: ERROR: line 21: add rule netdev test-netdev egress esp sequence != { 22, 24}: This rule should not have failed.
+inet/esp.t: ERROR: line 21: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/geneve.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/geneve.t: ERROR: line 11: add rule ip test-ip4 input udp dport 6081 geneve vni 10: This rule should not have failed.
+inet/geneve.t: ERROR: line 12: add rule ip test-ip4 input udp dport 6081 geneve ip saddr 10.141.11.2: This rule should not have failed.
+inet/geneve.t: ERROR: line 13: add rule ip test-ip4 input udp dport 6081 geneve ip saddr 10.141.11.0/24: This rule should not have failed.
+inet/geneve.t: ERROR: line 14: add rule ip test-ip4 input udp dport 6081 geneve ip protocol 1: This rule should not have failed.
+inet/geneve.t: ERROR: line 15: add rule ip test-ip4 input udp dport 6081 geneve udp sport 8888: This rule should not have failed.
+inet/geneve.t: ERROR: line 16: add rule ip test-ip4 input udp dport 6081 geneve icmp type echo-reply: This rule should not have failed.
+inet/geneve.t: ERROR: line 17: add rule ip test-ip4 input udp dport 6081 geneve ether saddr 62:87:4d:d6:19:05: This rule should not have failed.
+inet/geneve.t: ERROR: line 18: add rule ip test-ip4 input udp dport 6081 geneve vlan id 10: This rule should not have failed.
+inet/geneve.t: ERROR: line 19: add rule ip test-ip4 input udp dport 6081 geneve ip dscp 0x02: This rule should not have failed.
+inet/geneve.t: ERROR: line 20: add rule ip test-ip4 input udp dport 6081 geneve ip dscp 0x02: This rule should not have failed.
+inet/geneve.t: ERROR: line 21: add rule ip test-ip4 input udp dport 6081 geneve ip saddr . geneve ip daddr { 1.2.3.4 . 4.3.2.1 }: This rule should not have failed.
+inet/geneve.t: ERROR: line 23: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/udp.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/udp.t: ERROR: line 10: add rule netdev test-netdev egress udp sport 80 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 11: add rule netdev test-netdev egress udp sport != 60 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 12: add rule netdev test-netdev egress udp sport 50-70 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 13: add rule netdev test-netdev egress udp sport != 50-60 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 14: add rule netdev test-netdev egress udp sport { 49, 50} drop: This rule should not have failed.
+inet/udp.t: ERROR: line 15: add rule netdev test-netdev egress udp sport != { 50, 60} accept: This rule should not have failed.
+inet/udp.t: ERROR: line 19: add rule netdev test-netdev egress udp dport 80 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 20: add rule netdev test-netdev egress udp dport != 60 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 21: add rule netdev test-netdev egress udp dport 70-75 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 22: add rule netdev test-netdev egress udp dport != 50-60 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 23: add rule netdev test-netdev egress udp dport { 49, 50} drop: This rule should not have failed.
+inet/udp.t: ERROR: line 24: add rule netdev test-netdev egress udp dport != { 50, 60} accept: This rule should not have failed.
+inet/udp.t: ERROR: line 26: add rule netdev test-netdev egress udp length 6666: This rule should not have failed.
+inet/udp.t: ERROR: line 27: add rule netdev test-netdev egress udp length != 6666: This rule should not have failed.
+inet/udp.t: ERROR: line 28: add rule netdev test-netdev egress udp length 50-65 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 29: add rule netdev test-netdev egress udp length != 50-65 accept: This rule should not have failed.
+inet/udp.t: ERROR: line 30: add rule netdev test-netdev egress udp length { 50, 65} accept: This rule should not have failed.
+inet/udp.t: ERROR: line 31: add rule netdev test-netdev egress udp length != { 50, 65} accept: This rule should not have failed.
+inet/udp.t: ERROR: line 33: add rule netdev test-netdev egress udp checksum 6666 drop: This rule should not have failed.
+inet/udp.t: ERROR: line 34: add rule netdev test-netdev egress udp checksum != { 444, 555} accept: This rule should not have failed.
+inet/udp.t: ERROR: line 36: add rule netdev test-netdev egress udp checksum 22: This rule should not have failed.
+inet/udp.t: ERROR: line 37: add rule netdev test-netdev egress udp checksum != 233: This rule should not have failed.
+inet/udp.t: ERROR: line 38: add rule netdev test-netdev egress udp checksum 33-45: This rule should not have failed.
+inet/udp.t: ERROR: line 39: add rule netdev test-netdev egress udp checksum != 33-45: This rule should not have failed.
+inet/udp.t: ERROR: line 40: add rule netdev test-netdev egress udp checksum { 33, 55, 67, 88}: This rule should not have failed.
+inet/udp.t: ERROR: line 41: add rule netdev test-netdev egress udp checksum != { 33, 55, 67, 88}: This rule should not have failed.
+inet/udp.t: ERROR: line 44: add rule netdev test-netdev egress iif "lo" udp checksum set 0: This rule should not have failed.
+inet/udp.t: ERROR: line 45: add rule netdev test-netdev egress iif "lo" udp dport set 65535: This rule should not have failed.
+inet/udp.t: ERROR: line 45: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/sets.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/sets.t: ERROR: line 15: add rule netdev test-netdev egress ip saddr @set1 drop: This rule should not have failed.
+inet/sets.t: ERROR: line 18: add rule netdev test-netdev egress ip6 daddr != @set2 accept: This rule should not have failed.
+inet/sets.t: ERROR: line 24: add rule netdev test-netdev egress ip saddr . ip daddr . tcp dport @set3 accept: This rule should not have failed.
+inet/sets.t: ERROR: line 25: add rule netdev test-netdev egress ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept: This rule should not have failed.
+inet/sets.t: ERROR: line 25: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/gretap.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/gretap.t: ERROR: line 10: add rule ip test-ip4 input gretap ip saddr 10.141.11.2: This rule should not have failed.
+inet/gretap.t: ERROR: line 11: add rule ip test-ip4 input gretap ip saddr 10.141.11.0/24: This rule should not have failed.
+inet/gretap.t: ERROR: line 12: add rule ip test-ip4 input gretap ip protocol 1: This rule should not have failed.
+inet/gretap.t: ERROR: line 13: add rule ip test-ip4 input gretap udp sport 8888: This rule should not have failed.
+inet/gretap.t: ERROR: line 14: add rule ip test-ip4 input gretap icmp type echo-reply: This rule should not have failed.
+inet/gretap.t: ERROR: line 15: add rule ip test-ip4 input gretap ether saddr 62:87:4d:d6:19:05: This rule should not have failed.
+inet/gretap.t: ERROR: line 16: add rule ip test-ip4 input gretap vlan id 10: This rule should not have failed.
+inet/gretap.t: ERROR: line 17: add rule ip test-ip4 input gretap ip dscp 0x02: This rule should not have failed.
+inet/gretap.t: ERROR: line 18: add rule ip test-ip4 input gretap ip dscp 0x02: This rule should not have failed.
+inet/gretap.t: ERROR: line 19: add rule ip test-ip4 input gretap ip saddr . gretap ip daddr { 1.2.3.4 . 4.3.2.1 }: This rule should not have failed.
+inet/gretap.t: ERROR: line 21: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/osf.t: OK
+inet/gre.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/gre.t: ERROR: line 10: add rule netdev test-netdev egress gre version 0: This rule should not have failed.
+inet/gre.t: ERROR: line 11: add rule ip test-ip4 input gre ip saddr 10.141.11.2: This rule should not have failed.
+inet/gre.t: ERROR: line 12: add rule ip test-ip4 input gre ip saddr 10.141.11.0/24: This rule should not have failed.
+inet/gre.t: ERROR: line 13: add rule ip test-ip4 input gre ip protocol 1: This rule should not have failed.
+inet/gre.t: ERROR: line 14: add rule ip test-ip4 input gre udp sport 8888: This rule should not have failed.
+inet/gre.t: ERROR: line 15: add rule ip test-ip4 input gre icmp type echo-reply: This rule should not have failed.
+inet/gre.t: ERROR: line 18: add rule ip test-ip4 input gre ip dscp 0x02: This rule should not have failed.
+inet/gre.t: ERROR: line 19: add rule ip test-ip4 input gre ip dscp 0x02: This rule should not have failed.
+inet/gre.t: ERROR: line 20: add rule ip test-ip4 input gre ip saddr . gre ip daddr { 1.2.3.4 . 4.3.2.1 }: This rule should not have failed.
+inet/gre.t: ERROR: line 22: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/comp.t: ERROR: line 3: I cannot create the chain 'egress'
+inet/comp.t: ERROR: line 12: add rule netdev test-netdev egress comp nexthdr != esp: This rule should not have failed.
+inet/comp.t: ERROR: line 18: add rule netdev test-netdev egress comp flags 0x0: This rule should not have failed.
+inet/comp.t: ERROR: line 19: add rule netdev test-netdev egress comp flags != 0x23: This rule should not have failed.
+inet/comp.t: ERROR: line 20: add rule netdev test-netdev egress comp flags 0x33-0x45: This rule should not have failed.
+inet/comp.t: ERROR: line 21: add rule netdev test-netdev egress comp flags != 0x33-0x45: This rule should not have failed.
+inet/comp.t: ERROR: line 22: add rule netdev test-netdev egress comp flags {0x33, 0x55, 0x67, 0x88}: This rule should not have failed.
+inet/comp.t: ERROR: line 23: add rule netdev test-netdev egress comp flags != {0x33, 0x55, 0x67, 0x88}: This rule should not have failed.
+inet/comp.t: ERROR: line 25: add rule netdev test-netdev egress comp cpi 22: This rule should not have failed.
+inet/comp.t: ERROR: line 26: add rule netdev test-netdev egress comp cpi != 233: This rule should not have failed.
+inet/comp.t: ERROR: line 27: add rule netdev test-netdev egress comp cpi 33-45: This rule should not have failed.
+inet/comp.t: ERROR: line 28: add rule netdev test-netdev egress comp cpi != 33-45: This rule should not have failed.
+inet/comp.t: ERROR: line 29: add rule netdev test-netdev egress comp cpi {33, 55, 67, 88}: This rule should not have failed.
+inet/comp.t: ERROR: line 30: add rule netdev test-netdev egress comp cpi != {33, 55, 67, 88}: This rule should not have failed.
+inet/comp.t: ERROR: line 30: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+inet/reject.t: OK
+ip/meta.t: OK
+ip/snat.t: OK
+ip/masquerade.t: OK
+ip/redirect.t: OK
+ip/rt.t: OK
+ip/ct.t: OK
+ip/hash.t: OK
+ip/ip.t: ERROR: line 3: I cannot create the chain 'egress'
+ip/ip.t: ERROR: line 28: add rule netdev test-netdev egress ip dscp cs1: This rule should not have failed.
+ip/ip.t: ERROR: line 29: add rule netdev test-netdev egress ip dscp != cs1: This rule should not have failed.
+ip/ip.t: ERROR: line 30: add rule netdev test-netdev egress ip dscp 0x38: This rule should not have failed.
+ip/ip.t: ERROR: line 31: add rule netdev test-netdev egress ip dscp != 0x20: This rule should not have failed.
+ip/ip.t: ERROR: line 32: add rule netdev test-netdev egress ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}: This rule should not have failed.
+ip/ip.t: ERROR: line 34: add rule netdev test-netdev egress ip dscp != {cs0, cs3}: This rule should not have failed.
+ip/ip.t: ERROR: line 35: add rule netdev test-netdev egress ip dscp vmap { cs1 : continue , cs4 : accept } counter: This rule should not have failed.
+ip/ip.t: ERROR: line 37: add rule netdev test-netdev egress ip length 232: This rule should not have failed.
+ip/ip.t: ERROR: line 38: add rule netdev test-netdev egress ip length != 233: This rule should not have failed.
+ip/ip.t: ERROR: line 39: add rule netdev test-netdev egress ip length 333-435: This rule should not have failed.
+ip/ip.t: ERROR: line 40: add rule netdev test-netdev egress ip length != 333-453: This rule should not have failed.
+ip/ip.t: ERROR: line 41: add rule netdev test-netdev egress ip length { 333, 553, 673, 838}: This rule should not have failed.
+ip/ip.t: ERROR: line 42: add rule netdev test-netdev egress ip length != { 333, 553, 673, 838}: This rule should not have failed.
+ip/ip.t: ERROR: line 44: add rule netdev test-netdev egress ip id 22: This rule should not have failed.
+ip/ip.t: ERROR: line 45: add rule netdev test-netdev egress ip id != 233: This rule should not have failed.
+ip/ip.t: ERROR: line 46: add rule netdev test-netdev egress ip id 33-45: This rule should not have failed.
+ip/ip.t: ERROR: line 47: add rule netdev test-netdev egress ip id != 33-45: This rule should not have failed.
+ip/ip.t: ERROR: line 48: add rule netdev test-netdev egress ip id { 33, 55, 67, 88}: This rule should not have failed.
+ip/ip.t: ERROR: line 49: add rule netdev test-netdev egress ip id != { 33, 55, 67, 88}: This rule should not have failed.
+ip/ip.t: ERROR: line 51: add rule netdev test-netdev egress ip frag-off 222 accept: This rule should not have failed.
+ip/ip.t: ERROR: line 52: add rule netdev test-netdev egress ip frag-off != 233: This rule should not have failed.
+ip/ip.t: ERROR: line 53: add rule netdev test-netdev egress ip frag-off 33-45: This rule should not have failed.
+ip/ip.t: ERROR: line 54: add rule netdev test-netdev egress ip frag-off != 33-45: This rule should not have failed.
+ip/ip.t: ERROR: line 55: add rule netdev test-netdev egress ip frag-off { 33, 55, 67, 88}: This rule should not have failed.
+ip/ip.t: ERROR: line 56: add rule netdev test-netdev egress ip frag-off != { 33, 55, 67, 88}: This rule should not have failed.
+ip/ip.t: ERROR: line 58: add rule netdev test-netdev egress ip ttl 0 drop: This rule should not have failed.
+ip/ip.t: ERROR: line 59: add rule netdev test-netdev egress ip ttl 233: This rule should not have failed.
+ip/ip.t: ERROR: line 60: add rule netdev test-netdev egress ip ttl 33-55: This rule should not have failed.
+ip/ip.t: ERROR: line 61: add rule netdev test-netdev egress ip ttl != 45-50: This rule should not have failed.
+ip/ip.t: ERROR: line 62: add rule netdev test-netdev egress ip ttl {43, 53, 45 }: This rule should not have failed.
+ip/ip.t: ERROR: line 63: add rule netdev test-netdev egress ip ttl != {43, 53, 45 }: This rule should not have failed.
+ip/ip.t: ERROR: line 65: add rule netdev test-netdev egress ip protocol tcp: This rule should not have failed.
+ip/ip.t: ERROR: line 66: add rule netdev test-netdev egress ip protocol != tcp: This rule should not have failed.
+ip/ip.t: ERROR: line 67: add rule netdev test-netdev egress ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept: This rule should not have failed.
+ip/ip.t: ERROR: line 68: add rule netdev test-netdev egress ip protocol != { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept: This rule should not have failed.
+ip/ip.t: ERROR: line 70: add rule netdev test-netdev egress ip protocol 255: This rule should not have failed.
+ip/ip.t: ERROR: line 73: add rule netdev test-netdev egress ip checksum 13172 drop: This rule should not have failed.
+ip/ip.t: ERROR: line 74: add rule netdev test-netdev egress ip checksum 22: This rule should not have failed.
+ip/ip.t: ERROR: line 75: add rule netdev test-netdev egress ip checksum != 233: This rule should not have failed.
+ip/ip.t: ERROR: line 76: add rule netdev test-netdev egress ip checksum 33-45: This rule should not have failed.
+ip/ip.t: ERROR: line 77: add rule netdev test-netdev egress ip checksum != 33-45: This rule should not have failed.
+ip/ip.t: ERROR: line 78: add rule netdev test-netdev egress ip checksum { 33, 55, 67, 88}: This rule should not have failed.
+ip/ip.t: ERROR: line 79: add rule netdev test-netdev egress ip checksum != { 33, 55, 67, 88}: This rule should not have failed.
+ip/ip.t: ERROR: line 83: add rule netdev test-netdev egress ip saddr 192.168.2.0/24: This rule should not have failed.
+ip/ip.t: ERROR: line 84: add rule netdev test-netdev egress ip saddr != 192.168.2.0/24: This rule should not have failed.
+ip/ip.t: ERROR: line 85: add rule netdev test-netdev egress ip saddr 192.168.3.1 ip daddr 192.168.3.100: This rule should not have failed.
+ip/ip.t: ERROR: line 86: add rule netdev test-netdev egress ip saddr != 1.1.1.1: This rule should not have failed.
+ip/ip.t: ERROR: line 87: add rule netdev test-netdev egress ip saddr 1.1.1.1: This rule should not have failed.
+ip/ip.t: ERROR: line 88: add rule netdev test-netdev egress ip daddr 192.168.0.1-192.168.0.250: This rule should not have failed.
+ip/ip.t: ERROR: line 89: add rule netdev test-netdev egress ip daddr 10.0.0.0-10.255.255.255: This rule should not have failed.
+ip/ip.t: ERROR: line 90: add rule netdev test-netdev egress ip daddr 172.16.0.0-172.31.255.255: This rule should not have failed.
+ip/ip.t: ERROR: line 91: add rule netdev test-netdev egress ip daddr 192.168.3.1-192.168.4.250: This rule should not have failed.
+ip/ip.t: ERROR: line 92: add rule netdev test-netdev egress ip daddr != 192.168.0.1-192.168.0.250: This rule should not have failed.
+ip/ip.t: ERROR: line 93: add rule netdev test-netdev egress ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept: This rule should not have failed.
+ip/ip.t: ERROR: line 94: add rule netdev test-netdev egress ip daddr != { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept: This rule should not have failed.
+ip/ip.t: ERROR: line 96: add rule netdev test-netdev egress ip daddr 192.168.1.2-192.168.1.55: This rule should not have failed.
+ip/ip.t: ERROR: line 97: add rule netdev test-netdev egress ip daddr != 192.168.1.2-192.168.1.55: This rule should not have failed.
+ip/ip.t: ERROR: line 98: add rule netdev test-netdev egress ip saddr 192.168.1.3-192.168.33.55: This rule should not have failed.
+ip/ip.t: ERROR: line 99: add rule netdev test-netdev egress ip saddr != 192.168.1.3-192.168.33.55: This rule should not have failed.
+ip/ip.t: ERROR: line 101: add rule netdev test-netdev egress ip daddr 192.168.0.1: This rule should not have failed.
+ip/ip.t: ERROR: line 102: add rule netdev test-netdev egress ip daddr 192.168.0.1 drop: This rule should not have failed.
+ip/ip.t: ERROR: line 103: add rule netdev test-netdev egress ip daddr 192.168.0.2: This rule should not have failed.
+ip/ip.t: ERROR: line 105: add rule netdev test-netdev egress ip saddr & 0xff == 1: This rule should not have failed.
+ip/ip.t: ERROR: line 106: add rule netdev test-netdev egress ip saddr & 0.0.0.255 < 0.0.0.127: This rule should not have failed.
+ip/ip.t: ERROR: line 108: add rule netdev test-netdev egress ip saddr & 0xffff0000 == 0xffff0000: This rule should not have failed.
+ip/ip.t: ERROR: line 110: add rule netdev test-netdev egress ip version 4 ip hdrlength 5: This rule should not have failed.
+ip/ip.t: ERROR: line 111: add rule netdev test-netdev egress ip hdrlength 0: This rule should not have failed.
+ip/ip.t: ERROR: line 112: add rule netdev test-netdev egress ip hdrlength 15: This rule should not have failed.
+ip/ip.t: ERROR: line 113: add rule netdev test-netdev egress ip hdrlength vmap { 0-4 : drop, 5 : accept, 6 : continue } counter: This rule should not have failed.
+ip/ip.t: ERROR: line 117: add rule netdev test-netdev egress iif "lo" ip daddr set 127.0.0.1: This rule should not have failed.
+ip/ip.t: ERROR: line 118: add rule netdev test-netdev egress iif "lo" ip checksum set 0: This rule should not have failed.
+ip/ip.t: ERROR: line 119: add rule netdev test-netdev egress iif "lo" ip id set 0: This rule should not have failed.
+ip/ip.t: ERROR: line 120: add rule netdev test-netdev egress iif "lo" ip ecn set 1: This rule should not have failed.
+ip/ip.t: ERROR: line 121: add rule netdev test-netdev egress iif "lo" ip ecn set ce: This rule should not have failed.
+ip/ip.t: ERROR: line 122: add rule netdev test-netdev egress iif "lo" ip ttl set 23: This rule should not have failed.
+ip/ip.t: ERROR: line 123: add rule netdev test-netdev egress iif "lo" ip protocol set 1: This rule should not have failed.
+ip/ip.t: ERROR: line 125: add rule netdev test-netdev egress iif "lo" ip dscp set af23: This rule should not have failed.
+ip/ip.t: ERROR: line 126: add rule netdev test-netdev egress iif "lo" ip dscp set cs0: This rule should not have failed.
+ip/ip.t: ERROR: line 128: add rule netdev test-netdev egress ip saddr . ip daddr { 192.0.2.1 . 10.0.0.1-10.0.0.2 }: This rule should not have failed.
+ip/ip.t: ERROR: line 129: add rule netdev test-netdev egress ip saddr . ip daddr vmap { 192.168.5.1-192.168.5.128 . 192.168.6.1-192.168.6.128 : accept }: This rule should not have failed.
+ip/ip.t: ERROR: line 129: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+ip/igmp.t: OK
+ip/tcp.t: OK
+ip/icmp.t: OK
+ip/flowtable.t: OK
+ip/dup.t: OK
+ip/tproxy.t: OK
+ip/ether.t: OK
+ip/objects.t: OK
+ip/ip_tcp.t: OK
+ip/dnat.t: OK
+ip/sets.t: ERROR: line 3: I cannot create the chain 'egress'
+ip/sets.t: ERROR: line 32: add rule netdev test-netdev egress ip saddr @set1 drop: This rule should not have failed.
+ip/sets.t: ERROR: line 33: add rule netdev test-netdev egress ip saddr != @set1 drop: This rule should not have failed.
+ip/sets.t: ERROR: line 34: add rule netdev test-netdev egress ip saddr @set2 drop: This rule should not have failed.
+ip/sets.t: ERROR: line 35: add rule netdev test-netdev egress ip saddr != @set2 drop: This rule should not have failed.
+ip/sets.t: ERROR: line 52: add rule netdev test-netdev egress ip saddr . ip daddr @set5 drop: This rule should not have failed.
+ip/sets.t: ERROR: line 53: add rule netdev test-netdev egress add @set5 { ip saddr . ip daddr }: This rule should not have failed.
+ip/sets.t: ERROR: line 56: add rule netdev test-netdev egress ip saddr { { 1.1.1.0, 3.3.3.0 }, 2.2.2.0 }: This rule should not have failed.
+ip/sets.t: ERROR: line 57: add rule netdev test-netdev egress ip saddr { { 1.1.1.0/24, 3.3.3.0/24 }, 2.2.2.0/24 }: This rule should not have failed.
+ip/sets.t: ERROR: line 60: add element ip test-ip4 set6 { 192.168.3.5, * }: This rule should not have failed.
+ip/sets.t: ERROR: line 61: add rule netdev test-netdev egress ip saddr @set6 drop: This rule should not have failed.
+ip/sets.t: ERROR: line 63: add rule ip test-ip4 input ip saddr vmap { 1.1.1.1 : drop, * : accept }: This rule should not have failed.
+ip/sets.t: ERROR: line 64: add rule ip test-ip4 input meta mark set ip saddr map { 1.1.1.1 : 0x00000001, * : 0x00000002 }: This rule should not have failed.
+ip/sets.t: ERROR: line 65: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+ip/numgen.t: OK
+ip/reject.t: OK
+ip6/vmap.t: ERROR: line 3: I cannot create the chain 'egress'
+ip6/vmap.t: ERROR: line 9: add rule netdev test-netdev egress ip6 saddr vmap { abcd::3 : accept }: This rule should not have failed.
+ip6/vmap.t: ERROR: line 14: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 15: add rule netdev test-netdev egress ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 16: add rule netdev test-netdev egress ip6 saddr vmap { 1234::1234:1234:1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 17: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234::1234:1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 18: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234::1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 19: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234::1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 20: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234:1234::1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 21: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234:1234:1234::1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 22: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:1234:: : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 23: add rule netdev test-netdev egress ip6 saddr vmap { ::1234:1234:1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 24: add rule netdev test-netdev egress ip6 saddr vmap { 1234::1234:1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 25: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234::1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 26: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234::1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 27: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234::1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 28: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234:1234::1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 29: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234:1234:1234:: : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 30: add rule netdev test-netdev egress ip6 saddr vmap { ::1234:1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 31: add rule netdev test-netdev egress ip6 saddr vmap { 1234::1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 32: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234::1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 33: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234::1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 34: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234::1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 35: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234:1234:: : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 36: add rule netdev test-netdev egress ip6 saddr vmap { ::1234:1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 37: add rule netdev test-netdev egress ip6 saddr vmap { 1234::1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 38: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234::1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 39: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234::1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 40: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:1234:: : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 41: add rule netdev test-netdev egress ip6 saddr vmap { ::1234:1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 42: add rule netdev test-netdev egress ip6 saddr vmap { 1234::1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 43: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234::1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 44: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:1234:: : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 45: add rule netdev test-netdev egress ip6 saddr vmap { ::1234:1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 46: add rule netdev test-netdev egress ip6 saddr vmap { 1234::1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 47: add rule netdev test-netdev egress ip6 saddr vmap { 1234:1234:: : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 48: add rule netdev test-netdev egress ip6 saddr vmap { ::1234 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 49: add rule netdev test-netdev egress ip6 saddr vmap { 1234:: : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 50: add rule netdev test-netdev egress ip6 saddr vmap { ::/64 : accept}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 52: add rule netdev test-netdev egress ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:: : accept, ::aaaa : drop}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 53: add rule netdev test-netdev egress ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept, ::bbbb : drop}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 54: add rule netdev test-netdev egress ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::cccc : drop}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 55: add rule netdev test-netdev egress ip6 saddr vmap {1234:1234:1234:1234:1234:1234:aaaa:::accept,::dddd: drop}: This rule should not have failed.
+ip6/vmap.t: ERROR: line 58: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+ip6/rt0.t: OK
+ip6/meta.t: OK
+ip6/snat.t: OK
+ip6/srh.t: OK
+ip6/masquerade.t: OK
+ip6/redirect.t: OK
+ip6/rt.t: OK
+ip6/icmpv6.t: OK
+ip6/ct.t: OK
+ip6/flowtable.t: OK
+ip6/dst.t: OK
+ip6/ip6.t: OK
+ip6/dup.t: OK
+ip6/tproxy.t: OK
+ip6/ether.t: OK
+ip6/hbh.t: OK
+ip6/map.t: OK
+ip6/frag.t: ERROR: line 3: I cannot create the chain 'egress'
+ip6/frag.t: ERROR: line 9: add rule netdev test-netdev egress frag nexthdr tcp: This rule should not have failed.
+ip6/frag.t: ERROR: line 10: add rule netdev test-netdev egress frag nexthdr != icmp: This rule should not have failed.
+ip6/frag.t: ERROR: line 11: add rule netdev test-netdev egress frag nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp}: This rule should not have failed.
+ip6/frag.t: ERROR: line 12: add rule netdev test-netdev egress frag nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp}: This rule should not have failed.
+ip6/frag.t: ERROR: line 13: add rule netdev test-netdev egress frag nexthdr esp: This rule should not have failed.
+ip6/frag.t: ERROR: line 14: add rule netdev test-netdev egress frag nexthdr ah: This rule should not have failed.
+ip6/frag.t: ERROR: line 16: add rule netdev test-netdev egress frag reserved 22: This rule should not have failed.
+ip6/frag.t: ERROR: line 17: add rule netdev test-netdev egress frag reserved != 233: This rule should not have failed.
+ip6/frag.t: ERROR: line 18: add rule netdev test-netdev egress frag reserved 33-45: This rule should not have failed.
+ip6/frag.t: ERROR: line 19: add rule netdev test-netdev egress frag reserved != 33-45: This rule should not have failed.
+ip6/frag.t: ERROR: line 20: add rule netdev test-netdev egress frag reserved { 33, 55, 67, 88}: This rule should not have failed.
+ip6/frag.t: ERROR: line 21: add rule netdev test-netdev egress frag reserved != { 33, 55, 67, 88}: This rule should not have failed.
+ip6/frag.t: ERROR: line 23: add rule netdev test-netdev egress frag frag-off 22: This rule should not have failed.
+ip6/frag.t: ERROR: line 24: add rule netdev test-netdev egress frag frag-off != 233: This rule should not have failed.
+ip6/frag.t: ERROR: line 25: add rule netdev test-netdev egress frag frag-off 33-45: This rule should not have failed.
+ip6/frag.t: ERROR: line 26: add rule netdev test-netdev egress frag frag-off != 33-45: This rule should not have failed.
+ip6/frag.t: ERROR: line 27: add rule netdev test-netdev egress frag frag-off { 33, 55, 67, 88}: This rule should not have failed.
+ip6/frag.t: ERROR: line 28: add rule netdev test-netdev egress frag frag-off != { 33, 55, 67, 88}: This rule should not have failed.
+ip6/frag.t: ERROR: line 30: add rule netdev test-netdev egress frag reserved2 1: This rule should not have failed.
+ip6/frag.t: ERROR: line 31: add rule netdev test-netdev egress frag more-fragments 0: This rule should not have failed.
+ip6/frag.t: ERROR: line 32: add rule netdev test-netdev egress frag more-fragments 1: This rule should not have failed.
+ip6/frag.t: ERROR: line 34: add rule netdev test-netdev egress frag id 1: This rule should not have failed.
+ip6/frag.t: ERROR: line 35: add rule netdev test-netdev egress frag id 22: This rule should not have failed.
+ip6/frag.t: ERROR: line 36: add rule netdev test-netdev egress frag id != 33: This rule should not have failed.
+ip6/frag.t: ERROR: line 37: add rule netdev test-netdev egress frag id 33-45: This rule should not have failed.
+ip6/frag.t: ERROR: line 38: add rule netdev test-netdev egress frag id != 33-45: This rule should not have failed.
+ip6/frag.t: ERROR: line 39: add rule netdev test-netdev egress frag id { 33, 55, 67, 88}: This rule should not have failed.
+ip6/frag.t: ERROR: line 40: add rule netdev test-netdev egress frag id != { 33, 55, 67, 88}: This rule should not have failed.
+ip6/frag.t: ERROR: line 40: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+ip6/exthdr.t: OK
+ip6/dnat.t: OK
+ip6/sets.t: ERROR: line 3: I cannot create the chain 'egress'
+ip6/sets.t: ERROR: line 25: add rule netdev test-netdev egress ip6 saddr @set2 drop: This rule should not have failed.
+ip6/sets.t: ERROR: line 26: add rule netdev test-netdev egress ip6 saddr != @set2 drop: This rule should not have failed.
+ip6/sets.t: ERROR: line 42: add rule netdev test-netdev egress ip6 saddr . ip6 daddr @set5 drop: This rule should not have failed.
+ip6/sets.t: ERROR: line 43: add rule netdev test-netdev egress add @set5 { ip6 saddr . ip6 daddr }: This rule should not have failed.
+ip6/sets.t: ERROR: line 44: add rule netdev test-netdev egress delete @set5 { ip6 saddr . ip6 daddr }: This rule should not have failed.
+ip6/sets.t: ERROR: line 44: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+ip6/mh.t: OK
+ip6/reject.t: OK
+netdev/dup.t: ERROR: line 2: I cannot create the chain 'egress'
+netdev/dup.t: ERROR: line 6: add rule netdev test-netdev egress dup to "lo": This rule should not have failed.
+netdev/dup.t: ERROR: line 7: add rule netdev test-netdev egress dup to meta mark map { 0x00000001 : "lo", 0x00000002 : "lo"}: This rule should not have failed.
+netdev/dup.t: ERROR: line 8: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+netdev/fwd.t: ERROR: line 2: I cannot create the chain 'egress'
+netdev/fwd.t: ERROR: line 6: add rule netdev test-netdev egress fwd to "lo": This rule should not have failed.
+netdev/fwd.t: ERROR: line 7: add rule netdev test-netdev egress fwd to meta mark map { 0x00000001 : "lo", 0x00000002 : "lo"}: This rule should not have failed.
+netdev/fwd.t: ERROR: line 9: add rule netdev test-netdev egress fwd ip to 192.168.2.200 device "lo": This rule should not have failed.
+netdev/fwd.t: ERROR: line 9: The chain egress does not exist in netdev test-netdev. I cannot delete it.
+netdev/reject.t: ERROR: line 5: add rule netdev test-netdev ingress reject with icmp host-unreachable: This rule should not have failed.
+netdev/reject.t: ERROR: line 6: add rule netdev test-netdev ingress reject with icmp net-unreachable: This rule should not have failed.
+netdev/reject.t: ERROR: line 7: add rule netdev test-netdev ingress reject with icmp prot-unreachable: This rule should not have failed.
+netdev/reject.t: ERROR: line 8: add rule netdev test-netdev ingress reject with icmp port-unreachable: This rule should not have failed.
+netdev/reject.t: ERROR: line 9: add rule netdev test-netdev ingress reject with icmp net-prohibited: This rule should not have failed.
+netdev/reject.t: ERROR: line 10: add rule netdev test-netdev ingress reject with icmp host-prohibited: This rule should not have failed.
+netdev/reject.t: ERROR: line 11: add rule netdev test-netdev ingress reject with icmp admin-prohibited: This rule should not have failed.
+netdev/reject.t: ERROR: line 13: add rule netdev test-netdev ingress reject with icmpv6 no-route: This rule should not have failed.
+netdev/reject.t: ERROR: line 14: add rule netdev test-netdev ingress reject with icmpv6 admin-prohibited: This rule should not have failed.
+netdev/reject.t: ERROR: line 15: add rule netdev test-netdev ingress reject with icmpv6 addr-unreachable: This rule should not have failed.
+netdev/reject.t: ERROR: line 16: add rule netdev test-netdev ingress reject with icmpv6 port-unreachable: This rule should not have failed.
+netdev/reject.t: ERROR: line 17: add rule netdev test-netdev ingress reject with icmpv6 policy-fail: This rule should not have failed.
+netdev/reject.t: ERROR: line 18: add rule netdev test-netdev ingress reject with icmpv6 reject-route: This rule should not have failed.
+netdev/reject.t: ERROR: line 20: add rule netdev test-netdev ingress mark 12345 reject with tcp reset: This rule should not have failed.
+netdev/reject.t: ERROR: line 22: add rule netdev test-netdev ingress reject: This rule should not have failed.
+netdev/reject.t: ERROR: line 23: add rule netdev test-netdev ingress meta protocol ip reject: This rule should not have failed.
+netdev/reject.t: ERROR: line 24: add rule netdev test-netdev ingress meta protocol ip6 reject: This rule should not have failed.
+netdev/reject.t: ERROR: line 26: add rule netdev test-netdev ingress reject with icmpx host-unreachable: This rule should not have failed.
+netdev/reject.t: ERROR: line 27: add rule netdev test-netdev ingress reject with icmpx no-route: This rule should not have failed.
+netdev/reject.t: ERROR: line 28: add rule netdev test-netdev ingress reject with icmpx admin-prohibited: This rule should not have failed.
+netdev/reject.t: ERROR: line 29: add rule netdev test-netdev ingress reject with icmpx port-unreachable: This rule should not have failed.
+netdev/reject.t: ERROR: line 31: add rule netdev test-netdev ingress meta protocol ip reject with icmp host-unreachable: This rule should not have failed.
+netdev/reject.t: ERROR: line 32: add rule netdev test-netdev ingress meta protocol ip6 reject with icmpv6 no-route: This rule should not have failed.
+netdev/reject.t: ERROR: line 39: add rule netdev test-netdev ingress meta protocol ip reject with icmpx admin-prohibited: This rule should not have failed.
+netdev/reject.t: ERROR: line 40: add rule netdev test-netdev ingress meta protocol ip6 reject with icmpx admin-prohibited: This rule should not have failed.
+104 test files, 68 files passed, 1988 unit tests,
+805 error, 0 warning
+
+=================================================================
+==67823==ERROR: LeakSanitizer: detected memory leaks
+
+Direct leak of 464608 byte(s) in 116 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4f1cca in PyObject_Malloc (/usr/bin/python3.9+0x4f1cca)
+
+Direct leak of 17699 byte(s) in 20 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x50ee7b (/usr/bin/python3.9+0x50ee7b)
+
+Direct leak of 6256 byte(s) in 9 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x50c092 in PyDict_Copy (/usr/bin/python3.9+0x50c092)
+
+Direct leak of 5892 byte(s) in 8 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4f2b1d (/usr/bin/python3.9+0x4f2b1d)
+
+Direct leak of 4628 byte(s) in 6 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4fcaef in PyMem_Malloc (/usr/bin/python3.9+0x4fcaef)
+
+Direct leak of 2656 byte(s) in 5 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4f1b05 (/usr/bin/python3.9+0x4f1b05)
+
+Direct leak of 1226 byte(s) in 2 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x50ea16 in PyBytes_FromStringAndSize (/usr/bin/python3.9+0x50ea16)
+
+Direct leak of 1056 byte(s) in 2 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4f1db2 (/usr/bin/python3.9+0x4f1db2)
+
+Direct leak of 936 byte(s) in 1 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4fa38d in PyType_GenericAlloc (/usr/bin/python3.9+0x4fa38d)
+
+Direct leak of 96 byte(s) in 3 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x540d66 (/usr/bin/python3.9+0x540d66)
+
+Direct leak of 32 byte(s) in 1 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4f00d3 in PyThread_allocate_lock (/usr/bin/python3.9+0x4f00d3)
+
+Indirect leak of 54968 byte(s) in 57 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4fa38d in PyType_GenericAlloc (/usr/bin/python3.9+0x4fa38d)
+
+Indirect leak of 4963 byte(s) in 5 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x50ee7b (/usr/bin/python3.9+0x50ee7b)
+
+Indirect leak of 4779 byte(s) in 5 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4f2b1d (/usr/bin/python3.9+0x4f2b1d)
+
+Indirect leak of 576 byte(s) in 1 object(s) allocated from:
+ #0 0x7f739491de8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
+ #1 0x4f1cca in PyObject_Malloc (/usr/bin/python3.9+0x4f1cca)
+
+SUMMARY: AddressSanitizer: 570371 byte(s) leaked in 241 allocation(s).
diff --git a/tests/py/netdev/dup.t b/tests/py/netdev/dup.t
new file mode 100644
index 0000000..5632802
--- /dev/null
+++ b/tests/py/netdev/dup.t
@@ -0,0 +1,8 @@
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*netdev;test-netdev;ingress,egress
+
+dup to "lo";ok
+dup to meta mark map { 0x00000001 : "lo", 0x00000002 : "lo"};ok
+
diff --git a/tests/py/netdev/dup.t.json b/tests/py/netdev/dup.t.json
new file mode 100644
index 0000000..dc56f64
--- /dev/null
+++ b/tests/py/netdev/dup.t.json
@@ -0,0 +1,30 @@
+# dup to "lo"
+[
+ {
+ "dup": {
+ "addr": "lo"
+ }
+ }
+]
+
+# dup to meta mark map { 0x00000001 : "lo", 0x00000002 : "lo"}
+[
+ {
+ "dup": {
+ "addr": {
+ "map": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "data": {
+ "set": [
+ [ 1, "lo" ],
+ [ 2, "lo" ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/netdev/dup.t.payload b/tests/py/netdev/dup.t.payload
new file mode 100644
index 0000000..51ff782
--- /dev/null
+++ b/tests/py/netdev/dup.t.payload
@@ -0,0 +1,14 @@
+# dup to "lo"
+netdev test-netdev ingress
+ [ immediate reg 1 0x00000001 ]
+ [ dup sreg_dev 1 ]
+
+# dup to meta mark map { 0x00000001 : "lo", 0x00000002 : "lo"}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00000001 : 00000001 0 [end] element 00000002 : 00000001 0 [end]
+netdev test-netdev ingress
+ [ meta load mark => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ dup sreg_dev 1 ]
+
diff --git a/tests/py/netdev/fwd.t b/tests/py/netdev/fwd.t
new file mode 100644
index 0000000..6051560
--- /dev/null
+++ b/tests/py/netdev/fwd.t
@@ -0,0 +1,9 @@
+:ingress;type filter hook ingress device lo priority 0
+:egress;type filter hook egress device lo priority 0
+
+*netdev;test-netdev;ingress,egress
+
+fwd to "lo";ok
+fwd to meta mark map { 0x00000001 : "lo", 0x00000002 : "lo"};ok
+
+fwd ip to 192.168.2.200 device "lo";ok
diff --git a/tests/py/netdev/fwd.t.json b/tests/py/netdev/fwd.t.json
new file mode 100644
index 0000000..583606c
--- /dev/null
+++ b/tests/py/netdev/fwd.t.json
@@ -0,0 +1,47 @@
+# fwd to "lo"
+[
+ {
+ "fwd": {
+ "dev": "lo"
+ }
+ }
+]
+
+# fwd to meta mark map { 0x00000001 : "lo", 0x00000002 : "lo"}
+[
+ {
+ "fwd": {
+ "dev": {
+ "map": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "data": {
+ "set": [
+ [
+ "0x00000001",
+ "lo"
+ ],
+ [
+ "0x00000002",
+ "lo"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# fwd ip to 192.168.2.200 device "lo"
+[
+ {
+ "fwd": {
+ "addr": "192.168.2.200",
+ "dev": "lo",
+ "family": "ip"
+ }
+ }
+]
+
diff --git a/tests/py/netdev/fwd.t.json.output b/tests/py/netdev/fwd.t.json.output
new file mode 100644
index 0000000..8433e49
--- /dev/null
+++ b/tests/py/netdev/fwd.t.json.output
@@ -0,0 +1,27 @@
+# fwd to meta mark map { 0x00000001 : "lo", 0x00000002 : "lo"}
+[
+ {
+ "fwd": {
+ "dev": {
+ "map": {
+ "key": {
+ "meta": { "key": "mark" }
+ },
+ "data": {
+ "set": [
+ [
+ 1,
+ "lo"
+ ],
+ [
+ 2,
+ "lo"
+ ]
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
diff --git a/tests/py/netdev/fwd.t.payload b/tests/py/netdev/fwd.t.payload
new file mode 100644
index 0000000..f03077a
--- /dev/null
+++ b/tests/py/netdev/fwd.t.payload
@@ -0,0 +1,20 @@
+# fwd to "lo"
+netdev test-netdev ingress
+ [ immediate reg 1 0x00000001 ]
+ [ fwd sreg_dev 1 ]
+
+# fwd to meta mark map { 0x00000001 : "lo", 0x00000002 : "lo"}
+__map%d test-netdev b
+__map%d test-netdev 0
+ element 00000001 : 00000001 0 [end] element 00000002 : 00000001 0 [end]
+netdev test-netdev ingress
+ [ meta load mark => reg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ fwd sreg_dev 1 ]
+
+# fwd ip to 192.168.2.200 device "lo"
+netdev test-netdev ingress
+ [ immediate reg 1 0x00000001 ]
+ [ immediate reg 2 0xc802a8c0 ]
+ [ fwd sreg_dev 1 sreg_addr 2 nfproto 2 ]
+
diff --git a/tests/py/netdev/reject.t b/tests/py/netdev/reject.t
new file mode 100644
index 0000000..c66e649
--- /dev/null
+++ b/tests/py/netdev/reject.t
@@ -0,0 +1,40 @@
+:ingress;type filter hook ingress device lo priority 0
+
+*netdev;test-netdev;ingress
+
+reject with icmp host-unreachable;ok
+reject with icmp net-unreachable;ok
+reject with icmp prot-unreachable;ok
+reject with icmp port-unreachable;ok
+reject with icmp net-prohibited;ok
+reject with icmp host-prohibited;ok
+reject with icmp admin-prohibited;ok
+
+reject with icmpv6 no-route;ok
+reject with icmpv6 admin-prohibited;ok
+reject with icmpv6 addr-unreachable;ok
+reject with icmpv6 port-unreachable;ok
+reject with icmpv6 policy-fail;ok
+reject with icmpv6 reject-route;ok
+
+mark 12345 reject with tcp reset;ok;meta l4proto 6 meta mark 0x00003039 reject with tcp reset
+
+reject;ok
+meta protocol ip reject;ok;reject with icmp port-unreachable
+meta protocol ip6 reject;ok;reject with icmpv6 port-unreachable
+
+reject with icmpx host-unreachable;ok
+reject with icmpx no-route;ok
+reject with icmpx admin-prohibited;ok
+reject with icmpx port-unreachable;ok;reject
+
+meta protocol ip reject with icmp host-unreachable;ok;reject with icmp host-unreachable
+meta protocol ip6 reject with icmpv6 no-route;ok;reject with icmpv6 no-route
+
+meta protocol ip6 reject with icmp host-unreachable;fail
+meta protocol ip ip protocol icmp reject with icmpv6 no-route;fail
+meta protocol ip6 ip protocol icmp reject with icmp host-unreachable;fail
+meta l4proto udp reject with tcp reset;fail
+
+meta protocol ip reject with icmpx admin-prohibited;ok
+meta protocol ip6 reject with icmpx admin-prohibited;ok
diff --git a/tests/py/netdev/reject.t.json b/tests/py/netdev/reject.t.json
new file mode 100644
index 0000000..9968aaf
--- /dev/null
+++ b/tests/py/netdev/reject.t.json
@@ -0,0 +1,293 @@
+# reject with icmp host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp net-unreachable
+[
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp prot-unreachable
+[
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp net-prohibited
+[
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp host-prohibited
+[
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmpv6 no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 addr-unreachable
+[
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 policy-fail
+[
+ {
+ "reject": {
+ "expr": "policy-fail",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 reject-route
+[
+ {
+ "reject": {
+ "expr": "reject-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# mark 12345 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "right": 12345
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# meta protocol ip reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# meta protocol ip6 reject
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpx host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# meta protocol ip reject with icmp host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# meta protocol ip6 reject with icmpv6 no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# meta protocol ip reject with icmpx admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# meta protocol ip6 reject with icmpx admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
diff --git a/tests/py/netdev/reject.t.payload b/tests/py/netdev/reject.t.payload
new file mode 100644
index 0000000..d014ada
--- /dev/null
+++ b/tests/py/netdev/reject.t.payload
@@ -0,0 +1,142 @@
+# reject with icmp host-unreachable
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 1 ]
+
+# reject with icmp net-unreachable
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 0 ]
+
+# reject with icmp prot-unreachable
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 2 ]
+
+# reject with icmp port-unreachable
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 3 ]
+
+# reject with icmp net-prohibited
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 9 ]
+
+# reject with icmp host-prohibited
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 10 ]
+
+# reject with icmp admin-prohibited
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 13 ]
+
+# reject with icmpv6 no-route
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 0 ]
+
+# reject with icmpv6 admin-prohibited
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 1 ]
+
+# reject with icmpv6 addr-unreachable
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 3 ]
+
+# reject with icmpv6 port-unreachable
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 4 ]
+
+# reject with icmpv6 policy-fail
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 5 ]
+
+# reject with icmpv6 reject-route
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 6 ]
+
+# mark 12345 reject with tcp reset
+netdev
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x00003039 ]
+ [ reject type 1 code 0 ]
+
+# reject
+netdev
+ [ reject type 2 code 1 ]
+
+# meta protocol ip reject
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 3 ]
+
+# meta protocol ip6 reject
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 4 ]
+
+# reject with icmpx host-unreachable
+netdev
+ [ reject type 2 code 2 ]
+
+# reject with icmpx no-route
+netdev
+ [ reject type 2 code 0 ]
+
+# reject with icmpx admin-prohibited
+netdev
+ [ reject type 2 code 3 ]
+
+# reject with icmpx port-unreachable
+netdev
+ [ reject type 2 code 1 ]
+
+# meta protocol ip reject with icmp host-unreachable
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 1 ]
+
+# meta protocol ip6 reject with icmpv6 no-route
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 0 ]
+
+# meta protocol ip reject with icmpx admin-prohibited
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 2 code 3 ]
+
+# meta protocol ip6 reject with icmpx admin-prohibited
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 2 code 3 ]
+
diff --git a/tests/py/nft-test.py b/tests/py/nft-test.py
new file mode 100755
index 0000000..9a25503
--- /dev/null
+++ b/tests/py/nft-test.py
@@ -0,0 +1,1586 @@
+#!/usr/bin/env python
+#
+# (C) 2014 by Ana Rey Botello <anarey@gmail.com>
+#
+# Based on iptables-test.py:
+# (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>"
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Thanks to the Outreach Program for Women (OPW) for sponsoring this test
+# infrastructure.
+
+from __future__ import print_function
+import sys
+import os
+import argparse
+import signal
+import json
+import traceback
+import tempfile
+
+TESTS_PATH = os.path.dirname(os.path.abspath(__file__))
+sys.path.insert(0, os.path.join(TESTS_PATH, '../../py/'))
+os.environ['TZ'] = 'UTC-2'
+
+from nftables import Nftables
+
+TESTS_DIRECTORY = ["any", "arp", "bridge", "inet", "ip", "ip6", "netdev"]
+LOGFILE = "/tmp/nftables-test.log"
+log_file = None
+table_list = []
+chain_list = []
+all_set = dict()
+obj_list = []
+signal_received = 0
+
+
+class Colors:
+ if sys.stdout.isatty() and sys.stderr.isatty():
+ HEADER = '\033[95m'
+ GREEN = '\033[92m'
+ YELLOW = '\033[93m'
+ RED = '\033[91m'
+ ENDC = '\033[0m'
+ else:
+ HEADER = ''
+ GREEN = ''
+ YELLOW = ''
+ RED = ''
+ ENDC = ''
+
+
+class Chain:
+ """Class that represents a chain"""
+
+ def __init__(self, name, config, lineno):
+ self.name = name
+ self.config = config
+ self.lineno = lineno
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+ def __str__(self):
+ return "%s" % self.name
+
+
+class Table:
+ """Class that represents a table"""
+
+ def __init__(self, family, name, chains):
+ self.family = family
+ self.name = name
+ self.chains = chains
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+ def __str__(self):
+ return "%s %s" % (self.family, self.name)
+
+
+class Set:
+ """Class that represents a set"""
+
+ def __init__(self, family, table, name, type, data, timeout, flags):
+ self.family = family
+ self.table = table
+ self.name = name
+ self.type = type
+ self.data = data
+ self.timeout = timeout
+ self.flags = flags
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+
+class Obj:
+ """Class that represents an object"""
+
+ def __init__(self, table, family, name, type, spcf):
+ self.table = table
+ self.family = family
+ self.name = name
+ self.type = type
+ self.spcf = spcf
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+
+def print_msg(reason, errstr, filename=None, lineno=None, color=None):
+ '''
+ Prints a message with nice colors, indicating file and line number.
+ '''
+ color_errstr = "%s%s%s" % (color, errstr, Colors.ENDC)
+ if filename and lineno:
+ sys.stderr.write("%s: %s line %d: %s\n" %
+ (filename, color_errstr, lineno + 1, reason))
+ else:
+ sys.stderr.write("%s %s\n" % (color_errstr, reason))
+ sys.stderr.flush() # So that the message stay in the right place.
+
+
+def print_error(reason, filename=None, lineno=None):
+ print_msg(reason, "ERROR:", filename, lineno, Colors.RED)
+
+
+def print_warning(reason, filename=None, lineno=None):
+ print_msg(reason, "WARNING:", filename, lineno, Colors.YELLOW)
+
+def print_info(reason, filename=None, lineno=None):
+ print_msg(reason, "INFO:", filename, lineno, Colors.GREEN)
+
+def color_differences(rule, other, color):
+ rlen = len(rule)
+ olen = len(other)
+ out = ""
+ i = 0
+
+ # find equal part at start
+ for i in range(rlen):
+ if i >= olen or rule[i] != other[i]:
+ break
+ if i > 0:
+ out += rule[:i]
+ rule = rule[i:]
+ other = other[i:]
+ rlen = len(rule)
+ olen = len(other)
+
+ # find equal part at end
+ for i in range(1, rlen + 1):
+ if i > olen or rule[rlen - i] != other[olen - i]:
+ i -= 1
+ break
+ if rlen > i:
+ out += color + rule[:rlen - i] + Colors.ENDC
+ rule = rule[rlen - i:]
+
+ out += rule
+ return out
+
+def print_differences_warning(filename, lineno, rule1, rule2, cmd):
+ colored_rule1 = color_differences(rule1, rule2, Colors.YELLOW)
+ colored_rule2 = color_differences(rule2, rule1, Colors.YELLOW)
+ reason = "'%s': '%s' mismatches '%s'" % (cmd, colored_rule1, colored_rule2)
+ print_warning(reason, filename, lineno)
+
+
+def print_differences_error(filename, lineno, cmd):
+ reason = "'%s': Listing is broken." % cmd
+ print_error(reason, filename, lineno)
+
+
+def table_exist(table, filename, lineno):
+ '''
+ Exists a table.
+ '''
+ cmd = "list table %s" % table
+ ret = execute_cmd(cmd, filename, lineno)
+
+ return True if (ret == 0) else False
+
+
+def table_flush(table, filename, lineno):
+ '''
+ Flush a table.
+ '''
+ cmd = "flush table %s" % table
+ execute_cmd(cmd, filename, lineno)
+
+ return cmd
+
+
+def table_create(table, filename, lineno):
+ '''
+ Adds a table.
+ '''
+ # We check if table exists.
+ if table_exist(table, filename, lineno):
+ reason = "Table %s already exists" % table
+ print_error(reason, filename, lineno)
+ return -1
+
+ table_list.append(table)
+
+ # We add a new table
+ cmd = "add table %s" % table
+ ret = execute_cmd(cmd, filename, lineno)
+
+ if ret != 0:
+ reason = "Cannot " + cmd
+ print_error(reason, filename, lineno)
+ table_list.remove(table)
+ return -1
+
+ # We check if table was added correctly.
+ if not table_exist(table, filename, lineno):
+ table_list.remove(table)
+ reason = "I have just added the table %s " \
+ "but it does not exist. Giving up!" % table
+ print_error(reason, filename, lineno)
+ return -1
+
+ for table_chain in table.chains:
+ chain = chain_get_by_name(table_chain)
+ if chain is None:
+ reason = "The chain %s requested by table %s " \
+ "does not exist." % (table_chain, table)
+ print_error(reason, filename, lineno)
+ else:
+ chain_create(chain, table, filename)
+
+ return 0
+
+
+def table_delete(table, filename=None, lineno=None):
+ '''
+ Deletes a table.
+ '''
+ if not table_exist(table, filename, lineno):
+ reason = "Table %s does not exist but I added it before." % table
+ print_error(reason, filename, lineno)
+ return -1
+
+ cmd = "delete table %s" % table
+ ret = execute_cmd(cmd, filename, lineno)
+ if ret != 0:
+ reason = "%s: I cannot delete table %s. Giving up!" % (cmd, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+ if table_exist(table, filename, lineno):
+ reason = "I have just deleted the table %s " \
+ "but it still exists." % table
+ print_error(reason, filename, lineno)
+ return -1
+
+ return 0
+
+
+def chain_exist(chain, table, filename):
+ '''
+ Checks a chain
+ '''
+ cmd = "list chain %s %s" % (table, chain)
+ ret = execute_cmd(cmd, filename, chain.lineno)
+
+ return True if (ret == 0) else False
+
+
+def chain_create(chain, table, filename):
+ '''
+ Adds a chain
+ '''
+ if chain_exist(chain, table, filename):
+ reason = "This chain '%s' exists in %s. I cannot create " \
+ "two chains with same name." % (chain, table)
+ print_error(reason, filename, chain.lineno)
+ return -1
+
+ cmd = "add chain %s %s" % (table, chain)
+ if chain.config:
+ cmd += " { %s; }" % chain.config
+
+ ret = execute_cmd(cmd, filename, chain.lineno)
+ if ret != 0:
+ reason = "I cannot create the chain '%s'" % chain
+ print_error(reason, filename, chain.lineno)
+ return -1
+
+ if not chain_exist(chain, table, filename):
+ reason = "I have added the chain '%s' " \
+ "but it does not exist in %s" % (chain, table)
+ print_error(reason, filename, chain.lineno)
+ return -1
+
+ return 0
+
+
+def chain_delete(chain, table, filename=None, lineno=None):
+ '''
+ Flushes and deletes a chain.
+ '''
+ if not chain_exist(chain, table, filename):
+ reason = "The chain %s does not exist in %s. " \
+ "I cannot delete it." % (chain, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+ cmd = "flush chain %s %s" % (table, chain)
+ ret = execute_cmd(cmd, filename, lineno)
+ if ret != 0:
+ reason = "I cannot " + cmd
+ print_error(reason, filename, lineno)
+ return -1
+
+ cmd = "delete chain %s %s" % (table, chain)
+ ret = execute_cmd(cmd, filename, lineno)
+ if ret != 0:
+ reason = "I cannot " + cmd
+ print_error(reason, filename, lineno)
+ return -1
+
+ if chain_exist(chain, table, filename):
+ reason = "The chain %s exists in %s. " \
+ "I cannot delete this chain" % (chain, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+ return 0
+
+
+def chain_get_by_name(name):
+ for chain in chain_list:
+ if chain.name == name:
+ break
+ else:
+ chain = None
+
+ return chain
+
+
+def set_add(s, test_result, filename, lineno):
+ '''
+ Adds a set.
+ '''
+ if not table_list:
+ reason = "Missing table to add rule"
+ print_error(reason, filename, lineno)
+ return -1
+
+ for table in table_list:
+ s.table = table.name
+ s.family = table.family
+ if _set_exist(s, filename, lineno):
+ reason = "Set %s already exists in %s" % (s.name, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+ flags = s.flags
+ if flags != "":
+ flags = "flags %s; " % flags
+
+ if s.data == "":
+ cmd = "add set %s %s { type %s;%s %s}" % (table, s.name, s.type, s.timeout, flags)
+ else:
+ cmd = "add map %s %s { type %s : %s;%s %s}" % (table, s.name, s.type, s.data, s.timeout, flags)
+
+ ret = execute_cmd(cmd, filename, lineno)
+
+ if (ret == 0 and test_result == "fail") or \
+ (ret != 0 and test_result == "ok"):
+ reason = "%s: I cannot add the set %s" % (cmd, s.name)
+ print_error(reason, filename, lineno)
+ return -1
+
+ if not _set_exist(s, filename, lineno):
+ reason = "I have just added the set %s to " \
+ "the table %s but it does not exist" % (s.name, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+ return 0
+
+
+def map_add(s, test_result, filename, lineno):
+ '''
+ Adds a map
+ '''
+ if not table_list:
+ reason = "Missing table to add rule"
+ print_error(reason, filename, lineno)
+ return -1
+
+ for table in table_list:
+ s.table = table.name
+ s.family = table.family
+ if _map_exist(s, filename, lineno):
+ reason = "Map %s already exists in %s" % (s.name, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+ flags = s.flags
+ if flags != "":
+ flags = "flags %s; " % flags
+
+ cmd = "add map %s %s { type %s : %s;%s %s}" % (table, s.name, s.type, s.data, s.timeout, flags)
+
+ ret = execute_cmd(cmd, filename, lineno)
+
+ if (ret == 0 and test_result == "fail") or \
+ (ret != 0 and test_result == "ok"):
+ reason = "%s: I cannot add the set %s" % (cmd, s.name)
+ print_error(reason, filename, lineno)
+ return -1
+
+ if not _map_exist(s, filename, lineno):
+ reason = "I have just added the set %s to " \
+ "the table %s but it does not exist" % (s.name, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+
+def set_add_elements(set_element, set_name, state, filename, lineno):
+ '''
+ Adds elements to the set.
+ '''
+ if not table_list:
+ reason = "Missing table to add rules"
+ print_error(reason, filename, lineno)
+ return -1
+
+ for table in table_list:
+ # Check if set exists.
+ if (not set_exist(set_name, table, filename, lineno) or
+ set_name not in all_set) and state == "ok":
+ reason = "I cannot add an element to the set %s " \
+ "since it does not exist." % set_name
+ print_error(reason, filename, lineno)
+ return -1
+
+ element = ", ".join(set_element)
+ cmd = "add element %s %s { %s }" % (table, set_name, element)
+ ret = execute_cmd(cmd, filename, lineno)
+
+ if (state == "fail" and ret == 0) or (state == "ok" and ret != 0):
+ if state == "fail":
+ test_state = "This rule should have failed."
+ else:
+ test_state = "This rule should not have failed."
+
+ reason = cmd + ": " + test_state
+ print_error(reason, filename, lineno)
+ return -1
+
+ # Add element into all_set.
+ if ret == 0 and state == "ok":
+ for e in set_element:
+ all_set[set_name].add(e)
+
+ return 0
+
+
+def set_delete_elements(set_element, set_name, table, filename=None,
+ lineno=None):
+ '''
+ Deletes elements in a set.
+ '''
+ for element in set_element:
+ cmd = "delete element %s %s { %s }" % (table, set_name, element)
+ ret = execute_cmd(cmd, filename, lineno)
+ if ret != 0:
+ reason = "I cannot delete element %s " \
+ "from the set %s" % (element, set_name)
+ print_error(reason, filename, lineno)
+ return -1
+
+ return 0
+
+
+def set_delete(table, filename=None, lineno=None):
+ '''
+ Deletes set and its content.
+ '''
+ for set_name in all_set.keys():
+ # Check if exists the set
+ if not set_exist(set_name, table, filename, lineno):
+ reason = "The set %s does not exist, " \
+ "I cannot delete it" % set_name
+ print_error(reason, filename, lineno)
+ return -1
+
+ # We delete all elements in the set
+ set_delete_elements(all_set[set_name], set_name, table, filename,
+ lineno)
+
+ # We delete the set.
+ cmd = "delete set %s %s" % (table, set_name)
+ ret = execute_cmd(cmd, filename, lineno)
+
+ # Check if the set still exists after I deleted it.
+ if ret != 0 or set_exist(set_name, table, filename, lineno):
+ reason = "Cannot remove the set " + set_name
+ print_error(reason, filename, lineno)
+ return -1
+
+ return 0
+
+
+def set_exist(set_name, table, filename, lineno):
+ '''
+ Check if the set exists.
+ '''
+ cmd = "list set %s %s" % (table, set_name)
+ ret = execute_cmd(cmd, filename, lineno)
+
+ return True if (ret == 0) else False
+
+
+def _set_exist(s, filename, lineno):
+ '''
+ Check if the set exists.
+ '''
+ cmd = "list set %s %s %s" % (s.family, s.table, s.name)
+ ret = execute_cmd(cmd, filename, lineno)
+
+ return True if (ret == 0) else False
+
+
+def _map_exist(s, filename, lineno):
+ '''
+ Check if the map exists.
+ '''
+ cmd = "list map %s %s %s" % (s.family, s.table, s.name)
+ ret = execute_cmd(cmd, filename, lineno)
+
+ return True if (ret == 0) else False
+
+
+def set_check_element(rule1, rule2):
+ '''
+ Check if element exists in anonymous sets.
+ '''
+ pos1 = rule1.find("{")
+ pos2 = rule2.find("{")
+
+ if (rule1[:pos1] != rule2[:pos2]):
+ return False
+
+ end1 = rule1.find("}")
+ end2 = rule2.find("}")
+
+ if (pos1 != -1) and (pos2 != -1) and (end1 != -1) and (end2 != -1):
+ list1 = (rule1[pos1 + 1:end1].replace(" ", "")).split(",")
+ list2 = (rule2[pos2 + 1:end2].replace(" ", "")).split(",")
+ list1.sort()
+ list2.sort()
+ if list1 != list2:
+ return False
+
+ return rule1[end1:] == rule2[end2:]
+
+ return False
+
+
+def obj_add(o, test_result, filename, lineno):
+ '''
+ Adds an object.
+ '''
+ if not table_list:
+ reason = "Missing table to add rule"
+ print_error(reason, filename, lineno)
+ return -1
+
+ for table in table_list:
+ o.table = table.name
+ o.family = table.family
+ obj_handle = o.type + " " + o.name
+ if _obj_exist(o, filename, lineno):
+ reason = "The %s already exists in %s" % (obj_handle, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+ cmd = "add %s %s %s %s" % (o.type, table, o.name, o.spcf)
+ ret = execute_cmd(cmd, filename, lineno)
+
+ if (ret == 0 and test_result == "fail") or \
+ (ret != 0 and test_result == "ok"):
+ reason = "%s: I cannot add the %s" % (cmd, obj_handle)
+ print_error(reason, filename, lineno)
+ return -1
+
+ exist = _obj_exist(o, filename, lineno)
+
+ if exist:
+ if test_result == "ok":
+ return 0
+ reason = "I added the %s to the table %s " \
+ "but it should have failed" % (obj_handle, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+ if test_result == "fail":
+ return 0
+
+ reason = "I have just added the %s to " \
+ "the table %s but it does not exist" % (obj_handle, table)
+ print_error(reason, filename, lineno)
+ return -1
+
+def obj_delete(table, filename=None, lineno=None):
+ '''
+ Deletes object.
+ '''
+ for o in obj_list:
+ obj_handle = o.type + " " + o.name
+ # Check if exists the obj
+ if not obj_exist(o, table, filename, lineno):
+ reason = "The %s does not exist, I cannot delete it" % obj_handle
+ print_error(reason, filename, lineno)
+ return -1
+
+ # We delete the object.
+ cmd = "delete %s %s %s" % (o.type, table, o.name)
+ ret = execute_cmd(cmd, filename, lineno)
+
+ # Check if the object still exists after I deleted it.
+ if ret != 0 or obj_exist(o, table, filename, lineno):
+ reason = "Cannot remove the " + obj_handle
+ print_error(reason, filename, lineno)
+ return -1
+
+ return 0
+
+
+def obj_exist(o, table, filename, lineno):
+ '''
+ Check if the object exists.
+ '''
+ cmd = "list %s %s %s" % (o.type, table, o.name)
+ ret = execute_cmd(cmd, filename, lineno)
+
+ return True if (ret == 0) else False
+
+
+def _obj_exist(o, filename, lineno):
+ '''
+ Check if the object exists.
+ '''
+ cmd = "list %s %s %s %s" % (o.type, o.family, o.table, o.name)
+ ret = execute_cmd(cmd, filename, lineno)
+
+ return True if (ret == 0) else False
+
+
+def output_clean(pre_output, chain):
+ pos_chain = pre_output.find(chain.name)
+ if pos_chain == -1:
+ return ""
+ output_intermediate = pre_output[pos_chain:]
+ brace_start = output_intermediate.find("{")
+ brace_end = output_intermediate.find("}")
+ pre_rule = output_intermediate[brace_start:brace_end]
+ if pre_rule[1:].find("{") > -1: # this rule has a set.
+ set = pre_rule[1:].replace("\t", "").replace("\n", "").strip()
+ set = set.split(";")[2].strip() + "}"
+ remainder = output_clean(chain.name + " {;;" + output_intermediate[brace_end+1:], chain)
+ if len(remainder) <= 0:
+ return set
+ return set + " " + remainder
+ else:
+ rule = pre_rule.split(";")[2].replace("\t", "").replace("\n", "").\
+ strip()
+ if len(rule) < 0:
+ return ""
+ return rule
+
+
+def payload_check_elems_to_set(elems):
+ newset = set()
+
+ for n, line in enumerate(elems.split('[end]')):
+ e = line.strip()
+ if e in newset:
+ print_error("duplicate", e, n)
+ return newset
+
+ newset.add(e)
+
+ return newset
+
+
+def payload_check_set_elems(want, got):
+ if want.find('element') < 0 or want.find('[end]') < 0:
+ return 0
+
+ if got.find('element') < 0 or got.find('[end]') < 0:
+ return 0
+
+ set_want = payload_check_elems_to_set(want)
+ set_got = payload_check_elems_to_set(got)
+
+ return set_want == set_got
+
+
+def payload_check(payload_buffer, file, cmd):
+ file.seek(0, 0)
+ i = 0
+
+ if not payload_buffer:
+ return False
+
+ for lineno, want_line in enumerate(payload_buffer):
+ line = file.readline()
+
+ if want_line == line:
+ i += 1
+ continue
+
+ if want_line.find('[') < 0 and line.find('[') < 0:
+ continue
+ if want_line.find(']') < 0 and line.find(']') < 0:
+ continue
+
+ if payload_check_set_elems(want_line, line):
+ continue
+
+ print_differences_warning(file.name, lineno, want_line.strip(),
+ line.strip(), cmd)
+ return 0
+
+ return i > 0
+
+
+def json_dump_normalize(json_string, human_readable = False):
+ json_obj = json.loads(json_string)
+
+ if human_readable:
+ return json.dumps(json_obj, sort_keys = True,
+ indent = 4, separators = (',', ': '))
+ else:
+ return json.dumps(json_obj, sort_keys = True)
+
+def json_validate(json_string):
+ json_obj = json.loads(json_string)
+ try:
+ nftables.json_validate(json_obj)
+ except Exception:
+ print_error("schema validation failed for input '%s'" % json_string)
+ print_error(traceback.format_exc())
+
+def rule_add(rule, filename, lineno, force_all_family_option, filename_path):
+ '''
+ Adds a rule
+ '''
+ # TODO Check if a rule is added correctly.
+ ret = warning = error = unit_tests = 0
+
+ if not table_list or not chain_list:
+ reason = "Missing table or chain to add rule."
+ print_error(reason, filename, lineno)
+ return [-1, warning, error, unit_tests]
+
+ if rule[1].strip() == "ok":
+ payload_expected = None
+ payload_path = None
+ try:
+ payload_log = open("%s.payload" % filename_path)
+ payload_path = payload_log.name
+ payload_expected = payload_find_expected(payload_log, rule[0])
+ except:
+ payload_log = None
+
+ if enable_json_option:
+ try:
+ json_log = open("%s.json" % filename_path)
+ json_input = json_find_expected(json_log, rule[0])
+ except:
+ json_input = None
+
+ if not json_input:
+ print_error("did not find JSON equivalent for rule '%s'"
+ % rule[0])
+ else:
+ try:
+ json_input = json_dump_normalize(json_input)
+ except ValueError:
+ reason = "Invalid JSON syntax in rule: %s" % json_input
+ print_error(reason)
+ return [-1, warning, error, unit_tests]
+
+ try:
+ json_log = open("%s.json.output" % filename_path)
+ json_expected = json_find_expected(json_log, rule[0])
+ except:
+ # will use json_input for comparison
+ json_expected = None
+
+ if json_expected:
+ try:
+ json_expected = json_dump_normalize(json_expected)
+ except ValueError:
+ reason = "Invalid JSON syntax in expected output: %s" % json_expected
+ print_error(reason)
+ return [-1, warning, error, unit_tests]
+
+ for table in table_list:
+ if rule[1].strip() == "ok":
+ table_payload_expected = None
+ try:
+ payload_log = open("%s.payload.%s" % (filename_path, table.family))
+ payload_path = payload_log.name
+ table_payload_expected = payload_find_expected(payload_log, rule[0])
+ except:
+ if not payload_log:
+ print_error("did not find any payload information",
+ filename_path)
+ elif not payload_expected:
+ print_error("did not find payload information for "
+ "rule '%s'" % rule[0], payload_log.name, 1)
+ if not table_payload_expected:
+ table_payload_expected = payload_expected
+
+ for table_chain in table.chains:
+ chain = chain_get_by_name(table_chain)
+ unit_tests += 1
+ table_flush(table, filename, lineno)
+
+ payload_log = tempfile.TemporaryFile(mode="w+")
+
+ # Add rule and check return code
+ cmd = "add rule %s %s %s" % (table, chain, rule[0])
+ ret = execute_cmd(cmd, filename, lineno, payload_log, debug="netlink")
+
+ state = rule[1].rstrip()
+ if (ret in [0,134] and state == "fail") or (ret != 0 and state == "ok"):
+ if state == "fail":
+ test_state = "This rule should have failed."
+ else:
+ test_state = "This rule should not have failed."
+ reason = cmd + ": " + test_state
+ print_error(reason, filename, lineno)
+ ret = -1
+ error += 1
+ if not force_all_family_option:
+ return [ret, warning, error, unit_tests]
+
+ if state == "fail" and ret != 0:
+ ret = 0
+ continue
+
+ if ret != 0:
+ continue
+
+ # Check for matching payload
+ if state == "ok" and not payload_check(table_payload_expected,
+ payload_log, cmd):
+ error += 1
+
+ try:
+ gotf = open("%s.got" % payload_path)
+ gotf_payload_expected = payload_find_expected(gotf, rule[0])
+ gotf.close()
+ except:
+ gotf_payload_expected = None
+ payload_log.seek(0, 0)
+ if not payload_check(gotf_payload_expected, payload_log, cmd):
+ gotf = open("%s.got" % payload_path, 'a')
+ payload_log.seek(0, 0)
+ gotf.write("# %s\n" % rule[0])
+ while True:
+ line = payload_log.readline()
+ if line == "":
+ break
+ gotf.write(line)
+ gotf.close()
+ print_warning("Wrote payload for rule %s" % rule[0],
+ gotf.name, 1)
+
+ # Check for matching ruleset listing
+ numeric_proto_old = nftables.set_numeric_proto_output(True)
+ stateless_old = nftables.set_stateless_output(True)
+ list_cmd = 'list table %s' % table
+ rc, pre_output, err = nftables.cmd(list_cmd)
+ nftables.set_numeric_proto_output(numeric_proto_old)
+ nftables.set_stateless_output(stateless_old)
+
+ output = pre_output.split(";")
+ if len(output) < 2:
+ reason = cmd + ": Listing is broken."
+ print_error(reason, filename, lineno)
+ ret = -1
+ error += 1
+ if not force_all_family_option:
+ return [ret, warning, error, unit_tests]
+ continue
+
+ rule_output = output_clean(pre_output, chain)
+ retest_output = False
+ if len(rule) == 3:
+ teoric_exit = rule[2]
+ retest_output = True
+ else:
+ teoric_exit = rule[0]
+
+ if rule_output.rstrip() != teoric_exit.rstrip():
+ if rule[0].find("{") != -1: # anonymous sets
+ if not set_check_element(teoric_exit.rstrip(),
+ rule_output.rstrip()):
+ warning += 1
+ retest_output = True
+ print_differences_warning(filename, lineno,
+ teoric_exit.rstrip(),
+ rule_output, cmd)
+ if not force_all_family_option:
+ return [ret, warning, error, unit_tests]
+ else:
+ if len(rule_output) <= 0:
+ error += 1
+ print_differences_error(filename, lineno, cmd)
+ if not force_all_family_option:
+ return [ret, warning, error, unit_tests]
+
+ warning += 1
+ retest_output = True
+ print_differences_warning(filename, lineno,
+ teoric_exit.rstrip(),
+ rule_output, cmd)
+
+ if not force_all_family_option:
+ return [ret, warning, error, unit_tests]
+
+ if retest_output:
+ table_flush(table, filename, lineno)
+
+ # Add rule and check return code
+ cmd = "add rule %s %s %s" % (table, chain, rule_output.rstrip())
+ ret = execute_cmd(cmd, filename, lineno, payload_log, debug="netlink")
+
+ if ret != 0:
+ test_state = "Replaying rule failed."
+ reason = cmd + ": " + test_state
+ print_warning(reason, filename, lineno)
+ ret = -1
+ error += 1
+ if not force_all_family_option:
+ return [ret, warning, error, unit_tests]
+ # Check for matching payload
+ elif not payload_check(table_payload_expected,
+ payload_log, cmd):
+ error += 1
+
+ if not enable_json_option:
+ continue
+
+ # Generate JSON equivalent for rule if not found
+ if not json_input:
+ json_old = nftables.set_json_output(True)
+ rc, json_output, err = nftables.cmd(list_cmd)
+ nftables.set_json_output(json_old)
+
+ json_output = json.loads(json_output)
+ for item in json_output["nftables"]:
+ if "rule" in item:
+ del(item["rule"]["handle"])
+ json_output = item["rule"]
+ break
+ json_input = json.dumps(json_output["expr"], sort_keys = True)
+
+ gotf = open("%s.json.got" % filename_path, 'a')
+ jdump = json_dump_normalize(json_input, True)
+ gotf.write("# %s\n%s\n\n" % (rule[0], jdump))
+ gotf.close()
+ print_warning("Wrote JSON equivalent for rule %s" % rule[0],
+ gotf.name, 1)
+
+ table_flush(table, filename, lineno)
+ payload_log = tempfile.TemporaryFile(mode="w+")
+
+ # Add rule in JSON format
+ cmd = json.dumps({ "nftables": [{ "add": { "rule": {
+ "family": table.family,
+ "table": table.name,
+ "chain": chain.name,
+ "expr": json.loads(json_input),
+ }}}]})
+
+ if enable_json_schema:
+ json_validate(cmd)
+
+ json_old = nftables.set_json_output(True)
+ ret = execute_cmd(cmd, filename, lineno, payload_log, debug="netlink")
+ nftables.set_json_output(json_old)
+
+ if ret != 0:
+ reason = "Failed to add JSON equivalent rule"
+ print_error(reason, filename, lineno)
+ continue
+
+ # Check for matching payload
+ if not payload_check(table_payload_expected, payload_log, cmd):
+ error += 1
+ gotf = open("%s.json.payload.got" % filename_path, 'a')
+ payload_log.seek(0, 0)
+ gotf.write("# %s\n" % rule[0])
+ while True:
+ line = payload_log.readline()
+ if line == "":
+ break
+ gotf.write(line)
+ gotf.close()
+ print_warning("Wrote JSON payload for rule %s" % rule[0],
+ gotf.name, 1)
+
+ # Check for matching ruleset listing
+ numeric_proto_old = nftables.set_numeric_proto_output(True)
+ stateless_old = nftables.set_stateless_output(True)
+ json_old = nftables.set_json_output(True)
+ rc, json_output, err = nftables.cmd(list_cmd)
+ nftables.set_json_output(json_old)
+ nftables.set_numeric_proto_output(numeric_proto_old)
+ nftables.set_stateless_output(stateless_old)
+
+ if enable_json_schema:
+ json_validate(json_output)
+
+ json_output = json.loads(json_output)
+ for item in json_output["nftables"]:
+ if "rule" in item:
+ del(item["rule"]["handle"])
+ json_output = item["rule"]
+ break
+ json_output = json.dumps(json_output["expr"], sort_keys = True)
+
+ if not json_expected and json_output != json_input:
+ print_differences_warning(filename, lineno,
+ json_input, json_output, cmd)
+ error += 1
+ gotf = open("%s.json.output.got" % filename_path, 'a')
+ jdump = json_dump_normalize(json_output, True)
+ gotf.write("# %s\n%s\n\n" % (rule[0], jdump))
+ gotf.close()
+ print_warning("Wrote JSON output for rule %s" % rule[0],
+ gotf.name, 1)
+ # prevent further warnings and .got file updates
+ json_expected = json_output
+ elif json_expected and json_output != json_expected:
+ print_differences_warning(filename, lineno,
+ json_expected, json_output, cmd)
+ error += 1
+
+ return [ret, warning, error, unit_tests]
+
+
+def cleanup_on_exit():
+ for table in table_list:
+ for table_chain in table.chains:
+ chain = chain_get_by_name(table_chain)
+ chain_delete(chain, table, "", "")
+ if all_set:
+ set_delete(table)
+ if obj_list:
+ obj_delete(table)
+ table_delete(table)
+
+
+def signal_handler(signal, frame):
+ global signal_received
+ signal_received = 1
+
+
+def execute_cmd(cmd, filename, lineno, stdout_log=False, debug=False):
+ '''
+ Executes a command, checks for segfaults and returns the command exit
+ code.
+
+ :param cmd: string with the command to be executed
+ :param filename: name of the file tested (used for print_error purposes)
+ :param lineno: line number being tested (used for print_error purposes)
+ :param stdout_log: redirect stdout to this file instead of global log_file
+ :param debug: temporarily set these debug flags
+ '''
+ global log_file
+ print("command: {}".format(cmd), file=log_file)
+ if debug_option:
+ print(cmd)
+
+ log_file.flush()
+
+ if debug:
+ debug_old = nftables.get_debug()
+ nftables.set_debug(debug)
+
+ ret, out, err = nftables.cmd(cmd)
+
+ if not stdout_log:
+ stdout_log = log_file
+
+ stdout_log.write(out)
+ stdout_log.flush()
+ log_file.write(err)
+ log_file.flush()
+
+ if debug:
+ nftables.set_debug(debug_old)
+
+ return ret
+
+
+def print_result(filename, tests, warning, error):
+ return str(filename) + ": " + str(tests) + " unit tests, " + str(error) + \
+ " error, " + str(warning) + " warning"
+
+
+def print_result_all(filename, tests, warning, error, unit_tests):
+ return str(filename) + ": " + str(tests) + " unit tests, " + \
+ str(unit_tests) + " total test executed, " + str(error) + \
+ " error, " + str(warning) + " warning"
+
+
+def table_process(table_line, filename, lineno):
+ table_info = table_line.split(";")
+ table = Table(table_info[0], table_info[1], table_info[2].split(","))
+
+ return table_create(table, filename, lineno)
+
+
+def chain_process(chain_line, lineno):
+ chain_info = chain_line.split(";")
+ chain_list.append(Chain(chain_info[0], chain_info[1], lineno))
+
+ return 0
+
+
+def set_process(set_line, filename, lineno):
+ test_result = set_line[1]
+ timeout=""
+
+ tokens = set_line[0].split(" ")
+ set_name = tokens[0]
+ set_type = tokens[2]
+ set_data = ""
+ set_flags = ""
+
+ i = 3
+ while len(tokens) > i and tokens[i] == ".":
+ set_type += " . " + tokens[i+1]
+ i += 2
+
+ while len(tokens) > i and tokens[i] == ":":
+ set_data = tokens[i+1]
+ i += 2
+
+ if len(tokens) == i+2 and tokens[i] == "timeout":
+ timeout = "timeout " + tokens[i+1] + ";"
+ i += 2
+
+ if len(tokens) == i+2 and tokens[i] == "flags":
+ set_flags = tokens[i+1]
+ elif len(tokens) != i:
+ print_error(set_name + " bad flag: " + tokens[i], filename, lineno)
+
+ s = Set("", "", set_name, set_type, set_data, timeout, set_flags)
+
+ if set_data == "":
+ ret = set_add(s, test_result, filename, lineno)
+ else:
+ ret = map_add(s, test_result, filename, lineno)
+
+ if ret == 0:
+ all_set[set_name] = set()
+
+ return ret
+
+
+def set_element_process(element_line, filename, lineno):
+ rule_state = element_line[1]
+ element_line = element_line[0]
+ space = element_line.find(" ")
+ set_name = element_line[:space]
+ set_element = element_line[space:].split(",")
+
+ return set_add_elements(set_element, set_name, rule_state, filename, lineno)
+
+
+def obj_process(obj_line, filename, lineno):
+ test_result = obj_line[1]
+
+ tokens = obj_line[0].split(" ")
+ obj_name = tokens[0]
+ obj_type = tokens[2]
+ obj_spcf = ""
+
+ if obj_type == "ct" and tokens[3] == "helper":
+ obj_type = "ct helper"
+ tokens[3] = ""
+
+ if obj_type == "ct" and tokens[3] == "timeout":
+ obj_type = "ct timeout"
+ tokens[3] = ""
+
+ if obj_type == "ct" and tokens[3] == "expectation":
+ obj_type = "ct expectation"
+ tokens[3] = ""
+
+ if len(tokens) > 3:
+ obj_spcf = " ".join(tokens[3:])
+
+ o = Obj("", "", obj_name, obj_type, obj_spcf)
+
+ ret = obj_add(o, test_result, filename, lineno)
+ if ret == 0:
+ obj_list.append(o)
+
+ return ret
+
+
+def payload_find_expected(payload_log, rule):
+ '''
+ Find the netlink payload that should be generated by given rule in
+ payload_log
+
+ :param payload_log: open file handle of the payload data
+ :param rule: nft rule we are going to add
+ '''
+ found = 0
+ payload_buffer = []
+
+ while True:
+ line = payload_log.readline()
+ if not line:
+ break
+
+ if line[0] == "#": # rule start
+ rule_line = line.strip()[2:]
+
+ if rule_line == rule.strip():
+ found = 1
+ continue
+
+ if found == 1:
+ payload_buffer.append(line)
+ if line.isspace():
+ return payload_buffer
+
+ payload_log.seek(0, 0)
+ return payload_buffer
+
+
+def json_find_expected(json_log, rule):
+ '''
+ Find the corresponding JSON for given rule
+
+ :param json_log: open file handle of the json data
+ :param rule: nft rule we are going to add
+ '''
+ found = 0
+ json_buffer = ""
+
+ while True:
+ line = json_log.readline()
+ if not line:
+ break
+
+ if line[0] == "#": # rule start
+ rule_line = line.strip()[2:]
+
+ if rule_line == rule.strip():
+ found = 1
+ continue
+
+ if found == 1:
+ json_buffer += line.rstrip("\n").strip()
+ if line.isspace():
+ return json_buffer
+
+ json_log.seek(0, 0)
+ return json_buffer
+
+
+def run_test_file(filename, force_all_family_option, specific_file):
+ '''
+ Runs a test file
+
+ :param filename: name of the file with the test rules
+ '''
+ filename_path = os.path.join(TESTS_PATH, filename)
+ f = open(filename_path)
+ tests = passed = total_unit_run = total_warning = total_error = 0
+
+ for lineno, line in enumerate(f):
+ sys.stdout.flush()
+
+ if signal_received == 1:
+ print("\nSignal received. Cleaning up and Exitting...")
+ cleanup_on_exit()
+ sys.exit(0)
+
+ if line.isspace():
+ continue
+
+ if line[0] == "#": # Command-line
+ continue
+
+ if line[0] == '*': # Table
+ table_line = line.rstrip()[1:]
+ ret = table_process(table_line, filename, lineno)
+ if ret != 0:
+ break
+ continue
+
+ if line[0] == ":": # Chain
+ chain_line = line.rstrip()[1:]
+ ret = chain_process(chain_line, lineno)
+ if ret != 0:
+ break
+ continue
+
+ if line[0] == "!": # Adds this set
+ set_line = line.rstrip()[1:].split(";")
+ ret = set_process(set_line, filename, lineno)
+ tests += 1
+ if ret == -1:
+ continue
+ passed += 1
+ continue
+
+ if line[0] == "?": # Adds elements in a set
+ element_line = line.rstrip()[1:].split(";")
+ ret = set_element_process(element_line, filename, lineno)
+ tests += 1
+ if ret == -1:
+ continue
+
+ passed += 1
+ continue
+
+ if line[0] == "%": # Adds this object
+ brace = line.rfind("}")
+ if brace < 0:
+ obj_line = line.rstrip()[1:].split(";")
+ else:
+ obj_line = (line[1:brace+1], line[brace+2:].rstrip())
+
+ ret = obj_process(obj_line, filename, lineno)
+ tests += 1
+ if ret == -1:
+ continue
+ passed += 1
+ continue
+
+ # Rule
+ rule = line.split(';') # rule[1] Ok or FAIL
+ if len(rule) == 1 or len(rule) > 3 or rule[1].rstrip() \
+ not in {"ok", "fail"}:
+ reason = "Skipping malformed rule test. (%s)" % line.rstrip('\n')
+ print_warning(reason, filename, lineno)
+ continue
+
+ if line[0] == "-": # Run omitted lines
+ if need_fix_option:
+ rule[0] = rule[0].rstrip()[1:].strip()
+ else:
+ continue
+ elif need_fix_option:
+ continue
+
+ result = rule_add(rule, filename, lineno, force_all_family_option,
+ filename_path)
+ tests += 1
+ ret = result[0]
+ warning = result[1]
+ total_warning += warning
+ total_error += result[2]
+ total_unit_run += result[3]
+
+ if ret != 0:
+ continue
+
+ if warning == 0: # All ok.
+ passed += 1
+
+ # Delete rules, sets, chains and tables
+ for table in table_list:
+ # We delete chains
+ for table_chain in table.chains:
+ chain = chain_get_by_name(table_chain)
+ chain_delete(chain, table, filename, lineno)
+
+ # We delete sets.
+ if all_set:
+ ret = set_delete(table, filename, lineno)
+ if ret != 0:
+ reason = "There is a problem when we delete a set"
+ print_error(reason, filename, lineno)
+
+ # We delete tables.
+ table_delete(table, filename, lineno)
+
+ if specific_file:
+ if force_all_family_option:
+ print(print_result_all(filename, tests, total_warning, total_error,
+ total_unit_run))
+ else:
+ print(print_result(filename, tests, total_warning, total_error))
+ else:
+ if tests == passed and tests > 0:
+ print(filename + ": " + Colors.GREEN + "OK" + Colors.ENDC)
+
+ f.close()
+ del table_list[:]
+ del chain_list[:]
+ all_set.clear()
+
+ return [tests, passed, total_warning, total_error, total_unit_run]
+
+def spawn_netns():
+ # prefer unshare module
+ try:
+ import unshare
+ unshare.unshare(unshare.CLONE_NEWNET)
+ return True
+ except:
+ pass
+
+ # sledgehammer style:
+ # - call ourselves prefixed by 'unshare -n' if found
+ # - pass extra --no-netns parameter to avoid another recursion
+ try:
+ import shutil
+
+ unshare = shutil.which("unshare")
+ if unshare is None:
+ return False
+
+ sys.argv.append("--no-netns")
+ if debug_option:
+ print("calling: ", [unshare, "-n", sys.executable] + sys.argv)
+ os.execv(unshare, [unshare, "-n", sys.executable] + sys.argv)
+ except:
+ pass
+
+ return False
+
+def main():
+ parser = argparse.ArgumentParser(description='Run nft tests')
+
+ parser.add_argument('filenames', nargs='*', metavar='path/to/file.t',
+ help='Run only these tests')
+
+ parser.add_argument('-d', '--debug', action='store_true', dest='debug',
+ help='enable debugging mode')
+
+ parser.add_argument('-e', '--need-fix', action='store_true',
+ dest='need_fix_line', help='run rules that need a fix')
+
+ parser.add_argument('-f', '--force-family', action='store_true',
+ dest='force_all_family',
+ help='keep testing all families on error')
+
+ parser.add_argument('-H', '--host', action='store_true',
+ help='run tests against installed libnftables.so.1')
+
+ parser.add_argument('-j', '--enable-json', action='store_true',
+ dest='enable_json',
+ help='test JSON functionality as well')
+
+ parser.add_argument('-l', '--library', default=None,
+ help='path to libntables.so.1, overrides --host')
+
+ parser.add_argument('-N', '--no-netns', action='store_true',
+ dest='no_netns',
+ help='Do not run in own network namespace')
+
+ parser.add_argument('-s', '--schema', action='store_true',
+ dest='enable_schema',
+ help='verify json input/output against schema')
+
+ parser.add_argument('-v', '--version', action='version',
+ version='1.0',
+ help='Print the version information')
+
+ args = parser.parse_args()
+ global debug_option, need_fix_option, enable_json_option, enable_json_schema
+ debug_option = args.debug
+ need_fix_option = args.need_fix_line
+ force_all_family_option = args.force_all_family
+ enable_json_option = args.enable_json
+ enable_json_schema = args.enable_schema
+ specific_file = False
+
+ signal.signal(signal.SIGINT, signal_handler)
+ signal.signal(signal.SIGTERM, signal_handler)
+
+ if os.getuid() != 0:
+ print("You need to be root to run this, sorry")
+ return
+
+ if not args.no_netns and not spawn_netns():
+ print_warning("cannot run in own namespace, connectivity might break")
+
+ # Change working directory to repository root
+ os.chdir(TESTS_PATH + "/../..")
+
+ check_lib_path = True
+ if args.library is None:
+ if args.host:
+ args.library = 'libnftables.so.1'
+ check_lib_path = False
+ else:
+ args.library = 'src/.libs/libnftables.so.1'
+
+ if check_lib_path and not os.path.exists(args.library):
+ print("The nftables library at '%s' does not exist. "
+ "You need to build the project." % args.library)
+ return
+
+ if args.enable_schema and not args.enable_json:
+ print_error("Option --schema requires option --json")
+ return
+
+ global nftables
+ nftables = Nftables(sofile = args.library)
+
+ test_files = files_ok = run_total = 0
+ tests = passed = warnings = errors = 0
+ global log_file
+ try:
+ log_file = open(LOGFILE, 'w')
+ print_info("Log will be available at %s" % LOGFILE)
+ except IOError:
+ print_error("Cannot open log file %s" % LOGFILE)
+ return
+
+ file_list = []
+ if args.filenames:
+ file_list = args.filenames
+ if len(args.filenames) == 1:
+ specific_file = True
+ else:
+ for directory in TESTS_DIRECTORY:
+ path = os.path.join(TESTS_PATH, directory)
+ for root, dirs, files in os.walk(path):
+ for f in files:
+ if f.endswith(".t"):
+ file_list.append(os.path.join(directory, f))
+
+ for filename in file_list:
+ result = run_test_file(filename, force_all_family_option, specific_file)
+ file_tests = result[0]
+ file_passed = result[1]
+ file_warnings = result[2]
+ file_errors = result[3]
+ file_unit_run = result[4]
+
+ test_files += 1
+
+ if file_warnings == 0 and file_tests == file_passed:
+ files_ok += 1
+ if file_tests:
+ tests += file_tests
+ passed += file_passed
+ errors += file_errors
+ warnings += file_warnings
+ if force_all_family_option:
+ run_total += file_unit_run
+
+ if test_files == 0:
+ print("No test files to run")
+ else:
+ if not specific_file:
+ if force_all_family_option:
+ print("%d test files, %d files passed, %d unit tests, " % (test_files, files_ok, tests))
+ print("%d total executed, %d error, %d warning" % (run_total, errors,warnings))
+ else:
+ print("%d test files, %d files passed, %d unit tests, " % (test_files, files_ok, tests))
+ print("%d error, %d warning" % (errors, warnings))
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/py/tools/test-sanitizer.sh b/tests/py/tools/test-sanitizer.sh
new file mode 100755
index 0000000..92354d2
--- /dev/null
+++ b/tests/py/tools/test-sanitizer.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+# Do some simple sanity checks on tests:
+# - Report tests where reply matches command
+# - Report tests with non-ok exit but reply
+# - Check for duplicate test commands in *.t files
+# - Check for duplicate or stale payload records in *.t.payload* files
+# - Check for duplicate or stale json equivalents in *.t.json files
+
+cd $(dirname $0)/../
+
+[[ $1 ]] && tests="$@" || tests="*/*.t"
+
+reportfile=""
+report() { # (file, msg)
+ [[ "$reportfile" == "$1" ]] || {
+ reportfile="$1"
+ echo ""
+ echo "In $reportfile:"
+ }
+ shift
+ echo "$@"
+}
+
+for t in $tests; do
+ [[ -f $t ]] || continue
+
+ readarray -t cmdlines <<< $(grep -v -e '^ *[:*#-?]' -e '^ *$' $t)
+
+ cmds=""
+ for cmdline in "${cmdlines[@]}"; do
+ readarray -t -d ';' cmdparts <<< "$cmdline"
+ cmd="${cmdparts[0]}"
+ rc="${cmdparts[1]}"
+ out="${cmdparts[2]}"
+
+ [[ -n $cmd ]] || continue
+
+ #echo "cmdline: $cmdline"
+ #echo "cmd: $cmd"
+ #echo "rc: $rc"
+ #echo "out: $out"
+
+ [[ "$cmd" != "$out" ]] || \
+ report $t "reply matches cmd: $cmd"
+ [[ "$rc" != "ok" && "$out" ]] && \
+ report $t "output record with non-ok exit: $cmd"
+
+ cmds+="${cmd}\n"
+ done
+
+ readarray -t dups <<< $(echo -e "$cmds" | sort | uniq -d)
+ for dup in "${dups[@]}"; do
+ [[ -n $dup ]] || continue
+ report $t "duplicate command: $dup"
+ done
+
+ for p in $t.payload* $t.json; do
+ [[ -f $p ]] || continue
+ [[ $p == *.got ]] && continue
+ [[ $p == *.json ]] && t="json" || t="payload"
+
+ pcmds=$(grep '^#' $p)
+ readarray -t dups <<< $(echo "$pcmds" | sort | uniq -d)
+ readarray -t stales <<< $(echo "$pcmds" | while read hash pcmd; do
+ echo -e "$cmds" | grep -qxF "${pcmd}" || echo "# ${pcmd}"
+ done)
+
+ for stale in "${stales[@]}"; do
+ [[ -n $stale ]] || continue
+ report $p "stale $t record: $stale"
+ done
+ for dup in "${dups[@]}"; do
+ [[ -n $dup ]] || continue
+ report $p "duplicate $t record: $dup"
+ done
+ done
+done
diff --git a/tests/py/y b/tests/py/y
new file mode 100644
index 0000000..3ac1e95
--- /dev/null
+++ b/tests/py/y
@@ -0,0 +1,14 @@
+diff --git a/tests/py/ip/sets.t b/tests/py/ip/sets.t
+index a224d0fef13d..46d9686b7ddd 100644
+--- a/tests/py/ip/sets.t
++++ b/tests/py/ip/sets.t
+@@ -52,6 +52,9 @@ ip saddr != @set33 drop;fail
+ ip saddr . ip daddr @set5 drop;ok
+ add @set5 { ip saddr . ip daddr };ok
+
++!map1 type ipv4_addr . ipv4_addr : mark;ok
++add @map1 { ip saddr . ip daddr : meta mark };ok
++
+ # test nested anonymous sets
+ ip saddr { { 1.1.1.0, 3.3.3.0 }, 2.2.2.0 };ok;ip saddr { 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 };ok;ip saddr { 1.1.1.0/24, 2.2.2.0/24, 3.3.3.0/24 }