]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
Backport nftables tests/shell from 2a38f458f12b
authorPablo Neira Ayuso <pablo@netfilter.org>
Sun, 27 Jul 2025 21:27:14 +0000 (23:27 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 29 Jul 2025 00:50:22 +0000 (02:50 +0200)
Originally, the plan was to use tests/shell from git HEAD, but this
does not work well in practise because slight changes in the test
output break checks resulting in lots of [DUMP FAIL] errors.

It is easier to test infrastructure self-contained in this 1.0.6.y
branch.

However, backporting the tests/shell into 1.0.6.y turns out to be more
complicated than expected, so I decided to follow the opposite, which is
to (brute) force a copy of tests/shell from
2a38f458f12bc032dac1b3ba63f95ca5a3c03fbd into this branch.

This also requires a number follow up partial reverts on tests/shell
updates to work with 1.0.6.y.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
921 files changed:
tests/shell/features/bitshift.nft [new file with mode: 0644]
tests/shell/features/bitwise_multireg.nft [new file with mode: 0644]
tests/shell/features/catchall_element.nft [new file with mode: 0644]
tests/shell/features/cgroupsv2.nft [new file with mode: 0644]
tests/shell/features/chain_binding.nft [new file with mode: 0644]
tests/shell/features/comment.sh [new file with mode: 0755]
tests/shell/features/ctexpect.nft [new file with mode: 0644]
tests/shell/features/cttimeout.nft [new file with mode: 0644]
tests/shell/features/curl.sh [new file with mode: 0755]
tests/shell/features/destroy.nft [new file with mode: 0644]
tests/shell/features/dynset_op_delete.nft [new file with mode: 0644]
tests/shell/features/elem_timeout_update.sh [new file with mode: 0755]
tests/shell/features/flowtable_counter.sh [new file with mode: 0755]
tests/shell/features/flowtable_no_devices.nft [new file with mode: 0755]
tests/shell/features/ifname_based_hooks.sh [new file with mode: 0755]
tests/shell/features/inet_ingress.nft [new file with mode: 0644]
tests/shell/features/inet_nat.nft [new file with mode: 0644]
tests/shell/features/inner_matching.nft [new file with mode: 0644]
tests/shell/features/ip_options.nft [new file with mode: 0644]
tests/shell/features/ipsec.nft [new file with mode: 0644]
tests/shell/features/json.sh [new file with mode: 0755]
tests/shell/features/map_lookup.nft [new file with mode: 0644]
tests/shell/features/meta_time.nft [new file with mode: 0644]
tests/shell/features/netdev_chain_multidevice.sh [new file with mode: 0755]
tests/shell/features/netdev_chain_without_device.nft [new file with mode: 0644]
tests/shell/features/netdev_egress.nft [new file with mode: 0644]
tests/shell/features/netmap.nft [new file with mode: 0644]
tests/shell/features/osf.nft [new file with mode: 0644]
tests/shell/features/pipapo.nft [new file with mode: 0644]
tests/shell/features/position_id.sh [new file with mode: 0755]
tests/shell/features/prerouting_reject.nft [new file with mode: 0644]
tests/shell/features/rbtree_size_limit.nft [new file with mode: 0644]
tests/shell/features/reset_rule.sh [new file with mode: 0755]
tests/shell/features/reset_set.sh [new file with mode: 0755]
tests/shell/features/reset_tcp_options.nft [new file with mode: 0644]
tests/shell/features/sctp_chunks.nft [new file with mode: 0644]
tests/shell/features/secmark.nft [new file with mode: 0644]
tests/shell/features/set_expr.sh [new file with mode: 0755]
tests/shell/features/set_with_two_expressions.nft [new file with mode: 0644]
tests/shell/features/setelem_expiration.sh [new file with mode: 0755]
tests/shell/features/socat.sh [new file with mode: 0755]
tests/shell/features/stateful_object_update.sh [new file with mode: 0755]
tests/shell/features/synproxy.nft [new file with mode: 0644]
tests/shell/features/table_flag_owner.nft [new file with mode: 0644]
tests/shell/features/table_flag_persist.nft [new file with mode: 0644]
tests/shell/features/tcpdump.sh [new file with mode: 0755]
tests/shell/features/vsftpd.sh [new file with mode: 0755]
tests/shell/helpers/json-diff-pretty.sh [new file with mode: 0755]
tests/shell/helpers/json-pretty.sh [new file with mode: 0755]
tests/shell/helpers/json-sanitize-ruleset.sh [new file with mode: 0755]
tests/shell/helpers/nft-valgrind-wrapper.sh [new file with mode: 0755]
tests/shell/helpers/random-source.sh [new file with mode: 0755]
tests/shell/helpers/test-wrapper.sh [new file with mode: 0755]
tests/shell/run-tests.sh
tests/shell/testcases/bitwise/0040mark_binop_0 [moved from tests/shell/testcases/chains/0040mark_shift_0 with 55% similarity]
tests/shell/testcases/bitwise/0040mark_binop_1 [moved from tests/shell/testcases/chains/0040mark_shift_1 with 57% similarity]
tests/shell/testcases/bitwise/0040mark_binop_10 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_11 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_12 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_13 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_2 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_3 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_4 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_5 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_6 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_7 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_8 [new file with mode: 0755]
tests/shell/testcases/bitwise/0040mark_binop_9 [new file with mode: 0755]
tests/shell/testcases/bitwise/0044payload_binop_2 [new file with mode: 0755]
tests/shell/testcases/bitwise/0044payload_binop_5 [new file with mode: 0755]
tests/shell/testcases/bitwise/dumps/0040mark_binop_0.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_0.nft [moved from tests/shell/testcases/chains/dumps/0040mark_shift_0.nft with 58% similarity]
tests/shell/testcases/bitwise/dumps/0040mark_binop_1.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_1.nft [moved from tests/shell/testcases/chains/dumps/0040mark_shift_1.nft with 64% similarity]
tests/shell/testcases/bitwise/dumps/0040mark_binop_10.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_11.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_12.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_13.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_2.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_2.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_3.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_3.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_4.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_4.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_5.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_5.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_6.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_6.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_7.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_7.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_8.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_8.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_9.json-nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0040mark_binop_9.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0044payload_binop_2.nft [new file with mode: 0644]
tests/shell/testcases/bitwise/dumps/0044payload_binop_5.nft [new file with mode: 0644]
tests/shell/testcases/bogons/dumps/assert_failures.json-nft [new file with mode: 0644]
tests/shell/testcases/bogons/dumps/assert_failures.nft [new file with mode: 0644]
tests/shell/testcases/bogons/nft-f/delete_nonexistant_object_crash [new file with mode: 0644]
tests/shell/testcases/bogons/nft-f/mapping_with_invalid_datatype_crash [moved from tests/shell/testcases/bogons/nft-f/mapping_With_invalid_datatype_crash with 100% similarity]
tests/shell/testcases/bogons/nft-f/range_expression_corruption [new file with mode: 0644]
tests/shell/testcases/bogons/nft-f/set_definition_with_no_key_assert [new file with mode: 0644]
tests/shell/testcases/bogons/nft-f/use_after_free_on_chain_removal [new file with mode: 0644]
tests/shell/testcases/bogons/nft-f/zero_length_devicename2_assert [new file with mode: 0644]
tests/shell/testcases/bogons/nft-j-f/Assertion__out_failed_assert [new file with mode: 0644]
tests/shell/testcases/bogons/nft-j-f/binop_rhs_decode_error_crash [new file with mode: 0644]
tests/shell/testcases/bogons/nft-j-f/constant_expr_alloc_assert [new file with mode: 0644]
tests/shell/testcases/bogons/nft-j-f/expr_evaluate_concat_empty_concat_key_assert [new file with mode: 0644]
tests/shell/testcases/bogons/nft-j-f/list_a_destroyed_table_crash [new file with mode: 0644]
tests/shell/testcases/bogons/nft-j-f/reject_stmt_with_no_expression_crash [new file with mode: 0644]
tests/shell/testcases/bogons/nft-j-f/set_with_single_value_concat_assert [new file with mode: 0644]
tests/shell/testcases/bogons/nft-j-f/unkown_stateful_statement_type_19_assert [new file with mode: 0644]
tests/shell/testcases/cache/0008_delete_by_handle_0
tests/shell/testcases/cache/0010_implicit_chain_0
tests/shell/testcases/cache/0011_index_0
tests/shell/testcases/cache/dumps/0001_cache_handling_0.json-nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0002_interval_0.json-nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0003_cache_update_0.json-nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0003_cache_update_0.nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0004_cache_update_0.json-nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0004_cache_update_0.nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0005_cache_chain_flush.json-nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0005_cache_chain_flush.nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0006_cache_table_flush.json-nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0006_cache_table_flush.nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0007_echo_cache_init_0.json-nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0008_delete_by_handle_0.json-nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0008_delete_by_handle_0.nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0009_delete_by_handle_incorrect_0.json-nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0009_delete_by_handle_incorrect_0.nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0010_implicit_chain_0.nft [new file with mode: 0644]
tests/shell/testcases/cache/dumps/0011_index_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/0003jump_loop_1
tests/shell/testcases/chains/0010endless_jump_loop_1
tests/shell/testcases/chains/0011endless_jump_loop_1
tests/shell/testcases/chains/0014rename_0
tests/shell/testcases/chains/0018check_jump_loop_1
tests/shell/testcases/chains/0021prio_0
tests/shell/testcases/chains/0041chain_binding_0
tests/shell/testcases/chains/0042chain_variable_0
tests/shell/testcases/chains/0043chain_ingress_0
tests/shell/testcases/chains/0044chain_destroy_0 [new file with mode: 0755]
tests/shell/testcases/chains/dumps/0001jumps_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0002jumps_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0002jumps_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0003jump_loop_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0003jump_loop_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0004busy_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0004busy_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0005busy_map_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0005busy_map_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0006masquerade_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0007masquerade_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0007masquerade_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0008masquerade_jump_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0008masquerade_jump_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0009masquerade_jump_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0009masquerade_jump_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0010endless_jump_loop_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0010endless_jump_loop_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0011endless_jump_loop_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0011endless_jump_loop_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0013rename_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0014rename_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0014rename_0.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0015check_jump_loop_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0015check_jump_loop_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0016delete_handle_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0017masquerade_jump_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0017masquerade_jump_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0018check_jump_loop_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0018check_jump_loop_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0019masquerade_jump_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0019masquerade_jump_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0020depth_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0020depth_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0021prio_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0022prio_dummy_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0022prio_dummy_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0023prio_inet_srcnat_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0023prio_inet_srcnat_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0024prio_inet_dstnat_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0024prio_inet_dstnat_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0025prio_arp_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0025prio_arp_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0026prio_netdev_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0026prio_netdev_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0027prio_bridge_dstnat_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0027prio_bridge_dstnat_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0028prio_bridge_out_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0028prio_bridge_out_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0029prio_bridge_srcnat_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0029prio_bridge_srcnat_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0030create_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0031priority_variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0032priority_variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0033priority_variable_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0033priority_variable_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0034priority_variable_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0034priority_variable_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0035policy_variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0036policy_variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0036policy_variable_0.nft [moved from tests/shell/testcases/nft-f/dumps/0026policy_variable_0.nft with 100% similarity]
tests/shell/testcases/chains/dumps/0037policy_variable_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0037policy_variable_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0038policy_variable_1.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0038policy_variable_1.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0039negative_priority_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0039negative_priority_0.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0042chain_variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0042chain_variable_0.nft
tests/shell/testcases/chains/dumps/0043chain_ingress_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0043chain_ingress_0.nft [moved from tests/shell/testcases/chains/dumps/0043chain_ingress.nft with 72% similarity]
tests/shell/testcases/chains/dumps/0044chain_destroy_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/0044chain_destroy_0.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/jump_to_base_chain.nodump [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_chain_0.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_chain_0.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_chain_autoremove.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_chain_autoremove.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_chain_dev_addremove.nodump [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_chain_dev_gone.nodump [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.json-nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.nft [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_chain_multidev_gone.nodump [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_multidev_netns_gone.nodump [new file with mode: 0644]
tests/shell/testcases/chains/dumps/netdev_netns_gone.nodump [new file with mode: 0644]
tests/shell/testcases/chains/jump_to_base_chain [new file with mode: 0755]
tests/shell/testcases/chains/netdev_chain_0 [new file with mode: 0755]
tests/shell/testcases/chains/netdev_chain_autoremove [new file with mode: 0755]
tests/shell/testcases/chains/netdev_chain_dev_addremove [new file with mode: 0755]
tests/shell/testcases/chains/netdev_chain_dev_gone [new file with mode: 0755]
tests/shell/testcases/chains/netdev_chain_dormant_autoremove [new file with mode: 0755]
tests/shell/testcases/chains/netdev_chain_multidev_gone [new file with mode: 0755]
tests/shell/testcases/chains/netdev_move_device [new file with mode: 0755]
tests/shell/testcases/chains/netdev_multidev_netns_gone [new file with mode: 0755]
tests/shell/testcases/chains/netdev_netns_gone [new file with mode: 0755]
tests/shell/testcases/comments/dumps/comments_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/0012flowtable_variable_0
tests/shell/testcases/flowtable/0013addafterdelete_0
tests/shell/testcases/flowtable/0014addafterdelete_0
tests/shell/testcases/flowtable/dumps/0001flowtable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0002create_flowtable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0002create_flowtable_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0003add_after_flush_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0003add_after_flush_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0004delete_after_add_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0004delete_after_add_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0005delete_in_use_1.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0005delete_in_use_1.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0006segfault_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0006segfault_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0007prio_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0007prio_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0008prio_1.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0008prio_1.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0009deleteafterflush_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0009deleteafterflush_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0010delete_handle_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0010delete_handle_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0011deleteafterflush_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0011deleteafterflush_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.nft
tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0014addafterdelete_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0014addafterdelete_0.nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0015destroy_0.json-nft [new file with mode: 0644]
tests/shell/testcases/flowtable/dumps/0015destroy_0.nft [new file with mode: 0644]
tests/shell/testcases/include/0002relative_0
tests/shell/testcases/include/0003includepath_0
tests/shell/testcases/include/0013input_descriptors_included_files_0
tests/shell/testcases/include/0020include_chain_0
tests/shell/testcases/include/dumps/0001absolute_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0002relative_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0003includepath_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0004endlessloop_1.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0004endlessloop_1.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0005glob_empty_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0005glob_empty_0.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0006glob_single_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0007glob_double_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0008glob_nofile_wildcard_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0008glob_nofile_wildcard_0.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0009glob_nofile_1.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0009glob_nofile_1.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0010glob_broken_file_1.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0010glob_broken_file_1.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0011glob_dependency_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0012glob_dependency_1.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0012glob_dependency_1.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0013glob_dotfile_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0013input_descriptors_included_files_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0013input_descriptors_included_files_0.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0014glob_directory_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0014glob_directory_0.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0015doubleincludepath_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0016maxdepth_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0016maxdepth_0.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0017glob_more_than_maxdepth_1.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0017glob_more_than_maxdepth_1.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0018include_error_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0018include_error_0.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0019include_error_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0019include_error_0.nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/0020include_chain_0.json-nft [new file with mode: 0644]
tests/shell/testcases/include/dumps/glob_duplicated_include.nft [new file with mode: 0644]
tests/shell/testcases/include/glob_duplicated_include [new file with mode: 0755]
tests/shell/testcases/json/0001set_statements_0
tests/shell/testcases/json/0002table_map_0
tests/shell/testcases/json/0003json_schema_version_0
tests/shell/testcases/json/0004json_schema_version_1
tests/shell/testcases/json/0005secmark_objref_0
tests/shell/testcases/json/0006obj_comment_0
tests/shell/testcases/json/dumps/0001set_statements_0.json-nft [new file with mode: 0644]
tests/shell/testcases/json/dumps/0002table_map_0.json-nft [new file with mode: 0644]
tests/shell/testcases/json/dumps/0003json_schema_version_0.json-nft [new file with mode: 0644]
tests/shell/testcases/json/dumps/0004json_schema_version_1.json-nft [new file with mode: 0644]
tests/shell/testcases/json/dumps/0005secmark_objref_0.json-nft [new file with mode: 0644]
tests/shell/testcases/json/dumps/0006obj_comment_0.json-nft [new file with mode: 0644]
tests/shell/testcases/json/dumps/netdev.json-nft [new file with mode: 0644]
tests/shell/testcases/json/dumps/netdev.nft [new file with mode: 0644]
tests/shell/testcases/json/netdev
tests/shell/testcases/json/single_flag [new file with mode: 0755]
tests/shell/testcases/listing/0013objects_0
tests/shell/testcases/listing/0020flowtable_0
tests/shell/testcases/listing/0021ruleset_json_terse_0
tests/shell/testcases/listing/dumps/0001ruleset_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0002ruleset_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0002ruleset_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0003table_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0003table_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0004table_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0004table_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0005ruleset_ip_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0005ruleset_ip_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0006ruleset_ip6_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0006ruleset_ip6_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0007ruleset_inet_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0007ruleset_inet_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0008ruleset_arp_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0008ruleset_arp_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0009ruleset_bridge_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0009ruleset_bridge_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0010sets_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0010sets_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0011sets_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0011sets_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0012sets_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0012sets_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0013objects_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0013objects_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0014objects_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0014objects_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0015dynamic_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0015dynamic_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0016anonymous_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0016anonymous_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0017objects_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0017objects_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0018data_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0018data_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0019set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0019set_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0020flowtable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0020flowtable_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0021ruleset_json_terse_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0021ruleset_json_terse_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0022terse_0.json-nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/0022terse_0.nft [new file with mode: 0644]
tests/shell/testcases/listing/dumps/meta_time.nft [deleted file]
tests/shell/testcases/listing/dumps/meta_time.nodump [new file with mode: 0644]
tests/shell/testcases/listing/meta_time
tests/shell/testcases/listing/reset_objects [new file with mode: 0755]
tests/shell/testcases/maps/0003map_add_many_elements_0
tests/shell/testcases/maps/0004interval_map_create_once_0
tests/shell/testcases/maps/0008interval_map_delete_0
tests/shell/testcases/maps/0009vmap_0
tests/shell/testcases/maps/0010concat_map_0
tests/shell/testcases/maps/0011vmap_0
tests/shell/testcases/maps/0012map_0
tests/shell/testcases/maps/0012map_concat_0 [new file with mode: 0755]
tests/shell/testcases/maps/0013map_0
tests/shell/testcases/maps/0014destroy_0 [new file with mode: 0755]
tests/shell/testcases/maps/0016map_leak_0 [new file with mode: 0755]
tests/shell/testcases/maps/0017_map_variable_0
tests/shell/testcases/maps/0018map_leak_timeout_0 [new file with mode: 0755]
tests/shell/testcases/maps/0024named_objects_0 [moved from tests/shell/testcases/sets/0024named_objects_0 with 70% similarity]
tests/shell/testcases/maps/anon_objmap_concat
tests/shell/testcases/maps/delete_element [new file with mode: 0755]
tests/shell/testcases/maps/delete_element_catchall [new file with mode: 0755]
tests/shell/testcases/maps/dumps/0003map_add_many_elements_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0003map_add_many_elements_0.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0004interval_map_create_once_0.nodump [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0005interval_map_add_many_elements_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0005interval_map_add_many_elements_0.nft
tests/shell/testcases/maps/dumps/0006interval_map_overlap_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0006interval_map_overlap_0.nft
tests/shell/testcases/maps/dumps/0007named_ifname_dtype_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0008interval_map_delete_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0008interval_map_delete_0.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0009vmap_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0010concat_map_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0011vmap_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0011vmap_0.nft
tests/shell/testcases/maps/dumps/0012map_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0012map_0.nft
tests/shell/testcases/maps/dumps/0012map_concat_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0012map_concat_0.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0013map_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0014destroy_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0014destroy_0.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0016map_leak_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0016map_leak_0.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0017_map_variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0017_map_variable_0.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0018map_leak_timeout_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0018map_leak_timeout_0.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0024named_objects_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/0024named_objects_0.nft [moved from tests/shell/testcases/sets/dumps/0024named_objects_0.nft with 50% similarity]
tests/shell/testcases/maps/dumps/0024named_objects_2.nodump [new file with mode: 0644]
tests/shell/testcases/maps/dumps/anon_objmap_concat.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/anonymous_snat_map_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/anonymous_snat_map_2.nodump [new file with mode: 0644]
tests/shell/testcases/maps/dumps/delete_element.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/delete_element_catchall.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/different_map_types_1.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/different_map_types_1.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/map_catchall_double_deactivate.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/map_catchall_double_deactivate.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/map_catchall_double_free.nodump [new file with mode: 0644]
tests/shell/testcases/maps/dumps/map_catchall_double_free_2.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/map_catchall_double_free_2.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/map_with_flags_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/named_ct_objects.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/named_limits.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/named_limits.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/named_snat_map_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/pipapo_double_flush.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/pipapo_double_flush.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/typeof_integer_0.nft
tests/shell/testcases/maps/dumps/typeof_maps_0.nft
tests/shell/testcases/maps/dumps/typeof_maps_add_delete.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/typeof_maps_add_delete.nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/typeof_maps_update_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/typeof_raw_0.nft
tests/shell/testcases/maps/dumps/vmap_mark_bitwise_0.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/vmap_mark_bitwise_0.nft
tests/shell/testcases/maps/dumps/vmap_timeout.json-nft [new file with mode: 0644]
tests/shell/testcases/maps/dumps/vmap_timeout.nft [new file with mode: 0644]
tests/shell/testcases/maps/map_catchall_double_deactivate [new file with mode: 0755]
tests/shell/testcases/maps/map_catchall_double_free [new file with mode: 0755]
tests/shell/testcases/maps/map_catchall_double_free_2 [new file with mode: 0755]
tests/shell/testcases/maps/named_ct_objects [new file with mode: 0755]
tests/shell/testcases/maps/named_limits [new file with mode: 0755]
tests/shell/testcases/maps/nat_addr_port
tests/shell/testcases/maps/pipapo_double_flush [new file with mode: 0755]
tests/shell/testcases/maps/typeof_integer_0
tests/shell/testcases/maps/typeof_maps_0
tests/shell/testcases/maps/typeof_maps_add_delete [new file with mode: 0755]
tests/shell/testcases/maps/typeof_raw_0
tests/shell/testcases/maps/vmap_mark_bitwise_0
tests/shell/testcases/maps/vmap_timeout [new file with mode: 0755]
tests/shell/testcases/maps/vmap_unary
tests/shell/testcases/netns/dumps/0001nft-f_0.json-nft [new file with mode: 0644]
tests/shell/testcases/netns/dumps/0001nft-f_0.nft [new file with mode: 0644]
tests/shell/testcases/netns/dumps/0002loosecommands_0.json-nft [new file with mode: 0644]
tests/shell/testcases/netns/dumps/0002loosecommands_0.nft [new file with mode: 0644]
tests/shell/testcases/netns/dumps/0003many_0.json-nft [new file with mode: 0644]
tests/shell/testcases/netns/dumps/0003many_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/0011manydefines_0
tests/shell/testcases/nft-f/0017ct_timeout_obj_0
tests/shell/testcases/nft-f/0018ct_expectation_obj_0
tests/shell/testcases/nft-f/0025empty_dynset_0
tests/shell/testcases/nft-f/0032pknock_0 [new file with mode: 0755]
tests/shell/testcases/nft-f/dumps/0001define_slash_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0001define_slash_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0002rollback_rule_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0003rollback_jump_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0004rollback_set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0005rollback_map_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0006action_object_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0006action_object_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0008split_tables_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0009variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0010variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0011manydefines_0.nodump [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0013defines_1.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0013defines_1.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0014defines_1.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0014defines_1.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0015defines_1.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0015defines_1.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0016redefines_1.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0016redefines_1.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0018jump_variable_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0019jump_variable_1.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0019jump_variable_1.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0020jump_variable_1.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0020jump_variable_1.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0021list_ruleset_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0022variables_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0023check_1.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0023check_1.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0024priority_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0026listing_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0026listing_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0027split_chains_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0028variable_cmdline_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0029split_file_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0029split_file_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0030variable_reuse_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0031vmap_string_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0031vmap_string_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0032pknock_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-f/dumps/0032pknock_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-f/sample-ruleset [new file with mode: 0755]
tests/shell/testcases/nft-i/dumps/0001define_0.json-nft [new file with mode: 0644]
tests/shell/testcases/nft-i/dumps/0001define_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-i/dumps/index_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-i/dumps/set_0.nft [new file with mode: 0644]
tests/shell/testcases/nft-i/index_0 [new file with mode: 0755]
tests/shell/testcases/nft-i/set_0 [new file with mode: 0755]
tests/shell/testcases/optimizations/dumps/dependency_kill.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_nat.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_nat.nft
tests/shell/testcases/optimizations/dumps/merge_nat_concat.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_nat_concat.nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_nat_inet.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_nat_inet.nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_reject.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_stmts.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_stmts_concat_vmap.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_stmts_vmap.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_vmap_raw.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/merge_vmaps.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/not_mergeable.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/ruleset.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/ruleset.nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/single_anon_set.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/single_anon_set.nft
tests/shell/testcases/optimizations/dumps/single_anon_set.nft.input [deleted file]
tests/shell/testcases/optimizations/dumps/single_anon_set_expr.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/single_anon_set_expr.nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/skip_merge.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/skip_non_eq.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/skip_unsupported.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/variables.json-nft [new file with mode: 0644]
tests/shell/testcases/optimizations/dumps/variables.nft [new file with mode: 0644]
tests/shell/testcases/optimizations/merge_nat
tests/shell/testcases/optimizations/merge_nat_concat [new file with mode: 0755]
tests/shell/testcases/optimizations/merge_nat_inet [new file with mode: 0755]
tests/shell/testcases/optimizations/merge_stmts_concat
tests/shell/testcases/optimizations/merge_stmts_vmap
tests/shell/testcases/optimizations/merge_vmap_raw
tests/shell/testcases/optimizations/ruleset
tests/shell/testcases/optimizations/single_anon_set
tests/shell/testcases/optimizations/single_anon_set_expr [new file with mode: 0755]
tests/shell/testcases/optionals/comments_chain_0
tests/shell/testcases/optionals/comments_objects_0
tests/shell/testcases/optionals/comments_table_0
tests/shell/testcases/optionals/dumps/comments_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/comments_chain_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/comments_handles_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/comments_objects_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/comments_objects_0.nft
tests/shell/testcases/optionals/dumps/comments_objects_dup_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/comments_objects_dup_0.nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/comments_table_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/delete_object_handles_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/delete_object_handles_0.nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/handles_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/handles_1.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/handles_1.nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/log_prefix_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/update_object_handles_0.json-nft [new file with mode: 0644]
tests/shell/testcases/optionals/dumps/update_object_handles_0.nft [new file with mode: 0644]
tests/shell/testcases/optionals/update_object_handles_0
tests/shell/testcases/owner/0001-flowtable-uaf
tests/shell/testcases/owner/0002-persist [new file with mode: 0755]
tests/shell/testcases/owner/dumps/0001-flowtable-uaf.json-nft [new file with mode: 0644]
tests/shell/testcases/owner/dumps/0001-flowtable-uaf.nft [new file with mode: 0644]
tests/shell/testcases/owner/dumps/0002-persist.json-nft [new file with mode: 0644]
tests/shell/testcases/owner/dumps/0002-persist.nft [new file with mode: 0644]
tests/shell/testcases/packetpath/cgroupv2 [new file with mode: 0755]
tests/shell/testcases/packetpath/dumps/cgroupv2.nodump [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/flowtables.nodump [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/payload.nodump [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/policy.json-nft [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/policy.nft [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/set_lookups.json-nft [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/set_lookups.nft [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/tcp_reset.json-nft [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/tcp_reset.nft [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/vlan_8021ad_tag.nodump [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/vlan_mangling.nodump [new file with mode: 0644]
tests/shell/testcases/packetpath/dumps/vlan_qinq.nodump [new file with mode: 0644]
tests/shell/testcases/packetpath/flowtables [new file with mode: 0755]
tests/shell/testcases/packetpath/match_l4proto [new file with mode: 0755]
tests/shell/testcases/packetpath/nat_ftp [new file with mode: 0755]
tests/shell/testcases/packetpath/payload [new file with mode: 0755]
tests/shell/testcases/packetpath/policy [new file with mode: 0755]
tests/shell/testcases/packetpath/set_lookups [new file with mode: 0755]
tests/shell/testcases/packetpath/tcp_options
tests/shell/testcases/packetpath/tcp_reset [new file with mode: 0755]
tests/shell/testcases/packetpath/vlan_8021ad_tag [new file with mode: 0755]
tests/shell/testcases/packetpath/vlan_mangling [new file with mode: 0755]
tests/shell/testcases/packetpath/vlan_qinq [new file with mode: 0755]
tests/shell/testcases/parsing/dumps/describe.json-nft [new file with mode: 0644]
tests/shell/testcases/parsing/dumps/describe.nft [new file with mode: 0644]
tests/shell/testcases/parsing/dumps/large_rule_pipe.json-nft [new file with mode: 0644]
tests/shell/testcases/parsing/dumps/large_rule_pipe.nft [new file with mode: 0644]
tests/shell/testcases/parsing/dumps/log.json-nft [new file with mode: 0644]
tests/shell/testcases/parsing/dumps/log.nft [new file with mode: 0644]
tests/shell/testcases/parsing/dumps/octal.json-nft [new file with mode: 0644]
tests/shell/testcases/parsing/dumps/octal.nft [new file with mode: 0644]
tests/shell/testcases/parsing/large_rule_pipe [new file with mode: 0755]
tests/shell/testcases/rule_management/0004replace_0
tests/shell/testcases/rule_management/0010replace_0
tests/shell/testcases/rule_management/0011reset_0 [new file with mode: 0755]
tests/shell/testcases/rule_management/0012destroy_0 [new file with mode: 0755]
tests/shell/testcases/rule_management/dumps/0001addinsertposition_0.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0001addinsertposition_0.nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0002addinsertlocation_1.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0002addinsertlocation_1.nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0003insert_0.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0004replace_0.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0004replace_0.nft
tests/shell/testcases/rule_management/dumps/0005replace_1.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0005replace_1.nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0006replace_1.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0006replace_1.nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0007delete_0.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0008delete_1.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0008delete_1.nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0009delete_1.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0009delete_1.nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0010replace_0.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0010replace_0.nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0011reset_0.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0011reset_0.nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0012destroy_0.json-nft [new file with mode: 0644]
tests/shell/testcases/rule_management/dumps/0012destroy_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/0011add_many_elements_0
tests/shell/testcases/sets/0012add_delete_many_elements_0
tests/shell/testcases/sets/0013add_delete_many_elements_0
tests/shell/testcases/sets/0020comments_0
tests/shell/testcases/sets/0022type_selective_flush_0
tests/shell/testcases/sets/0024synproxy_0 [new file with mode: 0755]
tests/shell/testcases/sets/0030add_many_elements_interval_0
tests/shell/testcases/sets/0034get_element_0
tests/shell/testcases/sets/0036add_set_element_expiration_0
tests/shell/testcases/sets/0038meter_list_0
tests/shell/testcases/sets/0043concatenated_ranges_0
tests/shell/testcases/sets/0043concatenated_ranges_1
tests/shell/testcases/sets/0044interval_overlap_0
tests/shell/testcases/sets/0044interval_overlap_1
tests/shell/testcases/sets/0046netmap_0
tests/shell/testcases/sets/0047nat_0
tests/shell/testcases/sets/0048set_counters_0
tests/shell/testcases/sets/0051set_interval_counter_0
tests/shell/testcases/sets/0059set_update_multistmt_0
tests/shell/testcases/sets/0060set_multistmt_0
tests/shell/testcases/sets/0060set_multistmt_1
tests/shell/testcases/sets/0062set_connlimit_0
tests/shell/testcases/sets/0063set_catchall_0
tests/shell/testcases/sets/0064map_catchall_0
tests/shell/testcases/sets/0067nat_concat_interval_0
tests/shell/testcases/sets/0067nat_interval_0 [new file with mode: 0755]
tests/shell/testcases/sets/0068interval_stack_overflow_0
tests/shell/testcases/sets/0072destroy_0 [new file with mode: 0755]
tests/shell/testcases/sets/0073flat_interval_set [new file with mode: 0755]
tests/shell/testcases/sets/0074nested_interval_set [new file with mode: 0755]
tests/shell/testcases/sets/automerge_0
tests/shell/testcases/sets/collapse_elem_0
tests/shell/testcases/sets/concat_interval_0
tests/shell/testcases/sets/dumps/0001named_interval_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0002named_interval_automerging_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0003named_interval_missing_flag_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0004named_interval_shadow_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0005named_interval_shadow_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0006create_set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0007create_element_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0008comments_interval_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0008create_verdict_map_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0009comments_timeout_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0010comments_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0011add_many_elements_0.nodump [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0012add_delete_many_elements_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0013add_delete_many_elements_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0014malformed_set_is_not_defined_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0014malformed_set_is_not_defined_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0015rulesetflush_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0016element_leak_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0017add_after_flush_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0018set_check_size_1.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0018set_check_size_1.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0019set_check_size_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0020comments_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0021nesting_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0022type_selective_flush_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0022type_selective_flush_0.nft
tests/shell/testcases/sets/dumps/0023incomplete_add_set_command_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0024named_objects_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0024synproxy_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0024synproxy_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0025anonymous_set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0026named_limit_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0027ipv6_maps_ipv4_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0028autoselect_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0028autoselect_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0028delete_handle_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0028delete_handle_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0030add_many_elements_interval_0.nodump [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0031set_timeout_size_0.nodump [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0032restore_set_simple_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0033add_set_simple_flat_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0033add_set_simple_flat_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0034get_element_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0034get_element_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0035add_set_elements_flat_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0035add_set_elements_flat_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0036add_set_element_expiration_0.nodump [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0037_set_with_inet_service_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0038meter_list_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0038meter_list_0.nft
tests/shell/testcases/sets/dumps/0039delete_interval_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0039delete_interval_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0040get_host_endian_elements_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0040get_host_endian_elements_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0041interval_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0041interval_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0042update_set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0042update_set_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0043concatenated_ranges_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0043concatenated_ranges_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0043concatenated_ranges_1.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0043concatenated_ranges_1.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0044interval_overlap_0.nodump [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0044interval_overlap_1.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0044interval_overlap_1.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0045concat_ipv4_service.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0046netmap_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0047nat_0.nft
tests/shell/testcases/sets/dumps/0048set_counters_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0048set_counters_0.nft
tests/shell/testcases/sets/dumps/0049set_define_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0050set_define_1.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0050set_define_1.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0051set_interval_counter_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0052overlap_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0053echo_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0054comments_set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0055tcpflags_0.json-nft
tests/shell/testcases/sets/dumps/0056dynamic_limit_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0056dynamic_limit_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0057set_create_fails_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0057set_create_fails_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0058_setupdate_timeout_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0059set_update_multistmt_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0060set_multistmt_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0060set_multistmt_0.nft
tests/shell/testcases/sets/dumps/0060set_multistmt_1.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0060set_multistmt_1.nft
tests/shell/testcases/sets/dumps/0061anonymous_automerge_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0062set_connlimit_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0062set_connlimit_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0063set_catchall_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0063set_catchall_0.nft
tests/shell/testcases/sets/dumps/0064map_catchall_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0064map_catchall_0.nft
tests/shell/testcases/sets/dumps/0065_icmp_postprocessing.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0065_icmp_postprocessing.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0067nat_concat_interval_0.nft
tests/shell/testcases/sets/dumps/0067nat_interval_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0068interval_stack_overflow_0.nodump [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0069interval_merge_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0071unclosed_prefix_interval_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0072destroy_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0072destroy_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0073flat_interval_set.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0073flat_interval_set.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0074nested_interval_set.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/0074nested_interval_set.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/automerge_0.nodump [new file with mode: 0644]
tests/shell/testcases/sets/dumps/collapse_elem_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/collapse_elem_0.nft
tests/shell/testcases/sets/dumps/concat_interval_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/dynset_missing.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/elem_opts_compat_0.nodump [new file with mode: 0644]
tests/shell/testcases/sets/dumps/errors_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/errors_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/exact_overlap_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/exact_overlap_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/inner_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/inner_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/meter_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/meter_0.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/meter_set_reuse.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/meter_set_reuse.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/range_with_same_start_end.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/range_with_same_start_end.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/reset_command_0.nodump [new file with mode: 0644]
tests/shell/testcases/sets/dumps/set_element_timeout_updates.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/set_element_timeout_updates.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/set_eval_0.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/set_stmt.nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/sets_with_ifnames.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/type_set_symbol.json-nft [new file with mode: 0644]
tests/shell/testcases/sets/dumps/typeof_raw_0.nft
tests/shell/testcases/sets/dumps/typeof_sets_0.nft
tests/shell/testcases/sets/dumps/typeof_sets_concat.nft
tests/shell/testcases/sets/elem_limit_0
tests/shell/testcases/sets/elem_opts_compat_0
tests/shell/testcases/sets/inner_0 [new file with mode: 0755]
tests/shell/testcases/sets/interval_size [new file with mode: 0755]
tests/shell/testcases/sets/interval_size_random [new file with mode: 0755]
tests/shell/testcases/sets/meter_0 [new file with mode: 0755]
tests/shell/testcases/sets/meter_set_reuse [new file with mode: 0755]
tests/shell/testcases/sets/range_with_same_start_end [new file with mode: 0755]
tests/shell/testcases/sets/reset_command_0 [new file with mode: 0755]
tests/shell/testcases/sets/set_element_timeout_updates [new file with mode: 0755]
tests/shell/testcases/sets/set_stmt [new file with mode: 0755]
tests/shell/testcases/sets/sets_with_ifnames
tests/shell/testcases/sets/typeof_raw_0
tests/shell/testcases/sets/typeof_sets_0
tests/shell/testcases/sets/typeof_sets_concat
tests/shell/testcases/transactions/0023rule_1
tests/shell/testcases/transactions/0024rule_0
tests/shell/testcases/transactions/0049huge_0
tests/shell/testcases/transactions/0050rule_1
tests/shell/testcases/transactions/0051map_0 [new file with mode: 0755]
tests/shell/testcases/transactions/30s-stress [new file with mode: 0755]
tests/shell/testcases/transactions/anon_chain_loop [new file with mode: 0755]
tests/shell/testcases/transactions/atomic_replace.sh [new file with mode: 0755]
tests/shell/testcases/transactions/bad_expression [new file with mode: 0755]
tests/shell/testcases/transactions/bad_rule_graphs [new file with mode: 0755]
tests/shell/testcases/transactions/concat_range_abort [new file with mode: 0755]
tests/shell/testcases/transactions/doubled-set [new file with mode: 0755]
tests/shell/testcases/transactions/dumps/0001table_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0002table_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0003table_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0003table_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0010chain_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0011chain_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0012chain_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0013chain_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0014chain_1.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0014chain_1.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0015chain_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0015chain_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0020rule_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0020rule_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0021rule_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0022rule_1.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0022rule_1.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0023rule_1.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0023rule_1.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0024rule_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0025rule_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0030set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0031set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0032set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0033set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0034set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0035set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0036set_1.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0036set_1.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0037set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0038set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0039set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0040set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0041nat_restore_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0041nat_restore_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0042_stateful_expr_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0042_stateful_expr_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0043set_1.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0043set_1.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0044rule_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0044rule_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0045anon-unbind_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0045anon-unbind_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0046set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0046set_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0047set_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0047set_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0048helpers_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0048helpers_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0049huge_0.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0049huge_0.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0050rule_1.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0050rule_1.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/0051map_0.nodump [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/30s-stress.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/30s-stress.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/anon_chain_loop.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/anon_chain_loop.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/atomic_replace.sh.nodump [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/bad_expression.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/bad_expression.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/bad_rule_graphs.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/bad_rule_graphs.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/concat_range_abort.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/concat_range_abort.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/doubled-set.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/doubled-set.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/handle_bad_family.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/handle_bad_family.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/table_onoff.json-nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/table_onoff.nft [new file with mode: 0644]
tests/shell/testcases/transactions/dumps/validation_recursion.sh.nodump [new file with mode: 0644]
tests/shell/testcases/transactions/handle_bad_family [new file with mode: 0755]
tests/shell/testcases/transactions/table_onoff [new file with mode: 0755]
tests/shell/testcases/transactions/validation_recursion.sh [new file with mode: 0755]

diff --git a/tests/shell/features/bitshift.nft b/tests/shell/features/bitshift.nft
new file mode 100644 (file)
index 0000000..7f9ccb6
--- /dev/null
@@ -0,0 +1,7 @@
+# 567d746b55bc ("netfilter: bitwise: add support for shifts.")
+# v5.6-rc1~151^2~73^2
+table ip t {
+       chain c {
+               meta mark set meta mark << 2
+       }
+}
diff --git a/tests/shell/features/bitwise_multireg.nft b/tests/shell/features/bitwise_multireg.nft
new file mode 100644 (file)
index 0000000..cfce5a3
--- /dev/null
@@ -0,0 +1,5 @@
+table inet test {
+       chain y {
+               ct mark set ct mark | meta mark
+       }
+}
diff --git a/tests/shell/features/catchall_element.nft b/tests/shell/features/catchall_element.nft
new file mode 100644 (file)
index 0000000..1a02fd6
--- /dev/null
@@ -0,0 +1,8 @@
+# aaa31047a6d2 ("netfilter: nftables: add catch-all set element support")
+# v5.13-rc1~94^2~10^2~2
+table t {
+       map m {
+               type inet_service : inet_service
+               elements = { * : 42 }
+       }
+}
diff --git a/tests/shell/features/cgroupsv2.nft b/tests/shell/features/cgroupsv2.nft
new file mode 100644 (file)
index 0000000..b6a3869
--- /dev/null
@@ -0,0 +1,7 @@
+# e0bb96db96f8 ("netfilter: nft_socket: add support for cgroupsv2")
+# v5.13-rc1~94^2~35^2~20
+table ip t {
+       chain c {
+               socket cgroupv2 level 1 "user.slice" counter
+       }
+}
diff --git a/tests/shell/features/chain_binding.nft b/tests/shell/features/chain_binding.nft
new file mode 100644 (file)
index 0000000..b381ec5
--- /dev/null
@@ -0,0 +1,7 @@
+# d0e2c7de92c7 ("netfilter: nf_tables: add NFT_CHAIN_BINDING")
+# v5.9-rc1~133^2~302^2~1
+table ip t {
+       chain c {
+               jump { counter; }
+       }
+}
diff --git a/tests/shell/features/comment.sh b/tests/shell/features/comment.sh
new file mode 100755 (executable)
index 0000000..0ad24d0
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# 002f21765320 ("netfilter: nf_tables: add userdata attributes to nft_chain")
+# v5.10-rc1~107^2~60^2~5
+
+EXPECTED="table ip x {
+       chain y {
+               comment \"test\"
+       }
+}"
+
+$NFT -f - <<< $EXPECTED
+
+diff -u <($NFT list ruleset) - <<<"$EXPECTED"
diff --git a/tests/shell/features/ctexpect.nft b/tests/shell/features/ctexpect.nft
new file mode 100644 (file)
index 0000000..02c3dfd
--- /dev/null
@@ -0,0 +1,10 @@
+# 857b46027d6f ("netfilter: nft_ct: add ct expectations support")
+# v5.3-rc1~140^2~153^2~19
+table t {
+       ct expectation ctexpect {
+               protocol tcp
+               dport 5432
+               timeout 1h
+               size 12;
+       }
+}
diff --git a/tests/shell/features/cttimeout.nft b/tests/shell/features/cttimeout.nft
new file mode 100644 (file)
index 0000000..4be58cd
--- /dev/null
@@ -0,0 +1,8 @@
+# 7e0b2b57f01d ("netfilter: nft_ct: add ct timeout support")
+# v4.19-rc1~140^2~64^2~3
+table t {
+       ct timeout cttime {
+               protocol tcp;
+               policy = {established: 120 }
+       }
+}
diff --git a/tests/shell/features/curl.sh b/tests/shell/features/curl.sh
new file mode 100755 (executable)
index 0000000..6aa5162
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# check whether curl is installed and supports ftp
+curl --version | grep "^Protocols: "| grep -q " ftp"
diff --git a/tests/shell/features/destroy.nft b/tests/shell/features/destroy.nft
new file mode 100644 (file)
index 0000000..b97242e
--- /dev/null
@@ -0,0 +1,3 @@
+# f80a612dd77c ("netfilter: nf_tables: add support to destroy operation")
+# v6.3-rc1~162^2~264^2
+destroy table t
diff --git a/tests/shell/features/dynset_op_delete.nft b/tests/shell/features/dynset_op_delete.nft
new file mode 100644 (file)
index 0000000..125b452
--- /dev/null
@@ -0,0 +1,12 @@
+# d0a8d877da97 ("netfilter: nft_dynset: support for element deletion")
+# v5.4-rc1~131^2~59^2~4
+table ip x {
+       set s {
+               flags dynamic;
+               type inet_service;
+       }
+
+       chain y {
+               delete @s { tcp dport }
+       }
+}
diff --git a/tests/shell/features/elem_timeout_update.sh b/tests/shell/features/elem_timeout_update.sh
new file mode 100755 (executable)
index 0000000..6243170
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# 4201f3938914 ("netfilter: nf_tables: set element timeout update support")
+
+$NFT -f - <<EOF
+table ip t {
+       set s {
+               typeof ip saddr
+               timeout 1m
+               elements = { 1.2.3.4 }
+       }
+}
+EOF
+
+$NFT add element t s { 1.2.3.4 expires 1ms }
+
+sleep 0.001
+$NFT get element t s { 1.2.3.4 }
+
+[ $? -eq 0 ] && exit 111
+
+exit 0
diff --git a/tests/shell/features/flowtable_counter.sh b/tests/shell/features/flowtable_counter.sh
new file mode 100755 (executable)
index 0000000..a4c4c62
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# 53c2b2899af7 ("netfilter: flowtable: add counter support")
+# v5.7-rc1~146^2~12^2~16
+
+EXPECTED="table ip filter2 {
+       flowtable main_ft2 {
+               hook ingress priority filter
+               devices = { lo }
+               counter
+       }
+}"
+
+$NFT -f - <<< $EXPECTED
+
+diff -u <($NFT list ruleset) - <<<"$EXPECTED"
diff --git a/tests/shell/features/flowtable_no_devices.nft b/tests/shell/features/flowtable_no_devices.nft
new file mode 100755 (executable)
index 0000000..30dd3db
--- /dev/null
@@ -0,0 +1,8 @@
+# 05abe4456fa3 ("netfilter: nf_tables: allow to register flowtable with no devices")
+# v5.8-rc1~165^2~27^2~1
+table ip filter2 {
+       flowtable main_ft2 {
+               hook ingress priority filter
+               counter
+       }
+}
diff --git a/tests/shell/features/ifname_based_hooks.sh b/tests/shell/features/ifname_based_hooks.sh
new file mode 100755 (executable)
index 0000000..cada695
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# check if netdev chains survive without a single device
+
+unshare -n bash -c "ip link add d0 type dummy; \
+       $NFT \"table netdev t { \
+               chain c { \
+                       type filter hook ingress priority 0; devices = { d0 }; \
+               }; \
+       }\"; \
+       ip link del d0; \
+       $NFT list chain netdev t c"
diff --git a/tests/shell/features/inet_ingress.nft b/tests/shell/features/inet_ingress.nft
new file mode 100644 (file)
index 0000000..944a5c7
--- /dev/null
@@ -0,0 +1,7 @@
+# d3519cb89f6d ("netfilter: nf_tables: add inet ingress support")
+# v5.10-rc1~107^2~17^2~1
+table inet t {
+        chain c {
+                type filter hook ingress device "lo" priority filter; policy accept;
+        }
+}
diff --git a/tests/shell/features/inet_nat.nft b/tests/shell/features/inet_nat.nft
new file mode 100644 (file)
index 0000000..189ea1d
--- /dev/null
@@ -0,0 +1,7 @@
+# v5.2-rc1~133^2~174^2~15
+# d164385ec572 ("netfilter: nat: add inet family nat support")
+table inet x {
+        chain y {
+                type nat hook prerouting priority dstnat;
+       }
+}
diff --git a/tests/shell/features/inner_matching.nft b/tests/shell/features/inner_matching.nft
new file mode 100644 (file)
index 0000000..6c86fd3
--- /dev/null
@@ -0,0 +1,7 @@
+# 3a07327d10a0 ("netfilter: nft_inner: support for inner tunnel header matching")
+# v6.2-rc1~99^2~350^2~4
+table ip t {
+        chain c {
+                udp dport 4789 vxlan ip saddr 1.2.3.4
+        }
+}
diff --git a/tests/shell/features/ip_options.nft b/tests/shell/features/ip_options.nft
new file mode 100644 (file)
index 0000000..0b8cb09
--- /dev/null
@@ -0,0 +1,8 @@
+# dbb5281a1f84 ("netfilter: nf_tables: add support for matching IPv4 options")
+# v5.3-rc1~140^2~153^2~1
+
+table ip x {
+       chain y {
+               ip option ra value 255
+       }
+}
diff --git a/tests/shell/features/ipsec.nft b/tests/shell/features/ipsec.nft
new file mode 100644 (file)
index 0000000..e725227
--- /dev/null
@@ -0,0 +1,7 @@
+# 6c47260250fc ("netfilter: nf_tables: add xfrm expression")
+# v4.20-rc1~14^2~125^2~25
+table ip x {
+       chain y {
+               ipsec in reqid 23
+       }
+}
diff --git a/tests/shell/features/json.sh b/tests/shell/features/json.sh
new file mode 100755 (executable)
index 0000000..d811570
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Detect JSON support. Note that $NFT may not be the binary from our build
+# tree, hence we detect it by running the binary (instead of asking the build
+# configuration).
+$NFT -j list ruleset
diff --git a/tests/shell/features/map_lookup.nft b/tests/shell/features/map_lookup.nft
new file mode 100644 (file)
index 0000000..06c4c9d
--- /dev/null
@@ -0,0 +1,11 @@
+# a4878eeae390 ("netfilter: nf_tables: relax set/map validation checks")
+# v6.5-rc1~163^2~256^2~8
+table ip t {
+        map m {
+                typeof ip daddr : meta mark
+        }
+
+        chain c {
+                ip saddr @m
+        }
+}
diff --git a/tests/shell/features/meta_time.nft b/tests/shell/features/meta_time.nft
new file mode 100644 (file)
index 0000000..34550de
--- /dev/null
@@ -0,0 +1,7 @@
+# 63d10e12b00d ("netfilter: nft_meta: support for time matching")
+# v5.4-rc1~131^2~59^2~6
+table ip t {
+       chain c {
+               meta time "1970-05-23 21:07:14"
+       }
+}
diff --git a/tests/shell/features/netdev_chain_multidevice.sh b/tests/shell/features/netdev_chain_multidevice.sh
new file mode 100755 (executable)
index 0000000..d2a56d6
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# d54725cd11a5 ("netfilter: nf_tables: support for multiple devices per netdev hook")
+# v5.5-rc1~174^2~312^2~4
+
+trap "ip link del d0; ip link del d1" EXIT
+
+ip link add d0 type dummy
+ip link add d1 type dummy
+
+EXPECTED="table netdev filter2 {
+        chain Main_Ingress2 {
+                type filter hook ingress devices = { \"d0\", \"d1\" } priority -500; policy accept;
+        }
+}"
+
+$NFT -f - <<< $EXPECTED
diff --git a/tests/shell/features/netdev_chain_without_device.nft b/tests/shell/features/netdev_chain_without_device.nft
new file mode 100644 (file)
index 0000000..25eb200
--- /dev/null
@@ -0,0 +1,7 @@
+# 207296f1a03b ("netfilter: nf_tables: allow to create netdev chain without device")
+# v6.4-rc1~132^2~14^2
+table netdev t {
+       chain c {
+               type filter hook ingress priority 0; policy accept;
+        }
+}
diff --git a/tests/shell/features/netdev_egress.nft b/tests/shell/features/netdev_egress.nft
new file mode 100644 (file)
index 0000000..67d706d
--- /dev/null
@@ -0,0 +1,7 @@
+# 42df6e1d221d ("netfilter: Introduce egress hook")
+# v5.16-rc1~159^2~167^2~10
+table netdev t {
+       chain c {
+               type filter hook egress devices = { lo } priority 0; policy accept;
+       }
+}
diff --git a/tests/shell/features/netmap.nft b/tests/shell/features/netmap.nft
new file mode 100644 (file)
index 0000000..2580a8d
--- /dev/null
@@ -0,0 +1,8 @@
+# 3ff7ddb1353d ("netfilter: nft_nat: add netmap support")
+# v5.8-rc1~165^2~393^2
+table ip x {
+        chain y {
+              type nat hook postrouting priority srcnat; policy accept;
+              snat ip prefix to ip saddr map { 10.141.11.0/24 : 192.168.2.0/24 }
+        }
+}
diff --git a/tests/shell/features/osf.nft b/tests/shell/features/osf.nft
new file mode 100644 (file)
index 0000000..dbb6b4c
--- /dev/null
@@ -0,0 +1,7 @@
+# b96af92d6eaf ("netfilter: nf_tables: implement Passive OS fingerprint module in nft_osf")
+# v4.19-rc1~140^2~135^2~15
+table t {
+       chain c {
+               osf name "Linux"
+       }
+}
diff --git a/tests/shell/features/pipapo.nft b/tests/shell/features/pipapo.nft
new file mode 100644 (file)
index 0000000..3557721
--- /dev/null
@@ -0,0 +1,9 @@
+# 3c4287f62044 ("nf_tables: Add set type for arbitrary concatenation of ranges")
+# v5.6-rc1~151^2~28^2~1
+table t {
+       set s {
+               type ipv4_addr . inet_service
+               flags interval
+               elements = { 1.1.1.1-2.2.2.2 . 80-90 }
+       }
+}
diff --git a/tests/shell/features/position_id.sh b/tests/shell/features/position_id.sh
new file mode 100755 (executable)
index 0000000..43ac97a
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# 75dd48e2e420 ("netfilter: nf_tables: Support RULE_ID reference in new rule")
+# v5.1-rc1~178^2~405^2~27
+
+EXPECTED="table inet t {
+       chain c {
+               tcp dport 1234 accept
+               udp dport 4321 accept
+               accept
+       }
+}"
+
+RULESET="add table inet t
+add chain inet t c
+add rule inet t c tcp dport 1234 accept
+add rule inet t c accept
+insert rule inet t c index 1 udp dport 4321 accept
+"
+
+$NFT -f - <<< $RULESET
+
+diff -u <($NFT list ruleset) - <<<"$EXPECTED"
diff --git a/tests/shell/features/prerouting_reject.nft b/tests/shell/features/prerouting_reject.nft
new file mode 100644 (file)
index 0000000..3dcfb40
--- /dev/null
@@ -0,0 +1,8 @@
+# f53b9b0bdc59 netfilter: introduce support for reject at prerouting stage
+# v5.9-rc1~133^2~302^2~11
+table inet t {
+       chain nat_filter {
+               type filter hook prerouting priority 0; policy accept;
+               reject with icmpx type host-unreachable
+       }
+}
diff --git a/tests/shell/features/rbtree_size_limit.nft b/tests/shell/features/rbtree_size_limit.nft
new file mode 100644 (file)
index 0000000..7eb44fa
--- /dev/null
@@ -0,0 +1,10 @@
+# 8d738c1869f6 ("netfilter: nf_tables: fix set size with rbtree backend")
+# v6.14-rc1~162^2~7^2~13
+table inet x {
+        set y {
+                typeof ip saddr
+                flags interval
+                size 1
+                elements = { 10.1.1.0/24 }
+        }
+}
diff --git a/tests/shell/features/reset_rule.sh b/tests/shell/features/reset_rule.sh
new file mode 100755 (executable)
index 0000000..567ee2f
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# 8daa8fde3fc3 ("netfilter: nf_tables: Introduce NFT_MSG_GETRULE_RESET")
+# v6.2-rc1~99^2~210^2~2
+
+unshare -n bash -c "$NFT \"add table t; add chain t c ; add rule t c counter packets 1 bytes 42\"; \
+$NFT reset rules chain t c ; \
+$NFT reset rules chain t c |grep counter\ packets\ 0\ bytes\ 0"
diff --git a/tests/shell/features/reset_set.sh b/tests/shell/features/reset_set.sh
new file mode 100755 (executable)
index 0000000..3d03417
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# 079cd633219d ("netfilter: nf_tables: Introduce NFT_MSG_GETSETELEM_RESET")
+# v6.5-rc1~163^2~9^2~1
+
+unshare -n bash -c "$NFT add table t; \
+ $NFT add set t s { type ipv4_addr\; counter\; elements = { 127.0.0.1 counter packets 1 bytes 2 } } ; \
+ $NFT reset set t s ; \
+ $NFT reset set t s | grep counter\ packets\ 0\ bytes\ 0
+"
diff --git a/tests/shell/features/reset_tcp_options.nft b/tests/shell/features/reset_tcp_options.nft
new file mode 100644 (file)
index 0000000..47d1c7b
--- /dev/null
@@ -0,0 +1,5 @@
+table inet t {
+        chain c {
+               reset tcp option fastopen
+       }
+}
diff --git a/tests/shell/features/sctp_chunks.nft b/tests/shell/features/sctp_chunks.nft
new file mode 100644 (file)
index 0000000..520afd6
--- /dev/null
@@ -0,0 +1,7 @@
+# 133dc203d77d ("netfilter: nft_exthdr: Support SCTP chunks")
+# v5.14-rc1~119^2~373^2~15
+table ip t {
+       chain c {
+               sctp chunk init 0
+       }
+}
diff --git a/tests/shell/features/secmark.nft b/tests/shell/features/secmark.nft
new file mode 100644 (file)
index 0000000..ccbb572
--- /dev/null
@@ -0,0 +1,7 @@
+# fb961945457f ("netfilter: nf_tables: add SECMARK support")
+# v4.20-rc1~14^2~125^2~5
+table inet x {
+       secmark ssh_server {
+               "system_u:object_r:ssh_server_packet_t:s0"
+       }
+}
diff --git a/tests/shell/features/set_expr.sh b/tests/shell/features/set_expr.sh
new file mode 100755 (executable)
index 0000000..fbdfc22
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# 65038428b2c6 ("netfilter: nf_tables: allow to specify stateful expression in set definition")
+# v5.7-rc1~146^2~12^2~25
+
+# NFT_SET_EXPR to detect kernel feature only available since
+# b4e70d8dd9ea ("netfilter: nftables: add set expression flags")
+# v5.11-rc3~39^2^2
+
+EXPECTED="table ip x {
+       set y {
+               typeof ip saddr
+               counter
+       }
+}"
+
+$NFT -f - <<< $EXPECTED
+
+diff -u <($NFT list ruleset) - <<<"$EXPECTED"
diff --git a/tests/shell/features/set_with_two_expressions.nft b/tests/shell/features/set_with_two_expressions.nft
new file mode 100644 (file)
index 0000000..97632a7
--- /dev/null
@@ -0,0 +1,9 @@
+# 48b0ae046ee9 ("netfilter: nftables: netlink support for several set element expressions")
+# v5.11-rc1~169^2~25^2
+table x {
+        set y {
+                type ipv4_addr
+                size 65535
+                counter quota 500 bytes
+        }
+}
diff --git a/tests/shell/features/setelem_expiration.sh b/tests/shell/features/setelem_expiration.sh
new file mode 100755 (executable)
index 0000000..c539ceb
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# v5.3-rc1~140^2~153^2~8
+# 79ebb5bb4e38 ("netfilter: nf_tables: enable set expiration time for set elements")
+
+RULESET="table ip x {
+       set y {
+               type ipv4_addr
+               flags dynamic
+               timeout 1h
+       }
+}"
+
+$NFT -f - <<< $RULESET
+
+$NFT add element ip x y { 1.1.1.1 timeout 1h expires 15m59s }
+
+$NFT list ruleset | grep "expires 15m"
diff --git a/tests/shell/features/socat.sh b/tests/shell/features/socat.sh
new file mode 100755 (executable)
index 0000000..93cad6f
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# check whether socat is installed
+socat -h >/dev/null 2>&1
diff --git a/tests/shell/features/stateful_object_update.sh b/tests/shell/features/stateful_object_update.sh
new file mode 100755 (executable)
index 0000000..62fbf7e
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# d62d0ba97b58 ("netfilter: nf_tables: Introduce stateful object update operation")
+# v5.4-rc1~131^2~59^2~2
+
+set -e
+$NFT add table test-ip
+$NFT add quota test-ip traffic-quota 25 mbytes
+$NFT add quota test-ip traffic-quota 50 mbytes
+
+EXPECTED="table ip test-ip {
+       quota traffic-quota {
+               50 mbytes
+       }
+}"
+
+GET="$($NFT list ruleset)"
+if [ "$EXPECTED" != "$GET" ] ; then
+       diff -u <(echo "$EXPECTED") <(echo "$GET")
+       exit 1
+fi
diff --git a/tests/shell/features/synproxy.nft b/tests/shell/features/synproxy.nft
new file mode 100644 (file)
index 0000000..bea4f92
--- /dev/null
@@ -0,0 +1,9 @@
+# v5.3-rc1~140^2~44^2~10
+# ad49d86e07a4 ("netfilter: nf_tables: Add synproxy support")
+table inet x {
+       synproxy https-synproxy {
+               mss 1460
+               wscale 7
+               timestamp sack-perm
+       }
+}
diff --git a/tests/shell/features/table_flag_owner.nft b/tests/shell/features/table_flag_owner.nft
new file mode 100644 (file)
index 0000000..aef122a
--- /dev/null
@@ -0,0 +1,5 @@
+# 6001a930ce03 ("netfilter: nftables: introduce table ownership")
+# v5.12-rc1~200^2~6^2
+table t {
+       flags owner;
+}
diff --git a/tests/shell/features/table_flag_persist.nft b/tests/shell/features/table_flag_persist.nft
new file mode 100644 (file)
index 0000000..0da3e6d
--- /dev/null
@@ -0,0 +1,3 @@
+table t {
+       flags persist;
+}
diff --git a/tests/shell/features/tcpdump.sh b/tests/shell/features/tcpdump.sh
new file mode 100755 (executable)
index 0000000..70df9f6
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# check whether tcpdump is installed
+tcpdump -h >/dev/null 2>&1
diff --git a/tests/shell/features/vsftpd.sh b/tests/shell/features/vsftpd.sh
new file mode 100755 (executable)
index 0000000..d350064
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# check whether vsftpd is installed
+which vsftpd >/dev/null 2>&1
diff --git a/tests/shell/helpers/json-diff-pretty.sh b/tests/shell/helpers/json-diff-pretty.sh
new file mode 100755 (executable)
index 0000000..bebb7e8
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/bash -e
+
+BASEDIR="$(dirname "$0")"
+
+[ $# -eq 2 ] || (echo "$0: expects two JSON files as arguments" ; exit 1)
+
+FILE1="$1"
+FILE2="$2"
+
+pretty()
+{
+       "$BASEDIR/json-pretty.sh" < "$1" 2>&1 || :
+}
+
+echo "Cmd: \"$0\" \"$FILE1\" \"$FILE2\""
+diff -u "$FILE1" "$FILE2" 2>&1 || :
+diff -u <(pretty "$FILE1") <(pretty "$FILE2") 2>&1 || :
diff --git a/tests/shell/helpers/json-pretty.sh b/tests/shell/helpers/json-pretty.sh
new file mode 100755 (executable)
index 0000000..5407a84
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash -e
+
+exec_pretty() {
+       # The output of this command must be stable (and `jq` and python
+       # fallback must generate the same output.
+
+       if command -v jq &>/dev/null ; then
+               # If we have, use `jq`
+               exec jq
+       fi
+
+       # Fallback to python.
+       exec python -c '
+import json
+import sys
+
+parsed = json.load(sys.stdin)
+print(json.dumps(parsed, indent=2))
+'
+}
+
+[ "$#" -le 1 ] || { echo "At most one argument supported" ; exit 1 ; }
+
+if [ "$#" -eq 1 ] ; then
+       # One argument passed. This must be a JSON file.
+       [ -f "$1" ] || { echo "File \"$1\" does not exist" ; exit 1 ; }
+       exec_pretty < "$1"
+fi
+
+exec_pretty
diff --git a/tests/shell/helpers/json-sanitize-ruleset.sh b/tests/shell/helpers/json-sanitize-ruleset.sh
new file mode 100755 (executable)
index 0000000..31b85cb
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash -e
+
+die() {
+       printf "%s\n" "$*"
+       exit 1
+}
+
+do_sed() {
+       # Normalize the "version"/"release_name", otherwise we have to
+       # regenerate the JSON output upon new release.
+       #
+       # Also, "handle" are not stable. Normalize them 0.
+       sed \
+               -e '1s/^\({"nftables": \[{"metainfo": {"version": "\)[0-9.]\+\(", "release_name": "\)[^"]\+\(", "\)/\1VERSION\2RELEASE_NAME\3/' \
+               -e '1s/"handle": [0-9]\+\>/"handle": 0/g' \
+               "$@"
+}
+
+if [ "$#" = 0 ] ; then
+       do_sed
+       exit $?
+fi
+
+for f ; do
+       test -f "$f" || die "$0: file \"$f\" does not exist"
+done
+
+for f ; do
+       do_sed -i "$f" || die "$0: \`sed -i\` failed for \"$f\""
+done
diff --git a/tests/shell/helpers/nft-valgrind-wrapper.sh b/tests/shell/helpers/nft-valgrind-wrapper.sh
new file mode 100755 (executable)
index 0000000..98bbdf4
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash -e
+
+SUFFIX="$(date "+%H%M%S.%6N").$$"
+
+rc=0
+libtool \
+       --mode=execute \
+       valgrind \
+               --log-file="$NFT_TEST_TESTTMPDIR/valgrind.$SUFFIX.%p.log" \
+               --trace-children=yes \
+               --leak-check=full \
+               --show-leak-kinds=all \
+               --num-callers=100 \
+               --error-exitcode=122 \
+               --vgdb-prefix="$_NFT_TEST_VALGRIND_VGDB_PREFIX-$SUFFIX" \
+               $NFT_TEST_VALGRIND_OPTS \
+               "$NFT_REAL" \
+               "$@" \
+       || rc=$?
+
+if [ "$rc" -eq 122 ] ; then
+       shopt -s nullglob
+       FILES=( "$NFT_TEST_TESTTMPDIR/valgrind.$SUFFIX."*".log" )
+       shopt -u nullglob
+       (
+               printf '%s\n' "args: $*"
+               printf '%s\n' "${FILES[*]}"
+       ) >> "$NFT_TEST_TESTTMPDIR/rc-failed-valgrind"
+fi
+
+exit $rc
diff --git a/tests/shell/helpers/random-source.sh b/tests/shell/helpers/random-source.sh
new file mode 100755 (executable)
index 0000000..91a8248
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# Commands like `sort` and `shuf` have a "--random-source" argument, for
+# generating a stable, reproducible output. However, they require an input
+# that provides sufficiently many bytes (depending on the input).
+#
+# This script generates a stream that can be used like
+#
+#     shuf --random-source=<($0 "$seed")
+
+seed=""
+for a; do
+       seed="$seed${#a}:$a\n"
+done
+
+if command -v openssl &>/dev/null ; then
+       # We have openssl. Use it.
+       # https://www.gnu.org/software/coreutils/manual/html_node/Random-sources.html#Random-sources
+       #
+       # Note that we don't care that different installations/architectures generate the
+       # same output.
+       openssl enc -aes-256-ctr -pass "pass:$seed" -nosalt </dev/zero 2>/dev/null
+else
+       # Hack something. It's much slower.
+       idx=0
+       while : ; do
+               idx="$((idx++))"
+               seed="$(sha256sum <<<"$idx.$seed")"
+               echo ">>>$seed" >> a
+               seed="${seed%% *}"
+               LANG=C awk -v s="$seed" 'BEGIN{
+                       for (i=1; i <= length(s); i+=2) {
+                               xchar = substr(s, i, 2);
+                               decnum = strtonum("0x"xchar);
+                               printf("%c", decnum);
+                       }
+               }' || break
+       done
+fi
+exit 0
diff --git a/tests/shell/helpers/test-wrapper.sh b/tests/shell/helpers/test-wrapper.sh
new file mode 100755 (executable)
index 0000000..4a7e8b7
--- /dev/null
@@ -0,0 +1,328 @@
+#!/bin/bash -e
+
+# This wrapper wraps the invocation of the test. It is called by run-tests.sh,
+# and already in the unshared namespace.
+#
+# For some printf debugging, you can also patch this file.
+
+array_contains() {
+       local needle="$1"
+       local a
+       shift
+       for a; do
+               [ "$a" = "$needle" ] && return 0
+       done
+       return 1
+}
+
+show_file() {
+       local filename="$1"
+       shift
+       local msg="$*"
+
+       printf '%s\n>>>>\n' "$msg"
+       cat "$filename"
+       printf "<<<<\n"
+}
+
+json_pretty() {
+       "$NFT_TEST_BASEDIR/helpers/json-pretty.sh" "$@" 2>&1 || :
+}
+
+TEST="$1"
+TESTBASE="$(basename "$TEST")"
+TESTDIR="$(dirname "$TEST")"
+
+START_TIME="$(cut -d ' ' -f1 /proc/uptime)"
+
+export TMPDIR="$NFT_TEST_TESTTMPDIR"
+
+CLEANUP_UMOUNT_VAR_RUN=n
+
+cleanup() {
+       if [ "$CLEANUP_UMOUNT_VAR_RUN" = y ] ; then
+               umount "/var/run" &>/dev/null || :
+       fi
+}
+
+trap cleanup EXIT
+
+printf '%s\n' "$TEST" > "$NFT_TEST_TESTTMPDIR/name"
+
+read tainted_before < /proc/sys/kernel/tainted
+
+if [ "$NFT_TEST_HAS_UNSHARED_MOUNT" = y ] ; then
+       # We have a private mount namespace. We will mount /var/run/ as a tmpfs.
+       #
+       # The main purpose is so that we can create /var/run/netns, which is
+       # required for `ip netns add` to work.  When running as rootless, this
+       # is necessary to get such tests to pass. When running rootful, it's
+       # still useful to not touch the "real" /var/run/netns of the system.
+       #
+       # Note that this also hides everything that might reside in /var/run.
+       # That is desirable, as tests should not depend on content there (or if
+       # they do, we need to explicitly handle it as appropriate).
+       if mount -t tmpfs --make-private tmpfs "/var/run" 2>/dev/null ; then
+               CLEANUP_UMOUNT_VAR_RUN=y
+       fi
+       mkdir -p /var/run/netns
+fi
+
+TEST_TAGS_PARSED=0
+ensure_TEST_TAGS() {
+       if [ "$TEST_TAGS_PARSED" = 0 ] ; then
+               TEST_TAGS_PARSED=1
+               TEST_TAGS=( $(sed -n '1,10 { s/^.*\<\(NFT_TEST_REQUIRES\|NFT_TEST_SKIP\)\>\s*(\s*\(NFT_TEST_SKIP_[a-zA-Z0-9_]\+\|NFT_TEST_HAVE_[a-zA-Z0-9_]\+\)\s*).*$/\1(\2)/p }' "$1" 2>/dev/null || : ) )
+       fi
+}
+
+rc_test=0
+
+if [ "$rc_test" -eq 0 ] ; then
+       for KEY in $(compgen -v | grep '^NFT_TEST_HAVE_') ; do
+               if [ "${!KEY}" != n ]; then
+                       continue
+               fi
+               ensure_TEST_TAGS "$TEST"
+               if array_contains "NFT_TEST_REQUIRES($KEY)" "${TEST_TAGS[@]}" ; then
+                       echo "Test skipped due to $KEY=n (test has \"NFT_TEST_REQUIRES($KEY)\" tag)" >> "$NFT_TEST_TESTTMPDIR/testout.log"
+                       rc_test=77
+                       break
+               fi
+       done
+fi
+
+if [ "$rc_test" -eq 0 ] ; then
+       for KEY in $(compgen -v | grep '^NFT_TEST_SKIP_') ; do
+               if [ "${!KEY}" != y ]; then
+                       continue
+               fi
+               ensure_TEST_TAGS "$TEST"
+               if array_contains "NFT_TEST_SKIP($KEY)" "${TEST_TAGS[@]}" ; then
+                       echo "Test skipped due to $KEY=y (test has \"NFT_TEST_SKIP($KEY)\" tag)" >> "$NFT_TEST_TESTTMPDIR/testout.log"
+                       rc_test=77
+                       break
+               fi
+       done
+fi
+
+if [ "$rc_test" -eq 0 ] ; then
+       CMD=( "$TEST" )
+       if [ "$NFT_TEST_VERBOSE_TEST" = y ] ; then
+               X="$(sed -n '1 s/^#!\(\/bin\/bash\>.*$\)/\1/p' "$TEST" 2>/dev/null)"
+               if [ -n "$X" ] ; then
+                       # Note that kernel parses the shebang differently and does not
+                       # word splitting for the arguments. We do split the arguments here
+                       # which would matter if there are spaces. For our tests, there
+                       # are either no arguments or only one argument without space. So
+                       # this is good enough.
+                       CMD=( $X -x "$TEST" )
+               fi
+       fi
+       printf "Command: $(printf '%q ' "${CMD[@]}")\n" &>> "$NFT_TEST_TESTTMPDIR/testout.log"
+       "${CMD[@]}" &>> "$NFT_TEST_TESTTMPDIR/testout.log" || rc_test=$?
+fi
+
+rc_chkdump=0
+rc=0
+$NFT list ruleset > "$NFT_TEST_TESTTMPDIR/ruleset-after" 2> "$NFT_TEST_TESTTMPDIR/chkdump" || rc=$?
+if [ "$rc" -ne 0 -o -s "$NFT_TEST_TESTTMPDIR/chkdump" ] ; then
+       show_file "$NFT_TEST_TESTTMPDIR/chkdump" "Command \`$NFT list ruleset\` failed" >> "$NFT_TEST_TESTTMPDIR/rc-failed-chkdump"
+       rc_chkdump=1
+fi
+if [ "$NFT_TEST_HAVE_json" != n ] ; then
+       rc=0
+       $NFT -j list ruleset > "$NFT_TEST_TESTTMPDIR/ruleset-after.json" 2> "$NFT_TEST_TESTTMPDIR/chkdump" || rc=$?
+
+       # Workaround known bug in stmt_print_json(), due to
+       # "chain_stmt_ops.json" being NULL. This spams stderr.
+       sed -i '/^warning: stmt ops chain have no json callback$/d' "$NFT_TEST_TESTTMPDIR/chkdump"
+
+       if [ "$rc" -ne 0 -o -s "$NFT_TEST_TESTTMPDIR/chkdump" ] ; then
+               show_file "$NFT_TEST_TESTTMPDIR/chkdump" "Command \`$NFT -j list ruleset\` failed" >> "$NFT_TEST_TESTTMPDIR/rc-failed-chkdump"
+               rc_chkdump=1
+       fi
+       # JSON output needs normalization/sanitization, otherwise it's not stable.
+       "$NFT_TEST_BASEDIR/helpers/json-sanitize-ruleset.sh" "$NFT_TEST_TESTTMPDIR/ruleset-after.json"
+       json_pretty "$NFT_TEST_TESTTMPDIR/ruleset-after.json" > "$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty"
+fi
+
+read tainted_after < /proc/sys/kernel/tainted
+
+DUMPPATH="$TESTDIR/dumps"
+DUMPFILE="$DUMPPATH/$TESTBASE.nft"
+JDUMPFILE="$DUMPPATH/$TESTBASE.json-nft"
+NODUMPFILE="$DUMPPATH/$TESTBASE.nodump"
+
+# The caller can request a re-geneating of the .nft, .nodump, .json-nft dump files
+# by setting DUMPGEN=y. In that case, only the existing files will be regenerated
+# (unless all three files are missing, in which case all of them are generated).
+#
+# By setting DUMPGEN=all, all 3 files are always regenerated.
+dump_written=n
+if [ "$rc_test" -eq 0 -a '(' "$DUMPGEN" = all -o "$DUMPGEN" = y ')' ] ; then
+       dump_written=y
+       if [ ! -d "$DUMPPATH" ] ; then
+               mkdir "$DUMPPATH"
+       fi
+       if [ "$DUMPGEN" = all ] ; then
+               gen_nodumpfile=y
+               gen_dumpfile=y
+               gen_jdumpfile=y
+       else
+               # by default, only regenerate the files that we already have on disk.
+               gen_nodumpfile=n
+               gen_dumpfile=n
+               gen_jdumpfile=n
+               test -f "$DUMPFILE"  && gen_dumpfile=y
+               test -f "$JDUMPFILE" && gen_jdumpfile=y
+               test -f "$NODUMPFILE" && gen_nodumpfile=y
+               if [ "$gen_dumpfile" != y -a "$gen_jdumpfile" != y -a "$gen_nodumpfile" != y ] ; then
+                       # Except, if no files exist. Them generate all files.
+                       gen_dumpfile=y
+                       gen_jdumpfile=y
+                       gen_nodumpfile=y
+               fi
+       fi
+       if [ "$gen_nodumpfile" = y ] ; then
+               : > "$NODUMPFILE"
+       fi
+       if [ "$gen_dumpfile" = y ] ; then
+               cat "$NFT_TEST_TESTTMPDIR/ruleset-after" > "$DUMPFILE"
+       fi
+       if [ "$NFT_TEST_HAVE_json" != n -a "$gen_jdumpfile" = y ] ; then
+               cat "$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty" > "$JDUMPFILE"
+       fi
+fi
+
+rc_dump=0
+if [ "$rc_test" -ne 77 -a "$dump_written" != y ] ; then
+       if [ -f "$DUMPFILE" ] ; then
+               if ! $DIFF -u "$DUMPFILE" "$NFT_TEST_TESTTMPDIR/ruleset-after" &> "$NFT_TEST_TESTTMPDIR/ruleset-diff" ; then
+                       show_file "$NFT_TEST_TESTTMPDIR/ruleset-diff" "Failed \`$DIFF -u \"$DUMPFILE\" \"$NFT_TEST_TESTTMPDIR/ruleset-after\"\`" >> "$NFT_TEST_TESTTMPDIR/rc-failed-dump"
+                       rc_dump=1
+               else
+                       rm -f "$NFT_TEST_TESTTMPDIR/ruleset-diff"
+               fi
+       fi
+       if [ "$NFT_TEST_HAVE_json" != n -a -f "$JDUMPFILE" ] ; then
+               if ! $DIFF -u "$JDUMPFILE" "$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty" &> "$NFT_TEST_TESTTMPDIR/ruleset-diff.json" ; then
+                       show_file "$NFT_TEST_TESTTMPDIR/ruleset-diff.json" "Failed \`$DIFF -u \"$JDUMPFILE\" \"$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty\"\`" >> "$NFT_TEST_TESTTMPDIR/rc-failed-dump"
+                       rc_dump=1
+               else
+                       rm -f "$NFT_TEST_TESTTMPDIR/ruleset-diff.json"
+               fi
+       fi
+fi
+
+# check that a flush after the test succeeds. We anyway need a clean ruleset
+# for the `nft --check` next.
+rc=0
+$NFT flush ruleset &> "$NFT_TEST_TESTTMPDIR/chkdump" || rc=1
+if [ "$rc" = 1 -o -s "$NFT_TEST_TESTTMPDIR/chkdump" ] ; then
+       show_file "$NFT_TEST_TESTTMPDIR/chkdump" "Command \`$NFT flush ruleset\` failed" >> "$NFT_TEST_TESTTMPDIR/rc-failed-chkdump"
+       rc_chkdump=1
+fi
+# Check that `nft [-j] list ruleset | nft [-j] --check -f -` works.
+fail=n
+$NFT --check -f "$NFT_TEST_TESTTMPDIR/ruleset-after" &> "$NFT_TEST_TESTTMPDIR/chkdump" || fail=y
+test -s "$NFT_TEST_TESTTMPDIR/chkdump" && fail=y
+if [ "$fail" = y ] ; then
+       show_file "$NFT_TEST_TESTTMPDIR/chkdump" "Command \`$NFT --check -f \"$NFT_TEST_TESTTMPDIR/ruleset-after\"\` failed" >> "$NFT_TEST_TESTTMPDIR/rc-failed-chkdump"
+       rc_chkdump=1
+fi
+if [ -f "$DUMPFILE" ] && ! cmp "$DUMPFILE" "$NFT_TEST_TESTTMPDIR/ruleset-after" &>/dev/null ; then
+       # Also check the $DUMPFILE to hit possibly new code paths. This
+       # is useful to see crashes and with ASAN/valgrind.
+       $NFT --check -f "$DUMPFILE" &>/dev/null || :
+fi
+if [ "$NFT_TEST_HAVE_json" != n ] ; then
+       if [ ! -f "$JDUMPFILE" ] ; then
+               # Optimally, `nft -j list ruleset | nft -j --check -f -` never
+               # fails.  However, there are known issues where this doesn't
+               # work, and we cannot assert hard against that. It's those
+               # tests that don't have a .json-nft file.
+               #
+               # This should be fixed, every test should have a .json-nft
+               # file, and this workaround removed.
+               $NFT -j --check -f "$NFT_TEST_TESTTMPDIR/ruleset-after.json" &>/dev/null || :
+               $NFT -j --check -f "$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty" &>/dev/null || :
+       else
+               fail=n
+               $NFT -j --check -f "$NFT_TEST_TESTTMPDIR/ruleset-after.json" &> "$NFT_TEST_TESTTMPDIR/chkdump" || fail=y
+               test -s "$NFT_TEST_TESTTMPDIR/chkdump" && fail=y
+               if [ "$fail" = y ] ; then
+                       show_file "$NFT_TEST_TESTTMPDIR/chkdump" "Command \`$NFT -j --check -f \"$NFT_TEST_TESTTMPDIR/ruleset-after.json\"\` failed" >> "$NFT_TEST_TESTTMPDIR/rc-failed-chkdump"
+                       rc_chkdump=1
+               fi
+               fail=n
+               $NFT -j --check -f "$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty" &> "$NFT_TEST_TESTTMPDIR/chkdump" || fail=y
+               test -s "$NFT_TEST_TESTTMPDIR/chkdump" && fail=y
+               if [ "$fail" = y ] ; then
+                       show_file "$NFT_TEST_TESTTMPDIR/chkdump" "Command \`$NFT -j --check -f \"$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty\"\` failed" >> "$NFT_TEST_TESTTMPDIR/rc-failed-chkdump"
+                       rc_chkdump=1
+               fi
+       fi
+       if [ -f "$JDUMPFILE" ] \
+            && ! cmp "$JDUMPFILE" "$NFT_TEST_TESTTMPDIR/ruleset-after.json" &>/dev/null \
+            && ! cmp "$JDUMPFILE" "$NFT_TEST_TESTTMPDIR/ruleset-after.json-pretty" &>/dev/null ; \
+       then
+               $NFT -j --check -f "$JDUMPFILE" &>/dev/null || :
+       fi
+fi
+rm -f "$NFT_TEST_TESTTMPDIR/chkdump"
+
+rc_valgrind=0
+[ -f "$NFT_TEST_TESTTMPDIR/rc-failed-valgrind" ] && rc_valgrind=1
+
+rc_tainted=0
+if [ "$tainted_before" != "$tainted_after" ] ; then
+       echo "$tainted_after" > "$NFT_TEST_TESTTMPDIR/rc-failed-tainted"
+       rc_tainted=1
+fi
+
+if [ "$rc_valgrind" -ne 0 ] ; then
+       rc_exit=122
+elif [ "$rc_tainted" -ne 0 ] ; then
+       rc_exit=123
+elif [ "$rc_test" -ge 118 -a "$rc_test" -le 124 ] ; then
+       # Special exit codes are reserved. Coerce them.
+       rc_exit=125
+elif [ "$rc_test" -ne 0 ] ; then
+       rc_exit="$rc_test"
+elif [ "$rc_dump" -ne 0 ] ; then
+       rc_exit=124
+elif [ "$rc_chkdump" -ne 0 ] ; then
+       rc_exit=121
+else
+       rc_exit=0
+fi
+
+
+# We always write the real exit code of the test ($rc_test) to one of the files
+# rc-{ok,skipped,failed}, depending on which it is.
+#
+# Note that there might be other rc-failed-{dump,tainted,valgrind} files with
+# additional errors. Note that if such files exist, the overall state will
+# always be failed too (and an "rc-failed" file exists).
+#
+# On failure, we also write the combined "$rc_exit" code from "test-wrapper.sh"
+# to "rc-failed-exit" file.
+#
+# This means, failed tests will have a "rc-failed" file, and additional
+# "rc-failed-*" files exist for further information.
+if [ "$rc_exit" -eq 0 ] ; then
+       RC_FILENAME="rc-ok"
+elif [ "$rc_exit" -eq 77 ] ; then
+       RC_FILENAME="rc-skipped"
+else
+       RC_FILENAME="rc-failed"
+       echo "$rc_exit" > "$NFT_TEST_TESTTMPDIR/rc-failed-exit"
+fi
+echo "$rc_test" > "$NFT_TEST_TESTTMPDIR/$RC_FILENAME"
+
+END_TIME="$(cut -d ' ' -f1 /proc/uptime)"
+WALL_TIME="$(awk -v start="$START_TIME" -v end="$END_TIME" "BEGIN { print(end - start) }")"
+printf "%s\n" "$WALL_TIME" "$START_TIME" "$END_TIME" > "$NFT_TEST_TESTTMPDIR/times"
+
+exit "$rc_exit"
index 931bba967b37039ee0870ee6f1328ddd8264dbc1..2d2e0ad146c80f0d0803e41eaa46cebf959806a3 100755 (executable)
 #!/bin/bash
 
-# Configuration
-TESTDIR="./$(dirname $0)/testcases"
-SRC_NFT="$(dirname $0)/../../src/nft"
-DIFF=$(which diff)
+unset LANGUAGE
+export LANG=C
+export LC_ALL=C
+
+GREEN=""
+YELLOW=""
+RED=""
+RESET=""
+if [ -z "$NO_COLOR" ] ; then
+       if [ -n "$CLICOLOR_FORCE" ] || [[ -t 1 ]] ; then
+               # See https://bixense.com/clicolors/ . We only check isatty() on
+               # file descriptor 1, to decide whether colorizing happens (although,
+               # we might also colorize on other places/FDs).
+               GREEN=$'\e[32m'
+               YELLOW=$'\e[33m'
+               RED=$'\e[31m'
+               RESET=$'\e[0m'
+       fi
+fi
+
+array_contains() {
+       local needle="$1"
+       local a
+       shift
+       for a; do
+               [ "$a" = "$needle" ] && return 0
+       done
+       return 1
+}
+
+array_remove_first() {
+       local _varname="$1"
+       local _needle="$2"
+       local _result=()
+       local _a
+
+       eval "local _input=( \"\${$_varname[@]}\" )"
+       for _a in "${_input[@]}" ; do
+               if [ -n "${_needle+x}" -a "$_needle" = "$_a" ] ; then
+                       unset _needle
+               else
+                       _result+=("$_a")
+               fi
+       done
+       eval "$_varname="'( "${_result[@]}" )'
+}
+
+colorize_keywords() {
+       local out_variable="$1"
+       local color="$2"
+       local val="$3"
+       local val2
+       shift 3
+
+       printf -v val2 '%q' "$val"
+       array_contains "$val" "$@" && val2="$color$val2$RESET"
+       printf -v "$out_variable" '%s' "$val2"
+}
+
+strtonum() {
+       local s="$1"
+       local n
+       local n2
+
+       re='^[[:space:]]*([0-9]+)[[:space:]]*$'
+       if [[ "$s" =~ $re ]] ; then
+               n="${BASH_REMATCH[1]}"
+               if [ "$(( n + 0 ))" = "$n" ] ; then
+                       echo "$n"
+                       return 0
+               fi
+       fi
+       re='^[[:space:]]*0x([0-9a-fA-F]+)[[:space:]]*$'
+       if [[ "$s" =~ $re ]] ; then
+               n="${BASH_REMATCH[1]}"
+               n2="$(( 16#$n + 0 ))"
+               if [ "$n2" = "$(printf '%d' "0x$n" 2>/dev/null)" ] ; then
+                       echo "$n2"
+                       return 0
+               fi
+       fi
+       return 1
+}
+
+_msg() {
+       local level="$1"
+       shift
+
+       if [ "$level" = E ] ; then
+               printf '%s\n' "$RED$level$RESET: $*"
+       elif [ "$level" = W ] ; then
+               printf '%s\n' "$YELLOW$level$RESET: $*"
+       else
+               printf '%s\n' "$level: $*"
+       fi
+       if [ "$level" = E ] ; then
+               exit 1
+       fi
+}
 
 msg_error() {
-       echo "E: $1 ..." >&2
-       exit 1
+       _msg E "$@"
 }
 
 msg_warn() {
-       echo "W: $1" >&2
+       _msg W "$@"
 }
 
 msg_info() {
-       echo "I: $1"
+       _msg I "$@"
 }
 
-if [ "$(id -u)" != "0" ] ; then
-       msg_error "this requires root!"
+align_text() {
+       local _OUT_VARNAME="$1"
+       local _LEFT_OR_RIGHT="$2"
+       local _INDENT="$3"
+       shift 3
+       local _text="$*"
+       local _text_plain
+       local _text_align
+       local _text_result
+       local _i
+
+       # This function is needed, because "$text" might contain color escape
+       # sequences. A plain `printf '%12s' "$text"` will not align properly.
+
+       # strip escape sequences
+       _text_plain="${_text//$'\e['[0-9]m/}"
+       _text_plain="${_text_plain//$'\e['[0-9][0-9]m/}"
+
+       _text_align=""
+       for (( _i = "${#_text_plain}" ; "$_i" < "$_INDENT" ; _i++ )) ; do
+               _text_align="$_text_align "
+       done
+
+       if [ "$_LEFT_OR_RIGHT" = left ] ; then
+               _text_result="$(printf "%s$_text_align-" "$_text")"
+       else
+               _text_result="$(printf "$_text_align%s-" "$_text")"
+       fi
+       _text_result="${_text_result%-}"
+
+       eval "$_OUT_VARNAME=\"\$_text_result\""
+}
+
+bool_n() {
+       case "$1" in
+               n|N|no|No|NO|0|false|False|FALSE)
+                       printf n
+                       ;;
+               *)
+                       printf y
+                       ;;
+       esac
+}
+
+bool_y() {
+       case "$1" in
+               y|Y|yes|Yes|YES|1|true|True|TRUE)
+                       printf y
+                       ;;
+               *)
+                       printf n
+                       ;;
+       esac
+}
+
+usage() {
+       echo " $0 [OPTIONS] [TESTS...]"
+       echo
+       echo "OPTIONS:"
+       echo " -h|--help       : Print usage."
+       echo " -L|--list-tests : List test names and quit."
+       echo " -v              : Sets VERBOSE=y."
+       echo " -g              : Sets DUMPGEN=y."
+       echo " -V              : Sets VALGRIND=y."
+       echo " -K              : Sets KMEMLEAK=y."
+       echo " -R|--without-realroot : Sets NFT_TEST_HAS_REALROOT=n."
+       echo " -U|--no-unshare : Sets NFT_TEST_UNSHARE_CMD=\"\"."
+       echo " -k|--keep-logs  : Sets NFT_TEST_KEEP_LOGS=y."
+       echo " -x              : Sets NFT_TEST_VERBOSE_TEST=y."
+       echo " -s|--sequential : Sets NFT_TEST_JOBS=0, which also enables global cleanups."
+       echo "                   Also sets NFT_TEST_SHUFFLE_TESTS=n if left unspecified."
+       echo " -Q|--quick      : Sets NFT_TEST_SKIP_slow=y."
+       echo " -S|--setup-host : Modify the host to run as rootless. Otherwise, some tests will be"
+       echo "                   skipped. Basically, this bumps /proc/sys/net/core/{wmem_max,rmem_max}."
+       echo "                   Must run as root and this option must be specified alone."
+       echo " --              : Separate options from tests."
+       echo " [TESTS...]      : Other options are treated as test names,"
+       echo "                   that is, executables that are run by the runner."
+       echo
+       echo "ENVIRONMENT VARIABLES:"
+       echo " NFT=<CMD>     : Path to nft executable. Will be called as \`\$NFT [...]\` so"
+       echo "                 it can be a command with parameters. Note that in this mode quoting"
+       echo "                 does not work, so the usage is limited and the command cannot contain"
+       echo "                 spaces."
+       echo " NFT_REAL=<CMD> : Real nft comand. Usually this is just the same as \$NFT,"
+       echo "                 however, you may set NFT='valgrind nft' and NFT_REAL to the real command."
+       echo " VERBOSE=*|y   : Enable verbose output."
+       echo " NFT_TEST_VERBOSE_TEST=*|y: if true, enable verbose output for tests. For bash scripts, this means"
+       echo "                 to pass \"-x\" to the interpreter."
+       echo " DUMPGEN=*|y|all : Regenerate dump files \".{nft,json-nft,nodump}\". \"DUMPGEN=y\" only regenerates existing"
+       echo "                 files, unless the test has no files (then all three files are generated, and you need to"
+       echo "                 choose which to keep). With \"DUMPGEN=all\" all 3 files are regenerated, regardless"
+       echo "                 whether they already exist."
+       echo " VALGRIND=*|y  : Run \$NFT in valgrind."
+       echo " KMEMLEAK=*|y  : Check for kernel memleaks."
+       echo " NFT_TEST_HAS_REALROOT=*|y : To indicate whether the test has real root permissions."
+       echo "                 Usually, you don't need this and it gets autodetected."
+       echo "                 You might want to set it, if you know better than the"
+       echo "                 \`id -u\` check, whether the user is root in the main namespace."
+       echo "                 Note that without real root, certain tests may not work,"
+       echo "                 e.g. due to limited /proc/sys/net/core/{wmem_max,rmem_max}."
+       echo "                 Checks that cannot pass in such environment should check for"
+       echo "                 [ \"\$NFT_TEST_HAS_REALROOT\" != y ] and skip gracefully."
+       echo " NFT_TEST_HAS_SOCKET_LIMITS=*|n : some tests will fail if /proc/sys/net/core/{wmem_max,rmem_max} is"
+       echo "                 too small. When running as real root, then test can override those limits. However,"
+       echo "                 with rootless the test would fail. Tests will check for [ "\$NFT_TEST_HAS_SOCKET_LIMITS" = y ]"
+       echo "                 and skip. You may set NFT_TEST_HAS_SOCKET_LIMITS=n if you ensure those limits are"
+       echo "                 suitable to run the test rootless. Otherwise will be autodetected."
+       echo "                 Set /proc/sys/net/core/{wmem_max,rmem_max} to at least 4MB to get them to pass automatically."
+       echo " NFT_TEST_UNSHARE_CMD=cmd : when set, this is the command line for an unshare"
+       echo "                 command, which is used to sandbox each test invocation. By"
+       echo "                 setting it to empty, no unsharing is done."
+       echo "                 By default it is unset, in which case it's autodetected as"
+       echo "                 \`unshare -f -p\` (for root) or as \`unshare -f -p --mount-proc -U --map-root-user -n\`"
+       echo "                 for non-root."
+       echo "                 When setting this, you may also want to set NFT_TEST_HAS_UNSHARED=,"
+       echo "                 NFT_TEST_HAS_REALROOT= and NFT_TEST_HAS_UNSHARED_MOUNT= accordingly."
+       echo " NFT_TEST_HAS_UNSHARED=*|y : To indicate to the test whether the test run will be unshared."
+       echo "                 Test may consider this."
+       echo "                 This is only honored when \$NFT_TEST_UNSHARE_CMD= is set. Otherwise it's detected."
+       echo " NFT_TEST_HAS_UNSHARED_MOUNT=*|y : To indicate to the test whether the test run will have a private"
+       echo "                 mount namespace."
+       echo "                 This is only honored when \$NFT_TEST_UNSHARE_CMD= is set. Otherwise it's detected."
+       echo " NFT_TEST_KEEP_LOGS=*|y: Keep the temp directory. On success, it will be deleted by default."
+       echo " NFT_TEST_JOBS=<NUM}>: number of jobs for parallel execution. Defaults to \"\$(nproc)*1.5\" for parallel run."
+       echo "                 Setting this to \"0\" or \"1\", means to run jobs sequentially."
+       echo "                 Setting this to \"0\" means also to perform global cleanups between tests (remove"
+       echo "                 kernel modules)."
+       echo "                 Parallel jobs requires unshare and are disabled with NFT_TEST_UNSHARE_CMD=\"\"."
+       echo " NFT_TEST_FAIL_ON_SKIP=*|y: if any jobs are skipped, exit with error."
+       echo " NFT_TEST_RANDOM_SEED=<SEED>: The test runner will export the environment variable NFT_TEST_RANDOM_SEED"
+       echo "                 set to a random number. This can be used as a stable seed for tests to randomize behavior."
+       echo "                 Set this to a fixed value to get reproducible behavior."
+       echo " NFT_TEST_SHUFFLE_TESTS=*|n|y: control whether to randomly shuffle the order of tests. By default, if"
+       echo "                 tests are specified explicitly, they are not shuffled while they are shuffled when"
+       echo "                 all tests are run. The shuffling is based on NFT_TEST_RANDOM_SEED."
+       echo " TMPDIR=<PATH> : select a different base directory for the result data."
+       echo
+       echo " NFT_TEST_HAVE_<FEATURE>=*|y: Some tests requires certain features or will be skipped."
+       echo "                 The features are autodetected, but you can force it by setting the variable."
+       echo "                 Supported <FEATURE>s are: ${_HAVE_OPTS[@]}."
+       echo " NFT_TEST_SKIP_<OPTION>=*|y: if set, certain tests are skipped."
+       echo "                 Supported <OPTION>s are: ${_SKIP_OPTS[@]}."
+}
+
+NFT_TEST_BASEDIR="$(dirname "$0")"
+
+# Export the base directory. It may be used by tests.
+export NFT_TEST_BASEDIR
+
+_HAVE_OPTS=()
+shopt -s nullglob
+F=( "$NFT_TEST_BASEDIR/features/"*.nft "$NFT_TEST_BASEDIR/features/"*.sh )
+shopt -u nullglob
+for file in "${F[@]}"; do
+       feat="${file##*/}"
+       feat="${feat%.*}"
+       re="^[a-z_0-9]+$"
+       if [[ "$feat" =~ $re ]] && ! array_contains "$feat" "${_HAVE_OPTS[@]}" && [[ "$file" != *.sh || -x "$file" ]] ; then
+               _HAVE_OPTS+=( "$feat" )
+       else
+               msg_warn "Ignore feature file \"$file\""
+       fi
+done
+_HAVE_OPTS=( $(printf '%s\n' "${_HAVE_OPTS[@]}" | sort) )
+
+for KEY in $(compgen -v | grep '^NFT_TEST_HAVE_' | sort) ; do
+       if ! array_contains "${KEY#NFT_TEST_HAVE_}" "${_HAVE_OPTS[@]}" ; then
+               unset "$KEY"
+       fi
+done
+
+_SKIP_OPTS=( slow )
+for KEY in $(compgen -v | grep '^NFT_TEST_SKIP_' | sort) ; do
+       if ! array_contains "${KEY#NFT_TEST_SKIP_}" "${_SKIP_OPTS[@]}" ; then
+               unset "$KEY"
+       fi
+done
+
+_NFT_TEST_JOBS_DEFAULT="$(nproc)"
+[ "$_NFT_TEST_JOBS_DEFAULT" -gt 0 ] 2>/dev/null || _NFT_TEST_JOBS_DEFAULT=1
+_NFT_TEST_JOBS_DEFAULT="$(( _NFT_TEST_JOBS_DEFAULT + (_NFT_TEST_JOBS_DEFAULT + 1) / 2 ))"
+
+VERBOSE="$(bool_y "$VERBOSE")"
+NFT_TEST_VERBOSE_TEST="$(bool_y "$NFT_TEST_VERBOSE_TEST")"
+if [ "$DUMPGEN" != "all" ] ; then
+       DUMPGEN="$(bool_y "$DUMPGEN")"
 fi
+VALGRIND="$(bool_y "$VALGRIND")"
+KMEMLEAK="$(bool_y "$KMEMLEAK")"
+NFT_TEST_KEEP_LOGS="$(bool_y "$NFT_TEST_KEEP_LOGS")"
+NFT_TEST_HAS_REALROOT="$NFT_TEST_HAS_REALROOT"
+NFT_TEST_JOBS="${NFT_TEST_JOBS:-$_NFT_TEST_JOBS_DEFAULT}"
+NFT_TEST_FAIL_ON_SKIP="$(bool_y "$NFT_TEST_FAIL_ON_SKIP")"
+NFT_TEST_RANDOM_SEED="$NFT_TEST_RANDOM_SEED"
+NFT_TEST_SHUFFLE_TESTS="$NFT_TEST_SHUFFLE_TESTS"
+NFT_TEST_SKIP_slow="$(bool_y "$NFT_TEST_SKIP_slow")"
+DO_LIST_TESTS=
 
-if [ "${1}" != "run" ]; then
-       if unshare -f -n true; then
-               unshare -n "${0}" run $@
-               exit $?
+if [ -z "$NFT_TEST_RANDOM_SEED" ] ; then
+       # Choose a random value.
+       n="$SRANDOM"
+       [ -z "$n" ] && n="$RANDOM"
+else
+       # Parse as number.
+       n="$(strtonum "$NFT_TEST_RANDOM_SEED")"
+       if [ -z "$n" ] ; then
+               # If not a number, pick a hash based on the SHA-sum of the seed.
+               n="$(printf "%d" "0x$(sha256sum <<<"NFT_TEST_RANDOM_SEED:$NFT_TEST_RANDOM_SEED" | sed -n '1 { s/^\(........\).*/\1/p }')")"
        fi
-       msg_warn "cannot run in own namespace, connectivity might break"
 fi
-shift
+# Limit a 31 bit decimal so tests can rely on this being in a certain
+# restricted form.
+NFT_TEST_RANDOM_SEED="$(( $n % 0x80000000 ))"
+export NFT_TEST_RANDOM_SEED
 
-[ -z "$NFT" ] && NFT=$SRC_NFT
-${NFT} > /dev/null 2>&1
-ret=$?
-if [ ${ret} -eq 126 ] || [ ${ret} -eq 127 ]; then
-       msg_error "cannot execute nft command: ${NFT}"
+TESTS=()
+
+SETUP_HOST=
+SETUP_HOST_OTHER=
+
+ARGV_ORIG=( "$@" )
+
+while [ $# -gt 0 ] ; do
+       A="$1"
+       shift
+       case "$A" in
+               -S|--setup-host)
+                       ;;
+               *)
+                       SETUP_HOST_OTHER=y
+                       ;;
+       esac
+       case "$A" in
+               -S|--setup-host)
+                       SETUP_HOST="$A"
+                       ;;
+               -v)
+                       VERBOSE=y
+                       ;;
+               -x)
+                       NFT_TEST_VERBOSE_TEST=y
+                       ;;
+               -g)
+                       DUMPGEN=y
+                       ;;
+               -V)
+                       VALGRIND=y
+                       ;;
+               -K)
+                       KMEMLEAK=y
+                       ;;
+               -h|--help)
+                       usage
+                       exit 0
+                       ;;
+               -k|--keep-logs)
+                       NFT_TEST_KEEP_LOGS=y
+                       ;;
+               -L|--list-tests)
+                       DO_LIST_TESTS=y
+                       ;;
+               -R|--without-realroot)
+                       NFT_TEST_HAS_REALROOT=n
+                       ;;
+               -U|--no-unshare)
+                       NFT_TEST_UNSHARE_CMD=
+                       ;;
+               -s|--sequential)
+                       NFT_TEST_JOBS=0
+                       if [ -z "$NFT_TEST_SHUFFLE_TESTS" ] ; then
+                               NFT_TEST_SHUFFLE_TESTS=n
+                       fi
+                       ;;
+               -Q|--quick)
+                       NFT_TEST_SKIP_slow=y
+                       ;;
+               --)
+                       TESTS+=( "$@" )
+                       shift $#
+                       ;;
+               *)
+                       TESTS+=( "$A" )
+                       ;;
+       esac
+done
+
+sysctl_bump() {
+       local sysctl="$1"
+       local val="$2"
+       local cur;
+
+       cur="$(cat "$sysctl" 2>/dev/null)" || :
+       if [ -n "$cur" -a "$cur" -ge "$val" ] ; then
+               echo "# Skip: echo $val > $sysctl (current value $cur)"
+               return 0
+       fi
+       echo "    echo $val > $sysctl (previous value $cur)"
+       echo "$val" > "$sysctl"
+}
+
+setup_host() {
+       echo "Setting up host for running as rootless (requires root)."
+       sysctl_bump /proc/sys/net/core/rmem_max $((4000*1024)) || return $?
+       sysctl_bump /proc/sys/net/core/wmem_max $((4000*1024)) || return $?
+}
+
+if [ -n "$SETUP_HOST" ] ; then
+       if [ "$SETUP_HOST_OTHER" = y ] ; then
+               msg_error "The $SETUP_HOST option must be specified alone."
+       fi
+       setup_host
+       exit $?
+fi
+
+find_tests() {
+       find "$1" -type f -executable | sort
+}
+
+if [ "${#TESTS[@]}" -eq 0 ] ; then
+       d="$NFT_TEST_BASEDIR/testcases/"
+       d="${d#./}"
+       TESTS=( $(find_tests "$d") )
+       test "${#TESTS[@]}" -gt 0 || msg_error "Could not find tests"
+       if [ -z "$NFT_TEST_SHUFFLE_TESTS" ] ; then
+               NFT_TEST_SHUFFLE_TESTS=y
+       fi
+fi
+
+TESTSOLD=( "${TESTS[@]}" )
+TESTS=()
+for t in "${TESTSOLD[@]}" ; do
+       if [ -f "$t" -a -x "$t" ] ; then
+               TESTS+=( "$t" )
+       elif [ -d "$t" ] ; then
+               TESTS+=( $(find_tests "$t") )
+       else
+               msg_error "Unknown test \"$t\""
+       fi
+done
+
+NFT_TEST_SHUFFLE_TESTS="$(bool_y "$NFT_TEST_SHUFFLE_TESTS")"
+
+if [ "$DO_LIST_TESTS" = y ] ; then
+       printf '%s\n' "${TESTS[@]}"
+       exit 0
+fi
+
+START_TIME="$(cut -d ' ' -f1 /proc/uptime)"
+
+_TMPDIR="${TMPDIR:-/tmp}"
+
+# Export the orignal TMPDIR for the tests. "test-wrapper.sh" sets TMPDIR to
+# NFT_TEST_TESTTMPDIR, so that temporary files are placed along side the
+# test data. In some cases, we may want to know the original TMPDIR.
+export NFT_TEST_TMPDIR_ORIG="$_TMPDIR"
+
+if [ "$NFT_TEST_HAS_REALROOT" = "" ] ; then
+       # The caller didn't set NFT_TEST_HAS_REALROOT and didn't specify
+       # -R/--without-root option. Autodetect it based on `id -u`.
+       export NFT_TEST_HAS_REALROOT="$(test "$(id -u)" = "0" && echo y || echo n)"
 else
-       msg_info "using nft command: ${NFT}"
+       NFT_TEST_HAS_REALROOT="$(bool_y "$NFT_TEST_HAS_REALROOT")"
 fi
+export NFT_TEST_HAS_REALROOT
 
-if [ ! -d "$TESTDIR" ] ; then
-       msg_error "missing testdir $TESTDIR"
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = "" ] ; then
+       if [ "$NFT_TEST_HAS_REALROOT" = y ] ; then
+               NFT_TEST_HAS_SOCKET_LIMITS=n
+       elif [ "$(cat /proc/sys/net/core/wmem_max 2>/dev/null)" -ge $((4000*1024)) ] 2>/dev/null && \
+            [ "$(cat /proc/sys/net/core/rmem_max 2>/dev/null)" -ge $((4000*1024)) ] 2>/dev/null ; then
+               NFT_TEST_HAS_SOCKET_LIMITS=n
+       else
+               NFT_TEST_HAS_SOCKET_LIMITS=y
+       fi
+else
+       NFT_TEST_HAS_SOCKET_LIMITS="$(bool_n "$NFT_TEST_HAS_SOCKET_LIMITS")"
 fi
+export NFT_TEST_HAS_SOCKET_LIMITS
 
-FIND="$(which find)"
-if [ ! -x "$FIND" ] ; then
-       msg_error "no find binary found"
+detect_unshare() {
+       if ! $1 true &>/dev/null ; then
+               return 1
+       fi
+       NFT_TEST_UNSHARE_CMD="$1"
+       return 0
+}
+
+if [ -n "${NFT_TEST_UNSHARE_CMD+x}" ] ; then
+       # User overrides the unshare command.
+       if ! detect_unshare "$NFT_TEST_UNSHARE_CMD" ; then
+               msg_error "Cannot unshare via NFT_TEST_UNSHARE_CMD=$(printf '%q' "$NFT_TEST_UNSHARE_CMD")"
+       fi
+       if [ -z "${NFT_TEST_HAS_UNSHARED+x}" ] ; then
+               # Autodetect NFT_TEST_HAS_UNSHARED based one whether
+               # $NFT_TEST_UNSHARE_CMD is set.
+               if [ -n "$NFT_TEST_UNSHARE_CMD" ] ; then
+                       NFT_TEST_HAS_UNSHARED="y"
+               else
+                       NFT_TEST_HAS_UNSHARED="n"
+               fi
+       else
+               NFT_TEST_HAS_UNSHARED="$(bool_y "$NFT_TEST_HAS_UNSHARED")"
+       fi
+       if [ -z "${NFT_TEST_HAS_UNSHARED_MOUNT+x}" ] ; then
+               NFT_TEST_HAS_UNSHARED_MOUNT=n
+               if [ "$NFT_TEST_HAS_UNSHARED" == y ] ; then
+                       case "$NFT_TEST_UNSHARE_CMD" in
+                               unshare*-m*|unshare*--mount-proc*)
+                                       NFT_TEST_HAS_UNSHARED_MOUNT=y
+                                       ;;
+                       esac
+               fi
+       else
+               NFT_TEST_HAS_UNSHARED_MOUNT="$(bool_y "$NFT_TEST_HAS_UNSHARED_MOUNT")"
+       fi
+else
+       NFT_TEST_HAS_UNSHARED_MOUNT=n
+       if [ "$NFT_TEST_HAS_REALROOT" = y ] ; then
+               # We appear to have real root. So try to unshare
+               # without a separate USERNS. CLONE_NEWUSER will break
+               # tests that are limited by
+               # /proc/sys/net/core/{wmem_max,rmem_max}. With real
+               # root, we want to test that.
+               if detect_unshare "unshare -f -n -m" ; then
+                       NFT_TEST_HAS_UNSHARED_MOUNT=y
+               else
+                       detect_unshare "unshare -f -n" ||
+                       detect_unshare "unshare -f -p -m --mount-proc -U --map-root-user -n" ||
+                       detect_unshare "unshare -f -U --map-root-user -n"
+               fi
+       else
+               if detect_unshare "unshare -f -p -m --mount-proc -U --map-root-user -n" ; then
+                       NFT_TEST_HAS_UNSHARED_MOUNT=y
+               else
+                       detect_unshare "unshare -f -U --map-root-user -n"
+               fi
+       fi
+       if [ -z "$NFT_TEST_UNSHARE_CMD" ] ; then
+               msg_error "Unshare does not work. Run as root with -U/--no-unshare or set NFT_TEST_UNSHARE_CMD"
+       fi
+       NFT_TEST_HAS_UNSHARED=y
 fi
+# If tests wish, they can know whether they are unshared via this variable.
+export NFT_TEST_HAS_UNSHARED
+export NFT_TEST_HAS_UNSHARED_MOUNT
 
-MODPROBE="$(which modprobe)"
-if [ ! -x "$MODPROBE" ] ; then
-       msg_error "no modprobe binary found"
+# normalize the jobs number to be an integer.
+case "$NFT_TEST_JOBS" in
+       ''|*[!0-9]*) NFT_TEST_JOBS=_NFT_TEST_JOBS_DEFAULT ;;
+esac
+if [ -z "$NFT_TEST_UNSHARE_CMD" -a "$NFT_TEST_JOBS" -gt 1 ] ; then
+       NFT_TEST_JOBS=1
+fi
+
+[ -z "$NFT" ] && NFT="$NFT_TEST_BASEDIR/../../src/nft"
+${NFT} > /dev/null 2>&1
+ret=$?
+if [ ${ret} -eq 126 ] || [ ${ret} -eq 127 ]; then
+       msg_error "cannot execute nft command: $NFT"
+fi
+
+NFT_REAL="${NFT_REAL-$NFT}"
+
+feature_probe()
+{
+       local with_path="$NFT_TEST_BASEDIR/features/$1"
+
+       if [ -r "$with_path.nft" ] ; then
+               $NFT_TEST_UNSHARE_CMD "$NFT_REAL" --check -f "$with_path.nft" &>/dev/null
+               return $?
+       fi
+
+       if [ -x "$with_path.sh" ] ; then
+               NFT="$NFT_REAL" $NFT_TEST_UNSHARE_CMD "$with_path.sh" &>/dev/null
+               return $?
+       fi
+
+       return 1
+}
+
+for feat in "${_HAVE_OPTS[@]}" ; do
+       var="NFT_TEST_HAVE_$feat"
+       if [ -z "${!var+x}" ] ; then
+               val='y'
+               feature_probe "$feat" || val='n'
+       else
+               val="$(bool_n "${!var}")"
+       fi
+       eval "export $var=$val"
+       if [ "$NFT_TEST_HAS_UNSHARED" != y ] ; then
+               $NFT flush ruleset
+       fi
+done
+
+if [ "$NFT_TEST_JOBS" -eq 0 ] ; then
+       MODPROBE="$(which modprobe)"
+       if [ ! -x "$MODPROBE" ] ; then
+               msg_error "no modprobe binary found"
+       fi
 fi
 
 DIFF="$(which diff)"
@@ -59,23 +619,102 @@ if [ ! -x "$DIFF" ] ; then
        DIFF=true
 fi
 
-if [ "$1" == "-v" ] ; then
-       VERBOSE=y
-       shift
-fi
+JOBS_PIDLIST_ARR=()
+declare -A JOBS_PIDLIST
 
-if [ "$1" == "-g" ] ; then
-       DUMPGEN=y
-       shift
-fi
+_NFT_TEST_VALGRIND_VGDB_PREFIX=
+
+cleanup_on_exit() {
+       pids_search=''
+       for pid in "${JOBS_PIDLIST_ARR[@]}" ; do
+               kill -- "-$pid" &>/dev/null
+               pids_search="$pids_search\\|\\<$pid\\>"
+       done
+       if [ -n "$pids_search" ] ; then
+               pids_search="${pids_search:2}"
+               for i in {1..100}; do
+                       ps xh -o pgrp | grep -q "$pids_search" || break
+                       sleep 0.01
+               done
+       fi
+       if [ "$NFT_TEST_KEEP_LOGS" != y -a -n "$NFT_TEST_TMPDIR" ] ; then
+               rm -rf "$NFT_TEST_TMPDIR"
+       fi
+       if [ -n "$_NFT_TEST_VALGRIND_VGDB_PREFIX" ] ; then
+               rm -rf "$_NFT_TEST_VALGRIND_VGDB_PREFIX"* &>/dev/null
+       fi
+}
+
+trap 'exit 130' SIGINT
+trap 'exit 143' SIGTERM
+trap 'rc=$?; cleanup_on_exit; exit $rc' EXIT
+
+TIMESTAMP=$(date '+%Y%m%d-%H%M%S.%3N')
+NFT_TEST_TMPDIR="$(mktemp --tmpdir="$_TMPDIR" -d "nft-test.$TIMESTAMP$NFT_TEST_TMPDIR_TAG.XXXXXX")" ||
+       msg_error "Failure to create temp directory in \"$_TMPDIR\""
+chmod 755 "$NFT_TEST_TMPDIR"
 
-for arg in "$@"; do
-       SINGLE+=" $arg"
-       VERBOSE=y
+exec &> >(tee "$NFT_TEST_TMPDIR/test.log")
+
+msg_info "conf: NFT=$(printf '%q' "$NFT")"
+msg_info "conf: NFT_REAL=$(printf '%q' "$NFT_REAL")"
+msg_info "conf: VERBOSE=$(printf '%q' "$VERBOSE")"
+msg_info "conf: NFT_TEST_VERBOSE_TEST=$(printf '%q' "$NFT_TEST_VERBOSE_TEST")"
+msg_info "conf: DUMPGEN=$(printf '%q' "$DUMPGEN")"
+msg_info "conf: VALGRIND=$(printf '%q' "$VALGRIND")"
+msg_info "conf: KMEMLEAK=$(printf '%q' "$KMEMLEAK")"
+msg_info "conf: NFT_TEST_HAS_REALROOT=$(printf '%q' "$NFT_TEST_HAS_REALROOT")"
+colorize_keywords value "$YELLOW" "$NFT_TEST_HAS_SOCKET_LIMITS" y
+msg_info "conf: NFT_TEST_HAS_SOCKET_LIMITS=$value"
+msg_info "conf: NFT_TEST_UNSHARE_CMD=$(printf '%q' "$NFT_TEST_UNSHARE_CMD")"
+msg_info "conf: NFT_TEST_HAS_UNSHARED=$(printf '%q' "$NFT_TEST_HAS_UNSHARED")"
+msg_info "conf: NFT_TEST_HAS_UNSHARED_MOUNT=$(printf '%q' "$NFT_TEST_HAS_UNSHARED_MOUNT")"
+msg_info "conf: NFT_TEST_KEEP_LOGS=$(printf '%q' "$NFT_TEST_KEEP_LOGS")"
+msg_info "conf: NFT_TEST_JOBS=$NFT_TEST_JOBS"
+msg_info "conf: NFT_TEST_FAIL_ON_SKIP=$NFT_TEST_FAIL_ON_SKIP"
+msg_info "conf: NFT_TEST_RANDOM_SEED=$NFT_TEST_RANDOM_SEED"
+msg_info "conf: NFT_TEST_SHUFFLE_TESTS=$NFT_TEST_SHUFFLE_TESTS"
+msg_info "conf: TMPDIR=$(printf '%q' "$_TMPDIR")"
+echo
+for KEY in $(compgen -v | grep '^NFT_TEST_SKIP_' | sort) ; do
+       colorize_keywords value "$YELLOW" "${!KEY}" y
+       msg_info "conf: $KEY=$value"
+       export "$KEY"
+done
+for KEY in $(compgen -v | grep '^NFT_TEST_HAVE_' | sort) ; do
+       colorize_keywords value "$YELLOW" "${!KEY}" n
+       msg_info "conf: $KEY=$value"
+       export "$KEY"
 done
 
+NFT_TEST_LATEST="$_TMPDIR/nft-test.latest.$USER"
+
+ln -snf "$NFT_TEST_TMPDIR" "$NFT_TEST_LATEST"
+
+# export the tmp directory for tests. They may use it, but create distinct
+# files! On success, it will be deleted on EXIT. See also "--keep-logs"
+export NFT_TEST_TMPDIR
+
+echo
+msg_info "info: NFT_TEST_BASEDIR=$(printf '%q' "$NFT_TEST_BASEDIR")"
+msg_info "info: NFT_TEST_TMPDIR=$(printf '%q' "$NFT_TEST_TMPDIR")"
+
+if [ "$VALGRIND" == "y" ]; then
+       NFT="$NFT_TEST_BASEDIR/helpers/nft-valgrind-wrapper.sh"
+       msg_info "info: NFT=$(printf '%q' "$NFT")"
+       _NFT_TEST_VALGRIND_VGDB_PREFIX="$NFT_TEST_TMPDIR_ORIG/vgdb-pipe-nft-test-$TIMESTAMP.$$.$RANDOM"
+       export _NFT_TEST_VALGRIND_VGDB_PREFIX
+fi
+
 kernel_cleanup() {
-       $NFT flush ruleset
+       if [ "$NFT_TEST_JOBS" -ne 0 ] ; then
+               # When we run jobs in parallel (even with only one "parallel"
+               # job via `NFT_TEST_JOBS=1`), we skip such global cleanups.
+               return
+       fi
+       if [ "$NFT_TEST_HAS_UNSHARED" != y ] ; then
+               $NFT flush ruleset
+       fi
        $MODPROBE -raq \
        nft_reject_ipv4 nft_reject_bridge nft_reject_ipv6 nft_reject \
        nft_redir_ipv4 nft_redir_ipv6 nft_redir \
@@ -98,83 +737,262 @@ kernel_cleanup() {
        nft_xfrm
 }
 
-find_tests() {
-       if [ ! -z "$SINGLE" ] ; then
-               echo $SINGLE
-               return
-       fi
-       ${FIND} ${TESTDIR} -type f -executable | sort
-}
-
 echo ""
 ok=0
+skipped=0
 failed=0
-taint=0
 
-check_taint()
+kmem_runs=0
+kmemleak_found=0
+
+check_kmemleak_force()
 {
-       read taint_now < /proc/sys/kernel/tainted
-       if [ $taint -ne $taint_now ] ; then
-               msg_warn "[FAILED]      kernel is tainted: $taint  -> $taint_now"
-               ((failed++))
+       test -f /sys/kernel/debug/kmemleak || return 0
+
+       echo scan > /sys/kernel/debug/kmemleak
+
+       lines=$(grep "unreferenced object" /sys/kernel/debug/kmemleak | wc -l)
+       if [ $lines -ne $kmemleak_found ];then
+               msg_warn "[FAILED]      kmemleak detected $lines memory leaks"
+               kmemleak_found=$lines
+       fi
+
+       if [ $lines -ne 0 ];then
+               return 1
        fi
+
+       return 0
 }
 
-check_taint
+check_kmemleak()
+{
+       test -f /sys/kernel/debug/kmemleak || return
 
-for testfile in $(find_tests)
-do
-       read taint < /proc/sys/kernel/tainted
-       kernel_cleanup
+       if [ "$KMEMLEAK" == "y" ] ; then
+               check_kmemleak_force
+               return
+       fi
 
-       msg_info "[EXECUTING]   $testfile"
-       test_output=$(NFT="$NFT" DIFF=$DIFF ${testfile} 2>&1)
-       rc_got=$?
-       echo -en "\033[1A\033[K" # clean the [EXECUTING] foobar line
+       kmem_runs=$((kmem_runs + 1))
+       if [ $((kmem_runs % 30)) -eq 0 ]; then
+               # scan slows tests down quite a bit, hence
+               # do this only for every 30th test file by
+               # default.
+               check_kmemleak_force
+       fi
+}
+
+read kernel_tainted < /proc/sys/kernel/tainted
+if [ "$kernel_tainted" -ne 0 ] ; then
+       msg_warn "kernel is tainted ($kernel_tainted)"
+       echo
+fi
+
+print_test_header() {
+       local msglevel="$1"
+       local testfile="$2"
+       local testidx_completed="$3"
+       local status="$4"
+       local text
+       local s_idx
+
+       s_idx="${#TESTS[@]}"
+       align_text text right "${#s_idx}" "$testidx_completed"
+       s_idx="$text/${#TESTS[@]}"
+
+       align_text text left 12 "[$status]"
+       _msg "$msglevel" "$text $s_idx $testfile"
+}
+
+print_test_result() {
+       local NFT_TEST_TESTTMPDIR="$1"
+       local testfile="$2"
+       local rc_got="$3"
+
+       local result_msg_level="I"
+       local result_msg_files=( "$NFT_TEST_TESTTMPDIR/testout.log" "$NFT_TEST_TESTTMPDIR/ruleset-diff" )
+       local result_msg_status
 
        if [ "$rc_got" -eq 0 ] ; then
-               # check nft dump only for positive tests
-               dumppath="$(dirname ${testfile})/dumps"
-               dumpfile="${dumppath}/$(basename ${testfile}).nft"
-               rc_spec=0
-               if [ "$rc_got" -eq 0 ] && [ -f ${dumpfile} ]; then
-                       test_output=$(${DIFF} -u ${dumpfile} <($NFT list ruleset) 2>&1)
-                       rc_spec=$?
+               ((ok++))
+               result_msg_status="${GREEN}OK$RESET"
+       elif [ "$rc_got" -eq 77 ] ; then
+               ((skipped++))
+               result_msg_status="${YELLOW}SKIPPED$RESET"
+       else
+               ((failed++))
+               result_msg_level="W"
+               if [ "$rc_got" -eq 121 ] ; then
+                       result_msg_status="CHK DUMP"
+               elif [ "$rc_got" -eq 122 ] ; then
+                       result_msg_status="VALGRIND"
+               elif [ "$rc_got" -eq 123 ] ; then
+                       result_msg_status="TAINTED"
+               elif [ "$rc_got" -eq 124 ] ; then
+                       result_msg_status="DUMP FAIL"
+               else
+                       result_msg_status="FAILED"
                fi
+               result_msg_status="$RED$result_msg_status$RESET"
+               result_msg_files=( "$NFT_TEST_TESTTMPDIR/testout.log" )
+       fi
 
-               if [ "$rc_spec" -eq 0 ]; then
-                       msg_info "[OK]          $testfile"
-                       [ "$VERBOSE" == "y" ] && [ ! -z "$test_output" ] && echo "$test_output"
-                       ((ok++))
+       print_test_header "$result_msg_level" "$testfile" "$((ok + skipped + failed))" "$result_msg_status"
 
-                       if [ "$DUMPGEN" == "y" ] && [ "$rc_got" == 0 ] && [ ! -f "${dumpfile}" ]; then
-                               mkdir -p "${dumppath}"
-                               $NFT list ruleset > "${dumpfile}"
-                       fi
-               else
-                       ((failed++))
-                       if [ "$VERBOSE" == "y" ] ; then
-                               msg_warn "[DUMP FAIL]   $testfile: dump diff detected"
-                               [ ! -z "$test_output" ] && echo "$test_output"
-                       else
-                               msg_warn "[DUMP FAIL]   $testfile"
+       if [ "$VERBOSE" = "y" ] ; then
+               local f
+
+               for f in "${result_msg_files[@]}"; do
+                       if [ -s "$f" ] ; then
+                               cat "$f"
                        fi
+               done
+
+               if [ "$rc_got" -ne 0 ] ; then
+                       msg_info "check \"$NFT_TEST_TESTTMPDIR\""
                fi
-       else
-               ((failed++))
-               if [ "$VERBOSE" == "y" ] ; then
-                       msg_warn "[FAILED]      $testfile: got $rc_got"
-                       [ ! -z "$test_output" ] && echo "$test_output"
+       fi
+}
+
+declare -A JOBS_TEMPDIR
+
+job_start() {
+       local testfile="$1"
+       local testidx="$2"
+
+       if [ "$NFT_TEST_JOBS" -le 1 ] && [[ -t 1 ]]; then
+               print_test_header I "$testfile" "$testidx" "EXECUTING"
+       fi
+
+       NFT_TEST_TESTTMPDIR="${JOBS_TEMPDIR["$testfile"]}" \
+       NFT="$NFT" \
+       NFT_REAL="$NFT_REAL" \
+       DIFF="$DIFF" \
+       DUMPGEN="$DUMPGEN" \
+       NFT_TEST_VERBOSE_TEST="$NFT_TEST_VERBOSE_TEST" \
+       $NFT_TEST_UNSHARE_CMD "$NFT_TEST_BASEDIR/helpers/test-wrapper.sh" "$testfile"
+       local rc_got=$?
+
+       if [ "$NFT_TEST_JOBS" -le 1 ] && [[ -t 1 ]]; then
+               echo -en "\033[1A\033[K" # clean the [EXECUTING] foobar line
+       fi
+
+       return "$rc_got"
+}
+
+# `wait -p` is only supported since bash 5.1
+WAIT_SUPPORTS_P=1
+[ "${BASH_VERSINFO[0]}" -le 4 -o \( "${BASH_VERSINFO[0]}" -eq 5 -a "${BASH_VERSINFO[1]}" -eq 0 \) ] && WAIT_SUPPORTS_P=0
+
+job_wait()
+{
+       local num_jobs="$1"
+       local JOBCOMPLETED
+       local rc_got
+
+       while [ "${#JOBS_PIDLIST_ARR[@]}" -gt 0 -a "${#JOBS_PIDLIST_ARR[@]}" -ge "$num_jobs" ] ; do
+               if [ "$WAIT_SUPPORTS_P" = 1 ] ; then
+                       wait -n -p JOBCOMPLETED
+                       rc_got="$?"
+                       array_remove_first JOBS_PIDLIST_ARR "$JOBCOMPLETED"
                else
-                       msg_warn "[FAILED]      $testfile"
+                       # Without `wait -p` support, we need to explicitly wait
+                       # for a PID. That reduces parallelism.
+                       JOBCOMPLETED="${JOBS_PIDLIST_ARR[0]}"
+                       JOBS_PIDLIST_ARR=( "${JOBS_PIDLIST_ARR[@]:1}" )
+                       wait -n "$JOBCOMPLETED"
+                       rc_got="$?"
                fi
-       fi
 
-       check_taint
+               local testfile2="${JOBS_PIDLIST[$JOBCOMPLETED]}"
+               unset JOBS_PIDLIST[$JOBCOMPLETED]
+               print_test_result "${JOBS_TEMPDIR["$testfile2"]}" "$testfile2" "$rc_got"
+               check_kmemleak
+       done
+}
+
+if [ "$NFT_TEST_SHUFFLE_TESTS" = y ] ; then
+       TESTS=( $(printf '%s\n' "${TESTS[@]}" | shuf --random-source=<("$NFT_TEST_BASEDIR/helpers/random-source.sh" "nft-test-shuffle-tests" "$NFT_TEST_RANDOM_SEED") ) )
+fi
+
+TESTIDX=0
+for testfile in "${TESTS[@]}" ; do
+       job_wait "$NFT_TEST_JOBS"
+
+       kernel_cleanup
+
+       ((TESTIDX++))
+
+       NFT_TEST_TESTTMPDIR="$NFT_TEST_TMPDIR/test-${testfile//\//-}.$TESTIDX"
+       mkdir "$NFT_TEST_TESTTMPDIR"
+       chmod 755 "$NFT_TEST_TESTTMPDIR"
+       JOBS_TEMPDIR["$testfile"]="$NFT_TEST_TESTTMPDIR"
+
+       [[ -o monitor ]] && set_old_state='set -m' || set_old_state='set +m'
+       set -m
+       ( job_start "$testfile" "$TESTIDX" ) &
+       pid=$!
+       eval "$set_old_state"
+       JOBS_PIDLIST[$pid]="$testfile"
+       JOBS_PIDLIST_ARR+=( "$pid" )
 done
 
+job_wait 0
+
 echo ""
-msg_info "results: [OK] $ok [FAILED] $failed [TOTAL] $((ok+failed))"
+
+# kmemleak may report suspected leaks
+# that get free'd after all, so always do
+# a check after all test cases
+# have completed and reset the counter
+# so another warning gets emitted.
+kmemleak_found=0
+check_kmemleak_force
+
+failed_total="$failed"
+if [ "$NFT_TEST_FAIL_ON_SKIP" = y ] ; then
+       failed_total="$((failed_total + skipped))"
+fi
+
+if [ "$failed_total" -gt 0 ] ; then
+       RR="$RED"
+elif [ "$skipped" -gt 0 ] ; then
+       RR="$YELLOW"
+else
+       RR="$GREEN"
+fi
+msg_info "${RR}results$RESET: [OK] $GREEN$ok$RESET [SKIPPED] $YELLOW$skipped$RESET [FAILED] $RED$failed$RESET [TOTAL] $((ok+skipped+failed))"
 
 kernel_cleanup
-[ "$failed" -eq 0 ]
+
+#    ( \
+#        for d in /tmp/nft-test.latest.*/test-*/ ; do \
+#               printf '%10.2f  %s\n' \
+#                      "$(sed '1!d' "$d/times")" \
+#                      "$(cat "$d/name")" ; \
+#        done \
+#        | sort -n \
+#        | awk '{print $0; s+=$1} END{printf("%10.2f\n", s)}' ; \
+#        printf '%10.2f wall time\n' "$(sed '1!d' /tmp/nft-test.latest.*/times)" \
+#    )
+END_TIME="$(cut -d ' ' -f1 /proc/uptime)"
+WALL_TIME="$(awk -v start="$START_TIME" -v end="$END_TIME" "BEGIN { print(end - start) }")"
+printf "%s\n" "$WALL_TIME" "$START_TIME" "$END_TIME" > "$NFT_TEST_TMPDIR/times"
+
+if [ "$failed_total" -gt 0 -o "$NFT_TEST_KEEP_LOGS" = y ] ; then
+       msg_info "check the temp directory \"$NFT_TEST_TMPDIR\" (\"$NFT_TEST_LATEST\")"
+       msg_info "   ls -lad \"$NFT_TEST_LATEST\"/*/*"
+       msg_info "   grep -R ^ \"$NFT_TEST_LATEST\"/"
+       NFT_TEST_TMPDIR=
+fi
+
+if [ "$failed" -gt 0 ] ; then
+       exit 1
+elif [ "$NFT_TEST_FAIL_ON_SKIP" = y -a "$skipped" -gt 0 ] ; then
+       msg_info "some tests were skipped. Fail due to NFT_TEST_FAIL_ON_SKIP=y"
+       exit 1
+elif [ "$ok" -eq 0 -a "$skipped" -gt 0 ] ; then
+       exit 77
+else
+       exit 0
+fi
similarity index 55%
rename from tests/shell/testcases/chains/0040mark_shift_0
rename to tests/shell/testcases/bitwise/0040mark_binop_0
index ef3dccfa049aea7964852c191a000e71cde36f5e..4ecc9d3d6c830bc66f7d409bd4b9c769461bd0d2 100755 (executable)
@@ -1,10 +1,12 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
 set -e
 
 RULESET="
   add table t
-  add chain t c { type filter hook output priority mangle; }
+  add chain t c { type filter hook output priority filter; }
   add rule t c oif lo ct mark set (meta mark | 0x10) << 8
 "
 
similarity index 57%
rename from tests/shell/testcases/chains/0040mark_shift_1
rename to tests/shell/testcases/bitwise/0040mark_binop_1
index b609f5ef10ad73dc91399fbdf528e2dc7dee9327..bd9e028df78ce0ee19a18aeb82a6b5fbfcbd9ec1 100755 (executable)
@@ -1,10 +1,12 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
 set -e
 
 RULESET="
   add table t
-  add chain t c { type filter hook input priority mangle; }
+  add chain t c { type filter hook input priority filter; }
   add rule t c iif lo ct mark & 0xff 0x10 meta mark set ct mark >> 8
 "
 
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_10 b/tests/shell/testcases/bitwise/0040mark_binop_10
new file mode 100755 (executable)
index 0000000..f523bd7
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitwise_multireg)
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook output priority filter; }
+  add rule t c ct mark set ct mark and 0xffff0000 or meta mark and 0xffff
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_11 b/tests/shell/testcases/bitwise/0040mark_binop_11
new file mode 100755 (executable)
index 0000000..d6dfb3b
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitwise_multireg)
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook input priority filter; }
+  add rule t c meta mark set ct mark and 0xffff0000 or meta mark and 0xffff
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_12 b/tests/shell/testcases/bitwise/0040mark_binop_12
new file mode 100755 (executable)
index 0000000..bbddb55
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitwise_multireg)
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook output priority filter; }
+  add rule ip6 t c ct mark set ct mark and 0xffff0000 or meta mark and 0xffff
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_13 b/tests/shell/testcases/bitwise/0040mark_binop_13
new file mode 100755 (executable)
index 0000000..769acb6
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitwise_multireg)
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook input priority filter; }
+  add rule ip6 t c meta mark set ct mark and 0xffff0000 or meta mark and 0xffff
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_2 b/tests/shell/testcases/bitwise/0040mark_binop_2
new file mode 100755 (executable)
index 0000000..5e66a27
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook output priority filter; }
+  add rule t c ct mark set ip dscp lshift 2 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_3 b/tests/shell/testcases/bitwise/0040mark_binop_3
new file mode 100755 (executable)
index 0000000..21dda67
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook input priority filter; }
+  add rule t c meta mark set ip dscp lshift 2 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_4 b/tests/shell/testcases/bitwise/0040mark_binop_4
new file mode 100755 (executable)
index 0000000..e5c8a42
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook output priority filter; }
+  add rule t c ct mark set ip dscp lshift 26 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_5 b/tests/shell/testcases/bitwise/0040mark_binop_5
new file mode 100755 (executable)
index 0000000..184fbed
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook input priority filter; }
+  add rule t c meta mark set ip dscp lshift 26 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_6 b/tests/shell/testcases/bitwise/0040mark_binop_6
new file mode 100755 (executable)
index 0000000..129dd5c
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook output priority filter; }
+  add rule ip6 t c ct mark set ip6 dscp lshift 2 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_7 b/tests/shell/testcases/bitwise/0040mark_binop_7
new file mode 100755 (executable)
index 0000000..791a794
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook input priority filter; }
+  add rule ip6 t c meta mark set ip6 dscp lshift 2 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_8 b/tests/shell/testcases/bitwise/0040mark_binop_8
new file mode 100755 (executable)
index 0000000..5e7bd28
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook output priority filter; }
+  add rule ip6 t c ct mark set ip6 dscp lshift 26 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_9 b/tests/shell/testcases/bitwise/0040mark_binop_9
new file mode 100755 (executable)
index 0000000..a7b60fb
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook input priority filter; }
+  add rule ip6 t c meta mark set ip6 dscp lshift 26 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0044payload_binop_2 b/tests/shell/testcases/bitwise/0044payload_binop_2
new file mode 100755 (executable)
index 0000000..13c4ace
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitwise_multireg)
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook output priority filter; }
+  add rule t c ct mark set ct mark | ip dscp | 0x200 counter
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0044payload_binop_5 b/tests/shell/testcases/bitwise/0044payload_binop_5
new file mode 100755 (executable)
index 0000000..7e8095c
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitwise_multireg)
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook output priority filter; }
+  add rule ip6 t c ct mark set ct mark | ip6 dscp | 0x200 counter
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_0.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_0.json-nft
new file mode 100644 (file)
index 0000000..8973de8
--- /dev/null
@@ -0,0 +1,75 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "ct": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "<<": [
+                  {
+                    "|": [
+                      {
+                        "meta": {
+                          "key": "mark"
+                        }
+                      },
+                      16
+                    ]
+                  },
+                  8
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
similarity index 58%
rename from tests/shell/testcases/chains/dumps/0040mark_shift_0.nft
rename to tests/shell/testcases/bitwise/dumps/0040mark_binop_0.nft
index 52d59d2c6da4d7aaa894e087137dacefefa9f601..fc0a600a4dbede3bd34c3ceab51885b6ab8b1aed 100644 (file)
@@ -1,6 +1,6 @@
 table ip t {
        chain c {
-               type filter hook output priority mangle; policy accept;
+               type filter hook output priority filter; policy accept;
                oif "lo" ct mark set (meta mark | 0x00000010) << 8
        }
 }
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_1.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_1.json-nft
new file mode 100644 (file)
index 0000000..ed8e1a0
--- /dev/null
@@ -0,0 +1,86 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "&": [
+                  {
+                    "ct": {
+                      "key": "mark"
+                    }
+                  },
+                  255
+                ]
+              },
+              "right": 16
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                ">>": [
+                  {
+                    "ct": {
+                      "key": "mark"
+                    }
+                  },
+                  8
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
similarity index 64%
rename from tests/shell/testcases/chains/dumps/0040mark_shift_1.nft
rename to tests/shell/testcases/bitwise/dumps/0040mark_binop_1.nft
index 56ec8dc766cab80da8cce6fe45deb083da9be7ad..dbaacefb93c7eac21f5eff9f291f9aa7f5de0344 100644 (file)
@@ -1,6 +1,6 @@
 table ip t {
        chain c {
-               type filter hook input priority mangle; policy accept;
+               type filter hook input priority filter; policy accept;
                iif "lo" ct mark & 0x000000ff == 0x00000010 meta mark set ct mark >> 8
        }
 }
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_10.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_10.nft
new file mode 100644 (file)
index 0000000..5566f72
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       chain c {
+               type filter hook output priority filter; policy accept;
+               ct mark set ct mark & 0xffff0000 | meta mark & 0x0000ffff
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_11.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_11.nft
new file mode 100644 (file)
index 0000000..719980d
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       chain c {
+               type filter hook input priority filter; policy accept;
+               meta mark set ct mark & 0xffff0000 | meta mark & 0x0000ffff
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_12.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_12.nft
new file mode 100644 (file)
index 0000000..bd589fe
--- /dev/null
@@ -0,0 +1,6 @@
+table ip6 t {
+       chain c {
+               type filter hook output priority filter; policy accept;
+               ct mark set ct mark & 0xffff0000 | meta mark & 0x0000ffff
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_13.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_13.nft
new file mode 100644 (file)
index 0000000..2b046b1
--- /dev/null
@@ -0,0 +1,6 @@
+table ip6 t {
+       chain c {
+               type filter hook input priority filter; policy accept;
+               meta mark set ct mark & 0xffff0000 | meta mark & 0x0000ffff
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_2.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_2.json-nft
new file mode 100644 (file)
index 0000000..3cd9a83
--- /dev/null
@@ -0,0 +1,65 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "ct": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "|": [
+                  {
+                    "<<": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "dscp"
+                        }
+                      },
+                      2
+                    ]
+                  },
+                  16
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_2.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_2.nft
new file mode 100644 (file)
index 0000000..2b9be36
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       chain c {
+               type filter hook output priority filter; policy accept;
+               ct mark set ip dscp << 2 | 0x10
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_3.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_3.json-nft
new file mode 100644 (file)
index 0000000..00c5b78
--- /dev/null
@@ -0,0 +1,65 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "|": [
+                  {
+                    "<<": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "dscp"
+                        }
+                      },
+                      2
+                    ]
+                  },
+                  16
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_3.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_3.nft
new file mode 100644 (file)
index 0000000..8206fec
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       chain c {
+               type filter hook input priority filter; policy accept;
+               meta mark set ip dscp << 2 | 0x10
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_4.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_4.json-nft
new file mode 100644 (file)
index 0000000..3aa8160
--- /dev/null
@@ -0,0 +1,65 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "ct": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "|": [
+                  {
+                    "<<": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "dscp"
+                        }
+                      },
+                      26
+                    ]
+                  },
+                  16
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_4.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_4.nft
new file mode 100644 (file)
index 0000000..91d9f56
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       chain c {
+               type filter hook output priority filter; policy accept;
+               ct mark set ip dscp << 26 | 0x10
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_5.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_5.json-nft
new file mode 100644 (file)
index 0000000..a321497
--- /dev/null
@@ -0,0 +1,65 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "|": [
+                  {
+                    "<<": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "dscp"
+                        }
+                      },
+                      26
+                    ]
+                  },
+                  16
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_5.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_5.nft
new file mode 100644 (file)
index 0000000..f2b51eb
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       chain c {
+               type filter hook input priority filter; policy accept;
+               meta mark set ip dscp << 26 | 0x10
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_6.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_6.json-nft
new file mode 100644 (file)
index 0000000..2de0323
--- /dev/null
@@ -0,0 +1,65 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "ct": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "|": [
+                  {
+                    "<<": [
+                      {
+                        "payload": {
+                          "protocol": "ip6",
+                          "field": "dscp"
+                        }
+                      },
+                      2
+                    ]
+                  },
+                  16
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_6.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_6.nft
new file mode 100644 (file)
index 0000000..cf7be90
--- /dev/null
@@ -0,0 +1,6 @@
+table ip6 t {
+       chain c {
+               type filter hook output priority filter; policy accept;
+               ct mark set ip6 dscp << 2 | 0x10
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_7.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_7.json-nft
new file mode 100644 (file)
index 0000000..72aee70
--- /dev/null
@@ -0,0 +1,65 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "|": [
+                  {
+                    "<<": [
+                      {
+                        "payload": {
+                          "protocol": "ip6",
+                          "field": "dscp"
+                        }
+                      },
+                      2
+                    ]
+                  },
+                  16
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_7.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_7.nft
new file mode 100644 (file)
index 0000000..a9663e6
--- /dev/null
@@ -0,0 +1,6 @@
+table ip6 t {
+       chain c {
+               type filter hook input priority filter; policy accept;
+               meta mark set ip6 dscp << 2 | 0x10
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_8.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_8.json-nft
new file mode 100644 (file)
index 0000000..1cf84be
--- /dev/null
@@ -0,0 +1,65 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "ct": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "|": [
+                  {
+                    "<<": [
+                      {
+                        "payload": {
+                          "protocol": "ip6",
+                          "field": "dscp"
+                        }
+                      },
+                      26
+                    ]
+                  },
+                  16
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_8.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_8.nft
new file mode 100644 (file)
index 0000000..04b866a
--- /dev/null
@@ -0,0 +1,6 @@
+table ip6 t {
+       chain c {
+               type filter hook output priority filter; policy accept;
+               ct mark set ip6 dscp << 26 | 0x10
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_9.json-nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_9.json-nft
new file mode 100644 (file)
index 0000000..6f4494b
--- /dev/null
@@ -0,0 +1,65 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "|": [
+                  {
+                    "<<": [
+                      {
+                        "payload": {
+                          "protocol": "ip6",
+                          "field": "dscp"
+                        }
+                      },
+                      26
+                    ]
+                  },
+                  16
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_9.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_9.nft
new file mode 100644 (file)
index 0000000..d4745ea
--- /dev/null
@@ -0,0 +1,6 @@
+table ip6 t {
+       chain c {
+               type filter hook input priority filter; policy accept;
+               meta mark set ip6 dscp << 26 | 0x10
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0044payload_binop_2.nft b/tests/shell/testcases/bitwise/dumps/0044payload_binop_2.nft
new file mode 100644 (file)
index 0000000..ed347bb
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       chain c {
+               type filter hook output priority filter; policy accept;
+               ct mark set ct mark | ip dscp | 0x00000200 counter packets 0 bytes 0
+       }
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0044payload_binop_5.nft b/tests/shell/testcases/bitwise/dumps/0044payload_binop_5.nft
new file mode 100644 (file)
index 0000000..ccdb93d
--- /dev/null
@@ -0,0 +1,6 @@
+table ip6 t {
+       chain c {
+               type filter hook output priority filter; policy accept;
+               ct mark set ct mark | ip6 dscp | 0x00000200 counter packets 0 bytes 0
+       }
+}
diff --git a/tests/shell/testcases/bogons/dumps/assert_failures.json-nft b/tests/shell/testcases/bogons/dumps/assert_failures.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bogons/dumps/assert_failures.nft b/tests/shell/testcases/bogons/dumps/assert_failures.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/bogons/nft-f/delete_nonexistant_object_crash b/tests/shell/testcases/bogons/nft-f/delete_nonexistant_object_crash
new file mode 100644 (file)
index 0000000..c369dec
--- /dev/null
@@ -0,0 +1 @@
+delete quota a b
diff --git a/tests/shell/testcases/bogons/nft-f/range_expression_corruption b/tests/shell/testcases/bogons/nft-f/range_expression_corruption
new file mode 100644 (file)
index 0000000..b77221b
--- /dev/null
@@ -0,0 +1,2 @@
+aal    tht@nh,32,3 set ctag| oi to ip
+               p sept ct               l3proto map  q -u dscp |  ma
\ No newline at end of file
diff --git a/tests/shell/testcases/bogons/nft-f/set_definition_with_no_key_assert b/tests/shell/testcases/bogons/nft-f/set_definition_with_no_key_assert
new file mode 100644 (file)
index 0000000..59ef1ab
--- /dev/null
@@ -0,0 +1,12 @@
+table inet testifsets {
+       map map_wild {  elements = { "abcdex*",
+                            "othername",
+                            "ppp0" }
+       }
+       map map_wild {
+               type ifname : verdict
+               flags interval
+               elements = { "abcdez*" : jump do_nothing,
+                            "eth0" : jump do_nothing }
+       }
+}
diff --git a/tests/shell/testcases/bogons/nft-f/use_after_free_on_chain_removal b/tests/shell/testcases/bogons/nft-f/use_after_free_on_chain_removal
new file mode 100644 (file)
index 0000000..bb9632b
--- /dev/null
@@ -0,0 +1,5 @@
+delete chain d iUi {
+}}
+delete chain d hUi {
+delete chain o
+c b icmpv6  id$i
diff --git a/tests/shell/testcases/bogons/nft-f/zero_length_devicename2_assert b/tests/shell/testcases/bogons/nft-f/zero_length_devicename2_assert
new file mode 100644 (file)
index 0000000..fe416f8
--- /dev/null
@@ -0,0 +1,5 @@
+table netdev x {
+        chain Main_Ingress1 {
+                type filter hook ingress device "" priority -1
+       }
+}
diff --git a/tests/shell/testcases/bogons/nft-j-f/Assertion__out_failed_assert b/tests/shell/testcases/bogons/nft-j-f/Assertion__out_failed_assert
new file mode 100644 (file)
index 0000000..f8ce089
--- /dev/null
@@ -0,0 +1,6 @@
+table ip test-ip {
+       quota htquota {         comment "t\8est5"  5 kbytes
+       }
+}
+list ruleset      
+add rule t c counter
diff --git a/tests/shell/testcases/bogons/nft-j-f/binop_rhs_decode_error_crash b/tests/shell/testcases/bogons/nft-j-f/binop_rhs_decode_error_crash
new file mode 100644 (file)
index 0000000..8b5b729
--- /dev/null
@@ -0,0 +1,76 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "ct": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "<<": [
+                  {
+                    "|": [
+                      {
+                        "meta": {
+                          "key": "mark"
+                        }
+                      },
+                      16
+                    ]
+                  },
+                  {  },
+                  8
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bogons/nft-j-f/constant_expr_alloc_assert b/tests/shell/testcases/bogons/nft-j-f/constant_expr_alloc_assert
new file mode 100644 (file)
index 0000000..9c40030
--- /dev/null
@@ -0,0 +1,38 @@
+{
+  "nftables": [
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "testchain",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "testmap",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "verdict",
+        "elem": [
+          [
+            {
+              "jump": {
+                "target": ""
+              }
+            }
+          ]
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bogons/nft-j-f/expr_evaluate_concat_empty_concat_key_assert b/tests/shell/testcases/bogons/nft-j-f/expr_evaluate_concat_empty_concat_key_assert
new file mode 100644 (file)
index 0000000..956ecdc
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "table": { "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": [
+             ],
+        "elem": [
+          {
+            "concat": [
+              "foo", "bar"
+            ]
+          }
+        ]
+      }
+    }
+  ]
+}
+
diff --git a/tests/shell/testcases/bogons/nft-j-f/list_a_destroyed_table_crash b/tests/shell/testcases/bogons/nft-j-f/list_a_destroyed_table_crash
new file mode 100644 (file)
index 0000000..f06145c
--- /dev/null
@@ -0,0 +1,3 @@
+table t
+list table t
+destroy table t
diff --git a/tests/shell/testcases/bogons/nft-j-f/reject_stmt_with_no_expression_crash b/tests/shell/testcases/bogons/nft-j-f/reject_stmt_with_no_expression_crash
new file mode 100644 (file)
index 0000000..04c01aa
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "nftables": [
+    {
+      "table": { "family": "ip", "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "c",
+             "expr": [
+          {
+            "reject": {
+              "type": "icmpv6",
+              "exprlimit": "port-unreachable"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bogons/nft-j-f/set_with_single_value_concat_assert b/tests/shell/testcases/bogons/nft-j-f/set_with_single_value_concat_assert
new file mode 100644 (file)
index 0000000..c99a266
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+  "metainfo": {
+   "version": "nftables", "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+       "family": "ip",
+       "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+       "type": [ "ifname" ],
+        "flags": [ "interval" ],
+        "elem": [ [] ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/bogons/nft-j-f/unkown_stateful_statement_type_19_assert b/tests/shell/testcases/bogons/nft-j-f/unkown_stateful_statement_type_19_assert
new file mode 100644 (file)
index 0000000..e8a0f76
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "m",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "mark",
+        "stmt": [
+          {
+            "notrack": null
+          }
+        ]
+      }
+    }
+  ]
+}
+
index 529d6b85e4157255726e106910b4ef488ad9bada..0db4c693f6d4dd35205878270264bdd4e547370e 100755 (executable)
@@ -16,7 +16,7 @@ $NFT add set t s { type ipv4_addr\; }
 HANDLE=`$NFT -a list ruleset | grep "set.*handle" | cut -d' ' -f6`
 $NFT delete set t handle $HANDLE
 
-$NFT add flowtable t f { hook ingress priority 0\; }
+$NFT add flowtable t f { hook ingress priority 0\; devices = { lo } \; }
 HANDLE=`$NFT -a list ruleset | grep "flowtable.*handle" | cut -d' ' -f6`
 $NFT delete flowtable t handle $HANDLE
 
index 0ab0db957cf2fc91fd0d1556e83bae9e1b550abf..834dc6e4036c964834552bab047046cb433c7e92 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_chain_binding)
+
 set -e
 
 EXPECTED="table ip f {
index c9eb86830c8d7abf0a1a4fa1e2beb04eb31e17af..76f2615d471c836e8c5d042562839c1706347369 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_position_id)
+
 set -e
 
 RULESET="flush ruleset
diff --git a/tests/shell/testcases/cache/dumps/0001_cache_handling_0.json-nft b/tests/shell/testcases/cache/dumps/0001_cache_handling_0.json-nft
new file mode 100644 (file)
index 0000000..7a2eacd
--- /dev/null
@@ -0,0 +1,142 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "test",
+        "table": "test",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1",
+          "3.3.3.3"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "2.2.2.2",
+                  "4.4.4.4"
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@test"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "2.2.2.2",
+                  "4.4.4.4"
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/cache/dumps/0002_interval_0.json-nft b/tests/shell/testcases/cache/dumps/0002_interval_0.json-nft
new file mode 100644 (file)
index 0000000..5e2b9b4
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "192.168.0.0",
+              "len": 24
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/cache/dumps/0003_cache_update_0.json-nft b/tests/shell/testcases/cache/dumps/0003_cache_update_0.json-nft
new file mode 100644 (file)
index 0000000..e09a694
--- /dev/null
@@ -0,0 +1,137 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t2",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t3",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t4",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t4",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t4",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "icmp"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t4",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t4",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "igmp"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t4",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/cache/dumps/0003_cache_update_0.nft b/tests/shell/testcases/cache/dumps/0003_cache_update_0.nft
new file mode 100644 (file)
index 0000000..43898d3
--- /dev/null
@@ -0,0 +1,18 @@
+table ip t {
+       chain c {
+       }
+}
+table ip t2 {
+       chain c {
+       }
+}
+table ip t3 {
+}
+table ip t4 {
+       chain c {
+               meta l4proto icmp accept
+               drop
+               meta l4proto igmp accept
+               drop
+       }
+}
diff --git a/tests/shell/testcases/cache/dumps/0004_cache_update_0.json-nft b/tests/shell/testcases/cache/dumps/0004_cache_update_0.json-nft
new file mode 100644 (file)
index 0000000..d1864f0
--- /dev/null
@@ -0,0 +1,42 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "testfilter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "testfilter",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testfilter",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/cache/dumps/0004_cache_update_0.nft b/tests/shell/testcases/cache/dumps/0004_cache_update_0.nft
new file mode 100644 (file)
index 0000000..4f5761b
--- /dev/null
@@ -0,0 +1,5 @@
+table inet testfilter {
+       chain test {
+               counter packets 0 bytes 0
+       }
+}
diff --git a/tests/shell/testcases/cache/dumps/0005_cache_chain_flush.json-nft b/tests/shell/testcases/cache/dumps/0005_cache_chain_flush.json-nft
new file mode 100644 (file)
index 0000000..1c47d3e
--- /dev/null
@@ -0,0 +1,77 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "z",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "mapping",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "inet_service",
+        "size": 65535,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "map": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "sport"
+                }
+              },
+              "map": "@mapping"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/cache/dumps/0005_cache_chain_flush.nft b/tests/shell/testcases/cache/dumps/0005_cache_chain_flush.nft
new file mode 100644 (file)
index 0000000..8ab55a2
--- /dev/null
@@ -0,0 +1,14 @@
+table ip x {
+       map mapping {
+               type ipv4_addr : inet_service
+               size 65535
+               flags dynamic,timeout
+       }
+
+       chain y {
+               update @mapping { ip saddr : tcp sport }
+       }
+
+       chain z {
+       }
+}
diff --git a/tests/shell/testcases/cache/dumps/0006_cache_table_flush.json-nft b/tests/shell/testcases/cache/dumps/0006_cache_table_flush.json-nft
new file mode 100644 (file)
index 0000000..1c47d3e
--- /dev/null
@@ -0,0 +1,77 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "z",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "mapping",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "inet_service",
+        "size": 65535,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "map": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "sport"
+                }
+              },
+              "map": "@mapping"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/cache/dumps/0006_cache_table_flush.nft b/tests/shell/testcases/cache/dumps/0006_cache_table_flush.nft
new file mode 100644 (file)
index 0000000..8ab55a2
--- /dev/null
@@ -0,0 +1,14 @@
+table ip x {
+       map mapping {
+               type ipv4_addr : inet_service
+               size 65535
+               flags dynamic,timeout
+       }
+
+       chain y {
+               update @mapping { ip saddr : tcp sport }
+       }
+
+       chain z {
+       }
+}
diff --git a/tests/shell/testcases/cache/dumps/0007_echo_cache_init_0.json-nft b/tests/shell/testcases/cache/dumps/0007_echo_cache_init_0.json-nft
new file mode 100644 (file)
index 0000000..0968d8a
--- /dev/null
@@ -0,0 +1,68 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "comment": "first",
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "comment": "second",
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "comment": "third",
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/cache/dumps/0008_delete_by_handle_0.json-nft b/tests/shell/testcases/cache/dumps/0008_delete_by_handle_0.json-nft
new file mode 100644 (file)
index 0000000..e0e56fe
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/cache/dumps/0008_delete_by_handle_0.nft b/tests/shell/testcases/cache/dumps/0008_delete_by_handle_0.nft
new file mode 100644 (file)
index 0000000..985768b
--- /dev/null
@@ -0,0 +1,2 @@
+table ip t {
+}
diff --git a/tests/shell/testcases/cache/dumps/0009_delete_by_handle_incorrect_0.json-nft b/tests/shell/testcases/cache/dumps/0009_delete_by_handle_incorrect_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/cache/dumps/0009_delete_by_handle_incorrect_0.nft b/tests/shell/testcases/cache/dumps/0009_delete_by_handle_incorrect_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/cache/dumps/0010_implicit_chain_0.nft b/tests/shell/testcases/cache/dumps/0010_implicit_chain_0.nft
new file mode 100644 (file)
index 0000000..aba92c0
--- /dev/null
@@ -0,0 +1,7 @@
+table ip f {
+       chain c {
+               jump {
+                       accept
+               }
+       }
+}
diff --git a/tests/shell/testcases/cache/dumps/0011_index_0.json-nft b/tests/shell/testcases/cache/dumps/0011_index_0.json-nft
new file mode 100644 (file)
index 0000000..46b2909
--- /dev/null
@@ -0,0 +1,93 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 1234
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 4321
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
index 80e243f07bdb786b32ac49f16b241c63bef2e8c5..1a8eaf68674734979988dd86fbc87cd66e39a427 100755 (executable)
@@ -5,8 +5,9 @@ set -e
 MAX_JUMPS=16
 
 $NFT add table t
+$NFT "add chain t c1 { type filter hook prerouting priority 0; }"
 
-for i in $(seq 1 $MAX_JUMPS)
+for i in $(seq 2 $MAX_JUMPS)
 do
        $NFT add chain t c${i}
 done
index 5d3ef2393331674d81b605540a2bbca51e9f9a06..6000e5d7dbf3877cbe2a35cbe62bb21a780a3aa3 100755 (executable)
@@ -3,7 +3,7 @@
 set -e
 
 $NFT add table t
-$NFT add chain t c
+$NFT add chain "t c { type filter hook input priority 0; }"
 
 # kernel should return ELOOP
 $NFT add rule t c tcp dport vmap {1 : jump c} 2>/dev/null || exit 0
index d75932d7a7caca319147caec0fb4e813f40e4eb7..66abf8d04543e305d8c7fded0f6ca2e26ca0d88c 100755 (executable)
@@ -3,7 +3,7 @@
 set -e
 
 $NFT add table t
-$NFT add chain t c1
+$NFT add chain "t c1 { type filter hook forward priority 0; }"
 $NFT add chain t c2
 $NFT add map t m {type inet_service : verdict \;}
 $NFT add element t m {2 : jump c2}
index bebe48d67af9ec01a0dc7564306154a0fa33a218..bd84e95784a75a62c435da5dcfd4da7e3b7a33bc 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 $NFT add table t || exit 1
 $NFT add chain t c1 || exit 1
index b87520f287d781742f49fa9ad0051358ccd7b7ca..1e674d3dc12b49ee2892c41483eb4ac582648d9b 100755 (executable)
@@ -3,7 +3,7 @@
 set -e
 
 $NFT add table ip filter
-$NFT add chain ip filter ap1
+$NFT add chain ip filter ap1 "{ type filter hook input priority 0; }"
 $NFT add chain ip filter ap2
 $NFT add rule ip filter ap1 jump ap2
 
index d450dc0b6c345915ab040ec2c34b86d8e80d8a2e..ceda1558352040a547c2ef3d4abd5b95fb5b110a 100755 (executable)
@@ -69,7 +69,7 @@ done
 family=netdev
 echo "add table $family x"
 gen_chains $family ingress filter lo
-gen_chains $family egress filter lo
+[ "$NFT_TEST_HAVE_netdev_egress" != n ] && gen_chains $family egress filter lo
 
 family=bridge
 echo "add table $family x"
@@ -83,3 +83,8 @@ gen_chains $family postrouting srcnat
 
 ) >$tmpfile
 $NFT -f $tmpfile
+
+if [ "$NFT_TEST_HAVE_netdev_egress" = n ]; then
+       echo "Ran a modified version of the test due to NFT_TEST_HAVE_netdev_egress=n"
+       exit 77
+fi
index 4b541bb55c309bdef806e0ff0be43bd4c4e91a71..141a4b6d2c5920f464c6818cb2c987ad02b4e369 100755 (executable)
@@ -6,6 +6,11 @@ if [ $? -ne 1 ]; then
        exit 1
 fi
 
+if [ $NFT_TEST_HAVE_chain_binding = "n" ] ; then
+       echo "Test partially skipped due to NFT_TEST_HAVE_chain_binding=n"
+       exit 77
+fi
+
 set -e
 
 EXPECTED="table inet x {
index 5628e19cb85a7b60861eaf0fea67adadf25fd1c9..c5de495ef0746cb938dbd8b2372511496d731f8a 100755 (executable)
@@ -1,8 +1,11 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netdev_chain_multidevice)
+
 set -e
 
-ip link add name dummy0 type dummy
+ip link add name d23456789012345 type dummy
+
 
 EXPECTED="define if_main = \"lo\"
 
@@ -14,6 +17,7 @@ table netdev filter1 {
 
 $NFT -f - <<< $EXPECTED
 
+
 EXPECTED="define if_main = \"lo\"
 
 table netdev filter2 {
@@ -33,24 +37,35 @@ table netdev filter1 {
 }
 EOF
 
+
 EXPECTED="define if_main = \"lo\"
 
 table netdev filter2 {
        chain Main_Ingress2 {
-               type filter hook ingress devices = { \$if_main, dummy0 } priority -500; policy accept;
+               type filter hook ingress devices = { \$if_main, d23456789012345 } priority -500; policy accept;
        }
 }"
 
 $NFT -f - <<< $EXPECTED
 
-EXPECTED="define if_main = { lo, dummy0 }
+
+if [ "$NFT_TEST_HAVE_netdev_egress" = n ] ; then
+       echo "Skip parts of the test due to NFT_TEST_HAVE_netdev_egress=n"
+       exit 77
+fi
+
+
+EXPECTED="define if_main = { lo, d23456789012345 }
+define lan_interfaces = { lo }
 
 table netdev filter3 {
        chain Main_Ingress3 {
                type filter hook ingress devices = \$if_main priority -500; policy accept;
        }
+       chain Main_Egress3 {
+               type filter hook egress devices = \$lan_interfaces priority -500; policy accept;
+       }
 }"
 
 $NFT -f - <<< $EXPECTED
 
-
index bff464687a6f8c46bad406598748edc54e82470f..a6973b99e514ef2cd515c544e58f2f2a72bb663a 100755 (executable)
@@ -1,7 +1,8 @@
 #!/bin/bash
 
-set -e
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_inet_ingress)
 
+set -e
 RULESET="table inet filter {
        chain ingress {
                type filter hook ingress device \"lo\" priority filter; policy accept;
@@ -14,11 +15,5 @@ RULESET="table inet filter {
        }
 }"
 
-# Test auto-removal of chain hook on netns removal
-unshare -n bash -c "ip link add br0 type bridge; \
- $NFT add table netdev test; \
- $NFT add chain netdev test ingress { type filter hook ingress device \"br0\" priority 0\; policy drop\; } ; \
-" || exit 1
-
 $NFT -f - <<< "$RULESET" && exit 0
 exit 1
diff --git a/tests/shell/testcases/chains/0044chain_destroy_0 b/tests/shell/testcases/chains/0044chain_destroy_0
new file mode 100755 (executable)
index 0000000..5c5a10a
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash -e
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_destroy)
+
+$NFT add table t
+
+# pass for non-existent chain
+$NFT destroy chain t c
+
+# successfully delete existing chain
+$NFT add chain t c
+$NFT destroy chain t c
diff --git a/tests/shell/testcases/chains/dumps/0001jumps_0.json-nft b/tests/shell/testcases/chains/dumps/0001jumps_0.json-nft
new file mode 100644 (file)
index 0000000..ceef322
--- /dev/null
@@ -0,0 +1,371 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c3",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c4",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c5",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c6",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c7",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c8",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c9",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c10",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c11",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c12",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c13",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c14",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c15",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c16",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c2"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c2",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c3"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c3",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c4"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c4",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c5"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c5",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c6"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c6",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c7"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c7",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c8"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c8",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c9"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c9",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c10"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c10",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c11"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c11",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c12"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c12",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c13"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c13",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c14"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c14",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c15"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c15",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c16"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0002jumps_1.json-nft b/tests/shell/testcases/chains/dumps/0002jumps_1.json-nft
new file mode 100644 (file)
index 0000000..66f921a
--- /dev/null
@@ -0,0 +1,383 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c3",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c4",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c5",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c6",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c7",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c8",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c9",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c10",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c11",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c12",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c13",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c14",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c15",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c16",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c17",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c2"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c2",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c3"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c3",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c4"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c4",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c5"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c5",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c6"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c6",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c7"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c7",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c8"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c8",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c9"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c9",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c10"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c10",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c11"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c11",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c12"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c12",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c13"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c13",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c14"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c14",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c15"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c15",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c16"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0002jumps_1.nft b/tests/shell/testcases/chains/dumps/0002jumps_1.nft
new file mode 100644 (file)
index 0000000..ed37ad0
--- /dev/null
@@ -0,0 +1,68 @@
+table ip t {
+       chain c1 {
+               type filter hook input priority filter; policy accept;
+               jump c2
+       }
+
+       chain c2 {
+               jump c3
+       }
+
+       chain c3 {
+               jump c4
+       }
+
+       chain c4 {
+               jump c5
+       }
+
+       chain c5 {
+               jump c6
+       }
+
+       chain c6 {
+               jump c7
+       }
+
+       chain c7 {
+               jump c8
+       }
+
+       chain c8 {
+               jump c9
+       }
+
+       chain c9 {
+               jump c10
+       }
+
+       chain c10 {
+               jump c11
+       }
+
+       chain c11 {
+               jump c12
+       }
+
+       chain c12 {
+               jump c13
+       }
+
+       chain c13 {
+               jump c14
+       }
+
+       chain c14 {
+               jump c15
+       }
+
+       chain c15 {
+               jump c16
+       }
+
+       chain c16 {
+       }
+
+       chain c17 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0003jump_loop_1.json-nft b/tests/shell/testcases/chains/dumps/0003jump_loop_1.json-nft
new file mode 100644 (file)
index 0000000..d197e12
--- /dev/null
@@ -0,0 +1,375 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c3",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c4",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c5",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c6",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c7",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c8",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c9",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c10",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c11",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c12",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c13",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c14",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c15",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c16",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c2"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c2",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c3"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c3",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c4"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c4",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c5"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c5",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c6"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c6",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c7"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c7",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c8"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c8",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c9"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c9",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c10"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c10",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c11"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c11",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c12"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c12",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c13"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c13",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c14"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c14",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c15"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c15",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c16"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0003jump_loop_1.nft b/tests/shell/testcases/chains/dumps/0003jump_loop_1.nft
new file mode 100644 (file)
index 0000000..8d89bc4
--- /dev/null
@@ -0,0 +1,65 @@
+table ip t {
+       chain c1 {
+               type filter hook prerouting priority filter; policy accept;
+               jump c2
+       }
+
+       chain c2 {
+               jump c3
+       }
+
+       chain c3 {
+               jump c4
+       }
+
+       chain c4 {
+               jump c5
+       }
+
+       chain c5 {
+               jump c6
+       }
+
+       chain c6 {
+               jump c7
+       }
+
+       chain c7 {
+               jump c8
+       }
+
+       chain c8 {
+               jump c9
+       }
+
+       chain c9 {
+               jump c10
+       }
+
+       chain c10 {
+               jump c11
+       }
+
+       chain c11 {
+               jump c12
+       }
+
+       chain c12 {
+               jump c13
+       }
+
+       chain c13 {
+               jump c14
+       }
+
+       chain c14 {
+               jump c15
+       }
+
+       chain c15 {
+               jump c16
+       }
+
+       chain c16 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0004busy_1.json-nft b/tests/shell/testcases/chains/dumps/0004busy_1.json-nft
new file mode 100644 (file)
index 0000000..314245f
--- /dev/null
@@ -0,0 +1,49 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c2"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0004busy_1.nft b/tests/shell/testcases/chains/dumps/0004busy_1.nft
new file mode 100644 (file)
index 0000000..429dd49
--- /dev/null
@@ -0,0 +1,8 @@
+table ip t {
+       chain c1 {
+               jump c2
+       }
+
+       chain c2 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0005busy_map_1.json-nft b/tests/shell/testcases/chains/dumps/0005busy_map_1.json-nft
new file mode 100644 (file)
index 0000000..ce77682
--- /dev/null
@@ -0,0 +1,66 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    1,
+                    {
+                      "jump": {
+                        "target": "c2"
+                      }
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0005busy_map_1.nft b/tests/shell/testcases/chains/dumps/0005busy_map_1.nft
new file mode 100644 (file)
index 0000000..acf2318
--- /dev/null
@@ -0,0 +1,8 @@
+table ip t {
+       chain c1 {
+               tcp dport vmap { 1 : jump c2 }
+       }
+
+       chain c2 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0006masquerade_0.json-nft b/tests/shell/testcases/chains/dumps/0006masquerade_0.json-nft
new file mode 100644 (file)
index 0000000..b6fc221
--- /dev/null
@@ -0,0 +1,43 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0,
+        "type": "nat",
+        "hook": "postrouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "masquerade": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0007masquerade_1.json-nft b/tests/shell/testcases/chains/dumps/0007masquerade_1.json-nft
new file mode 100644 (file)
index 0000000..98b5104
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0007masquerade_1.nft b/tests/shell/testcases/chains/dumps/0007masquerade_1.nft
new file mode 100644 (file)
index 0000000..b25355f
--- /dev/null
@@ -0,0 +1,5 @@
+table ip t {
+       chain c1 {
+               type filter hook output priority filter; policy accept;
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0008masquerade_jump_1.json-nft b/tests/shell/testcases/chains/dumps/0008masquerade_jump_1.json-nft
new file mode 100644 (file)
index 0000000..3215496
--- /dev/null
@@ -0,0 +1,51 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "output",
+        "handle": 0,
+        "type": "nat",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "masquerade": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0008masquerade_jump_1.nft b/tests/shell/testcases/chains/dumps/0008masquerade_jump_1.nft
new file mode 100644 (file)
index 0000000..4991071
--- /dev/null
@@ -0,0 +1,9 @@
+table ip t {
+       chain output {
+               type nat hook output priority filter; policy accept;
+       }
+
+       chain c1 {
+               masquerade
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0009masquerade_jump_1.json-nft b/tests/shell/testcases/chains/dumps/0009masquerade_jump_1.json-nft
new file mode 100644 (file)
index 0000000..3215496
--- /dev/null
@@ -0,0 +1,51 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "output",
+        "handle": 0,
+        "type": "nat",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "masquerade": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0009masquerade_jump_1.nft b/tests/shell/testcases/chains/dumps/0009masquerade_jump_1.nft
new file mode 100644 (file)
index 0000000..4991071
--- /dev/null
@@ -0,0 +1,9 @@
+table ip t {
+       chain output {
+               type nat hook output priority filter; policy accept;
+       }
+
+       chain c1 {
+               masquerade
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0010endless_jump_loop_1.json-nft b/tests/shell/testcases/chains/dumps/0010endless_jump_loop_1.json-nft
new file mode 100644 (file)
index 0000000..af99873
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0010endless_jump_loop_1.nft b/tests/shell/testcases/chains/dumps/0010endless_jump_loop_1.nft
new file mode 100644 (file)
index 0000000..62fefaf
--- /dev/null
@@ -0,0 +1,5 @@
+table ip t {
+       chain c {
+               type filter hook input priority filter; policy accept;
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0011endless_jump_loop_1.json-nft b/tests/shell/testcases/chains/dumps/0011endless_jump_loop_1.json-nft
new file mode 100644 (file)
index 0000000..75a4d89
--- /dev/null
@@ -0,0 +1,79 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "m",
+        "table": "t",
+        "type": "inet_service",
+        "handle": 0,
+        "map": "verdict",
+        "elem": [
+          [
+            2,
+            {
+              "jump": {
+                "target": "c2"
+              }
+            }
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "data": "@m"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0011endless_jump_loop_1.nft b/tests/shell/testcases/chains/dumps/0011endless_jump_loop_1.nft
new file mode 100644 (file)
index 0000000..d35736e
--- /dev/null
@@ -0,0 +1,14 @@
+table ip t {
+       map m {
+               type inet_service : verdict
+               elements = { 2 : jump c2 }
+       }
+
+       chain c1 {
+               type filter hook forward priority filter; policy accept;
+               tcp dport vmap @m
+       }
+
+       chain c2 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0013rename_0.json-nft b/tests/shell/testcases/chains/dumps/0013rename_0.json-nft
new file mode 100644 (file)
index 0000000..f89c455
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0014rename_0.json-nft b/tests/shell/testcases/chains/dumps/0014rename_0.json-nft
new file mode 100644 (file)
index 0000000..f4c6855
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0014rename_0.nft b/tests/shell/testcases/chains/dumps/0014rename_0.nft
new file mode 100644 (file)
index 0000000..574c486
--- /dev/null
@@ -0,0 +1,7 @@
+table ip t {
+       chain c1 {
+       }
+
+       chain c2 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0015check_jump_loop_1.json-nft b/tests/shell/testcases/chains/dumps/0015check_jump_loop_1.json-nft
new file mode 100644 (file)
index 0000000..314245f
--- /dev/null
@@ -0,0 +1,49 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c2"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0015check_jump_loop_1.nft b/tests/shell/testcases/chains/dumps/0015check_jump_loop_1.nft
new file mode 100644 (file)
index 0000000..429dd49
--- /dev/null
@@ -0,0 +1,8 @@
+table ip t {
+       chain c1 {
+               jump c2
+       }
+
+       chain c2 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0016delete_handle_0.json-nft b/tests/shell/testcases/chains/dumps/0016delete_handle_0.json-nft
new file mode 100644 (file)
index 0000000..ca1311d
--- /dev/null
@@ -0,0 +1,57 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test-ip",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test-ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test-ip",
+        "name": "z",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test-ip6",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "test-ip6",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "test-ip6",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0017masquerade_jump_1.json-nft b/tests/shell/testcases/chains/dumps/0017masquerade_jump_1.json-nft
new file mode 100644 (file)
index 0000000..b368c23
--- /dev/null
@@ -0,0 +1,53 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 4,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c1"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0017masquerade_jump_1.nft b/tests/shell/testcases/chains/dumps/0017masquerade_jump_1.nft
new file mode 100644 (file)
index 0000000..636e844
--- /dev/null
@@ -0,0 +1,9 @@
+table ip t {
+       chain input {
+               type filter hook input priority filter + 4; policy accept;
+               jump c1
+       }
+
+       chain c1 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0018check_jump_loop_1.json-nft b/tests/shell/testcases/chains/dumps/0018check_jump_loop_1.json-nft
new file mode 100644 (file)
index 0000000..ac7e119
--- /dev/null
@@ -0,0 +1,53 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "ap1",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "ap2",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "ap1",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "ap2"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0018check_jump_loop_1.nft b/tests/shell/testcases/chains/dumps/0018check_jump_loop_1.nft
new file mode 100644 (file)
index 0000000..bdd0ead
--- /dev/null
@@ -0,0 +1,9 @@
+table ip filter {
+       chain ap1 {
+               type filter hook input priority filter; policy accept;
+               jump ap2
+       }
+
+       chain ap2 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0019masquerade_jump_1.json-nft b/tests/shell/testcases/chains/dumps/0019masquerade_jump_1.json-nft
new file mode 100644 (file)
index 0000000..c164ffb
--- /dev/null
@@ -0,0 +1,70 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 4,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    "1.1.1.1",
+                    {
+                      "jump": {
+                        "target": "c1"
+                      }
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0019masquerade_jump_1.nft b/tests/shell/testcases/chains/dumps/0019masquerade_jump_1.nft
new file mode 100644 (file)
index 0000000..81cf9cc
--- /dev/null
@@ -0,0 +1,9 @@
+table ip t {
+       chain input {
+               type filter hook input priority filter + 4; policy accept;
+               ip saddr vmap { 1.1.1.1 : jump c1 }
+       }
+
+       chain c1 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0020depth_1.json-nft b/tests/shell/testcases/chains/dumps/0020depth_1.json-nft
new file mode 100644 (file)
index 0000000..31bc2b1
--- /dev/null
@@ -0,0 +1,475 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a0",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a3",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a4",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a5",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a6",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a7",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a8",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a9",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a10",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a11",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a12",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a13",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a14",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a15",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a16",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a17",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a18",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "a19",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a1"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a0",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a1"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a1",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a2"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a2",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a3"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a3",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a4"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a4",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a5"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a5",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a6"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a6",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a7"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a7",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a8"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a8",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a9"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a9",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a10"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a11",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a12"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a12",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a13"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a13",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a14"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a14",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a15"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a15",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a16"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a16",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a17"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a17",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a18"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "a18",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "a19"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0020depth_1.nft b/tests/shell/testcases/chains/dumps/0020depth_1.nft
new file mode 100644 (file)
index 0000000..422c395
--- /dev/null
@@ -0,0 +1,84 @@
+table ip filter {
+       chain input {
+               type filter hook input priority filter; policy accept;
+               jump a1
+       }
+
+       chain a0 {
+               jump a1
+       }
+
+       chain a1 {
+               jump a2
+       }
+
+       chain a2 {
+               jump a3
+       }
+
+       chain a3 {
+               jump a4
+       }
+
+       chain a4 {
+               jump a5
+       }
+
+       chain a5 {
+               jump a6
+       }
+
+       chain a6 {
+               jump a7
+       }
+
+       chain a7 {
+               jump a8
+       }
+
+       chain a8 {
+               jump a9
+       }
+
+       chain a9 {
+               jump a10
+       }
+
+       chain a10 {
+       }
+
+       chain a11 {
+               jump a12
+       }
+
+       chain a12 {
+               jump a13
+       }
+
+       chain a13 {
+               jump a14
+       }
+
+       chain a14 {
+               jump a15
+       }
+
+       chain a15 {
+               jump a16
+       }
+
+       chain a16 {
+               jump a17
+       }
+
+       chain a17 {
+               jump a18
+       }
+
+       chain a18 {
+               jump a19
+       }
+
+       chain a19 {
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0021prio_0.json-nft b/tests/shell/testcases/chains/dumps/0021prio_0.json-nft
new file mode 100644 (file)
index 0000000..1a3e116
--- /dev/null
@@ -0,0 +1,4743 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "inputsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "forwardsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "outputsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingdstnatm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -111,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingdstnatm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingdstnat",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -100,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingdstnatp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "preroutingdstnatp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -89,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsrcnatm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 89,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsrcnatm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsrcnat",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 100,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsrcnatp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "postroutingsrcnatp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 111,
+        "policy": "accept"
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "inputsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "forwardsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "outputsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingdstnatm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -111,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingdstnatm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingdstnat",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -100,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingdstnatp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "preroutingdstnatp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -89,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsrcnatm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 89,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsrcnatm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsrcnat",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 100,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsrcnatp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "postroutingsrcnatp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 111,
+        "policy": "accept"
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "inputsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "forwardsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "outputsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingrawm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingrawm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingraw",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingrawp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingrawp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingmanglem11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -161,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingmanglem10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -160,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingmangle",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -150,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingmanglep10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingmanglep11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -139,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsecuritym11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 39,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsecuritym10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 40,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsecurity",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 50,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsecurityp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 60,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsecurityp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 61,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingdstnatm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -111,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingdstnatm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingdstnat",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -100,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingdstnatp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "preroutingdstnatp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -89,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsrcnatm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 89,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsrcnatm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsrcnat",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 100,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsrcnatp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "postroutingsrcnatp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 111,
+        "policy": "accept"
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "inputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "inputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "inputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "inputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "inputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "outputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "outputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "outputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "outputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "x",
+        "name": "outputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "ingressfilterm11",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "ingress",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "ingressfilterm10",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "ingress",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "ingressfilter",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "ingress",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "ingressfilterp10",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "ingress",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "ingressfilterp11",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "ingress",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "egressfilterm11",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "egress",
+        "prio": -11,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "egressfilterm10",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "egress",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "egressfilter",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "egress",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "egressfilterp10",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "egress",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "egressfilterp11",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "egress",
+        "prio": 11,
+        "policy": "accept"
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -211,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -210,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -200,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -190,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -189,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "inputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -211,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "inputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -210,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "inputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -200,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "inputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -190,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "inputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -189,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "forwardfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -211,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "forwardfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -210,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "forwardfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -200,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "forwardfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -190,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "forwardfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": -189,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -211,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -210,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -200,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -190,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": -189,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingfilterm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -211,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingfilterm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -210,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingfilter",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -200,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingfilterp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -190,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingfilterp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -189,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingdstnatm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -311,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingdstnatm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingdstnat",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingdstnatp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "preroutingdstnatp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputoutm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 89,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputoutm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputout",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 100,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputoutp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "outputoutp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 111,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingsrcnatm11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 289,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingsrcnatm10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingsrcnat",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 300,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingsrcnatp10",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 310,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "x",
+        "name": "postroutingsrcnatp11",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 311,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0022prio_dummy_1.json-nft b/tests/shell/testcases/chains/dumps/0022prio_dummy_1.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0022prio_dummy_1.nft b/tests/shell/testcases/chains/dumps/0022prio_dummy_1.nft
new file mode 100644 (file)
index 0000000..5d4d2ca
--- /dev/null
@@ -0,0 +1,2 @@
+table ip x {
+}
diff --git a/tests/shell/testcases/chains/dumps/0023prio_inet_srcnat_1.json-nft b/tests/shell/testcases/chains/dumps/0023prio_inet_srcnat_1.json-nft
new file mode 100644 (file)
index 0000000..72e0d43
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0023prio_inet_srcnat_1.nft b/tests/shell/testcases/chains/dumps/0023prio_inet_srcnat_1.nft
new file mode 100644 (file)
index 0000000..46912ea
--- /dev/null
@@ -0,0 +1,6 @@
+table ip x {
+}
+table ip6 x {
+}
+table inet x {
+}
diff --git a/tests/shell/testcases/chains/dumps/0024prio_inet_dstnat_1.json-nft b/tests/shell/testcases/chains/dumps/0024prio_inet_dstnat_1.json-nft
new file mode 100644 (file)
index 0000000..72e0d43
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0024prio_inet_dstnat_1.nft b/tests/shell/testcases/chains/dumps/0024prio_inet_dstnat_1.nft
new file mode 100644 (file)
index 0000000..46912ea
--- /dev/null
@@ -0,0 +1,6 @@
+table ip x {
+}
+table ip6 x {
+}
+table inet x {
+}
diff --git a/tests/shell/testcases/chains/dumps/0025prio_arp_1.json-nft b/tests/shell/testcases/chains/dumps/0025prio_arp_1.json-nft
new file mode 100644 (file)
index 0000000..17410e3
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0025prio_arp_1.nft b/tests/shell/testcases/chains/dumps/0025prio_arp_1.nft
new file mode 100644 (file)
index 0000000..7483cda
--- /dev/null
@@ -0,0 +1,2 @@
+table arp x {
+}
diff --git a/tests/shell/testcases/chains/dumps/0026prio_netdev_1.json-nft b/tests/shell/testcases/chains/dumps/0026prio_netdev_1.json-nft
new file mode 100644 (file)
index 0000000..7d78bd6
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0026prio_netdev_1.nft b/tests/shell/testcases/chains/dumps/0026prio_netdev_1.nft
new file mode 100644 (file)
index 0000000..aa571e0
--- /dev/null
@@ -0,0 +1,2 @@
+table netdev x {
+}
diff --git a/tests/shell/testcases/chains/dumps/0027prio_bridge_dstnat_1.json-nft b/tests/shell/testcases/chains/dumps/0027prio_bridge_dstnat_1.json-nft
new file mode 100644 (file)
index 0000000..af6ff0a
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0027prio_bridge_dstnat_1.nft b/tests/shell/testcases/chains/dumps/0027prio_bridge_dstnat_1.nft
new file mode 100644 (file)
index 0000000..d17be81
--- /dev/null
@@ -0,0 +1,2 @@
+table bridge x {
+}
diff --git a/tests/shell/testcases/chains/dumps/0028prio_bridge_out_1.json-nft b/tests/shell/testcases/chains/dumps/0028prio_bridge_out_1.json-nft
new file mode 100644 (file)
index 0000000..af6ff0a
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0028prio_bridge_out_1.nft b/tests/shell/testcases/chains/dumps/0028prio_bridge_out_1.nft
new file mode 100644 (file)
index 0000000..d17be81
--- /dev/null
@@ -0,0 +1,2 @@
+table bridge x {
+}
diff --git a/tests/shell/testcases/chains/dumps/0029prio_bridge_srcnat_1.json-nft b/tests/shell/testcases/chains/dumps/0029prio_bridge_srcnat_1.json-nft
new file mode 100644 (file)
index 0000000..af6ff0a
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0029prio_bridge_srcnat_1.nft b/tests/shell/testcases/chains/dumps/0029prio_bridge_srcnat_1.nft
new file mode 100644 (file)
index 0000000..d17be81
--- /dev/null
@@ -0,0 +1,2 @@
+table bridge x {
+}
diff --git a/tests/shell/testcases/chains/dumps/0030create_0.json-nft b/tests/shell/testcases/chains/dumps/0030create_0.json-nft
new file mode 100644 (file)
index 0000000..b6088c8
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0031priority_variable_0.json-nft b/tests/shell/testcases/chains/dumps/0031priority_variable_0.json-nft
new file mode 100644 (file)
index 0000000..9572eda
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "global",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "global",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0032priority_variable_0.json-nft b/tests/shell/testcases/chains/dumps/0032priority_variable_0.json-nft
new file mode 100644 (file)
index 0000000..3044a66
--- /dev/null
@@ -0,0 +1,54 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "global",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "global",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "global",
+        "name": "forward",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -100,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "global",
+        "name": "postrouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": -10,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0033priority_variable_1.json-nft b/tests/shell/testcases/chains/dumps/0033priority_variable_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0033priority_variable_1.nft b/tests/shell/testcases/chains/dumps/0033priority_variable_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/0034priority_variable_1.json-nft b/tests/shell/testcases/chains/dumps/0034priority_variable_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0034priority_variable_1.nft b/tests/shell/testcases/chains/dumps/0034priority_variable_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/0035policy_variable_0.json-nft b/tests/shell/testcases/chains/dumps/0035policy_variable_0.json-nft
new file mode 100644 (file)
index 0000000..9572eda
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "global",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "global",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0036policy_variable_0.json-nft b/tests/shell/testcases/chains/dumps/0036policy_variable_0.json-nft
new file mode 100644 (file)
index 0000000..fc68846
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "global",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "global",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "drop"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0037policy_variable_1.json-nft b/tests/shell/testcases/chains/dumps/0037policy_variable_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0037policy_variable_1.nft b/tests/shell/testcases/chains/dumps/0037policy_variable_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/0038policy_variable_1.json-nft b/tests/shell/testcases/chains/dumps/0038policy_variable_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0038policy_variable_1.nft b/tests/shell/testcases/chains/dumps/0038policy_variable_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/0039negative_priority_0.json-nft b/tests/shell/testcases/chains/dumps/0039negative_priority_0.json-nft
new file mode 100644 (file)
index 0000000..94218a8
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -30,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0039negative_priority_0.nft b/tests/shell/testcases/chains/dumps/0039negative_priority_0.nft
new file mode 100644 (file)
index 0000000..20f8272
--- /dev/null
@@ -0,0 +1,5 @@
+table ip t {
+       chain c {
+               type filter hook input priority -30; policy accept;
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/0042chain_variable_0.json-nft b/tests/shell/testcases/chains/dumps/0042chain_variable_0.json-nft
new file mode 100644 (file)
index 0000000..4059e85
--- /dev/null
@@ -0,0 +1,90 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "filter1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "filter1",
+        "name": "Main_Ingress1",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "ingress",
+        "prio": -500,
+        "policy": "accept"
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "filter2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "filter2",
+        "name": "Main_Ingress2",
+        "handle": 0,
+        "dev": [
+          "d23456789012345",
+          "lo"
+        ],
+        "type": "filter",
+        "hook": "ingress",
+        "prio": -500,
+        "policy": "accept"
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "filter3",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "filter3",
+        "name": "Main_Ingress3",
+        "handle": 0,
+        "dev": [
+          "d23456789012345",
+          "lo"
+        ],
+        "type": "filter",
+        "hook": "ingress",
+        "prio": -500,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "filter3",
+        "name": "Main_Egress3",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "egress",
+        "prio": -500,
+        "policy": "accept"
+      }
+    }
+  ]
+}
index 12931aadb39fa197fb0695987747e8718fb9b638..84a908d33dee1dbee1760f56b02515f8556eead6 100644 (file)
@@ -5,11 +5,15 @@ table netdev filter1 {
 }
 table netdev filter2 {
        chain Main_Ingress2 {
-               type filter hook ingress devices = { dummy0, lo } priority -500; policy accept;
+               type filter hook ingress devices = { d23456789012345, lo } priority -500; policy accept;
        }
 }
 table netdev filter3 {
        chain Main_Ingress3 {
-               type filter hook ingress devices = { dummy0, lo } priority -500; policy accept;
+               type filter hook ingress devices = { d23456789012345, lo } priority -500; policy accept;
+       }
+
+       chain Main_Egress3 {
+               type filter hook egress device "lo" priority -500; policy accept;
        }
 }
diff --git a/tests/shell/testcases/chains/dumps/0043chain_ingress_0.json-nft b/tests/shell/testcases/chains/dumps/0043chain_ingress_0.json-nft
new file mode 100644 (file)
index 0000000..6753658
--- /dev/null
@@ -0,0 +1,55 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "ingress",
+        "handle": 0,
+        "dev": "lo",
+        "type": "filter",
+        "hook": "ingress",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "forward",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
similarity index 72%
rename from tests/shell/testcases/chains/dumps/0043chain_ingress.nft
rename to tests/shell/testcases/chains/dumps/0043chain_ingress_0.nft
index 74670423fc845381ac3c48c3b3a580fd04dfb444..8483b265c1a4e830ec149583c0ad4bfce844692a 100644 (file)
@@ -1,10 +1,12 @@
 table inet filter {
        chain ingress {
-               type filter hook ingress device \"lo\" priority filter; policy accept;
+               type filter hook ingress device "lo" priority filter; policy accept;
        }
+
        chain input {
                type filter hook input priority filter; policy accept;
        }
+
        chain forward {
                type filter hook forward priority filter; policy accept;
        }
diff --git a/tests/shell/testcases/chains/dumps/0044chain_destroy_0.json-nft b/tests/shell/testcases/chains/dumps/0044chain_destroy_0.json-nft
new file mode 100644 (file)
index 0000000..e0e56fe
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/0044chain_destroy_0.nft b/tests/shell/testcases/chains/dumps/0044chain_destroy_0.nft
new file mode 100644 (file)
index 0000000..985768b
--- /dev/null
@@ -0,0 +1,2 @@
+table ip t {
+}
diff --git a/tests/shell/testcases/chains/dumps/jump_to_base_chain.nodump b/tests/shell/testcases/chains/dumps/jump_to_base_chain.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_0.json-nft b/tests/shell/testcases/chains/dumps/netdev_chain_0.json-nft
new file mode 100644 (file)
index 0000000..7d78bd6
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_0.nft b/tests/shell/testcases/chains/dumps/netdev_chain_0.nft
new file mode 100644 (file)
index 0000000..aa571e0
--- /dev/null
@@ -0,0 +1,2 @@
+table netdev x {
+}
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_autoremove.json-nft b/tests/shell/testcases/chains/dumps/netdev_chain_autoremove.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_autoremove.nft b/tests/shell/testcases/chains/dumps/netdev_chain_autoremove.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_dev_addremove.nodump b/tests/shell/testcases/chains/dumps/netdev_chain_dev_addremove.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_dev_gone.nodump b/tests/shell/testcases/chains/dumps/netdev_chain_dev_gone.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.json-nft b/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.json-nft
new file mode 100644 (file)
index 0000000..9151d42
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "test",
+        "handle": 0,
+        "flags": "dormant"
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "test",
+        "name": "ingress",
+        "handle": 0,
+        "dev": "dummy1",
+        "type": "filter",
+        "hook": "ingress",
+        "prio": 0,
+        "policy": "drop"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.nft b/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.nft
new file mode 100644 (file)
index 0000000..aad7cb6
--- /dev/null
@@ -0,0 +1,7 @@
+table netdev test {
+       flags dormant
+
+       chain ingress {
+               type filter hook ingress device "dummy1" priority filter; policy drop;
+       }
+}
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_multidev_gone.nodump b/tests/shell/testcases/chains/dumps/netdev_chain_multidev_gone.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/netdev_multidev_netns_gone.nodump b/tests/shell/testcases/chains/dumps/netdev_multidev_netns_gone.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/dumps/netdev_netns_gone.nodump b/tests/shell/testcases/chains/dumps/netdev_netns_gone.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/chains/jump_to_base_chain b/tests/shell/testcases/chains/jump_to_base_chain
new file mode 100755 (executable)
index 0000000..d71da4c
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+$NFT -f - <<EOF
+table t {
+       chain i {
+               type filter hook input priority 0
+       }
+
+       chain o {
+               type filter hook output priority 0
+               jump c
+       }
+
+       chain c {
+               jump i
+       }
+}
+EOF
+
+if [ $? -eq 0 ];then
+       echo "E: Accepted jump to a base chain"
+       exit 1
+fi
+
+exit 0
diff --git a/tests/shell/testcases/chains/netdev_chain_0 b/tests/shell/testcases/chains/netdev_chain_0
new file mode 100755 (executable)
index 0000000..f2eae6a
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netdev_chain_without_device)
+
+set -e
+
+iface_cleanup() {
+       ip link del d0 &>/dev/null || :
+       ip link del d1 &>/dev/null || :
+       ip link del d2 &>/dev/null || :
+}
+trap 'iface_cleanup' EXIT
+iface_cleanup
+
+ip link add d0 type dummy
+ip link add d1 type dummy
+ip link add d2 type dummy
+
+RULESET="table netdev x {
+       chain y {
+               type filter hook ingress priority 0; policy accept;
+       }
+}"
+
+$NFT -f - <<< "$RULESET"
+
+$NFT add chain netdev x y '{ devices = { d0 }; }'
+$NFT add chain netdev x y '{ devices = { d1, d2, lo }; }'
+$NFT delete chain netdev x y '{ devices = { lo }; }'
+$NFT delete chain netdev x y
diff --git a/tests/shell/testcases/chains/netdev_chain_autoremove b/tests/shell/testcases/chains/netdev_chain_autoremove
new file mode 100755 (executable)
index 0000000..21f3ad2
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+set -e
+
+# Test auto-removal of chain hook on netns removal
+unshare -n bash -e -c "ip link add br0 type bridge; \
+ $NFT add table netdev test; \
+ $NFT add chain netdev test ingress { type filter hook ingress device \"br0\" priority 0\; policy drop\; } ; \
+"
diff --git a/tests/shell/testcases/chains/netdev_chain_dev_addremove b/tests/shell/testcases/chains/netdev_chain_dev_addremove
new file mode 100755 (executable)
index 0000000..43bf227
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_inet_ingress)
+
+set -e
+
+read taint < /proc/sys/kernel/tainted
+if [ "$taint" -ne 0 ]; then
+       echo "Kernel already tainted up front."
+       exit 77
+fi
+
+iface_cleanup() {
+        ip link del d0 &>/dev/null || :
+}
+trap 'iface_cleanup' EXIT
+
+load_rules()
+{
+       if [ "$NFT_TEST_HAVE_netdev_egress" != n ]; then
+               EGRESS="add chain netdev nm-mlag-dummy0 tx-snoop-source-mac { type filter hook egress devices = { dummy0 } priority filter; policy accept; }
+add rule netdev nm-mlag-dummy0 tx-snoop-source-mac update @macset-tagged { ether saddr . vlan id timeout 5s } return
+add rule netdev nm-mlag-dummy0 tx-snoop-source-mac update @macset-untagged { ether saddr timeout 5s }"
+       fi
+
+RULESET="add table netdev nm-mlag-dummy0
+add set netdev nm-mlag-dummy0 macset-tagged { typeof ether saddr . vlan id; size 65535; flags dynamic,timeout; }
+add set netdev nm-mlag-dummy0 macset-untagged { typeof ether saddr; size 65535; flags dynamic,timeout; }
+$EGRESS
+add chain netdev nm-mlag-dummy0 rx-drop-looped-packets { type filter hook ingress devices = { dummy0 } priority filter; policy accept; }
+add rule netdev nm-mlag-dummy0 rx-drop-looped-packets ether saddr . vlan id @macset-tagged drop
+add rule netdev nm-mlag-dummy0 rx-drop-looped-packets ether type 8021q return
+add rule netdev nm-mlag-dummy0 rx-drop-looped-packets ether saddr @macset-untagged drop"
+
+       $NFT -f - <<< $RULESET
+}
+
+for i in $(seq 1 500);do
+       ip link add dummy0 type dummy
+       load_rules
+
+       # zap ruleset and down device at same time
+       $NFT flush ruleset &
+       ip link del dummy0 &
+       wait
+
+       read taint < /proc/sys/kernel/tainted
+       if [ "$taint" -ne 0 ]; then
+               exit 1
+       fi
+done
+
+exit 0
diff --git a/tests/shell/testcases/chains/netdev_chain_dev_gone b/tests/shell/testcases/chains/netdev_chain_dev_gone
new file mode 100755 (executable)
index 0000000..99933a3
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_inet_ingress)
+
+set -e
+
+iface_cleanup() {
+        ip link del d0 &>/dev/null || :
+}
+trap 'iface_cleanup' EXIT
+
+ip link add d0 type dummy
+
+load_ruleset() {
+       family=$1
+
+       # Test auto-removal of chain hook on device removal
+       RULESET="table $family x {
+       chain x {}
+       chain w {
+               ip daddr 8.7.6.0/24 jump x
+       }
+       chain y {
+               type filter hook ingress device \"d0\" priority 0;
+               ip saddr { 1.2.3.4, 2.3.4.5 } counter
+               ip daddr vmap { 5.4.3.0/24 : jump w, 8.9.0.0/24 : jump x }
+       }
+}"
+       $NFT -c -f - <<< $RULESET
+       $NFT -f - <<< $RULESET
+}
+
+load_ruleset "inet"
+load_ruleset "netdev"
diff --git a/tests/shell/testcases/chains/netdev_chain_dormant_autoremove b/tests/shell/testcases/chains/netdev_chain_dormant_autoremove
new file mode 100755 (executable)
index 0000000..8455f31
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netdev_chain_multidevice)
+
+set -e
+
+ip link add dummy0 type dummy
+ip link add dummy1 type dummy
+$NFT add table netdev test { flags dormant\; }
+$NFT add chain netdev test ingress { type filter hook ingress devices = { "dummy0", "dummy1" } priority 0\; policy drop\; }
+ip link del dummy0
+if [ "$NFT_TEST_HAVE_ifname_based_hooks" = y ]; then
+       $NFT 'delete chain netdev test ingress { devices = { "dummy0" }; }'
+fi
diff --git a/tests/shell/testcases/chains/netdev_chain_multidev_gone b/tests/shell/testcases/chains/netdev_chain_multidev_gone
new file mode 100755 (executable)
index 0000000..e82698a
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_chain_binding)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netdev_chain_multidevice)
+
+set -e
+
+iface_cleanup() {
+        ip link del d0 &>/dev/null || :
+        ip link del d1 &>/dev/null || :
+        ip link del d2 &>/dev/null || :
+}
+trap 'iface_cleanup' EXIT
+
+ip link add d0 type dummy
+ip link add d1 type dummy
+ip link add d2 type dummy
+
+load_ruleset() {
+       family=$1
+
+       # Test auto-removal of chain hook on device removal
+       RULESET="table $family x {
+       chain x {}
+       chain w {
+               ip daddr 8.7.6.0/24 jump {
+                       ip daddr vmap { 8.7.6.3 : jump x, 8.7.6.4 : jump x }
+               }
+       }
+       chain y {
+               type filter hook ingress devices = { d0, d1, d2 } priority 0;
+               ip saddr { 1.2.3.4, 2.3.4.5 } counter
+               ip daddr vmap { 5.4.3.0/24 : jump w, 8.9.0.0/24 : jump x }
+       }
+}"
+       $NFT -c -f - <<< $RULESET
+       $NFT -f - <<< $RULESET
+}
+
+load_ruleset "inet"
+load_ruleset "netdev"
diff --git a/tests/shell/testcases/chains/netdev_move_device b/tests/shell/testcases/chains/netdev_move_device
new file mode 100755 (executable)
index 0000000..762ca59
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+set -e
+
+rnd=$(mktemp -u XXXXXXXX)
+ns1="nft1-$rnd"
+
+cleanup() {
+       ip netns del "$ns1"
+       ip link del d0 &>/dev/null || :
+}
+trap 'cleanup' EXIT
+
+RULESET="table netdev x {
+       chain x {}
+       chain w {
+               ip daddr 8.7.6.0/24 counter
+       }
+       chain y {
+               type filter hook ingress device d0 priority 0;
+               ip saddr { 1.2.3.4, 2.3.4.5 } counter
+               ip daddr vmap { 5.4.3.0/24 : jump w, 8.9.0.0/24 : jump x }
+       }
+}"
+
+ip link add d0 type dummy
+$NFT -f - <<< $RULESET
+
+ip netns add $ns1
+# move device to $ns1 triggers UNREGISTER event
+ip link set d0 netns $ns1
+
+cleanup
+$NFT delete table netdev x
+
+# a simple test that also triggers UNREGISTER event
+ip netns add $ns1
+ip -netns $ns1 link add d0 type dummy
+ip netns exec $ns1 $NFT -f - <<< $RULESET
diff --git a/tests/shell/testcases/chains/netdev_multidev_netns_gone b/tests/shell/testcases/chains/netdev_multidev_netns_gone
new file mode 100755 (executable)
index 0000000..31ab29b
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_chain_binding)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netdev_chain_multidevice)
+
+set -e
+
+rnd=$(mktemp -u XXXXXXXX)
+ns1="nft1ns-$rnd"
+
+iface_cleanup() {
+       ip netns del $ns1 &>/dev/null || :
+}
+trap 'iface_cleanup' EXIT
+
+load_ruleset() {
+       family=$1
+
+       ip netns add $ns1
+       ip -net $ns1 link add d0 type dummy
+       ip -net $ns1 link add d1 type dummy
+       ip -net $ns1 link add d2 type dummy
+
+       # Test auto-removal of chain hook on device removal
+       RULESET="table $family x {
+       chain x {}
+       chain w {
+               ip daddr 8.7.6.0/24 jump {
+                       ip daddr vmap { 8.7.6.3 : jump x, 8.7.6.4 : jump x }
+               }
+       }
+       chain y {
+               type filter hook ingress devices = { d0, d1, d2 } priority 0;
+               ip saddr { 1.2.3.4, 2.3.4.5 } counter
+               ip daddr vmap { 5.4.3.0/24 : jump w, 8.9.0.0/24 : jump x }
+       }
+}"
+       ip netns exec $ns1 $NFT -f - <<< $RULESET
+       ip netns del $ns1
+}
+
+load_ruleset "inet"
+load_ruleset "netdev"
diff --git a/tests/shell/testcases/chains/netdev_netns_gone b/tests/shell/testcases/chains/netdev_netns_gone
new file mode 100755 (executable)
index 0000000..3a92c99
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_inet_ingress)
+
+set -e
+
+rnd=$(mktemp -u XXXXXXXX)
+ns1="nft1ns-$rnd"
+
+iface_cleanup() {
+       ip netns del $ns1 &>/dev/null || :
+}
+trap 'iface_cleanup' EXIT
+
+load_ruleset() {
+       family=$1
+
+       ip netns add $ns1
+       ip -net $ns1 link add d0 type dummy
+
+       RULESET="table $family x {
+       chain x {}
+       chain w {
+               ip daddr 8.7.6.0/24 jump x
+       }
+       chain y {
+               type filter hook ingress device \"d0\" priority 0;
+               ip saddr { 1.2.3.4, 2.3.4.5 } counter
+               ip daddr vmap { 5.4.3.0/24 : jump w, 8.9.0.0/24 : jump x }
+       }
+}"
+       ip netns exec $ns1 $NFT -f - <<< $RULESET
+       ip netns del $ns1
+}
+
+load_ruleset "inet"
+load_ruleset "netdev"
diff --git a/tests/shell/testcases/comments/dumps/comments_0.json-nft b/tests/shell/testcases/comments/dumps/comments_0.json-nft
new file mode 100644 (file)
index 0000000..201abd6
--- /dev/null
@@ -0,0 +1,135 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "2.2.2.2",
+          "3.3.3.3"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmpv6",
+                  "field": "type"
+                }
+              },
+              "right": {
+                "set": [
+                  "destination-unreachable",
+                  "packet-too-big"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": {
+                "set": [
+                  1,
+                  2
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  21,
+                  2121
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
index 8e334224ac66f2039b02f9f38a1f8f724954c29c..ff35548ed8543b7df9a12bd8fe2d539c469a679a 100755 (executable)
@@ -1,7 +1,22 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_flowtable_counter)
+
 set -e
 
+ft_deldev() {
+       $NFT "delete flowtable $1 $2 { devices = { $3 }; }"
+}
+
+iface_cleanup() {
+       ip link del dummy1 &>/dev/null || :
+       if [ "$NFT_TEST_HAVE_ifname_based_hooks" = y ]; then
+               ft_deldev filter1 Main_ft1 dummy1
+               ft_deldev filter2 Main_ft2 dummy1
+       fi
+}
+trap 'iface_cleanup' EXIT
+
 ip link add name dummy1 type dummy
 
 EXPECTED="define if_main = { lo, dummy1 }
index b23ab9782909e49a1ec98deab4ddbbd88c6b46d3..56c9834f526f9fee12ff81741ba3b9367595a136 100755 (executable)
@@ -7,7 +7,6 @@ RULESET='table inet filter {
     flowtable f {
        hook ingress priority filter - 1
        devices = { lo }
-       counter
     }
 }'
 
@@ -20,7 +19,6 @@ table inet filter {
     flowtable f {
        hook ingress priority filter - 1
        devices = { lo }
-       counter
     }
 }'
 
index 6a24c4b9a140613f5bebd023843fb495b090cf7c..1ac651044d48f79e6bb313c32ff41aec9cc65b90 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_flowtable_counter)
+
 set -e
 
 RULESET='table inet filter {
diff --git a/tests/shell/testcases/flowtable/dumps/0001flowtable_0.json-nft b/tests/shell/testcases/flowtable/dumps/0001flowtable_0.json-nft
new file mode 100644 (file)
index 0000000..4d15fe3
--- /dev/null
@@ -0,0 +1,53 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "flowtable": {
+        "family": "inet",
+        "name": "f",
+        "table": "t",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 10,
+        "dev": "lo"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "flow": {
+              "op": "add",
+              "flowtable": "@f"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0002create_flowtable_0.json-nft b/tests/shell/testcases/flowtable/dumps/0002create_flowtable_0.json-nft
new file mode 100644 (file)
index 0000000..0013512
--- /dev/null
@@ -0,0 +1,29 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "flowtable": {
+        "family": "ip",
+        "name": "f",
+        "table": "t",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 10,
+        "dev": "lo"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0002create_flowtable_0.nft b/tests/shell/testcases/flowtable/dumps/0002create_flowtable_0.nft
new file mode 100644 (file)
index 0000000..aecfb2a
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       flowtable f {
+               hook ingress priority filter + 10
+               devices = { lo }
+       }
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0003add_after_flush_0.json-nft b/tests/shell/testcases/flowtable/dumps/0003add_after_flush_0.json-nft
new file mode 100644 (file)
index 0000000..04057f1
--- /dev/null
@@ -0,0 +1,29 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "flowtable": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 0,
+        "dev": "lo"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0003add_after_flush_0.nft b/tests/shell/testcases/flowtable/dumps/0003add_after_flush_0.nft
new file mode 100644 (file)
index 0000000..dd904f4
--- /dev/null
@@ -0,0 +1,6 @@
+table ip x {
+       flowtable y {
+               hook ingress priority filter
+               devices = { lo }
+       }
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0004delete_after_add_0.json-nft b/tests/shell/testcases/flowtable/dumps/0004delete_after_add_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0004delete_after_add_0.nft b/tests/shell/testcases/flowtable/dumps/0004delete_after_add_0.nft
new file mode 100644 (file)
index 0000000..5d4d2ca
--- /dev/null
@@ -0,0 +1,2 @@
+table ip x {
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0005delete_in_use_1.json-nft b/tests/shell/testcases/flowtable/dumps/0005delete_in_use_1.json-nft
new file mode 100644 (file)
index 0000000..302502d
--- /dev/null
@@ -0,0 +1,53 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "flowtable": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 0,
+        "dev": "lo"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "x",
+        "handle": 0,
+        "expr": [
+          {
+            "flow": {
+              "op": "add",
+              "flowtable": "@y"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0005delete_in_use_1.nft b/tests/shell/testcases/flowtable/dumps/0005delete_in_use_1.nft
new file mode 100644 (file)
index 0000000..c1d79e7
--- /dev/null
@@ -0,0 +1,10 @@
+table ip x {
+       flowtable y {
+               hook ingress priority filter
+               devices = { lo }
+       }
+
+       chain x {
+               flow add @y
+       }
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0006segfault_0.json-nft b/tests/shell/testcases/flowtable/dumps/0006segfault_0.json-nft
new file mode 100644 (file)
index 0000000..e0e56fe
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0006segfault_0.nft b/tests/shell/testcases/flowtable/dumps/0006segfault_0.nft
new file mode 100644 (file)
index 0000000..985768b
--- /dev/null
@@ -0,0 +1,2 @@
+table ip t {
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0007prio_0.json-nft b/tests/shell/testcases/flowtable/dumps/0007prio_0.json-nft
new file mode 100644 (file)
index 0000000..e0e56fe
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0007prio_0.nft b/tests/shell/testcases/flowtable/dumps/0007prio_0.nft
new file mode 100644 (file)
index 0000000..985768b
--- /dev/null
@@ -0,0 +1,2 @@
+table ip t {
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0008prio_1.json-nft b/tests/shell/testcases/flowtable/dumps/0008prio_1.json-nft
new file mode 100644 (file)
index 0000000..e0e56fe
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0008prio_1.nft b/tests/shell/testcases/flowtable/dumps/0008prio_1.nft
new file mode 100644 (file)
index 0000000..985768b
--- /dev/null
@@ -0,0 +1,2 @@
+table ip t {
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0009deleteafterflush_0.json-nft b/tests/shell/testcases/flowtable/dumps/0009deleteafterflush_0.json-nft
new file mode 100644 (file)
index 0000000..b6088c8
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0009deleteafterflush_0.nft b/tests/shell/testcases/flowtable/dumps/0009deleteafterflush_0.nft
new file mode 100644 (file)
index 0000000..8e818d2
--- /dev/null
@@ -0,0 +1,4 @@
+table ip x {
+       chain y {
+       }
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0010delete_handle_0.json-nft b/tests/shell/testcases/flowtable/dumps/0010delete_handle_0.json-nft
new file mode 100644 (file)
index 0000000..10372b0
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0010delete_handle_0.nft b/tests/shell/testcases/flowtable/dumps/0010delete_handle_0.nft
new file mode 100644 (file)
index 0000000..17838bd
--- /dev/null
@@ -0,0 +1,2 @@
+table inet t {
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0011deleteafterflush_0.json-nft b/tests/shell/testcases/flowtable/dumps/0011deleteafterflush_0.json-nft
new file mode 100644 (file)
index 0000000..b6088c8
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0011deleteafterflush_0.nft b/tests/shell/testcases/flowtable/dumps/0011deleteafterflush_0.nft
new file mode 100644 (file)
index 0000000..8e818d2
--- /dev/null
@@ -0,0 +1,4 @@
+table ip x {
+       chain y {
+       }
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.json-nft b/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.json-nft
new file mode 100644 (file)
index 0000000..10f1df9
--- /dev/null
@@ -0,0 +1,47 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter1",
+        "handle": 0
+      }
+    },
+    {
+      "flowtable": {
+        "family": "ip",
+        "name": "Main_ft1",
+        "table": "filter1",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 0,
+        "dev": "lo"
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter2",
+        "handle": 0
+      }
+    },
+    {
+      "flowtable": {
+        "family": "ip",
+        "name": "Main_ft2",
+        "table": "filter2",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 0,
+        "dev": "lo"
+      }
+    }
+  ]
+}
index 1cbb2f1103f03eb07b4fb0974283caa798c8e3e1..df1c51a247033aa58aaf96d841bac7783953a3ee 100644 (file)
@@ -1,14 +1,14 @@
 table ip filter1 {
        flowtable Main_ft1 {
                hook ingress priority filter
-               devices = { dummy1, lo }
+               devices = { lo }
                counter
        }
 }
 table ip filter2 {
        flowtable Main_ft2 {
                hook ingress priority filter
-               devices = { dummy1, lo }
+               devices = { lo }
                counter
        }
 }
diff --git a/tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.json-nft b/tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.json-nft
new file mode 100644 (file)
index 0000000..85c7b32
--- /dev/null
@@ -0,0 +1,29 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "flowtable": {
+        "family": "inet",
+        "name": "f",
+        "table": "filter",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": -1,
+        "dev": "lo"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.nft b/tests/shell/testcases/flowtable/dumps/0013addafterdelete_0.nft
new file mode 100644 (file)
index 0000000..67db7d0
--- /dev/null
@@ -0,0 +1,6 @@
+table inet filter {
+       flowtable f {
+               hook ingress priority filter - 1
+               devices = { lo }
+       }
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0014addafterdelete_0.json-nft b/tests/shell/testcases/flowtable/dumps/0014addafterdelete_0.json-nft
new file mode 100644 (file)
index 0000000..471ba5b
--- /dev/null
@@ -0,0 +1,63 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "flowtable": {
+        "family": "inet",
+        "name": "f",
+        "table": "filter",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": -1,
+        "dev": "lo"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "flow": {
+              "op": "add",
+              "flowtable": "@f"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0014addafterdelete_0.nft b/tests/shell/testcases/flowtable/dumps/0014addafterdelete_0.nft
new file mode 100644 (file)
index 0000000..145aa08
--- /dev/null
@@ -0,0 +1,12 @@
+table inet filter {
+       flowtable f {
+               hook ingress priority filter - 1
+               devices = { lo }
+               counter
+       }
+
+       chain y {
+               type filter hook forward priority filter; policy accept;
+               flow add @f counter packets 0 bytes 0
+       }
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0015destroy_0.json-nft b/tests/shell/testcases/flowtable/dumps/0015destroy_0.json-nft
new file mode 100644 (file)
index 0000000..e0e56fe
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/flowtable/dumps/0015destroy_0.nft b/tests/shell/testcases/flowtable/dumps/0015destroy_0.nft
new file mode 100644 (file)
index 0000000..985768b
--- /dev/null
@@ -0,0 +1,2 @@
+table ip t {
+}
index a91cd8f00047ff0758acd63d90e398f09b76fee2..ac8355475320e84a09a3624bcedd8a30382ffc37 100755 (executable)
@@ -1,20 +1,21 @@
 #!/bin/bash
 
-set -e
-
 tmpfile1=$(mktemp -p .)
-if [ ! -w $tmpfile1 ] ; then
-        echo "Failed to create tmp file" >&2
-        exit 0
+if [ ! -w "$tmpfile1" ] ; then
+       # cwd might be readonly, mark as skip.
+       echo "Failed to create tmp file" >&2
+       exit 77
 fi
 
-tmpfile2=$(mktemp -p .)
-if [ ! -w $tmpfile2 ] ; then
-        echo "Failed to create tmp file" >&2
-        exit 0
-fi
+cleanup()
+{
+       rm -f "$tmpfile1" "$tmpfile2"
+}
 
-trap "rm -rf $tmpfile1 $tmpfile2" EXIT # cleanup if aborted
+trap cleanup EXIT
+
+set -e
+tmpfile2=$(mktemp -p .)
 
 RULESET1="add table x"
 RULESET2="include \"$tmpfile1\""
index ba722068b363a5db76f39b6cad3432e89ac0a4bd..20037a8f02794b2864d9a6413b38d8522e0a88c8 100755 (executable)
@@ -8,7 +8,7 @@ if [ ! -w $tmpfile1 ] ; then
         exit 0
 fi
 
-tmpfile3=$(echo "$tmpfile1" | cut -d'/' -f 3)
+tmpfile3="$(basename "$tmpfile1")"
 
 tmpfile2=$(mktemp)
 if [ ! -w $tmpfile2 ] ; then
@@ -24,7 +24,7 @@ RULESET2="include \"$tmpfile3\""
 echo "$RULESET1" > $tmpfile1
 echo "$RULESET2" > $tmpfile2
 
-$NFT -I /tmp -f $tmpfile2
+$NFT -I "$(dirname "$tmpfile1")" -f $tmpfile2
 if [ $? -ne 0 ] ; then
        echo "E: unable to load good ruleset" >&2
        exit 1
index 03de50b3c4992bb7308d503856d4e657991176f6..af374d661898689584bf83938d168e5777515a48 100755 (executable)
@@ -7,32 +7,32 @@
 # instead of return value of nft.
 
 
-tmpfile1=$(mktemp -p .)
-if [ ! -w $tmpfile1 ] ; then
+tmpfile1=$(mktemp)
+if [ ! -w "$tmpfile1" ] ; then
         echo "Failed to create tmp file" >&2
-        exit 0
+        exit 1
 fi
 
-tmpfile2=$(mktemp -p .)
-if [ ! -w $tmpfile2 ] ; then
+trap "rm -rf $tmpfile1 $tmpfile2 $tmpfile3 $tmpfile4" EXIT # cleanup if aborted
+
+tmpfile2=$(mktemp)
+if [ ! -w "$tmpfile2" ] ; then
         echo "Failed to create tmp file" >&2
-        exit 0
+        exit 1
 fi
 
-tmpfile3=$(mktemp -p .)
-if [ ! -w $tmpfile3 ] ; then
+tmpfile3=$(mktemp)
+if [ ! -w "$tmpfile3" ] ; then
         echo "Failed to create tmp file" >&2
-        exit 0
+        exit 1
 fi
 
-tmpfile4=$(mktemp -p .)
-if [ ! -w $tmpfile4 ]; then
+tmpfile4=$(mktemp)
+if [ ! -w "$tmpfile4" ]; then
         echo "Failed to create tmp file" >&2
-        exit 0
+        exit 1
 fi
 
-trap "rm -rf $tmpfile1 $tmpfile2 $tmpfile3 $tmpfile4" EXIT # cleanup if aborted
-
 RULESET1="include \"$tmpfile2\""
 RULESET2="include \"$tmpfile3\""
 RULESET3="add rule x y anything everything"                    # wrong nft syntax
@@ -44,7 +44,7 @@ echo "$RULESET3" > $tmpfile2
 
 $NFT -f $tmpfile1 2> $tmpfile4
 
-var=$(awk -F: '$4==" Error"{print $1;exit;}' $tmpfile4)
+var=$(awk -F: '$4==" Error"{print $1;exit;}' "$tmpfile4")
 
 if [ $var == "$tmpfile3" ]; then
        echo "E: Test failed" >&2
index 49b6f76c6a8df84bf1a5c2b758ca5d7c2a7a46e1..1501d7191fbf4c8caec95a29e8483f8647cf4630 100755 (executable)
@@ -2,11 +2,7 @@
 
 set -e
 
-tmpfile1=$(mktemp -p .)
-if [ ! -w $tmpfile1 ] ; then
-       echo "Failed to create tmp file" >&2
-       exit 0
-fi
+tmpfile1=$(mktemp)
 
 trap "rm -rf $tmpfile1" EXIT # cleanup if aborted
 
diff --git a/tests/shell/testcases/include/dumps/0001absolute_0.json-nft b/tests/shell/testcases/include/dumps/0001absolute_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0002relative_0.json-nft b/tests/shell/testcases/include/dumps/0002relative_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0003includepath_0.json-nft b/tests/shell/testcases/include/dumps/0003includepath_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0004endlessloop_1.json-nft b/tests/shell/testcases/include/dumps/0004endlessloop_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0004endlessloop_1.nft b/tests/shell/testcases/include/dumps/0004endlessloop_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0005glob_empty_0.json-nft b/tests/shell/testcases/include/dumps/0005glob_empty_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0005glob_empty_0.nft b/tests/shell/testcases/include/dumps/0005glob_empty_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0006glob_single_0.json-nft b/tests/shell/testcases/include/dumps/0006glob_single_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0007glob_double_0.json-nft b/tests/shell/testcases/include/dumps/0007glob_double_0.json-nft
new file mode 100644 (file)
index 0000000..ea75b43
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0008glob_nofile_wildcard_0.json-nft b/tests/shell/testcases/include/dumps/0008glob_nofile_wildcard_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0008glob_nofile_wildcard_0.nft b/tests/shell/testcases/include/dumps/0008glob_nofile_wildcard_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0009glob_nofile_1.json-nft b/tests/shell/testcases/include/dumps/0009glob_nofile_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0009glob_nofile_1.nft b/tests/shell/testcases/include/dumps/0009glob_nofile_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0010glob_broken_file_1.json-nft b/tests/shell/testcases/include/dumps/0010glob_broken_file_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0010glob_broken_file_1.nft b/tests/shell/testcases/include/dumps/0010glob_broken_file_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0011glob_dependency_0.json-nft b/tests/shell/testcases/include/dumps/0011glob_dependency_0.json-nft
new file mode 100644 (file)
index 0000000..b6088c8
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0012glob_dependency_1.json-nft b/tests/shell/testcases/include/dumps/0012glob_dependency_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0012glob_dependency_1.nft b/tests/shell/testcases/include/dumps/0012glob_dependency_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0013glob_dotfile_0.json-nft b/tests/shell/testcases/include/dumps/0013glob_dotfile_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0013input_descriptors_included_files_0.json-nft b/tests/shell/testcases/include/dumps/0013input_descriptors_included_files_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0013input_descriptors_included_files_0.nft b/tests/shell/testcases/include/dumps/0013input_descriptors_included_files_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0014glob_directory_0.json-nft b/tests/shell/testcases/include/dumps/0014glob_directory_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0014glob_directory_0.nft b/tests/shell/testcases/include/dumps/0014glob_directory_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0015doubleincludepath_0.json-nft b/tests/shell/testcases/include/dumps/0015doubleincludepath_0.json-nft
new file mode 100644 (file)
index 0000000..b6088c8
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0016maxdepth_0.json-nft b/tests/shell/testcases/include/dumps/0016maxdepth_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0016maxdepth_0.nft b/tests/shell/testcases/include/dumps/0016maxdepth_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0017glob_more_than_maxdepth_1.json-nft b/tests/shell/testcases/include/dumps/0017glob_more_than_maxdepth_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0017glob_more_than_maxdepth_1.nft b/tests/shell/testcases/include/dumps/0017glob_more_than_maxdepth_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0018include_error_0.json-nft b/tests/shell/testcases/include/dumps/0018include_error_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0018include_error_0.nft b/tests/shell/testcases/include/dumps/0018include_error_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0019include_error_0.json-nft b/tests/shell/testcases/include/dumps/0019include_error_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/0019include_error_0.nft b/tests/shell/testcases/include/dumps/0019include_error_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/include/dumps/0020include_chain_0.json-nft b/tests/shell/testcases/include/dumps/0020include_chain_0.json-nft
new file mode 100644 (file)
index 0000000..e893ccf
--- /dev/null
@@ -0,0 +1,128 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input2",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "output2",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input2",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "1.2.3.4"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  22,
+                  123,
+                  443
+                ]
+              }
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "output2",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "1.2.3.4"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  22,
+                  123,
+                  443
+                ]
+              }
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/include/dumps/glob_duplicated_include.nft b/tests/shell/testcases/include/dumps/glob_duplicated_include.nft
new file mode 100644 (file)
index 0000000..8e316e9
--- /dev/null
@@ -0,0 +1,6 @@
+table inet test {
+       chain test {
+               tcp dport 22 accept
+               tcp dport 25 accept
+       }
+}
diff --git a/tests/shell/testcases/include/glob_duplicated_include b/tests/shell/testcases/include/glob_duplicated_include
new file mode 100755 (executable)
index 0000000..4507f5d
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -e
+
+trap "rm -rf $tmpdir" EXIT
+
+tmpdir=$(mktemp -d)
+mkdir -p $tmpdir/test/include
+cat > $tmpdir/test/main << EOF
+table inet test {
+        chain test {
+                include "include/*";
+        }
+}
+EOF
+echo "tcp dport 22 accept;" > $tmpdir/test/include/one
+echo "tcp dport 25 accept;" > $tmpdir/test/include/two
+
+$NFT -I $tmpdir/test/ -f $tmpdir/test/main
index 1c72d35b2dbdecff0df748fa1964f7a0147f04fe..fc4941f4da1101fc215b337961574fafe108a41e 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json)
+
 set -e
 
 $NFT flush ruleset
index 4b54527bc8399e69d5453f9b1420f28d65a1d4ce..a1e9f2634978e830beac9d23a35b14bab073d56e 100755 (executable)
@@ -1,5 +1,8 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
 set -e
 
 $NFT flush ruleset
index 0ccf94c88cc51db1ff4c584b1ddf05192f37532a..43f387a194446c1f9399fe1bb21d45437bcffbfd 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json)
+
 set -e
 
 $NFT flush ruleset
index bc451ae7eaaad86bf6a9e512f70df735e9ef549d..0f8d586f9d7c500775cf54cc72bf0e3a8f25a213 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json)
+
 set -e
 
 $NFT flush ruleset
index ae967435038f6867294065ddeeac864d3ef5282f..5c44f09337be1969ba7681bfc105b70c39c89776 100755 (executable)
@@ -1,5 +1,8 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_secmark)
+
 set -e
 
 $NFT flush ruleset
index 76d8fe1652ac0bc18e43f9ad11d5e266e116fe44..7ce859d2529f3d7ba991f79108752105c47bc5a0 100755 (executable)
@@ -1,5 +1,8 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_comment)
+
 set -e
 
 $NFT flush ruleset
diff --git a/tests/shell/testcases/json/dumps/0001set_statements_0.json-nft b/tests/shell/testcases/json/dumps/0001set_statements_0.json-nft
new file mode 100644 (file)
index 0000000..ecc7ead
--- /dev/null
@@ -0,0 +1,98 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "testt",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "testt",
+        "name": "testc",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "ssh_meter",
+        "table": "testt",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "testt",
+        "chain": "testc",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "set": "@ssh_meter",
+              "stmt": [
+                {
+                  "limit": {
+                    "rate": 10,
+                    "burst": 5,
+                    "per": "second"
+                  }
+                }
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/json/dumps/0002table_map_0.json-nft b/tests/shell/testcases/json/dumps/0002table_map_0.json-nft
new file mode 100644 (file)
index 0000000..78e3c8a
--- /dev/null
@@ -0,0 +1,33 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "m",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "mark",
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/json/dumps/0003json_schema_version_0.json-nft b/tests/shell/testcases/json/dumps/0003json_schema_version_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/json/dumps/0004json_schema_version_1.json-nft b/tests/shell/testcases/json/dumps/0004json_schema_version_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/json/dumps/0005secmark_objref_0.json-nft b/tests/shell/testcases/json/dumps/0005secmark_objref_0.json-nft
new file mode 100644 (file)
index 0000000..3783c6b
--- /dev/null
@@ -0,0 +1,233 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -225,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "z",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 225,
+        "policy": "accept"
+      }
+    },
+    {
+      "secmark": {
+        "family": "inet",
+        "name": "ssh_server",
+        "table": "x",
+        "handle": 0,
+        "context": "system_u:object_r:ssh_server_packet_t:s0"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 2222
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          },
+          {
+            "secmark": "ssh_server"
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "ct": {
+                  "key": "secmark"
+                }
+              },
+              "value": {
+                "meta": {
+                  "key": "secmark"
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "established",
+                "related"
+              ]
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "secmark"
+                }
+              },
+              "value": {
+                "ct": {
+                  "key": "secmark"
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "z",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "ct": {
+                  "key": "secmark"
+                }
+              },
+              "value": {
+                "meta": {
+                  "key": "secmark"
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "z",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "established",
+                "related"
+              ]
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "secmark"
+                }
+              },
+              "value": {
+                "ct": {
+                  "key": "secmark"
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/json/dumps/0006obj_comment_0.json-nft b/tests/shell/testcases/json/dumps/0006obj_comment_0.json-nft
new file mode 100644 (file)
index 0000000..208e13a
--- /dev/null
@@ -0,0 +1,29 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "counter": {
+        "family": "inet",
+        "name": "mycounter",
+        "table": "t",
+        "handle": 0,
+        "comment": "my comment in counter",
+        "packets": 0,
+        "bytes": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/json/dumps/netdev.json-nft b/tests/shell/testcases/json/dumps/netdev.json-nft
new file mode 100644 (file)
index 0000000..e0d2bfb
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "test_table",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/json/dumps/netdev.nft b/tests/shell/testcases/json/dumps/netdev.nft
new file mode 100644 (file)
index 0000000..3c568ed
--- /dev/null
@@ -0,0 +1,2 @@
+table netdev test_table {
+}
index a16a4f5e030e1d1950ea529b46459159aec7c380..23776c35d97d6650a9b1c342bafc174ea5579ea6 100755 (executable)
@@ -1,12 +1,14 @@
 #!/bin/bash
 
-ip link add d0 type dummy || {
-        echo "Skipping, no dummy interface available"
-        exit 0
+set -e
+
+iface_cleanup() {
+       ip link del d0 &>/dev/null || :
 }
-trap "ip link del d0" EXIT
+trap 'iface_cleanup' EXIT
+iface_cleanup
 
-set -e
+ip link add d0 type dummy
 
 $NFT flush ruleset
 $NFT add table inet test
@@ -16,4 +18,13 @@ $NFT flush ruleset
 
 RULESET='{"nftables":[{"flush":{"ruleset":null}},{"add":{"table":{"family":"netdev","name":"test_table"}}},{"add":{"chain":{"family":"netdev","table":"test_table","name":"test_chain","type":"filter","hook":"ingress","prio":0,"dev":"d0","policy":"accept"}}}]}'
 
-$NFT -j -f - <<< $RULESET
+if [ "$NFT_TEST_HAVE_json" != n ]; then
+       $NFT -j -f - <<< $RULESET
+fi
+
+if [ "$NFT_TEST_HAVE_json" = n ]; then
+       echo "Test partially skipped due to missing JSON support."
+       exit 77
+fi
+
+$NFT delete chain netdev test_table test_chain
diff --git a/tests/shell/testcases/json/single_flag b/tests/shell/testcases/json/single_flag
new file mode 100755 (executable)
index 0000000..43ae452
--- /dev/null
@@ -0,0 +1,190 @@
+#!/bin/bash
+#
+# Test various "flags" properties in JSON syntax:
+# - single item arrays are abbreviated as non-array in output
+# - both non-array and single item array accepted in input
+# - single and multiple item values are correctly printed in output and
+#   recognized in input (checked against standard syntax input/output)
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_table_flag_persist)
+
+set -e
+
+json_sanitize() {
+       sed -e 's/{"metainfo": {[^}]*}}, //' \
+           -e 's/\("handle":\) [0-9]*/\1 0/g'
+}
+back_n_forth() { # (std, json)
+       $NFT flush ruleset
+       $NFT -f - <<< "$1"
+       diff --label "line ${BASH_LINENO[0]}: JSON output" \
+            --label "line ${BASH_LINENO[0]}: JSON expect" \
+            -u <($NFT -j list ruleset | json_sanitize) <(echo "$2")
+
+       $NFT flush ruleset
+       $NFT -j -f - <<< "$2"
+       diff --label "line ${BASH_LINENO[0]}: std output" \
+            --label "line ${BASH_LINENO[0]}: std expect" \
+            -u <($NFT list ruleset) <(echo "$1")
+}
+json_equiv() { # (json_in, json_out)
+       $NFT flush ruleset
+       $NFT -j -f - <<< "$1"
+       diff --label "line ${BASH_LINENO[0]}: JSON equiv output" \
+            --label "line ${BASH_LINENO[0]}: JSON equiv expect" \
+            -u <($NFT -j list ruleset | json_sanitize) <(echo "$2")
+}
+
+#
+# test table flags
+#
+
+STD_TABLE_1="table ip t {
+       flags dormant
+}"
+JSON_TABLE_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0, "flags": "dormant"}}]}'
+JSON_TABLE_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_TABLE_1")
+
+STD_TABLE_2=$(sed 's/\(flags dormant\)/\1,persist/' <<< "$STD_TABLE_1")
+JSON_TABLE_2=$(sed 's/\("flags":\) \("dormant"\)/\1 [\2, "persist"]/' <<< "$JSON_TABLE_1")
+
+back_n_forth "$STD_TABLE_1" "$JSON_TABLE_1"
+json_equiv "$JSON_TABLE_1_EQUIV" "$JSON_TABLE_1"
+back_n_forth "$STD_TABLE_2" "$JSON_TABLE_2"
+
+#
+# test set flags
+#
+
+STD_SET_1="table ip t {
+       set s {
+               type inet_proto
+               flags interval
+       }
+}"
+JSON_SET_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"set": {"family": "ip", "name": "s", "table": "t", "type": "inet_proto", "handle": 0, "flags": "interval"}}]}'
+JSON_SET_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_SET_1")
+
+STD_SET_2=$(sed 's/\(flags interval\)/\1,timeout/' <<< "$STD_SET_1")
+JSON_SET_2=$(sed 's/\("flags":\) \("interval"\)/\1 [\2, "timeout"]/' <<< "$JSON_SET_1")
+
+back_n_forth "$STD_SET_1" "$JSON_SET_1"
+json_equiv "$JSON_SET_1_EQUIV" "$JSON_SET_1"
+back_n_forth "$STD_SET_2" "$JSON_SET_2"
+
+#
+# test fib expression flags
+#
+
+STD_FIB_1="table ip t {
+       chain c {
+               fib saddr oif exists
+       }
+}"
+JSON_FIB_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"match": {"op": "==", "left": {"fib": {"result": "oif", "flags": "saddr"}}, "right": true}}]}}]}'
+JSON_FIB_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_FIB_1")
+
+STD_FIB_2=$(sed 's/\(fib saddr\)/\1 . iif/' <<< "$STD_FIB_1")
+JSON_FIB_2=$(sed 's/\("flags":\) \("saddr"\)/\1 [\2, "iif"]/' <<< "$JSON_FIB_1")
+
+back_n_forth "$STD_FIB_1" "$JSON_FIB_1"
+json_equiv "$JSON_FIB_1_EQUIV" "$JSON_FIB_1"
+back_n_forth "$STD_FIB_2" "$JSON_FIB_2"
+
+#
+# test nat statement flags
+#
+
+STD_NAT_1="table ip t {
+       chain c {
+               dnat to 192.168.0.0/24 persistent
+       }
+}"
+JSON_NAT_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"dnat": {"addr": {"prefix": {"addr": "192.168.0.0", "len": 24}}, "flags": "persistent"}}]}}]}'
+JSON_NAT_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_NAT_1")
+
+STD_NAT_2=$(sed 's/\(persistent\)/random,\1/' <<< "$STD_NAT_1")
+JSON_NAT_2=$(sed 's/\("flags":\) \("persistent"\)/\1 ["random", \2]/' <<< "$JSON_NAT_1")
+
+back_n_forth "$STD_NAT_1" "$JSON_NAT_1"
+json_equiv "$JSON_NAT_1_EQUIV" "$JSON_NAT_1"
+back_n_forth "$STD_NAT_2" "$JSON_NAT_2"
+
+#
+# test log statement flags
+#
+
+STD_LOG_1="table ip t {
+       chain c {
+               log flags tcp sequence
+       }
+}"
+JSON_LOG_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"log": {"flags": "tcp sequence"}}]}}]}'
+JSON_LOG_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_LOG_1")
+
+STD_LOG_2=$(sed 's/\(tcp sequence\)/\1,options/' <<< "$STD_LOG_1")
+JSON_LOG_2=$(sed 's/\("flags":\) \("tcp sequence"\)/\1 [\2, "tcp options"]/' <<< "$JSON_LOG_1")
+
+back_n_forth "$STD_LOG_1" "$JSON_LOG_1"
+json_equiv "$JSON_LOG_1_EQUIV" "$JSON_LOG_1"
+back_n_forth "$STD_LOG_2" "$JSON_LOG_2"
+
+#
+# test synproxy statement flags
+#
+
+STD_SYNPROXY_1="table ip t {
+       chain c {
+               synproxy sack-perm
+       }
+}"
+JSON_SYNPROXY_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"synproxy": {"flags": "sack-perm"}}]}}]}'
+JSON_SYNPROXY_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_SYNPROXY_1")
+
+STD_SYNPROXY_2=$(sed 's/\(sack-perm\)/timestamp \1/' <<< "$STD_SYNPROXY_1")
+JSON_SYNPROXY_2=$(sed 's/\("flags":\) \("sack-perm"\)/\1 ["timestamp", \2]/' <<< "$JSON_SYNPROXY_1")
+
+back_n_forth "$STD_SYNPROXY_1" "$JSON_SYNPROXY_1"
+json_equiv "$JSON_SYNPROXY_1_EQUIV" "$JSON_SYNPROXY_1"
+back_n_forth "$STD_SYNPROXY_2" "$JSON_SYNPROXY_2"
+
+#
+# test synproxy object flags
+#
+
+STD_SYNPROXY_OBJ_1="table ip t {
+       synproxy s {
+               mss 1280
+               wscale 64
+                sack-perm
+       }
+}"
+JSON_SYNPROXY_OBJ_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"synproxy": {"family": "ip", "name": "s", "table": "t", "handle": 0, "mss": 1280, "wscale": 64, "flags": "sack-perm"}}]}'
+JSON_SYNPROXY_OBJ_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_SYNPROXY_OBJ_1")
+
+STD_SYNPROXY_OBJ_2=$(sed 's/ \(sack-perm\)/timestamp \1/' <<< "$STD_SYNPROXY_OBJ_1")
+JSON_SYNPROXY_OBJ_2=$(sed 's/\("flags":\) \("sack-perm"\)/\1 ["timestamp", \2]/' <<< "$JSON_SYNPROXY_OBJ_1")
+
+back_n_forth "$STD_SYNPROXY_OBJ_1" "$JSON_SYNPROXY_OBJ_1"
+json_equiv "$JSON_SYNPROXY_OBJ_1_EQUIV" "$JSON_SYNPROXY_OBJ_1"
+back_n_forth "$STD_SYNPROXY_OBJ_2" "$JSON_SYNPROXY_OBJ_2"
+
+#
+# test queue statement flags
+#
+
+STD_QUEUE_1="table ip t {
+       chain c {
+               queue flags bypass to 1-10
+       }
+}"
+JSON_QUEUE_1='{"nftables": [{"table": {"family": "ip", "name": "t", "handle": 0}}, {"chain": {"family": "ip", "table": "t", "name": "c", "handle": 0}}, {"rule": {"family": "ip", "table": "t", "chain": "c", "handle": 0, "expr": [{"queue": {"num": {"range": [1, 10]}, "flags": "bypass"}}]}}]}'
+JSON_QUEUE_1_EQUIV=$(sed 's/\("flags":\) \([^}]*\)/\1 [\2]/' <<< "$JSON_QUEUE_1")
+
+STD_QUEUE_2=$(sed 's/\(bypass\)/\1,fanout/' <<< "$STD_QUEUE_1")
+JSON_QUEUE_2=$(sed 's/\("flags":\) \("bypass"\)/\1 [\2, "fanout"]/' <<< "$JSON_QUEUE_1")
+
+back_n_forth "$STD_QUEUE_1" "$JSON_QUEUE_1"
+json_equiv "$JSON_QUEUE_1_EQUIV" "$JSON_QUEUE_1"
+back_n_forth "$STD_QUEUE_2" "$JSON_QUEUE_2"
index c81b94e20f65bdb784851df53320137647d6fee7..c78ada947a944d5aa961fa4bbdf2168ed488a4ec 100755 (executable)
@@ -1,47 +1,23 @@
 #!/bin/bash
 
-# list table with all objects and chains
-
-EXPECTED="table ip test {
-       quota https-quota {
-               25 mbytes
-       }
-
-       ct helper cthelp {
-               type \"sip\" protocol tcp
-               l3proto ip
-       }
-
-       ct timeout cttime {
-               protocol udp
-               l3proto ip
-               policy = { unreplied : 15s, replied : 12s }
-       }
-
-       ct expectation ctexpect {
-               protocol tcp
-               dport 5432
-               timeout 1h
-               size 12
-               l3proto ip
-       }
-
-       chain input {
-       }
-}"
-
 set -e
 
 $NFT add table test
 $NFT add chain test input
 $NFT add quota test https-quota 25 mbytes
 $NFT add ct helper test cthelp { type \"sip\" protocol tcp \; }
-$NFT add ct timeout test cttime { protocol udp \; policy = {replied : 12, unreplied : 15 } \; }
-$NFT add ct expectation test ctexpect { protocol tcp \; dport 5432 \; timeout 1h \; size 12 \; }
-$NFT add table test-ip
+if [ "$NFT_TEST_HAVE_cttimeout" != n ] ; then
+       $NFT add ct timeout test cttime { protocol udp \; policy = {replied : 12, unreplied : 15 } \; }
+fi
+if [ "$NFT_TEST_HAVE_ctexpect" != n ] ; then
+       $NFT add ct expectation test ctexpect { protocol tcp \; dport 5432 \; timeout 1h \; size 12 \; }
+fi
 
-GET="$($NFT list table test)"
-if [ "$EXPECTED" != "$GET" ] ; then
-       $DIFF -u <(echo "$EXPECTED") <(echo "$GET")
-       exit 1
+if [ "$NFT_TEST_HAVE_cttimeout" = n ] ; then
+       echo "Ran partial test due to NFT_TEST_HAVE_cttimeout=n (skipped)"
+       exit 77
+fi
+if [ "$NFT_TEST_HAVE_ctexpect" = n ] ; then
+       echo "Ran partial test due to NFT_TEST_HAVE_ctexpect=n (skipped)"
+       exit 77
 fi
index 47488d8ea92a46410e6cbdad6f64a4bc2b57a101..14b0c909a7eba2a84e9f515a4bf6b5eebbba1e02 100755 (executable)
@@ -1,7 +1,11 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_flowtable_no_devices)
+
 # list only the flowtable asked for with table
 
+set -e
+
 FLOWTABLES="flowtable f {
        hook ingress priority filter
        devices = { lo }
@@ -41,13 +45,19 @@ EXPECTED3="table ip filter {
        }
 }"
 
-ip link add d0 type dummy || {
-       echo "Skipping, no dummy interface available"
-       exit 0
+iface_cleanup() {
+       ip link del d0 &>/dev/null || :
 }
-trap "ip link del d0" EXIT
+ft_cleanup() {
+       if [ "$NFT_TEST_HAVE_ifname_based_hooks" = y ]; then
+               $NFT 'delete flowtable ip filter f2 { devices = { d0 }; }'
+               $NFT 'delete flowtable inet filter f2 { devices = { d0 }; }'
+       fi
+}
+trap 'iface_cleanup; ft_cleanup' EXIT
+iface_cleanup
 
-set -e
+ip link add d0 type dummy
 
 $NFT -f - <<< "$RULESET"
 
index c739ac3f29d0d2c613c1e9ac1c977452eeb392c9..98a7ce8a4be945c6dfb22cd31f2c2664402684f6 100755 (executable)
@@ -6,7 +6,14 @@ $NFT add chain ip test c
 $NFT add set ip test s { type ipv4_addr\; }
 $NFT add element ip test s { 192.168.3.4, 192.168.3.5 }
 
-if $NFT -j -t list ruleset | grep '192'
-then
-       exit 1
+if [ "$NFT_TEST_HAVE_json" != n ]; then
+       if $NFT -j -t list ruleset | grep '192\.168'
+       then
+               exit 1
+       fi
+fi
+
+if [ "$NFT_TEST_HAVE_json" = n ]; then
+    echo "Test partially skipped due to missing JSON support."
+    exit 77
 fi
diff --git a/tests/shell/testcases/listing/dumps/0001ruleset_0.json-nft b/tests/shell/testcases/listing/dumps/0001ruleset_0.json-nft
new file mode 100644 (file)
index 0000000..1bb0e1b
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0002ruleset_0.json-nft b/tests/shell/testcases/listing/dumps/0002ruleset_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0002ruleset_0.nft b/tests/shell/testcases/listing/dumps/0002ruleset_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/listing/dumps/0003table_0.json-nft b/tests/shell/testcases/listing/dumps/0003table_0.json-nft
new file mode 100644 (file)
index 0000000..1bb0e1b
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0003table_0.nft b/tests/shell/testcases/listing/dumps/0003table_0.nft
new file mode 100644 (file)
index 0000000..1c9f40c
--- /dev/null
@@ -0,0 +1,2 @@
+table ip test {
+}
diff --git a/tests/shell/testcases/listing/dumps/0004table_0.json-nft b/tests/shell/testcases/listing/dumps/0004table_0.json-nft
new file mode 100644 (file)
index 0000000..85e9b28
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test2",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0004table_0.nft b/tests/shell/testcases/listing/dumps/0004table_0.nft
new file mode 100644 (file)
index 0000000..56d035d
--- /dev/null
@@ -0,0 +1,4 @@
+table ip test {
+}
+table ip test2 {
+}
diff --git a/tests/shell/testcases/listing/dumps/0005ruleset_ip_0.json-nft b/tests/shell/testcases/listing/dumps/0005ruleset_ip_0.json-nft
new file mode 100644 (file)
index 0000000..ffd657e
--- /dev/null
@@ -0,0 +1,46 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "test",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0005ruleset_ip_0.nft b/tests/shell/testcases/listing/dumps/0005ruleset_ip_0.nft
new file mode 100644 (file)
index 0000000..c37261b
--- /dev/null
@@ -0,0 +1,10 @@
+table ip test {
+}
+table ip6 test {
+}
+table inet test {
+}
+table arp test {
+}
+table bridge test {
+}
diff --git a/tests/shell/testcases/listing/dumps/0006ruleset_ip6_0.json-nft b/tests/shell/testcases/listing/dumps/0006ruleset_ip6_0.json-nft
new file mode 100644 (file)
index 0000000..ffd657e
--- /dev/null
@@ -0,0 +1,46 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "test",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0006ruleset_ip6_0.nft b/tests/shell/testcases/listing/dumps/0006ruleset_ip6_0.nft
new file mode 100644 (file)
index 0000000..c37261b
--- /dev/null
@@ -0,0 +1,10 @@
+table ip test {
+}
+table ip6 test {
+}
+table inet test {
+}
+table arp test {
+}
+table bridge test {
+}
diff --git a/tests/shell/testcases/listing/dumps/0007ruleset_inet_0.json-nft b/tests/shell/testcases/listing/dumps/0007ruleset_inet_0.json-nft
new file mode 100644 (file)
index 0000000..ffd657e
--- /dev/null
@@ -0,0 +1,46 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "test",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0007ruleset_inet_0.nft b/tests/shell/testcases/listing/dumps/0007ruleset_inet_0.nft
new file mode 100644 (file)
index 0000000..c37261b
--- /dev/null
@@ -0,0 +1,10 @@
+table ip test {
+}
+table ip6 test {
+}
+table inet test {
+}
+table arp test {
+}
+table bridge test {
+}
diff --git a/tests/shell/testcases/listing/dumps/0008ruleset_arp_0.json-nft b/tests/shell/testcases/listing/dumps/0008ruleset_arp_0.json-nft
new file mode 100644 (file)
index 0000000..ffd657e
--- /dev/null
@@ -0,0 +1,46 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "test",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0008ruleset_arp_0.nft b/tests/shell/testcases/listing/dumps/0008ruleset_arp_0.nft
new file mode 100644 (file)
index 0000000..c37261b
--- /dev/null
@@ -0,0 +1,10 @@
+table ip test {
+}
+table ip6 test {
+}
+table inet test {
+}
+table arp test {
+}
+table bridge test {
+}
diff --git a/tests/shell/testcases/listing/dumps/0009ruleset_bridge_0.json-nft b/tests/shell/testcases/listing/dumps/0009ruleset_bridge_0.json-nft
new file mode 100644 (file)
index 0000000..ffd657e
--- /dev/null
@@ -0,0 +1,46 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "test",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0009ruleset_bridge_0.nft b/tests/shell/testcases/listing/dumps/0009ruleset_bridge_0.nft
new file mode 100644 (file)
index 0000000..c37261b
--- /dev/null
@@ -0,0 +1,10 @@
+table ip test {
+}
+table ip6 test {
+}
+table inet test {
+}
+table arp test {
+}
+table bridge test {
+}
diff --git a/tests/shell/testcases/listing/dumps/0010sets_0.json-nft b/tests/shell/testcases/listing/dumps/0010sets_0.json-nft
new file mode 100644 (file)
index 0000000..6aa99b4
--- /dev/null
@@ -0,0 +1,120 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "nat",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "ssh",
+        "table": "nat",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip6",
+        "name": "testset",
+        "table": "test",
+        "type": "ipv6_addr",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "test_arp",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "arp",
+        "name": "test_set_arp00",
+        "table": "test_arp",
+        "type": "inet_service",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "arp",
+        "name": "test_set_arp01",
+        "table": "test_arp",
+        "type": "inet_service",
+        "handle": 0,
+        "flags": "constant"
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "test_bridge",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "bridge",
+        "name": "test_set_bridge",
+        "table": "test_bridge",
+        "type": "inet_service",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "set0",
+        "table": "filter",
+        "type": "inet_service",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "set1",
+        "table": "filter",
+        "type": "inet_service",
+        "handle": 0,
+        "flags": "constant"
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "set2",
+        "table": "filter",
+        "type": "icmpv6_type",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0010sets_0.nft b/tests/shell/testcases/listing/dumps/0010sets_0.nft
new file mode 100644 (file)
index 0000000..7303c40
--- /dev/null
@@ -0,0 +1,39 @@
+table ip nat {
+       set ssh {
+               type ipv4_addr
+       }
+}
+table ip6 test {
+       set testset {
+               type ipv6_addr
+       }
+}
+table arp test_arp {
+       set test_set_arp00 {
+               type inet_service
+       }
+
+       set test_set_arp01 {
+               type inet_service
+               flags constant
+       }
+}
+table bridge test_bridge {
+       set test_set_bridge {
+               type inet_service
+       }
+}
+table inet filter {
+       set set0 {
+               type inet_service
+       }
+
+       set set1 {
+               type inet_service
+               flags constant
+       }
+
+       set set2 {
+               type icmpv6_type
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0011sets_0.json-nft b/tests/shell/testcases/listing/dumps/0011sets_0.json-nft
new file mode 100644 (file)
index 0000000..a742fa4
--- /dev/null
@@ -0,0 +1,220 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "nat",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "nat",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "nat",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  123,
+                  321
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "sport"
+                }
+              },
+              "right": {
+                "set": [
+                  123,
+                  321
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "test_arp",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "arp",
+        "table": "test_arp",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "arp",
+        "table": "test_arp",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "right": {
+                "set": [
+                  123,
+                  321
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "test_bridge",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "test_bridge",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "bridge",
+        "table": "test_bridge",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "1.1.1.1",
+                  "2.2.2.2"
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  80,
+                  443
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0011sets_0.nft b/tests/shell/testcases/listing/dumps/0011sets_0.nft
new file mode 100644 (file)
index 0000000..4d0aeaf
--- /dev/null
@@ -0,0 +1,25 @@
+table ip nat {
+       chain test {
+               tcp dport { 123, 321 }
+       }
+}
+table ip6 test {
+       chain test {
+               udp sport { 123, 321 }
+       }
+}
+table arp test_arp {
+       chain test {
+               meta mark { 0x0000007b, 0x00000141 }
+       }
+}
+table bridge test_bridge {
+       chain test {
+               ip daddr { 1.1.1.1, 2.2.2.2 }
+       }
+}
+table inet filter {
+       chain test {
+               tcp dport { 80, 443 }
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0012sets_0.json-nft b/tests/shell/testcases/listing/dumps/0012sets_0.json-nft
new file mode 100644 (file)
index 0000000..6aa99b4
--- /dev/null
@@ -0,0 +1,120 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "nat",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "ssh",
+        "table": "nat",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip6",
+        "name": "testset",
+        "table": "test",
+        "type": "ipv6_addr",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "arp",
+        "name": "test_arp",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "arp",
+        "name": "test_set_arp00",
+        "table": "test_arp",
+        "type": "inet_service",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "arp",
+        "name": "test_set_arp01",
+        "table": "test_arp",
+        "type": "inet_service",
+        "handle": 0,
+        "flags": "constant"
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "test_bridge",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "bridge",
+        "name": "test_set_bridge",
+        "table": "test_bridge",
+        "type": "inet_service",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "set0",
+        "table": "filter",
+        "type": "inet_service",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "set1",
+        "table": "filter",
+        "type": "inet_service",
+        "handle": 0,
+        "flags": "constant"
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "set2",
+        "table": "filter",
+        "type": "icmpv6_type",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0012sets_0.nft b/tests/shell/testcases/listing/dumps/0012sets_0.nft
new file mode 100644 (file)
index 0000000..7303c40
--- /dev/null
@@ -0,0 +1,39 @@
+table ip nat {
+       set ssh {
+               type ipv4_addr
+       }
+}
+table ip6 test {
+       set testset {
+               type ipv6_addr
+       }
+}
+table arp test_arp {
+       set test_set_arp00 {
+               type inet_service
+       }
+
+       set test_set_arp01 {
+               type inet_service
+               flags constant
+       }
+}
+table bridge test_bridge {
+       set test_set_bridge {
+               type inet_service
+       }
+}
+table inet filter {
+       set set0 {
+               type inet_service
+       }
+
+       set set1 {
+               type inet_service
+               flags constant
+       }
+
+       set set2 {
+               type icmpv6_type
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0013objects_0.json-nft b/tests/shell/testcases/listing/dumps/0013objects_0.json-nft
new file mode 100644 (file)
index 0000000..830aad8
--- /dev/null
@@ -0,0 +1,75 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "input",
+        "handle": 0
+      }
+    },
+    {
+      "quota": {
+        "family": "ip",
+        "name": "https-quota",
+        "table": "test",
+        "handle": 0,
+        "bytes": 26214400,
+        "used": 0,
+        "inv": false
+      }
+    },
+    {
+      "ct helper": {
+        "family": "ip",
+        "name": "cthelp",
+        "table": "test",
+        "handle": 0,
+        "type": "sip",
+        "protocol": "tcp",
+        "l3proto": "ip"
+      }
+    },
+    {
+      "ct timeout": {
+        "family": "ip",
+        "name": "cttime",
+        "table": "test",
+        "handle": 0,
+        "protocol": "udp",
+        "l3proto": "ip",
+        "policy": {
+          "unreplied": 15,
+          "replied": 12
+        }
+      }
+    },
+    {
+      "ct expectation": {
+        "family": "ip",
+        "name": "ctexpect",
+        "table": "test",
+        "handle": 0,
+        "protocol": "tcp",
+        "dport": 5432,
+        "timeout": 3600000,
+        "size": 12,
+        "l3proto": "ip"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0013objects_0.nft b/tests/shell/testcases/listing/dumps/0013objects_0.nft
new file mode 100644 (file)
index 0000000..427db26
--- /dev/null
@@ -0,0 +1,27 @@
+table ip test {
+       quota https-quota {
+               25 mbytes
+       }
+
+       ct helper cthelp {
+               type "sip" protocol tcp
+               l3proto ip
+       }
+
+       ct timeout cttime {
+               protocol udp
+               l3proto ip
+               policy = { unreplied : 15s, replied : 12s }
+       }
+
+       ct expectation ctexpect {
+               protocol tcp
+               dport 5432
+               timeout 1h
+               size 12
+               l3proto ip
+       }
+
+       chain input {
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0014objects_0.json-nft b/tests/shell/testcases/listing/dumps/0014objects_0.json-nft
new file mode 100644 (file)
index 0000000..83f72d4
--- /dev/null
@@ -0,0 +1,47 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "quota": {
+        "family": "ip",
+        "name": "https-quota",
+        "table": "test",
+        "handle": 0,
+        "bytes": 26214400,
+        "used": 0,
+        "inv": false
+      }
+    },
+    {
+      "ct helper": {
+        "family": "ip",
+        "name": "cthelp",
+        "table": "test",
+        "handle": 0,
+        "type": "sip",
+        "protocol": "tcp",
+        "l3proto": "ip"
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test-ip",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0014objects_0.nft b/tests/shell/testcases/listing/dumps/0014objects_0.nft
new file mode 100644 (file)
index 0000000..9281a1a
--- /dev/null
@@ -0,0 +1,12 @@
+table ip test {
+       quota https-quota {
+               25 mbytes
+       }
+
+       ct helper cthelp {
+               type "sip" protocol tcp
+               l3proto ip
+       }
+}
+table ip test-ip {
+}
diff --git a/tests/shell/testcases/listing/dumps/0015dynamic_0.json-nft b/tests/shell/testcases/listing/dumps/0015dynamic_0.json-nft
new file mode 100644 (file)
index 0000000..a94a1b0
--- /dev/null
@@ -0,0 +1,38 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "test_set",
+        "table": "filter",
+        "type": [
+          "ipv4_addr",
+          "inet_service",
+          "ipv4_addr",
+          "inet_service",
+          "inet_proto"
+        ],
+        "handle": 0,
+        "size": 100000,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0015dynamic_0.nft b/tests/shell/testcases/listing/dumps/0015dynamic_0.nft
new file mode 100644 (file)
index 0000000..0f4244b
--- /dev/null
@@ -0,0 +1,7 @@
+table ip filter {
+       set test_set {
+               type ipv4_addr . inet_service . ipv4_addr . inet_service . inet_proto
+               size 100000
+               flags dynamic,timeout
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0016anonymous_0.json-nft b/tests/shell/testcases/listing/dumps/0016anonymous_0.json-nft
new file mode 100644 (file)
index 0000000..e47ccb8
--- /dev/null
@@ -0,0 +1,85 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "1.1.1.1"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        "1.1.1.1",
+                        2
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0016anonymous_0.nft b/tests/shell/testcases/listing/dumps/0016anonymous_0.nft
new file mode 100644 (file)
index 0000000..cb08933
--- /dev/null
@@ -0,0 +1,6 @@
+table ip x {
+       chain y {
+               ip saddr 1.1.1.1
+               meta mark set ip saddr map { 1.1.1.1 : 0x00000002 }
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0017objects_0.json-nft b/tests/shell/testcases/listing/dumps/0017objects_0.json-nft
new file mode 100644 (file)
index 0000000..d735f7a
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "countermap",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "counter"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0017objects_0.nft b/tests/shell/testcases/listing/dumps/0017objects_0.nft
new file mode 100644 (file)
index 0000000..e60e3af
--- /dev/null
@@ -0,0 +1,5 @@
+table inet filter {
+       map countermap {
+               type ipv4_addr : counter
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0018data_0.json-nft b/tests/shell/testcases/listing/dumps/0018data_0.json-nft
new file mode 100644 (file)
index 0000000..211dcd3
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "ipmap",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "ipv4_addr"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0018data_0.nft b/tests/shell/testcases/listing/dumps/0018data_0.nft
new file mode 100644 (file)
index 0000000..5d31855
--- /dev/null
@@ -0,0 +1,5 @@
+table inet filter {
+       map ipmap {
+               type ipv4_addr : ipv4_addr
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0019set_0.json-nft b/tests/shell/testcases/listing/dumps/0019set_0.json-nft
new file mode 100644 (file)
index 0000000..3bb7cb8
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "ipset",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0019set_0.nft b/tests/shell/testcases/listing/dumps/0019set_0.nft
new file mode 100644 (file)
index 0000000..915922c
--- /dev/null
@@ -0,0 +1,5 @@
+table inet filter {
+       set ipset {
+               type ipv4_addr
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0020flowtable_0.json-nft b/tests/shell/testcases/listing/dumps/0020flowtable_0.json-nft
new file mode 100644 (file)
index 0000000..d511739
--- /dev/null
@@ -0,0 +1,67 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "flowtable": {
+        "family": "inet",
+        "name": "f",
+        "table": "filter",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 0,
+        "dev": "lo"
+      }
+    },
+    {
+      "flowtable": {
+        "family": "inet",
+        "name": "f2",
+        "table": "filter",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "flowtable": {
+        "family": "ip",
+        "name": "f",
+        "table": "filter",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 0,
+        "dev": "lo"
+      }
+    },
+    {
+      "flowtable": {
+        "family": "ip",
+        "name": "f2",
+        "table": "filter",
+        "handle": 0,
+        "hook": "ingress",
+        "prio": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0020flowtable_0.nft b/tests/shell/testcases/listing/dumps/0020flowtable_0.nft
new file mode 100644 (file)
index 0000000..4a64e53
--- /dev/null
@@ -0,0 +1,20 @@
+table inet filter {
+       flowtable f {
+               hook ingress priority filter
+               devices = { lo }
+       }
+
+       flowtable f2 {
+               hook ingress priority filter
+       }
+}
+table ip filter {
+       flowtable f {
+               hook ingress priority filter
+               devices = { lo }
+       }
+
+       flowtable f2 {
+               hook ingress priority filter
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0021ruleset_json_terse_0.json-nft b/tests/shell/testcases/listing/dumps/0021ruleset_json_terse_0.json-nft
new file mode 100644 (file)
index 0000000..d1131bb
--- /dev/null
@@ -0,0 +1,39 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "test",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "192.168.3.4",
+          "192.168.3.5"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0021ruleset_json_terse_0.nft b/tests/shell/testcases/listing/dumps/0021ruleset_json_terse_0.nft
new file mode 100644 (file)
index 0000000..13c8ac6
--- /dev/null
@@ -0,0 +1,9 @@
+table ip test {
+       set s {
+               type ipv4_addr
+               elements = { 192.168.3.4, 192.168.3.5 }
+       }
+
+       chain c {
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/0022terse_0.json-nft b/tests/shell/testcases/listing/dumps/0022terse_0.json-nft
new file mode 100644 (file)
index 0000000..1a33d68
--- /dev/null
@@ -0,0 +1,86 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "example",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          "10.10.10.10",
+          "10.10.11.11"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "!=",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "10.10.10.100",
+                  "10.10.10.111"
+                ]
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@example"
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/listing/dumps/0022terse_0.nft b/tests/shell/testcases/listing/dumps/0022terse_0.nft
new file mode 100644 (file)
index 0000000..40665cb
--- /dev/null
@@ -0,0 +1,12 @@
+table inet filter {
+       set example {
+               type ipv4_addr
+               flags interval
+               elements = { 10.10.10.10, 10.10.11.11 }
+       }
+
+       chain input {
+               type filter hook prerouting priority filter; policy accept;
+               ip saddr != { 10.10.10.100, 10.10.10.111 } ip saddr @example drop
+       }
+}
diff --git a/tests/shell/testcases/listing/dumps/meta_time.nft b/tests/shell/testcases/listing/dumps/meta_time.nft
deleted file mode 100644 (file)
index 9121aef..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-table ip t {
-       chain c {
-               meta hour "01:00"-"01:59"
-               meta hour "02:00"-"02:59"
-               meta hour "03:00"-"03:59"
-               meta hour "04:00"-"04:59"
-               meta hour "05:00"-"05:59"
-               meta hour "06:00"-"06:59"
-               meta hour "07:00"-"07:59"
-               meta hour "08:00"-"08:59"
-               meta hour "09:00"-"09:59"
-               meta hour "10:00"-"10:59"
-               meta hour "11:00"-"11:59"
-               meta hour "12:00"-"12:59"
-               meta hour "13:00"-"13:59"
-               meta hour "14:00"-"14:59"
-               meta hour "15:00"-"15:59"
-               meta hour "16:00"-"16:59"
-               meta hour "17:00"-"17:59"
-               meta hour "18:00"-"18:59"
-               meta hour "19:00"-"19:59"
-               meta hour "20:00"-"20:59"
-               meta hour "21:00"-"21:59"
-               meta hour "22:00"-"22:59"
-               meta hour "23:00"-"23:59"
-               meta hour "00:00"-"00:59"
-               meta hour "04:00"-"15:00"
-               meta hour "05:00"-"16:00"
-               meta hour "06:00"-"17:00"
-               meta hour "07:00"-"18:00"
-       }
-}
diff --git a/tests/shell/testcases/listing/dumps/meta_time.nodump b/tests/shell/testcases/listing/dumps/meta_time.nodump
new file mode 100644 (file)
index 0000000..e69de29
index a78a4c5b2b2894f31ad2655113d566914bd7b0fc..96a9d5570fd14bf0de3a2671d7864f5e42aa1ea8 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_meta_time)
+
 set -e
 
 TMP1=$(mktemp)
diff --git a/tests/shell/testcases/listing/reset_objects b/tests/shell/testcases/listing/reset_objects
new file mode 100755 (executable)
index 0000000..0b6720b
--- /dev/null
@@ -0,0 +1,104 @@
+#!/bin/bash
+
+set -e
+
+load_ruleset()
+{
+       $NFT -f - <<EOF
+table ip test {
+       quota https-quota {
+               25 mbytes used 10 mbytes
+       }
+       counter https-counter {
+               packets 10 bytes 4096
+       }
+}
+EOF
+}
+
+check_list_quota()
+{
+       EXPECT="table ip test {
+       quota https-quota {
+               25 mbytes
+       }
+}"
+       $DIFF -u <(echo "$EXPECT") <($NFT list quotas)
+}
+
+check_list_counter()
+{
+       EXPECT="table ip test {
+       counter https-counter {
+               packets 0 bytes 0
+       }
+}"
+       $DIFF -u <(echo "$EXPECT") <($NFT list counters)
+}
+
+load_ruleset
+
+EXPECT="table ip test {
+       quota https-quota {
+               25 mbytes used 10 mbytes
+       }
+}"
+$DIFF -u <(echo "$EXPECT") <($NFT reset quotas)
+
+check_list_quota
+$NFT flush ruleset
+load_ruleset
+
+EXPECT="table ip test {
+       quota https-quota {
+               25 mbytes used 10 mbytes
+       }
+}"
+$DIFF -u <(echo "$EXPECT") <($NFT reset quotas ip)
+
+check_list_quota
+$NFT flush ruleset
+load_ruleset
+
+EXPECT="table ip test {
+       quota https-quota {
+               25 mbytes used 10 mbytes
+       }
+}"
+$DIFF -u <(echo "$EXPECT") <($NFT reset quota ip test https-quota)
+
+check_list_quota
+$NFT flush ruleset
+load_ruleset
+
+EXPECT="table ip test {
+       counter https-counter {
+               packets 10 bytes 4096
+       }
+}"
+$DIFF -u <(echo "$EXPECT") <($NFT reset counters)
+
+check_list_counter
+$NFT flush ruleset
+load_ruleset
+
+EXPECT="table ip test {
+       counter https-counter {
+               packets 10 bytes 4096
+       }
+}"
+$DIFF -u <(echo "$EXPECT") <($NFT reset counters ip)
+
+check_list_counter
+$NFT flush ruleset
+load_ruleset
+
+EXPECT="table ip test {
+       counter https-counter {
+               packets 10 bytes 4096
+       }
+}"
+$DIFF -u <(echo "$EXPECT") <($NFT reset counter ip test https-counter)
+
+check_list_counter
+$NFT flush ruleset
index 2b254c51b3c3f0bbcf3e826142e10bc8e9670c52..427d94dfbfbe809dedf738f6cf0f061ad7c9f228 100755 (executable)
@@ -24,19 +24,12 @@ generate_add() {
 }
 
 generate_test() {
-       count=0
        elements=""
        for ((i=1; i<=HOWMANY; i++)) ; do
                for ((j=1; j<=HOWMANY; j++)) ; do
-                       ((count++))
                        elements="${elements}10.0.${i}.${j} : 10.0.${i}.${j}"
                        [ "$i" == "$HOWMANY" ] && [ "$j" == "$HOWMANY" ] && break
-                       if [ "$count" == "2" ] ; then
-                               count=0
-                               elements="${elements},\\n\\t\\t\\t     "
-                       else
-                               elements="${elements}, "
-                       fi
+                       elements="${elements},\\n\\t\\t\\t     "
                done
        done
        echo -e "$elements"
index 3de0c9de4f9347df910ab9475c2b74d70eba732f..7d3825596c4996e298a53d157d6c21e25c0c8260 100755 (executable)
@@ -5,6 +5,10 @@
 
 HOWMANY=63
 
+if [ "$NFT_TEST_SKIP_slow" = y ] ; then
+       HOWMANY=5
+fi
+
 tmpfile=$(mktemp)
 if [ ! -w $tmpfile ] ; then
        echo "Failed to create tmp file" >&2
@@ -26,19 +30,12 @@ generate_add() {
 }
 
 generate_test() {
-       count=0
        elements=""
        for ((i=1; i<=HOWMANY; i++)) ; do
                for ((j=1; j<=HOWMANY; j++)) ; do
-                       ((count++))
                        elements="${elements}10.${i}.${j}.0/24 : 10.0.${i}.${j}"
                        [ "$i" == "$HOWMANY" ] && [ "$j" == "$HOWMANY" ] && break
-                       if [ "$count" == "2" ] ; then
-                               count=0
-                               elements="${elements},\\n\\t\\t\\t     "
-                       else
-                               elements="${elements}, "
-                       fi
+                       elements="${elements},\\n\\t\\t\\t     "
                done
        done
        echo -e "$elements"
@@ -64,3 +61,7 @@ if [ "$EXPECTED" != "$GET" ] ; then
        exit 1
 fi
 
+if [ "$HOWMANY" != 63 ] ; then
+       echo "Run a partial test due to NFT_TEST_SKIP_slow=y. Skip"
+       exit 77
+fi
index 39ea3127be89aab1c44548b9fc68edfeabc10f21..86e54b68ecd41834cf45c94f608f83c341a7ecf0 100755 (executable)
@@ -6,7 +6,8 @@ EXPECTED="table ip filter {
        map m {
                type ipv4_addr : mark
                flags interval
-               elements = { 127.0.0.2 : 0x00000002, 127.0.0.3 : 0x00000003 }
+               elements = { 127.0.0.2 : 0x00000002,
+                            127.0.0.3 : 0x00000003 }
        }
 
        chain input {
index d31e1608f792c91b41388d4bf1600031de96f9e0..4e133b72f6ef012e3f0d89fdfa503ba285d0b347 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
 set -e
 
 EXPECTED="table inet filter {
index 4848d97212fd89d702ab8c158ed19d382f510be1..859bbfcf69e4a023f086e4ec337f90f4330a48f0 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_inet_nat)
+
 set -e
 
 EXPECTED="table inet x {
index 83704d484b28110235a6692397907a98b58db897..3e6fa78d7d4c9fc116930889eb93de7800b16466 100755 (executable)
@@ -22,4 +22,12 @@ EXPECTED="table inet filter {
 }"
 
 $NFT -f - <<< "$EXPECTED"
-$NFT 'add element inet filter portmap { 22 : jump ssh_input, * : drop }'
+
+if [ "$NFT_TEST_HAVE_catchall_element" != n ]; then
+       $NFT 'add element inet filter portmap { 22 : jump ssh_input, * : drop }'
+fi
+
+if [ "$NFT_TEST_HAVE_catchall_element" = n ]; then
+       echo "Ran partial tests due to NFT_TEST_HAVE_catchall_element=n (skipped)"
+       exit 77
+fi
index 49e51b755b0fcc7087aeffce93c3c15362109b11..dd93c482f4413578bae592083e8a33bc3d8f38ca 100755 (executable)
@@ -15,22 +15,3 @@ table ip x {
 }"
 
 $NFT -f - <<< "$EXPECTED"
-
-EXPECTED="table ip x {
-       map w {
-               typeof ip saddr . meta mark : verdict
-               flags interval
-               counter
-               elements = {
-                       127.0.0.1-127.0.0.4 . 0x123434-0xb00122 : accept,
-               }
-       }
-
-       chain k {
-               type filter hook input priority filter + 1; policy accept;
-               meta mark set 0x123434
-               ip saddr . meta mark vmap @w
-       }
-}"
-
-$NFT -f - <<< "$EXPECTED"
diff --git a/tests/shell/testcases/maps/0012map_concat_0 b/tests/shell/testcases/maps/0012map_concat_0
new file mode 100755 (executable)
index 0000000..d18c7a7
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
+set -e
+
+EXPECTED="table ip x {
+        map w {
+                typeof ip saddr . meta mark : verdict
+                flags interval
+                counter
+                elements = {
+                        127.0.0.1-127.0.0.4 . 0x123434-0xb00122 : accept,
+                }
+        }
+
+        chain k {
+                type filter hook input priority filter + 1; policy accept;
+                meta mark set 0x123434
+                ip saddr . meta mark vmap @w
+        }
+}"
+
+$NFT -f - <<< "$EXPECTED"
index 70d7fd3b002f48673031ef226509f3f7adcc950e..c8d20cee7ca7c9701e7a8ef0e56cf00729213f9f 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 set -e
 
 RULESET="
diff --git a/tests/shell/testcases/maps/0014destroy_0 b/tests/shell/testcases/maps/0014destroy_0
new file mode 100755 (executable)
index 0000000..ee81e3c
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash -e
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_destroy)
+
+$NFT add table x
+
+# pass for non-existent map
+$NFT destroy map x y
+
+# successfully delete existing map
+$NFT add map x y '{ type ipv4_addr : ipv4_addr; }'
+$NFT destroy map x y
diff --git a/tests/shell/testcases/maps/0016map_leak_0 b/tests/shell/testcases/maps/0016map_leak_0
new file mode 100755 (executable)
index 0000000..e110ee4
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+set -e
+
+RULESET="table ip t {
+        map sourcemap {
+                type ipv4_addr : verdict
+                elements = { 100.123.10.2 : jump c }
+        }
+
+        chain c {
+        }
+}"
+
+$NFT -f - <<< "$RULESET"
+# again, since it is addition, not creation, it is successful
+$NFT -f - <<< "$RULESET"
+# flush it to check for refcount leak
+$NFT flush ruleset
+
+#
+# again with stateful objects
+#
+
+RULESET="table ip t {
+       counter c {}
+
+        map sourcemap {
+                type ipv4_addr : counter
+                elements = { 100.123.10.2 : \"c\" }
+        }
+}"
+
+$NFT -f - <<< "$RULESET"
+# again, since it is addition, not creation, it is successful
+$NFT -f - <<< "$RULESET"
+# flush it to check for refcount leak
+$NFT flush ruleset
index 70cea88de23812b0ae4500c4e0f42bde2eda4d9d..e01adb4c6ac944d69500211ff5f066e85ccf4062 100755 (executable)
@@ -2,9 +2,15 @@
 
 set -e
 
+if [ "$NFT_TEST_HAVE_catchall_element" != n ] ; then
+       CATCHALL="* : 3,"
+else
+       CATCHALL=","
+fi
+
 RULESET="define x = {
         1.1.1.1 : 2,
-        * : 3,
+        $CATCHALL
 }
 
 table ip x {
@@ -19,3 +25,8 @@ table ip x {
 }"
 
 $NFT -f - <<< "$RULESET"
+
+if [ "$NFT_TEST_HAVE_catchall_element" = n ] ; then
+       echo "Ran modified version of test due to NFT_TEST_HAVE_catchall_element=n (skipped)"
+       exit 77
+fi
diff --git a/tests/shell/testcases/maps/0018map_leak_timeout_0 b/tests/shell/testcases/maps/0018map_leak_timeout_0
new file mode 100755 (executable)
index 0000000..09db315
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# NFT_TEST_SKIP(NFT_TEST_SKIP_slow)
+
+set -e
+
+RULESET="table ip t {
+        map sourcemap {
+                type ipv4_addr : verdict
+                timeout 3s
+                elements = { 100.123.10.2 : jump c }
+        }
+
+        chain c {
+        }
+}"
+
+$NFT -f - <<< "$RULESET"
+# again, since it is addition, not creation, it is successful
+$NFT -f - <<< "$RULESET"
+
+# wait for elements to expire
+sleep 5
+
+# flush it to check for refcount leak
+$NFT flush ruleset
+
+#
+# again with stateful objects
+#
+
+RULESET="table ip t {
+       counter c {}
+
+        map sourcemap {
+                type ipv4_addr : counter
+                timeout 3s
+                elements = { 100.123.10.2 : \"c\" }
+        }
+}"
+
+$NFT -f - <<< "$RULESET"
+# again, since it is addition, not creation, it is successful
+$NFT -f - <<< "$RULESET"
+# flush it to check for refcount leak
+
+# wait for elements to expire
+sleep 5
+
+$NFT flush ruleset
similarity index 70%
rename from tests/shell/testcases/sets/0024named_objects_0
rename to tests/shell/testcases/maps/0024named_objects_0
index 6d21e3884da995ecbf5c7beee945fb6ed6164b6a..21200c3cca3cd45bdb85580253e4a6d2dedcdfa0 100755 (executable)
@@ -18,15 +18,6 @@ table inet x {
        quota user124 {
                over 2000 bytes
        }
-       synproxy https-synproxy {
-               mss 1460
-               wscale 7
-               timestamp sack-perm
-       }
-       synproxy other-synproxy {
-               mss 1460
-               wscale 5
-       }
        set y {
                type ipv4_addr
        }
@@ -34,15 +25,9 @@ table inet x {
                type ipv4_addr : quota
                elements = { 192.168.2.2 : "user124", 192.168.2.3 : "user124"}
        }
-       map test2 {
-               type ipv4_addr : synproxy
-               flags interval
-               elements = { 192.168.1.0/24 : "https-synproxy", 192.168.2.0/24 : "other-synproxy" }
-       }
        chain y {
                type filter hook input priority 0; policy accept;
                counter name ip saddr map { 192.168.2.2 : "user123", 1.1.1.1 : "user123", 2.2.2.2 : "user123"}
-               synproxy name ip saddr map { 192.168.1.0/24 : "https-synproxy", 192.168.2.0/24 : "other-synproxy" }
                quota name ip saddr map @test drop
        }
 }"
index 07820b7c4fdd80716baa3bb40ea156d1a9eb392a..34465f1da0bec3138d84ddd0bfd20ed12ecb17ef 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 set -e
 dumpfile=$(dirname $0)/dumps/$(basename $0).nft
 
diff --git a/tests/shell/testcases/maps/delete_element b/tests/shell/testcases/maps/delete_element
new file mode 100755 (executable)
index 0000000..75272f4
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+set -e
+
+RULESET="flush ruleset
+
+table ip x {
+        map m {
+                typeof ct bytes : meta priority
+                flags interval
+                elements = {
+                        0-2048000 : 1:0001,
+                        2048001-4000000 : 1:0002,
+                }
+        }
+
+        chain y {
+                type filter hook output priority 0; policy accept;
+
+                meta priority set ct bytes map @m
+        }
+}"
+
+$NFT -f - <<< $RULESET
+
+$NFT delete element ip x m { 0-2048000 }
+$NFT add element ip x m { 0-2048000 : 1:0002 }
+$NFT delete element ip x m { 0-2048000 : 1:0002 }
diff --git a/tests/shell/testcases/maps/delete_element_catchall b/tests/shell/testcases/maps/delete_element_catchall
new file mode 100755 (executable)
index 0000000..a6a0fc6
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_catchall_element)
+
+set -e
+
+RULESET="flush ruleset
+
+table ip x {
+        map m {
+                typeof ct bytes : meta priority
+                flags interval
+                elements = {
+                        0-2048000 : 1:0001,
+                        * : 1:0002,
+                }
+        }
+
+        chain y {
+                type filter hook output priority 0; policy accept;
+
+                meta priority set ct bytes map @m
+        }
+}"
+
+$NFT -f - <<< $RULESET
+
+$NFT delete element ip x m { 0-2048000 }
+$NFT add element ip x m { 0-2048000 : 1:0002 }
+$NFT delete element ip x m { 0-2048000 : 1:0002 }
+
+$NFT 'delete element ip x m { * }'
+$NFT 'add element ip x m { * : 1:0003 }'
+$NFT 'delete element ip x m { * : 1:0003 }'
+$NFT 'add element ip x m { * : 1:0003 }'
diff --git a/tests/shell/testcases/maps/dumps/0003map_add_many_elements_0.json-nft b/tests/shell/testcases/maps/dumps/0003map_add_many_elements_0.json-nft
new file mode 100644 (file)
index 0000000..1b5c2a2
--- /dev/null
@@ -0,0 +1,3874 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "ipv4_addr",
+        "elem": [
+          [
+            "10.0.1.1",
+            "10.0.1.1"
+          ],
+          [
+            "10.0.1.2",
+            "10.0.1.2"
+          ],
+          [
+            "10.0.1.3",
+            "10.0.1.3"
+          ],
+          [
+            "10.0.1.4",
+            "10.0.1.4"
+          ],
+          [
+            "10.0.1.5",
+            "10.0.1.5"
+          ],
+          [
+            "10.0.1.6",
+            "10.0.1.6"
+          ],
+          [
+            "10.0.1.7",
+            "10.0.1.7"
+          ],
+          [
+            "10.0.1.8",
+            "10.0.1.8"
+          ],
+          [
+            "10.0.1.9",
+            "10.0.1.9"
+          ],
+          [
+            "10.0.1.10",
+            "10.0.1.10"
+          ],
+          [
+            "10.0.1.11",
+            "10.0.1.11"
+          ],
+          [
+            "10.0.1.12",
+            "10.0.1.12"
+          ],
+          [
+            "10.0.1.13",
+            "10.0.1.13"
+          ],
+          [
+            "10.0.1.14",
+            "10.0.1.14"
+          ],
+          [
+            "10.0.1.15",
+            "10.0.1.15"
+          ],
+          [
+            "10.0.1.16",
+            "10.0.1.16"
+          ],
+          [
+            "10.0.1.17",
+            "10.0.1.17"
+          ],
+          [
+            "10.0.1.18",
+            "10.0.1.18"
+          ],
+          [
+            "10.0.1.19",
+            "10.0.1.19"
+          ],
+          [
+            "10.0.1.20",
+            "10.0.1.20"
+          ],
+          [
+            "10.0.1.21",
+            "10.0.1.21"
+          ],
+          [
+            "10.0.1.22",
+            "10.0.1.22"
+          ],
+          [
+            "10.0.1.23",
+            "10.0.1.23"
+          ],
+          [
+            "10.0.1.24",
+            "10.0.1.24"
+          ],
+          [
+            "10.0.1.25",
+            "10.0.1.25"
+          ],
+          [
+            "10.0.1.26",
+            "10.0.1.26"
+          ],
+          [
+            "10.0.1.27",
+            "10.0.1.27"
+          ],
+          [
+            "10.0.1.28",
+            "10.0.1.28"
+          ],
+          [
+            "10.0.1.29",
+            "10.0.1.29"
+          ],
+          [
+            "10.0.1.30",
+            "10.0.1.30"
+          ],
+          [
+            "10.0.1.31",
+            "10.0.1.31"
+          ],
+          [
+            "10.0.2.1",
+            "10.0.2.1"
+          ],
+          [
+            "10.0.2.2",
+            "10.0.2.2"
+          ],
+          [
+            "10.0.2.3",
+            "10.0.2.3"
+          ],
+          [
+            "10.0.2.4",
+            "10.0.2.4"
+          ],
+          [
+            "10.0.2.5",
+            "10.0.2.5"
+          ],
+          [
+            "10.0.2.6",
+            "10.0.2.6"
+          ],
+          [
+            "10.0.2.7",
+            "10.0.2.7"
+          ],
+          [
+            "10.0.2.8",
+            "10.0.2.8"
+          ],
+          [
+            "10.0.2.9",
+            "10.0.2.9"
+          ],
+          [
+            "10.0.2.10",
+            "10.0.2.10"
+          ],
+          [
+            "10.0.2.11",
+            "10.0.2.11"
+          ],
+          [
+            "10.0.2.12",
+            "10.0.2.12"
+          ],
+          [
+            "10.0.2.13",
+            "10.0.2.13"
+          ],
+          [
+            "10.0.2.14",
+            "10.0.2.14"
+          ],
+          [
+            "10.0.2.15",
+            "10.0.2.15"
+          ],
+          [
+            "10.0.2.16",
+            "10.0.2.16"
+          ],
+          [
+            "10.0.2.17",
+            "10.0.2.17"
+          ],
+          [
+            "10.0.2.18",
+            "10.0.2.18"
+          ],
+          [
+            "10.0.2.19",
+            "10.0.2.19"
+          ],
+          [
+            "10.0.2.20",
+            "10.0.2.20"
+          ],
+          [
+            "10.0.2.21",
+            "10.0.2.21"
+          ],
+          [
+            "10.0.2.22",
+            "10.0.2.22"
+          ],
+          [
+            "10.0.2.23",
+            "10.0.2.23"
+          ],
+          [
+            "10.0.2.24",
+            "10.0.2.24"
+          ],
+          [
+            "10.0.2.25",
+            "10.0.2.25"
+          ],
+          [
+            "10.0.2.26",
+            "10.0.2.26"
+          ],
+          [
+            "10.0.2.27",
+            "10.0.2.27"
+          ],
+          [
+            "10.0.2.28",
+            "10.0.2.28"
+          ],
+          [
+            "10.0.2.29",
+            "10.0.2.29"
+          ],
+          [
+            "10.0.2.30",
+            "10.0.2.30"
+          ],
+          [
+            "10.0.2.31",
+            "10.0.2.31"
+          ],
+          [
+            "10.0.3.1",
+            "10.0.3.1"
+          ],
+          [
+            "10.0.3.2",
+            "10.0.3.2"
+          ],
+          [
+            "10.0.3.3",
+            "10.0.3.3"
+          ],
+          [
+            "10.0.3.4",
+            "10.0.3.4"
+          ],
+          [
+            "10.0.3.5",
+            "10.0.3.5"
+          ],
+          [
+            "10.0.3.6",
+            "10.0.3.6"
+          ],
+          [
+            "10.0.3.7",
+            "10.0.3.7"
+          ],
+          [
+            "10.0.3.8",
+            "10.0.3.8"
+          ],
+          [
+            "10.0.3.9",
+            "10.0.3.9"
+          ],
+          [
+            "10.0.3.10",
+            "10.0.3.10"
+          ],
+          [
+            "10.0.3.11",
+            "10.0.3.11"
+          ],
+          [
+            "10.0.3.12",
+            "10.0.3.12"
+          ],
+          [
+            "10.0.3.13",
+            "10.0.3.13"
+          ],
+          [
+            "10.0.3.14",
+            "10.0.3.14"
+          ],
+          [
+            "10.0.3.15",
+            "10.0.3.15"
+          ],
+          [
+            "10.0.3.16",
+            "10.0.3.16"
+          ],
+          [
+            "10.0.3.17",
+            "10.0.3.17"
+          ],
+          [
+            "10.0.3.18",
+            "10.0.3.18"
+          ],
+          [
+            "10.0.3.19",
+            "10.0.3.19"
+          ],
+          [
+            "10.0.3.20",
+            "10.0.3.20"
+          ],
+          [
+            "10.0.3.21",
+            "10.0.3.21"
+          ],
+          [
+            "10.0.3.22",
+            "10.0.3.22"
+          ],
+          [
+            "10.0.3.23",
+            "10.0.3.23"
+          ],
+          [
+            "10.0.3.24",
+            "10.0.3.24"
+          ],
+          [
+            "10.0.3.25",
+            "10.0.3.25"
+          ],
+          [
+            "10.0.3.26",
+            "10.0.3.26"
+          ],
+          [
+            "10.0.3.27",
+            "10.0.3.27"
+          ],
+          [
+            "10.0.3.28",
+            "10.0.3.28"
+          ],
+          [
+            "10.0.3.29",
+            "10.0.3.29"
+          ],
+          [
+            "10.0.3.30",
+            "10.0.3.30"
+          ],
+          [
+            "10.0.3.31",
+            "10.0.3.31"
+          ],
+          [
+            "10.0.4.1",
+            "10.0.4.1"
+          ],
+          [
+            "10.0.4.2",
+            "10.0.4.2"
+          ],
+          [
+            "10.0.4.3",
+            "10.0.4.3"
+          ],
+          [
+            "10.0.4.4",
+            "10.0.4.4"
+          ],
+          [
+            "10.0.4.5",
+            "10.0.4.5"
+          ],
+          [
+            "10.0.4.6",
+            "10.0.4.6"
+          ],
+          [
+            "10.0.4.7",
+            "10.0.4.7"
+          ],
+          [
+            "10.0.4.8",
+            "10.0.4.8"
+          ],
+          [
+            "10.0.4.9",
+            "10.0.4.9"
+          ],
+          [
+            "10.0.4.10",
+            "10.0.4.10"
+          ],
+          [
+            "10.0.4.11",
+            "10.0.4.11"
+          ],
+          [
+            "10.0.4.12",
+            "10.0.4.12"
+          ],
+          [
+            "10.0.4.13",
+            "10.0.4.13"
+          ],
+          [
+            "10.0.4.14",
+            "10.0.4.14"
+          ],
+          [
+            "10.0.4.15",
+            "10.0.4.15"
+          ],
+          [
+            "10.0.4.16",
+            "10.0.4.16"
+          ],
+          [
+            "10.0.4.17",
+            "10.0.4.17"
+          ],
+          [
+            "10.0.4.18",
+            "10.0.4.18"
+          ],
+          [
+            "10.0.4.19",
+            "10.0.4.19"
+          ],
+          [
+            "10.0.4.20",
+            "10.0.4.20"
+          ],
+          [
+            "10.0.4.21",
+            "10.0.4.21"
+          ],
+          [
+            "10.0.4.22",
+            "10.0.4.22"
+          ],
+          [
+            "10.0.4.23",
+            "10.0.4.23"
+          ],
+          [
+            "10.0.4.24",
+            "10.0.4.24"
+          ],
+          [
+            "10.0.4.25",
+            "10.0.4.25"
+          ],
+          [
+            "10.0.4.26",
+            "10.0.4.26"
+          ],
+          [
+            "10.0.4.27",
+            "10.0.4.27"
+          ],
+          [
+            "10.0.4.28",
+            "10.0.4.28"
+          ],
+          [
+            "10.0.4.29",
+            "10.0.4.29"
+          ],
+          [
+            "10.0.4.30",
+            "10.0.4.30"
+          ],
+          [
+            "10.0.4.31",
+            "10.0.4.31"
+          ],
+          [
+            "10.0.5.1",
+            "10.0.5.1"
+          ],
+          [
+            "10.0.5.2",
+            "10.0.5.2"
+          ],
+          [
+            "10.0.5.3",
+            "10.0.5.3"
+          ],
+          [
+            "10.0.5.4",
+            "10.0.5.4"
+          ],
+          [
+            "10.0.5.5",
+            "10.0.5.5"
+          ],
+          [
+            "10.0.5.6",
+            "10.0.5.6"
+          ],
+          [
+            "10.0.5.7",
+            "10.0.5.7"
+          ],
+          [
+            "10.0.5.8",
+            "10.0.5.8"
+          ],
+          [
+            "10.0.5.9",
+            "10.0.5.9"
+          ],
+          [
+            "10.0.5.10",
+            "10.0.5.10"
+          ],
+          [
+            "10.0.5.11",
+            "10.0.5.11"
+          ],
+          [
+            "10.0.5.12",
+            "10.0.5.12"
+          ],
+          [
+            "10.0.5.13",
+            "10.0.5.13"
+          ],
+          [
+            "10.0.5.14",
+            "10.0.5.14"
+          ],
+          [
+            "10.0.5.15",
+            "10.0.5.15"
+          ],
+          [
+            "10.0.5.16",
+            "10.0.5.16"
+          ],
+          [
+            "10.0.5.17",
+            "10.0.5.17"
+          ],
+          [
+            "10.0.5.18",
+            "10.0.5.18"
+          ],
+          [
+            "10.0.5.19",
+            "10.0.5.19"
+          ],
+          [
+            "10.0.5.20",
+            "10.0.5.20"
+          ],
+          [
+            "10.0.5.21",
+            "10.0.5.21"
+          ],
+          [
+            "10.0.5.22",
+            "10.0.5.22"
+          ],
+          [
+            "10.0.5.23",
+            "10.0.5.23"
+          ],
+          [
+            "10.0.5.24",
+            "10.0.5.24"
+          ],
+          [
+            "10.0.5.25",
+            "10.0.5.25"
+          ],
+          [
+            "10.0.5.26",
+            "10.0.5.26"
+          ],
+          [
+            "10.0.5.27",
+            "10.0.5.27"
+          ],
+          [
+            "10.0.5.28",
+            "10.0.5.28"
+          ],
+          [
+            "10.0.5.29",
+            "10.0.5.29"
+          ],
+          [
+            "10.0.5.30",
+            "10.0.5.30"
+          ],
+          [
+            "10.0.5.31",
+            "10.0.5.31"
+          ],
+          [
+            "10.0.6.1",
+            "10.0.6.1"
+          ],
+          [
+            "10.0.6.2",
+            "10.0.6.2"
+          ],
+          [
+            "10.0.6.3",
+            "10.0.6.3"
+          ],
+          [
+            "10.0.6.4",
+            "10.0.6.4"
+          ],
+          [
+            "10.0.6.5",
+            "10.0.6.5"
+          ],
+          [
+            "10.0.6.6",
+            "10.0.6.6"
+          ],
+          [
+            "10.0.6.7",
+            "10.0.6.7"
+          ],
+          [
+            "10.0.6.8",
+            "10.0.6.8"
+          ],
+          [
+            "10.0.6.9",
+            "10.0.6.9"
+          ],
+          [
+            "10.0.6.10",
+            "10.0.6.10"
+          ],
+          [
+            "10.0.6.11",
+            "10.0.6.11"
+          ],
+          [
+            "10.0.6.12",
+            "10.0.6.12"
+          ],
+          [
+            "10.0.6.13",
+            "10.0.6.13"
+          ],
+          [
+            "10.0.6.14",
+            "10.0.6.14"
+          ],
+          [
+            "10.0.6.15",
+            "10.0.6.15"
+          ],
+          [
+            "10.0.6.16",
+            "10.0.6.16"
+          ],
+          [
+            "10.0.6.17",
+            "10.0.6.17"
+          ],
+          [
+            "10.0.6.18",
+            "10.0.6.18"
+          ],
+          [
+            "10.0.6.19",
+            "10.0.6.19"
+          ],
+          [
+            "10.0.6.20",
+            "10.0.6.20"
+          ],
+          [
+            "10.0.6.21",
+            "10.0.6.21"
+          ],
+          [
+            "10.0.6.22",
+            "10.0.6.22"
+          ],
+          [
+            "10.0.6.23",
+            "10.0.6.23"
+          ],
+          [
+            "10.0.6.24",
+            "10.0.6.24"
+          ],
+          [
+            "10.0.6.25",
+            "10.0.6.25"
+          ],
+          [
+            "10.0.6.26",
+            "10.0.6.26"
+          ],
+          [
+            "10.0.6.27",
+            "10.0.6.27"
+          ],
+          [
+            "10.0.6.28",
+            "10.0.6.28"
+          ],
+          [
+            "10.0.6.29",
+            "10.0.6.29"
+          ],
+          [
+            "10.0.6.30",
+            "10.0.6.30"
+          ],
+          [
+            "10.0.6.31",
+            "10.0.6.31"
+          ],
+          [
+            "10.0.7.1",
+            "10.0.7.1"
+          ],
+          [
+            "10.0.7.2",
+            "10.0.7.2"
+          ],
+          [
+            "10.0.7.3",
+            "10.0.7.3"
+          ],
+          [
+            "10.0.7.4",
+            "10.0.7.4"
+          ],
+          [
+            "10.0.7.5",
+            "10.0.7.5"
+          ],
+          [
+            "10.0.7.6",
+            "10.0.7.6"
+          ],
+          [
+            "10.0.7.7",
+            "10.0.7.7"
+          ],
+          [
+            "10.0.7.8",
+            "10.0.7.8"
+          ],
+          [
+            "10.0.7.9",
+            "10.0.7.9"
+          ],
+          [
+            "10.0.7.10",
+            "10.0.7.10"
+          ],
+          [
+            "10.0.7.11",
+            "10.0.7.11"
+          ],
+          [
+            "10.0.7.12",
+            "10.0.7.12"
+          ],
+          [
+            "10.0.7.13",
+            "10.0.7.13"
+          ],
+          [
+            "10.0.7.14",
+            "10.0.7.14"
+          ],
+          [
+            "10.0.7.15",
+            "10.0.7.15"
+          ],
+          [
+            "10.0.7.16",
+            "10.0.7.16"
+          ],
+          [
+            "10.0.7.17",
+            "10.0.7.17"
+          ],
+          [
+            "10.0.7.18",
+            "10.0.7.18"
+          ],
+          [
+            "10.0.7.19",
+            "10.0.7.19"
+          ],
+          [
+            "10.0.7.20",
+            "10.0.7.20"
+          ],
+          [
+            "10.0.7.21",
+            "10.0.7.21"
+          ],
+          [
+            "10.0.7.22",
+            "10.0.7.22"
+          ],
+          [
+            "10.0.7.23",
+            "10.0.7.23"
+          ],
+          [
+            "10.0.7.24",
+            "10.0.7.24"
+          ],
+          [
+            "10.0.7.25",
+            "10.0.7.25"
+          ],
+          [
+            "10.0.7.26",
+            "10.0.7.26"
+          ],
+          [
+            "10.0.7.27",
+            "10.0.7.27"
+          ],
+          [
+            "10.0.7.28",
+            "10.0.7.28"
+          ],
+          [
+            "10.0.7.29",
+            "10.0.7.29"
+          ],
+          [
+            "10.0.7.30",
+            "10.0.7.30"
+          ],
+          [
+            "10.0.7.31",
+            "10.0.7.31"
+          ],
+          [
+            "10.0.8.1",
+            "10.0.8.1"
+          ],
+          [
+            "10.0.8.2",
+            "10.0.8.2"
+          ],
+          [
+            "10.0.8.3",
+            "10.0.8.3"
+          ],
+          [
+            "10.0.8.4",
+            "10.0.8.4"
+          ],
+          [
+            "10.0.8.5",
+            "10.0.8.5"
+          ],
+          [
+            "10.0.8.6",
+            "10.0.8.6"
+          ],
+          [
+            "10.0.8.7",
+            "10.0.8.7"
+          ],
+          [
+            "10.0.8.8",
+            "10.0.8.8"
+          ],
+          [
+            "10.0.8.9",
+            "10.0.8.9"
+          ],
+          [
+            "10.0.8.10",
+            "10.0.8.10"
+          ],
+          [
+            "10.0.8.11",
+            "10.0.8.11"
+          ],
+          [
+            "10.0.8.12",
+            "10.0.8.12"
+          ],
+          [
+            "10.0.8.13",
+            "10.0.8.13"
+          ],
+          [
+            "10.0.8.14",
+            "10.0.8.14"
+          ],
+          [
+            "10.0.8.15",
+            "10.0.8.15"
+          ],
+          [
+            "10.0.8.16",
+            "10.0.8.16"
+          ],
+          [
+            "10.0.8.17",
+            "10.0.8.17"
+          ],
+          [
+            "10.0.8.18",
+            "10.0.8.18"
+          ],
+          [
+            "10.0.8.19",
+            "10.0.8.19"
+          ],
+          [
+            "10.0.8.20",
+            "10.0.8.20"
+          ],
+          [
+            "10.0.8.21",
+            "10.0.8.21"
+          ],
+          [
+            "10.0.8.22",
+            "10.0.8.22"
+          ],
+          [
+            "10.0.8.23",
+            "10.0.8.23"
+          ],
+          [
+            "10.0.8.24",
+            "10.0.8.24"
+          ],
+          [
+            "10.0.8.25",
+            "10.0.8.25"
+          ],
+          [
+            "10.0.8.26",
+            "10.0.8.26"
+          ],
+          [
+            "10.0.8.27",
+            "10.0.8.27"
+          ],
+          [
+            "10.0.8.28",
+            "10.0.8.28"
+          ],
+          [
+            "10.0.8.29",
+            "10.0.8.29"
+          ],
+          [
+            "10.0.8.30",
+            "10.0.8.30"
+          ],
+          [
+            "10.0.8.31",
+            "10.0.8.31"
+          ],
+          [
+            "10.0.9.1",
+            "10.0.9.1"
+          ],
+          [
+            "10.0.9.2",
+            "10.0.9.2"
+          ],
+          [
+            "10.0.9.3",
+            "10.0.9.3"
+          ],
+          [
+            "10.0.9.4",
+            "10.0.9.4"
+          ],
+          [
+            "10.0.9.5",
+            "10.0.9.5"
+          ],
+          [
+            "10.0.9.6",
+            "10.0.9.6"
+          ],
+          [
+            "10.0.9.7",
+            "10.0.9.7"
+          ],
+          [
+            "10.0.9.8",
+            "10.0.9.8"
+          ],
+          [
+            "10.0.9.9",
+            "10.0.9.9"
+          ],
+          [
+            "10.0.9.10",
+            "10.0.9.10"
+          ],
+          [
+            "10.0.9.11",
+            "10.0.9.11"
+          ],
+          [
+            "10.0.9.12",
+            "10.0.9.12"
+          ],
+          [
+            "10.0.9.13",
+            "10.0.9.13"
+          ],
+          [
+            "10.0.9.14",
+            "10.0.9.14"
+          ],
+          [
+            "10.0.9.15",
+            "10.0.9.15"
+          ],
+          [
+            "10.0.9.16",
+            "10.0.9.16"
+          ],
+          [
+            "10.0.9.17",
+            "10.0.9.17"
+          ],
+          [
+            "10.0.9.18",
+            "10.0.9.18"
+          ],
+          [
+            "10.0.9.19",
+            "10.0.9.19"
+          ],
+          [
+            "10.0.9.20",
+            "10.0.9.20"
+          ],
+          [
+            "10.0.9.21",
+            "10.0.9.21"
+          ],
+          [
+            "10.0.9.22",
+            "10.0.9.22"
+          ],
+          [
+            "10.0.9.23",
+            "10.0.9.23"
+          ],
+          [
+            "10.0.9.24",
+            "10.0.9.24"
+          ],
+          [
+            "10.0.9.25",
+            "10.0.9.25"
+          ],
+          [
+            "10.0.9.26",
+            "10.0.9.26"
+          ],
+          [
+            "10.0.9.27",
+            "10.0.9.27"
+          ],
+          [
+            "10.0.9.28",
+            "10.0.9.28"
+          ],
+          [
+            "10.0.9.29",
+            "10.0.9.29"
+          ],
+          [
+            "10.0.9.30",
+            "10.0.9.30"
+          ],
+          [
+            "10.0.9.31",
+            "10.0.9.31"
+          ],
+          [
+            "10.0.10.1",
+            "10.0.10.1"
+          ],
+          [
+            "10.0.10.2",
+            "10.0.10.2"
+          ],
+          [
+            "10.0.10.3",
+            "10.0.10.3"
+          ],
+          [
+            "10.0.10.4",
+            "10.0.10.4"
+          ],
+          [
+            "10.0.10.5",
+            "10.0.10.5"
+          ],
+          [
+            "10.0.10.6",
+            "10.0.10.6"
+          ],
+          [
+            "10.0.10.7",
+            "10.0.10.7"
+          ],
+          [
+            "10.0.10.8",
+            "10.0.10.8"
+          ],
+          [
+            "10.0.10.9",
+            "10.0.10.9"
+          ],
+          [
+            "10.0.10.10",
+            "10.0.10.10"
+          ],
+          [
+            "10.0.10.11",
+            "10.0.10.11"
+          ],
+          [
+            "10.0.10.12",
+            "10.0.10.12"
+          ],
+          [
+            "10.0.10.13",
+            "10.0.10.13"
+          ],
+          [
+            "10.0.10.14",
+            "10.0.10.14"
+          ],
+          [
+            "10.0.10.15",
+            "10.0.10.15"
+          ],
+          [
+            "10.0.10.16",
+            "10.0.10.16"
+          ],
+          [
+            "10.0.10.17",
+            "10.0.10.17"
+          ],
+          [
+            "10.0.10.18",
+            "10.0.10.18"
+          ],
+          [
+            "10.0.10.19",
+            "10.0.10.19"
+          ],
+          [
+            "10.0.10.20",
+            "10.0.10.20"
+          ],
+          [
+            "10.0.10.21",
+            "10.0.10.21"
+          ],
+          [
+            "10.0.10.22",
+            "10.0.10.22"
+          ],
+          [
+            "10.0.10.23",
+            "10.0.10.23"
+          ],
+          [
+            "10.0.10.24",
+            "10.0.10.24"
+          ],
+          [
+            "10.0.10.25",
+            "10.0.10.25"
+          ],
+          [
+            "10.0.10.26",
+            "10.0.10.26"
+          ],
+          [
+            "10.0.10.27",
+            "10.0.10.27"
+          ],
+          [
+            "10.0.10.28",
+            "10.0.10.28"
+          ],
+          [
+            "10.0.10.29",
+            "10.0.10.29"
+          ],
+          [
+            "10.0.10.30",
+            "10.0.10.30"
+          ],
+          [
+            "10.0.10.31",
+            "10.0.10.31"
+          ],
+          [
+            "10.0.11.1",
+            "10.0.11.1"
+          ],
+          [
+            "10.0.11.2",
+            "10.0.11.2"
+          ],
+          [
+            "10.0.11.3",
+            "10.0.11.3"
+          ],
+          [
+            "10.0.11.4",
+            "10.0.11.4"
+          ],
+          [
+            "10.0.11.5",
+            "10.0.11.5"
+          ],
+          [
+            "10.0.11.6",
+            "10.0.11.6"
+          ],
+          [
+            "10.0.11.7",
+            "10.0.11.7"
+          ],
+          [
+            "10.0.11.8",
+            "10.0.11.8"
+          ],
+          [
+            "10.0.11.9",
+            "10.0.11.9"
+          ],
+          [
+            "10.0.11.10",
+            "10.0.11.10"
+          ],
+          [
+            "10.0.11.11",
+            "10.0.11.11"
+          ],
+          [
+            "10.0.11.12",
+            "10.0.11.12"
+          ],
+          [
+            "10.0.11.13",
+            "10.0.11.13"
+          ],
+          [
+            "10.0.11.14",
+            "10.0.11.14"
+          ],
+          [
+            "10.0.11.15",
+            "10.0.11.15"
+          ],
+          [
+            "10.0.11.16",
+            "10.0.11.16"
+          ],
+          [
+            "10.0.11.17",
+            "10.0.11.17"
+          ],
+          [
+            "10.0.11.18",
+            "10.0.11.18"
+          ],
+          [
+            "10.0.11.19",
+            "10.0.11.19"
+          ],
+          [
+            "10.0.11.20",
+            "10.0.11.20"
+          ],
+          [
+            "10.0.11.21",
+            "10.0.11.21"
+          ],
+          [
+            "10.0.11.22",
+            "10.0.11.22"
+          ],
+          [
+            "10.0.11.23",
+            "10.0.11.23"
+          ],
+          [
+            "10.0.11.24",
+            "10.0.11.24"
+          ],
+          [
+            "10.0.11.25",
+            "10.0.11.25"
+          ],
+          [
+            "10.0.11.26",
+            "10.0.11.26"
+          ],
+          [
+            "10.0.11.27",
+            "10.0.11.27"
+          ],
+          [
+            "10.0.11.28",
+            "10.0.11.28"
+          ],
+          [
+            "10.0.11.29",
+            "10.0.11.29"
+          ],
+          [
+            "10.0.11.30",
+            "10.0.11.30"
+          ],
+          [
+            "10.0.11.31",
+            "10.0.11.31"
+          ],
+          [
+            "10.0.12.1",
+            "10.0.12.1"
+          ],
+          [
+            "10.0.12.2",
+            "10.0.12.2"
+          ],
+          [
+            "10.0.12.3",
+            "10.0.12.3"
+          ],
+          [
+            "10.0.12.4",
+            "10.0.12.4"
+          ],
+          [
+            "10.0.12.5",
+            "10.0.12.5"
+          ],
+          [
+            "10.0.12.6",
+            "10.0.12.6"
+          ],
+          [
+            "10.0.12.7",
+            "10.0.12.7"
+          ],
+          [
+            "10.0.12.8",
+            "10.0.12.8"
+          ],
+          [
+            "10.0.12.9",
+            "10.0.12.9"
+          ],
+          [
+            "10.0.12.10",
+            "10.0.12.10"
+          ],
+          [
+            "10.0.12.11",
+            "10.0.12.11"
+          ],
+          [
+            "10.0.12.12",
+            "10.0.12.12"
+          ],
+          [
+            "10.0.12.13",
+            "10.0.12.13"
+          ],
+          [
+            "10.0.12.14",
+            "10.0.12.14"
+          ],
+          [
+            "10.0.12.15",
+            "10.0.12.15"
+          ],
+          [
+            "10.0.12.16",
+            "10.0.12.16"
+          ],
+          [
+            "10.0.12.17",
+            "10.0.12.17"
+          ],
+          [
+            "10.0.12.18",
+            "10.0.12.18"
+          ],
+          [
+            "10.0.12.19",
+            "10.0.12.19"
+          ],
+          [
+            "10.0.12.20",
+            "10.0.12.20"
+          ],
+          [
+            "10.0.12.21",
+            "10.0.12.21"
+          ],
+          [
+            "10.0.12.22",
+            "10.0.12.22"
+          ],
+          [
+            "10.0.12.23",
+            "10.0.12.23"
+          ],
+          [
+            "10.0.12.24",
+            "10.0.12.24"
+          ],
+          [
+            "10.0.12.25",
+            "10.0.12.25"
+          ],
+          [
+            "10.0.12.26",
+            "10.0.12.26"
+          ],
+          [
+            "10.0.12.27",
+            "10.0.12.27"
+          ],
+          [
+            "10.0.12.28",
+            "10.0.12.28"
+          ],
+          [
+            "10.0.12.29",
+            "10.0.12.29"
+          ],
+          [
+            "10.0.12.30",
+            "10.0.12.30"
+          ],
+          [
+            "10.0.12.31",
+            "10.0.12.31"
+          ],
+          [
+            "10.0.13.1",
+            "10.0.13.1"
+          ],
+          [
+            "10.0.13.2",
+            "10.0.13.2"
+          ],
+          [
+            "10.0.13.3",
+            "10.0.13.3"
+          ],
+          [
+            "10.0.13.4",
+            "10.0.13.4"
+          ],
+          [
+            "10.0.13.5",
+            "10.0.13.5"
+          ],
+          [
+            "10.0.13.6",
+            "10.0.13.6"
+          ],
+          [
+            "10.0.13.7",
+            "10.0.13.7"
+          ],
+          [
+            "10.0.13.8",
+            "10.0.13.8"
+          ],
+          [
+            "10.0.13.9",
+            "10.0.13.9"
+          ],
+          [
+            "10.0.13.10",
+            "10.0.13.10"
+          ],
+          [
+            "10.0.13.11",
+            "10.0.13.11"
+          ],
+          [
+            "10.0.13.12",
+            "10.0.13.12"
+          ],
+          [
+            "10.0.13.13",
+            "10.0.13.13"
+          ],
+          [
+            "10.0.13.14",
+            "10.0.13.14"
+          ],
+          [
+            "10.0.13.15",
+            "10.0.13.15"
+          ],
+          [
+            "10.0.13.16",
+            "10.0.13.16"
+          ],
+          [
+            "10.0.13.17",
+            "10.0.13.17"
+          ],
+          [
+            "10.0.13.18",
+            "10.0.13.18"
+          ],
+          [
+            "10.0.13.19",
+            "10.0.13.19"
+          ],
+          [
+            "10.0.13.20",
+            "10.0.13.20"
+          ],
+          [
+            "10.0.13.21",
+            "10.0.13.21"
+          ],
+          [
+            "10.0.13.22",
+            "10.0.13.22"
+          ],
+          [
+            "10.0.13.23",
+            "10.0.13.23"
+          ],
+          [
+            "10.0.13.24",
+            "10.0.13.24"
+          ],
+          [
+            "10.0.13.25",
+            "10.0.13.25"
+          ],
+          [
+            "10.0.13.26",
+            "10.0.13.26"
+          ],
+          [
+            "10.0.13.27",
+            "10.0.13.27"
+          ],
+          [
+            "10.0.13.28",
+            "10.0.13.28"
+          ],
+          [
+            "10.0.13.29",
+            "10.0.13.29"
+          ],
+          [
+            "10.0.13.30",
+            "10.0.13.30"
+          ],
+          [
+            "10.0.13.31",
+            "10.0.13.31"
+          ],
+          [
+            "10.0.14.1",
+            "10.0.14.1"
+          ],
+          [
+            "10.0.14.2",
+            "10.0.14.2"
+          ],
+          [
+            "10.0.14.3",
+            "10.0.14.3"
+          ],
+          [
+            "10.0.14.4",
+            "10.0.14.4"
+          ],
+          [
+            "10.0.14.5",
+            "10.0.14.5"
+          ],
+          [
+            "10.0.14.6",
+            "10.0.14.6"
+          ],
+          [
+            "10.0.14.7",
+            "10.0.14.7"
+          ],
+          [
+            "10.0.14.8",
+            "10.0.14.8"
+          ],
+          [
+            "10.0.14.9",
+            "10.0.14.9"
+          ],
+          [
+            "10.0.14.10",
+            "10.0.14.10"
+          ],
+          [
+            "10.0.14.11",
+            "10.0.14.11"
+          ],
+          [
+            "10.0.14.12",
+            "10.0.14.12"
+          ],
+          [
+            "10.0.14.13",
+            "10.0.14.13"
+          ],
+          [
+            "10.0.14.14",
+            "10.0.14.14"
+          ],
+          [
+            "10.0.14.15",
+            "10.0.14.15"
+          ],
+          [
+            "10.0.14.16",
+            "10.0.14.16"
+          ],
+          [
+            "10.0.14.17",
+            "10.0.14.17"
+          ],
+          [
+            "10.0.14.18",
+            "10.0.14.18"
+          ],
+          [
+            "10.0.14.19",
+            "10.0.14.19"
+          ],
+          [
+            "10.0.14.20",
+            "10.0.14.20"
+          ],
+          [
+            "10.0.14.21",
+            "10.0.14.21"
+          ],
+          [
+            "10.0.14.22",
+            "10.0.14.22"
+          ],
+          [
+            "10.0.14.23",
+            "10.0.14.23"
+          ],
+          [
+            "10.0.14.24",
+            "10.0.14.24"
+          ],
+          [
+            "10.0.14.25",
+            "10.0.14.25"
+          ],
+          [
+            "10.0.14.26",
+            "10.0.14.26"
+          ],
+          [
+            "10.0.14.27",
+            "10.0.14.27"
+          ],
+          [
+            "10.0.14.28",
+            "10.0.14.28"
+          ],
+          [
+            "10.0.14.29",
+            "10.0.14.29"
+          ],
+          [
+            "10.0.14.30",
+            "10.0.14.30"
+          ],
+          [
+            "10.0.14.31",
+            "10.0.14.31"
+          ],
+          [
+            "10.0.15.1",
+            "10.0.15.1"
+          ],
+          [
+            "10.0.15.2",
+            "10.0.15.2"
+          ],
+          [
+            "10.0.15.3",
+            "10.0.15.3"
+          ],
+          [
+            "10.0.15.4",
+            "10.0.15.4"
+          ],
+          [
+            "10.0.15.5",
+            "10.0.15.5"
+          ],
+          [
+            "10.0.15.6",
+            "10.0.15.6"
+          ],
+          [
+            "10.0.15.7",
+            "10.0.15.7"
+          ],
+          [
+            "10.0.15.8",
+            "10.0.15.8"
+          ],
+          [
+            "10.0.15.9",
+            "10.0.15.9"
+          ],
+          [
+            "10.0.15.10",
+            "10.0.15.10"
+          ],
+          [
+            "10.0.15.11",
+            "10.0.15.11"
+          ],
+          [
+            "10.0.15.12",
+            "10.0.15.12"
+          ],
+          [
+            "10.0.15.13",
+            "10.0.15.13"
+          ],
+          [
+            "10.0.15.14",
+            "10.0.15.14"
+          ],
+          [
+            "10.0.15.15",
+            "10.0.15.15"
+          ],
+          [
+            "10.0.15.16",
+            "10.0.15.16"
+          ],
+          [
+            "10.0.15.17",
+            "10.0.15.17"
+          ],
+          [
+            "10.0.15.18",
+            "10.0.15.18"
+          ],
+          [
+            "10.0.15.19",
+            "10.0.15.19"
+          ],
+          [
+            "10.0.15.20",
+            "10.0.15.20"
+          ],
+          [
+            "10.0.15.21",
+            "10.0.15.21"
+          ],
+          [
+            "10.0.15.22",
+            "10.0.15.22"
+          ],
+          [
+            "10.0.15.23",
+            "10.0.15.23"
+          ],
+          [
+            "10.0.15.24",
+            "10.0.15.24"
+          ],
+          [
+            "10.0.15.25",
+            "10.0.15.25"
+          ],
+          [
+            "10.0.15.26",
+            "10.0.15.26"
+          ],
+          [
+            "10.0.15.27",
+            "10.0.15.27"
+          ],
+          [
+            "10.0.15.28",
+            "10.0.15.28"
+          ],
+          [
+            "10.0.15.29",
+            "10.0.15.29"
+          ],
+          [
+            "10.0.15.30",
+            "10.0.15.30"
+          ],
+          [
+            "10.0.15.31",
+            "10.0.15.31"
+          ],
+          [
+            "10.0.16.1",
+            "10.0.16.1"
+          ],
+          [
+            "10.0.16.2",
+            "10.0.16.2"
+          ],
+          [
+            "10.0.16.3",
+            "10.0.16.3"
+          ],
+          [
+            "10.0.16.4",
+            "10.0.16.4"
+          ],
+          [
+            "10.0.16.5",
+            "10.0.16.5"
+          ],
+          [
+            "10.0.16.6",
+            "10.0.16.6"
+          ],
+          [
+            "10.0.16.7",
+            "10.0.16.7"
+          ],
+          [
+            "10.0.16.8",
+            "10.0.16.8"
+          ],
+          [
+            "10.0.16.9",
+            "10.0.16.9"
+          ],
+          [
+            "10.0.16.10",
+            "10.0.16.10"
+          ],
+          [
+            "10.0.16.11",
+            "10.0.16.11"
+          ],
+          [
+            "10.0.16.12",
+            "10.0.16.12"
+          ],
+          [
+            "10.0.16.13",
+            "10.0.16.13"
+          ],
+          [
+            "10.0.16.14",
+            "10.0.16.14"
+          ],
+          [
+            "10.0.16.15",
+            "10.0.16.15"
+          ],
+          [
+            "10.0.16.16",
+            "10.0.16.16"
+          ],
+          [
+            "10.0.16.17",
+            "10.0.16.17"
+          ],
+          [
+            "10.0.16.18",
+            "10.0.16.18"
+          ],
+          [
+            "10.0.16.19",
+            "10.0.16.19"
+          ],
+          [
+            "10.0.16.20",
+            "10.0.16.20"
+          ],
+          [
+            "10.0.16.21",
+            "10.0.16.21"
+          ],
+          [
+            "10.0.16.22",
+            "10.0.16.22"
+          ],
+          [
+            "10.0.16.23",
+            "10.0.16.23"
+          ],
+          [
+            "10.0.16.24",
+            "10.0.16.24"
+          ],
+          [
+            "10.0.16.25",
+            "10.0.16.25"
+          ],
+          [
+            "10.0.16.26",
+            "10.0.16.26"
+          ],
+          [
+            "10.0.16.27",
+            "10.0.16.27"
+          ],
+          [
+            "10.0.16.28",
+            "10.0.16.28"
+          ],
+          [
+            "10.0.16.29",
+            "10.0.16.29"
+          ],
+          [
+            "10.0.16.30",
+            "10.0.16.30"
+          ],
+          [
+            "10.0.16.31",
+            "10.0.16.31"
+          ],
+          [
+            "10.0.17.1",
+            "10.0.17.1"
+          ],
+          [
+            "10.0.17.2",
+            "10.0.17.2"
+          ],
+          [
+            "10.0.17.3",
+            "10.0.17.3"
+          ],
+          [
+            "10.0.17.4",
+            "10.0.17.4"
+          ],
+          [
+            "10.0.17.5",
+            "10.0.17.5"
+          ],
+          [
+            "10.0.17.6",
+            "10.0.17.6"
+          ],
+          [
+            "10.0.17.7",
+            "10.0.17.7"
+          ],
+          [
+            "10.0.17.8",
+            "10.0.17.8"
+          ],
+          [
+            "10.0.17.9",
+            "10.0.17.9"
+          ],
+          [
+            "10.0.17.10",
+            "10.0.17.10"
+          ],
+          [
+            "10.0.17.11",
+            "10.0.17.11"
+          ],
+          [
+            "10.0.17.12",
+            "10.0.17.12"
+          ],
+          [
+            "10.0.17.13",
+            "10.0.17.13"
+          ],
+          [
+            "10.0.17.14",
+            "10.0.17.14"
+          ],
+          [
+            "10.0.17.15",
+            "10.0.17.15"
+          ],
+          [
+            "10.0.17.16",
+            "10.0.17.16"
+          ],
+          [
+            "10.0.17.17",
+            "10.0.17.17"
+          ],
+          [
+            "10.0.17.18",
+            "10.0.17.18"
+          ],
+          [
+            "10.0.17.19",
+            "10.0.17.19"
+          ],
+          [
+            "10.0.17.20",
+            "10.0.17.20"
+          ],
+          [
+            "10.0.17.21",
+            "10.0.17.21"
+          ],
+          [
+            "10.0.17.22",
+            "10.0.17.22"
+          ],
+          [
+            "10.0.17.23",
+            "10.0.17.23"
+          ],
+          [
+            "10.0.17.24",
+            "10.0.17.24"
+          ],
+          [
+            "10.0.17.25",
+            "10.0.17.25"
+          ],
+          [
+            "10.0.17.26",
+            "10.0.17.26"
+          ],
+          [
+            "10.0.17.27",
+            "10.0.17.27"
+          ],
+          [
+            "10.0.17.28",
+            "10.0.17.28"
+          ],
+          [
+            "10.0.17.29",
+            "10.0.17.29"
+          ],
+          [
+            "10.0.17.30",
+            "10.0.17.30"
+          ],
+          [
+            "10.0.17.31",
+            "10.0.17.31"
+          ],
+          [
+            "10.0.18.1",
+            "10.0.18.1"
+          ],
+          [
+            "10.0.18.2",
+            "10.0.18.2"
+          ],
+          [
+            "10.0.18.3",
+            "10.0.18.3"
+          ],
+          [
+            "10.0.18.4",
+            "10.0.18.4"
+          ],
+          [
+            "10.0.18.5",
+            "10.0.18.5"
+          ],
+          [
+            "10.0.18.6",
+            "10.0.18.6"
+          ],
+          [
+            "10.0.18.7",
+            "10.0.18.7"
+          ],
+          [
+            "10.0.18.8",
+            "10.0.18.8"
+          ],
+          [
+            "10.0.18.9",
+            "10.0.18.9"
+          ],
+          [
+            "10.0.18.10",
+            "10.0.18.10"
+          ],
+          [
+            "10.0.18.11",
+            "10.0.18.11"
+          ],
+          [
+            "10.0.18.12",
+            "10.0.18.12"
+          ],
+          [
+            "10.0.18.13",
+            "10.0.18.13"
+          ],
+          [
+            "10.0.18.14",
+            "10.0.18.14"
+          ],
+          [
+            "10.0.18.15",
+            "10.0.18.15"
+          ],
+          [
+            "10.0.18.16",
+            "10.0.18.16"
+          ],
+          [
+            "10.0.18.17",
+            "10.0.18.17"
+          ],
+          [
+            "10.0.18.18",
+            "10.0.18.18"
+          ],
+          [
+            "10.0.18.19",
+            "10.0.18.19"
+          ],
+          [
+            "10.0.18.20",
+            "10.0.18.20"
+          ],
+          [
+            "10.0.18.21",
+            "10.0.18.21"
+          ],
+          [
+            "10.0.18.22",
+            "10.0.18.22"
+          ],
+          [
+            "10.0.18.23",
+            "10.0.18.23"
+          ],
+          [
+            "10.0.18.24",
+            "10.0.18.24"
+          ],
+          [
+            "10.0.18.25",
+            "10.0.18.25"
+          ],
+          [
+            "10.0.18.26",
+            "10.0.18.26"
+          ],
+          [
+            "10.0.18.27",
+            "10.0.18.27"
+          ],
+          [
+            "10.0.18.28",
+            "10.0.18.28"
+          ],
+          [
+            "10.0.18.29",
+            "10.0.18.29"
+          ],
+          [
+            "10.0.18.30",
+            "10.0.18.30"
+          ],
+          [
+            "10.0.18.31",
+            "10.0.18.31"
+          ],
+          [
+            "10.0.19.1",
+            "10.0.19.1"
+          ],
+          [
+            "10.0.19.2",
+            "10.0.19.2"
+          ],
+          [
+            "10.0.19.3",
+            "10.0.19.3"
+          ],
+          [
+            "10.0.19.4",
+            "10.0.19.4"
+          ],
+          [
+            "10.0.19.5",
+            "10.0.19.5"
+          ],
+          [
+            "10.0.19.6",
+            "10.0.19.6"
+          ],
+          [
+            "10.0.19.7",
+            "10.0.19.7"
+          ],
+          [
+            "10.0.19.8",
+            "10.0.19.8"
+          ],
+          [
+            "10.0.19.9",
+            "10.0.19.9"
+          ],
+          [
+            "10.0.19.10",
+            "10.0.19.10"
+          ],
+          [
+            "10.0.19.11",
+            "10.0.19.11"
+          ],
+          [
+            "10.0.19.12",
+            "10.0.19.12"
+          ],
+          [
+            "10.0.19.13",
+            "10.0.19.13"
+          ],
+          [
+            "10.0.19.14",
+            "10.0.19.14"
+          ],
+          [
+            "10.0.19.15",
+            "10.0.19.15"
+          ],
+          [
+            "10.0.19.16",
+            "10.0.19.16"
+          ],
+          [
+            "10.0.19.17",
+            "10.0.19.17"
+          ],
+          [
+            "10.0.19.18",
+            "10.0.19.18"
+          ],
+          [
+            "10.0.19.19",
+            "10.0.19.19"
+          ],
+          [
+            "10.0.19.20",
+            "10.0.19.20"
+          ],
+          [
+            "10.0.19.21",
+            "10.0.19.21"
+          ],
+          [
+            "10.0.19.22",
+            "10.0.19.22"
+          ],
+          [
+            "10.0.19.23",
+            "10.0.19.23"
+          ],
+          [
+            "10.0.19.24",
+            "10.0.19.24"
+          ],
+          [
+            "10.0.19.25",
+            "10.0.19.25"
+          ],
+          [
+            "10.0.19.26",
+            "10.0.19.26"
+          ],
+          [
+            "10.0.19.27",
+            "10.0.19.27"
+          ],
+          [
+            "10.0.19.28",
+            "10.0.19.28"
+          ],
+          [
+            "10.0.19.29",
+            "10.0.19.29"
+          ],
+          [
+            "10.0.19.30",
+            "10.0.19.30"
+          ],
+          [
+            "10.0.19.31",
+            "10.0.19.31"
+          ],
+          [
+            "10.0.20.1",
+            "10.0.20.1"
+          ],
+          [
+            "10.0.20.2",
+            "10.0.20.2"
+          ],
+          [
+            "10.0.20.3",
+            "10.0.20.3"
+          ],
+          [
+            "10.0.20.4",
+            "10.0.20.4"
+          ],
+          [
+            "10.0.20.5",
+            "10.0.20.5"
+          ],
+          [
+            "10.0.20.6",
+            "10.0.20.6"
+          ],
+          [
+            "10.0.20.7",
+            "10.0.20.7"
+          ],
+          [
+            "10.0.20.8",
+            "10.0.20.8"
+          ],
+          [
+            "10.0.20.9",
+            "10.0.20.9"
+          ],
+          [
+            "10.0.20.10",
+            "10.0.20.10"
+          ],
+          [
+            "10.0.20.11",
+            "10.0.20.11"
+          ],
+          [
+            "10.0.20.12",
+            "10.0.20.12"
+          ],
+          [
+            "10.0.20.13",
+            "10.0.20.13"
+          ],
+          [
+            "10.0.20.14",
+            "10.0.20.14"
+          ],
+          [
+            "10.0.20.15",
+            "10.0.20.15"
+          ],
+          [
+            "10.0.20.16",
+            "10.0.20.16"
+          ],
+          [
+            "10.0.20.17",
+            "10.0.20.17"
+          ],
+          [
+            "10.0.20.18",
+            "10.0.20.18"
+          ],
+          [
+            "10.0.20.19",
+            "10.0.20.19"
+          ],
+          [
+            "10.0.20.20",
+            "10.0.20.20"
+          ],
+          [
+            "10.0.20.21",
+            "10.0.20.21"
+          ],
+          [
+            "10.0.20.22",
+            "10.0.20.22"
+          ],
+          [
+            "10.0.20.23",
+            "10.0.20.23"
+          ],
+          [
+            "10.0.20.24",
+            "10.0.20.24"
+          ],
+          [
+            "10.0.20.25",
+            "10.0.20.25"
+          ],
+          [
+            "10.0.20.26",
+            "10.0.20.26"
+          ],
+          [
+            "10.0.20.27",
+            "10.0.20.27"
+          ],
+          [
+            "10.0.20.28",
+            "10.0.20.28"
+          ],
+          [
+            "10.0.20.29",
+            "10.0.20.29"
+          ],
+          [
+            "10.0.20.30",
+            "10.0.20.30"
+          ],
+          [
+            "10.0.20.31",
+            "10.0.20.31"
+          ],
+          [
+            "10.0.21.1",
+            "10.0.21.1"
+          ],
+          [
+            "10.0.21.2",
+            "10.0.21.2"
+          ],
+          [
+            "10.0.21.3",
+            "10.0.21.3"
+          ],
+          [
+            "10.0.21.4",
+            "10.0.21.4"
+          ],
+          [
+            "10.0.21.5",
+            "10.0.21.5"
+          ],
+          [
+            "10.0.21.6",
+            "10.0.21.6"
+          ],
+          [
+            "10.0.21.7",
+            "10.0.21.7"
+          ],
+          [
+            "10.0.21.8",
+            "10.0.21.8"
+          ],
+          [
+            "10.0.21.9",
+            "10.0.21.9"
+          ],
+          [
+            "10.0.21.10",
+            "10.0.21.10"
+          ],
+          [
+            "10.0.21.11",
+            "10.0.21.11"
+          ],
+          [
+            "10.0.21.12",
+            "10.0.21.12"
+          ],
+          [
+            "10.0.21.13",
+            "10.0.21.13"
+          ],
+          [
+            "10.0.21.14",
+            "10.0.21.14"
+          ],
+          [
+            "10.0.21.15",
+            "10.0.21.15"
+          ],
+          [
+            "10.0.21.16",
+            "10.0.21.16"
+          ],
+          [
+            "10.0.21.17",
+            "10.0.21.17"
+          ],
+          [
+            "10.0.21.18",
+            "10.0.21.18"
+          ],
+          [
+            "10.0.21.19",
+            "10.0.21.19"
+          ],
+          [
+            "10.0.21.20",
+            "10.0.21.20"
+          ],
+          [
+            "10.0.21.21",
+            "10.0.21.21"
+          ],
+          [
+            "10.0.21.22",
+            "10.0.21.22"
+          ],
+          [
+            "10.0.21.23",
+            "10.0.21.23"
+          ],
+          [
+            "10.0.21.24",
+            "10.0.21.24"
+          ],
+          [
+            "10.0.21.25",
+            "10.0.21.25"
+          ],
+          [
+            "10.0.21.26",
+            "10.0.21.26"
+          ],
+          [
+            "10.0.21.27",
+            "10.0.21.27"
+          ],
+          [
+            "10.0.21.28",
+            "10.0.21.28"
+          ],
+          [
+            "10.0.21.29",
+            "10.0.21.29"
+          ],
+          [
+            "10.0.21.30",
+            "10.0.21.30"
+          ],
+          [
+            "10.0.21.31",
+            "10.0.21.31"
+          ],
+          [
+            "10.0.22.1",
+            "10.0.22.1"
+          ],
+          [
+            "10.0.22.2",
+            "10.0.22.2"
+          ],
+          [
+            "10.0.22.3",
+            "10.0.22.3"
+          ],
+          [
+            "10.0.22.4",
+            "10.0.22.4"
+          ],
+          [
+            "10.0.22.5",
+            "10.0.22.5"
+          ],
+          [
+            "10.0.22.6",
+            "10.0.22.6"
+          ],
+          [
+            "10.0.22.7",
+            "10.0.22.7"
+          ],
+          [
+            "10.0.22.8",
+            "10.0.22.8"
+          ],
+          [
+            "10.0.22.9",
+            "10.0.22.9"
+          ],
+          [
+            "10.0.22.10",
+            "10.0.22.10"
+          ],
+          [
+            "10.0.22.11",
+            "10.0.22.11"
+          ],
+          [
+            "10.0.22.12",
+            "10.0.22.12"
+          ],
+          [
+            "10.0.22.13",
+            "10.0.22.13"
+          ],
+          [
+            "10.0.22.14",
+            "10.0.22.14"
+          ],
+          [
+            "10.0.22.15",
+            "10.0.22.15"
+          ],
+          [
+            "10.0.22.16",
+            "10.0.22.16"
+          ],
+          [
+            "10.0.22.17",
+            "10.0.22.17"
+          ],
+          [
+            "10.0.22.18",
+            "10.0.22.18"
+          ],
+          [
+            "10.0.22.19",
+            "10.0.22.19"
+          ],
+          [
+            "10.0.22.20",
+            "10.0.22.20"
+          ],
+          [
+            "10.0.22.21",
+            "10.0.22.21"
+          ],
+          [
+            "10.0.22.22",
+            "10.0.22.22"
+          ],
+          [
+            "10.0.22.23",
+            "10.0.22.23"
+          ],
+          [
+            "10.0.22.24",
+            "10.0.22.24"
+          ],
+          [
+            "10.0.22.25",
+            "10.0.22.25"
+          ],
+          [
+            "10.0.22.26",
+            "10.0.22.26"
+          ],
+          [
+            "10.0.22.27",
+            "10.0.22.27"
+          ],
+          [
+            "10.0.22.28",
+            "10.0.22.28"
+          ],
+          [
+            "10.0.22.29",
+            "10.0.22.29"
+          ],
+          [
+            "10.0.22.30",
+            "10.0.22.30"
+          ],
+          [
+            "10.0.22.31",
+            "10.0.22.31"
+          ],
+          [
+            "10.0.23.1",
+            "10.0.23.1"
+          ],
+          [
+            "10.0.23.2",
+            "10.0.23.2"
+          ],
+          [
+            "10.0.23.3",
+            "10.0.23.3"
+          ],
+          [
+            "10.0.23.4",
+            "10.0.23.4"
+          ],
+          [
+            "10.0.23.5",
+            "10.0.23.5"
+          ],
+          [
+            "10.0.23.6",
+            "10.0.23.6"
+          ],
+          [
+            "10.0.23.7",
+            "10.0.23.7"
+          ],
+          [
+            "10.0.23.8",
+            "10.0.23.8"
+          ],
+          [
+            "10.0.23.9",
+            "10.0.23.9"
+          ],
+          [
+            "10.0.23.10",
+            "10.0.23.10"
+          ],
+          [
+            "10.0.23.11",
+            "10.0.23.11"
+          ],
+          [
+            "10.0.23.12",
+            "10.0.23.12"
+          ],
+          [
+            "10.0.23.13",
+            "10.0.23.13"
+          ],
+          [
+            "10.0.23.14",
+            "10.0.23.14"
+          ],
+          [
+            "10.0.23.15",
+            "10.0.23.15"
+          ],
+          [
+            "10.0.23.16",
+            "10.0.23.16"
+          ],
+          [
+            "10.0.23.17",
+            "10.0.23.17"
+          ],
+          [
+            "10.0.23.18",
+            "10.0.23.18"
+          ],
+          [
+            "10.0.23.19",
+            "10.0.23.19"
+          ],
+          [
+            "10.0.23.20",
+            "10.0.23.20"
+          ],
+          [
+            "10.0.23.21",
+            "10.0.23.21"
+          ],
+          [
+            "10.0.23.22",
+            "10.0.23.22"
+          ],
+          [
+            "10.0.23.23",
+            "10.0.23.23"
+          ],
+          [
+            "10.0.23.24",
+            "10.0.23.24"
+          ],
+          [
+            "10.0.23.25",
+            "10.0.23.25"
+          ],
+          [
+            "10.0.23.26",
+            "10.0.23.26"
+          ],
+          [
+            "10.0.23.27",
+            "10.0.23.27"
+          ],
+          [
+            "10.0.23.28",
+            "10.0.23.28"
+          ],
+          [
+            "10.0.23.29",
+            "10.0.23.29"
+          ],
+          [
+            "10.0.23.30",
+            "10.0.23.30"
+          ],
+          [
+            "10.0.23.31",
+            "10.0.23.31"
+          ],
+          [
+            "10.0.24.1",
+            "10.0.24.1"
+          ],
+          [
+            "10.0.24.2",
+            "10.0.24.2"
+          ],
+          [
+            "10.0.24.3",
+            "10.0.24.3"
+          ],
+          [
+            "10.0.24.4",
+            "10.0.24.4"
+          ],
+          [
+            "10.0.24.5",
+            "10.0.24.5"
+          ],
+          [
+            "10.0.24.6",
+            "10.0.24.6"
+          ],
+          [
+            "10.0.24.7",
+            "10.0.24.7"
+          ],
+          [
+            "10.0.24.8",
+            "10.0.24.8"
+          ],
+          [
+            "10.0.24.9",
+            "10.0.24.9"
+          ],
+          [
+            "10.0.24.10",
+            "10.0.24.10"
+          ],
+          [
+            "10.0.24.11",
+            "10.0.24.11"
+          ],
+          [
+            "10.0.24.12",
+            "10.0.24.12"
+          ],
+          [
+            "10.0.24.13",
+            "10.0.24.13"
+          ],
+          [
+            "10.0.24.14",
+            "10.0.24.14"
+          ],
+          [
+            "10.0.24.15",
+            "10.0.24.15"
+          ],
+          [
+            "10.0.24.16",
+            "10.0.24.16"
+          ],
+          [
+            "10.0.24.17",
+            "10.0.24.17"
+          ],
+          [
+            "10.0.24.18",
+            "10.0.24.18"
+          ],
+          [
+            "10.0.24.19",
+            "10.0.24.19"
+          ],
+          [
+            "10.0.24.20",
+            "10.0.24.20"
+          ],
+          [
+            "10.0.24.21",
+            "10.0.24.21"
+          ],
+          [
+            "10.0.24.22",
+            "10.0.24.22"
+          ],
+          [
+            "10.0.24.23",
+            "10.0.24.23"
+          ],
+          [
+            "10.0.24.24",
+            "10.0.24.24"
+          ],
+          [
+            "10.0.24.25",
+            "10.0.24.25"
+          ],
+          [
+            "10.0.24.26",
+            "10.0.24.26"
+          ],
+          [
+            "10.0.24.27",
+            "10.0.24.27"
+          ],
+          [
+            "10.0.24.28",
+            "10.0.24.28"
+          ],
+          [
+            "10.0.24.29",
+            "10.0.24.29"
+          ],
+          [
+            "10.0.24.30",
+            "10.0.24.30"
+          ],
+          [
+            "10.0.24.31",
+            "10.0.24.31"
+          ],
+          [
+            "10.0.25.1",
+            "10.0.25.1"
+          ],
+          [
+            "10.0.25.2",
+            "10.0.25.2"
+          ],
+          [
+            "10.0.25.3",
+            "10.0.25.3"
+          ],
+          [
+            "10.0.25.4",
+            "10.0.25.4"
+          ],
+          [
+            "10.0.25.5",
+            "10.0.25.5"
+          ],
+          [
+            "10.0.25.6",
+            "10.0.25.6"
+          ],
+          [
+            "10.0.25.7",
+            "10.0.25.7"
+          ],
+          [
+            "10.0.25.8",
+            "10.0.25.8"
+          ],
+          [
+            "10.0.25.9",
+            "10.0.25.9"
+          ],
+          [
+            "10.0.25.10",
+            "10.0.25.10"
+          ],
+          [
+            "10.0.25.11",
+            "10.0.25.11"
+          ],
+          [
+            "10.0.25.12",
+            "10.0.25.12"
+          ],
+          [
+            "10.0.25.13",
+            "10.0.25.13"
+          ],
+          [
+            "10.0.25.14",
+            "10.0.25.14"
+          ],
+          [
+            "10.0.25.15",
+            "10.0.25.15"
+          ],
+          [
+            "10.0.25.16",
+            "10.0.25.16"
+          ],
+          [
+            "10.0.25.17",
+            "10.0.25.17"
+          ],
+          [
+            "10.0.25.18",
+            "10.0.25.18"
+          ],
+          [
+            "10.0.25.19",
+            "10.0.25.19"
+          ],
+          [
+            "10.0.25.20",
+            "10.0.25.20"
+          ],
+          [
+            "10.0.25.21",
+            "10.0.25.21"
+          ],
+          [
+            "10.0.25.22",
+            "10.0.25.22"
+          ],
+          [
+            "10.0.25.23",
+            "10.0.25.23"
+          ],
+          [
+            "10.0.25.24",
+            "10.0.25.24"
+          ],
+          [
+            "10.0.25.25",
+            "10.0.25.25"
+          ],
+          [
+            "10.0.25.26",
+            "10.0.25.26"
+          ],
+          [
+            "10.0.25.27",
+            "10.0.25.27"
+          ],
+          [
+            "10.0.25.28",
+            "10.0.25.28"
+          ],
+          [
+            "10.0.25.29",
+            "10.0.25.29"
+          ],
+          [
+            "10.0.25.30",
+            "10.0.25.30"
+          ],
+          [
+            "10.0.25.31",
+            "10.0.25.31"
+          ],
+          [
+            "10.0.26.1",
+            "10.0.26.1"
+          ],
+          [
+            "10.0.26.2",
+            "10.0.26.2"
+          ],
+          [
+            "10.0.26.3",
+            "10.0.26.3"
+          ],
+          [
+            "10.0.26.4",
+            "10.0.26.4"
+          ],
+          [
+            "10.0.26.5",
+            "10.0.26.5"
+          ],
+          [
+            "10.0.26.6",
+            "10.0.26.6"
+          ],
+          [
+            "10.0.26.7",
+            "10.0.26.7"
+          ],
+          [
+            "10.0.26.8",
+            "10.0.26.8"
+          ],
+          [
+            "10.0.26.9",
+            "10.0.26.9"
+          ],
+          [
+            "10.0.26.10",
+            "10.0.26.10"
+          ],
+          [
+            "10.0.26.11",
+            "10.0.26.11"
+          ],
+          [
+            "10.0.26.12",
+            "10.0.26.12"
+          ],
+          [
+            "10.0.26.13",
+            "10.0.26.13"
+          ],
+          [
+            "10.0.26.14",
+            "10.0.26.14"
+          ],
+          [
+            "10.0.26.15",
+            "10.0.26.15"
+          ],
+          [
+            "10.0.26.16",
+            "10.0.26.16"
+          ],
+          [
+            "10.0.26.17",
+            "10.0.26.17"
+          ],
+          [
+            "10.0.26.18",
+            "10.0.26.18"
+          ],
+          [
+            "10.0.26.19",
+            "10.0.26.19"
+          ],
+          [
+            "10.0.26.20",
+            "10.0.26.20"
+          ],
+          [
+            "10.0.26.21",
+            "10.0.26.21"
+          ],
+          [
+            "10.0.26.22",
+            "10.0.26.22"
+          ],
+          [
+            "10.0.26.23",
+            "10.0.26.23"
+          ],
+          [
+            "10.0.26.24",
+            "10.0.26.24"
+          ],
+          [
+            "10.0.26.25",
+            "10.0.26.25"
+          ],
+          [
+            "10.0.26.26",
+            "10.0.26.26"
+          ],
+          [
+            "10.0.26.27",
+            "10.0.26.27"
+          ],
+          [
+            "10.0.26.28",
+            "10.0.26.28"
+          ],
+          [
+            "10.0.26.29",
+            "10.0.26.29"
+          ],
+          [
+            "10.0.26.30",
+            "10.0.26.30"
+          ],
+          [
+            "10.0.26.31",
+            "10.0.26.31"
+          ],
+          [
+            "10.0.27.1",
+            "10.0.27.1"
+          ],
+          [
+            "10.0.27.2",
+            "10.0.27.2"
+          ],
+          [
+            "10.0.27.3",
+            "10.0.27.3"
+          ],
+          [
+            "10.0.27.4",
+            "10.0.27.4"
+          ],
+          [
+            "10.0.27.5",
+            "10.0.27.5"
+          ],
+          [
+            "10.0.27.6",
+            "10.0.27.6"
+          ],
+          [
+            "10.0.27.7",
+            "10.0.27.7"
+          ],
+          [
+            "10.0.27.8",
+            "10.0.27.8"
+          ],
+          [
+            "10.0.27.9",
+            "10.0.27.9"
+          ],
+          [
+            "10.0.27.10",
+            "10.0.27.10"
+          ],
+          [
+            "10.0.27.11",
+            "10.0.27.11"
+          ],
+          [
+            "10.0.27.12",
+            "10.0.27.12"
+          ],
+          [
+            "10.0.27.13",
+            "10.0.27.13"
+          ],
+          [
+            "10.0.27.14",
+            "10.0.27.14"
+          ],
+          [
+            "10.0.27.15",
+            "10.0.27.15"
+          ],
+          [
+            "10.0.27.16",
+            "10.0.27.16"
+          ],
+          [
+            "10.0.27.17",
+            "10.0.27.17"
+          ],
+          [
+            "10.0.27.18",
+            "10.0.27.18"
+          ],
+          [
+            "10.0.27.19",
+            "10.0.27.19"
+          ],
+          [
+            "10.0.27.20",
+            "10.0.27.20"
+          ],
+          [
+            "10.0.27.21",
+            "10.0.27.21"
+          ],
+          [
+            "10.0.27.22",
+            "10.0.27.22"
+          ],
+          [
+            "10.0.27.23",
+            "10.0.27.23"
+          ],
+          [
+            "10.0.27.24",
+            "10.0.27.24"
+          ],
+          [
+            "10.0.27.25",
+            "10.0.27.25"
+          ],
+          [
+            "10.0.27.26",
+            "10.0.27.26"
+          ],
+          [
+            "10.0.27.27",
+            "10.0.27.27"
+          ],
+          [
+            "10.0.27.28",
+            "10.0.27.28"
+          ],
+          [
+            "10.0.27.29",
+            "10.0.27.29"
+          ],
+          [
+            "10.0.27.30",
+            "10.0.27.30"
+          ],
+          [
+            "10.0.27.31",
+            "10.0.27.31"
+          ],
+          [
+            "10.0.28.1",
+            "10.0.28.1"
+          ],
+          [
+            "10.0.28.2",
+            "10.0.28.2"
+          ],
+          [
+            "10.0.28.3",
+            "10.0.28.3"
+          ],
+          [
+            "10.0.28.4",
+            "10.0.28.4"
+          ],
+          [
+            "10.0.28.5",
+            "10.0.28.5"
+          ],
+          [
+            "10.0.28.6",
+            "10.0.28.6"
+          ],
+          [
+            "10.0.28.7",
+            "10.0.28.7"
+          ],
+          [
+            "10.0.28.8",
+            "10.0.28.8"
+          ],
+          [
+            "10.0.28.9",
+            "10.0.28.9"
+          ],
+          [
+            "10.0.28.10",
+            "10.0.28.10"
+          ],
+          [
+            "10.0.28.11",
+            "10.0.28.11"
+          ],
+          [
+            "10.0.28.12",
+            "10.0.28.12"
+          ],
+          [
+            "10.0.28.13",
+            "10.0.28.13"
+          ],
+          [
+            "10.0.28.14",
+            "10.0.28.14"
+          ],
+          [
+            "10.0.28.15",
+            "10.0.28.15"
+          ],
+          [
+            "10.0.28.16",
+            "10.0.28.16"
+          ],
+          [
+            "10.0.28.17",
+            "10.0.28.17"
+          ],
+          [
+            "10.0.28.18",
+            "10.0.28.18"
+          ],
+          [
+            "10.0.28.19",
+            "10.0.28.19"
+          ],
+          [
+            "10.0.28.20",
+            "10.0.28.20"
+          ],
+          [
+            "10.0.28.21",
+            "10.0.28.21"
+          ],
+          [
+            "10.0.28.22",
+            "10.0.28.22"
+          ],
+          [
+            "10.0.28.23",
+            "10.0.28.23"
+          ],
+          [
+            "10.0.28.24",
+            "10.0.28.24"
+          ],
+          [
+            "10.0.28.25",
+            "10.0.28.25"
+          ],
+          [
+            "10.0.28.26",
+            "10.0.28.26"
+          ],
+          [
+            "10.0.28.27",
+            "10.0.28.27"
+          ],
+          [
+            "10.0.28.28",
+            "10.0.28.28"
+          ],
+          [
+            "10.0.28.29",
+            "10.0.28.29"
+          ],
+          [
+            "10.0.28.30",
+            "10.0.28.30"
+          ],
+          [
+            "10.0.28.31",
+            "10.0.28.31"
+          ],
+          [
+            "10.0.29.1",
+            "10.0.29.1"
+          ],
+          [
+            "10.0.29.2",
+            "10.0.29.2"
+          ],
+          [
+            "10.0.29.3",
+            "10.0.29.3"
+          ],
+          [
+            "10.0.29.4",
+            "10.0.29.4"
+          ],
+          [
+            "10.0.29.5",
+            "10.0.29.5"
+          ],
+          [
+            "10.0.29.6",
+            "10.0.29.6"
+          ],
+          [
+            "10.0.29.7",
+            "10.0.29.7"
+          ],
+          [
+            "10.0.29.8",
+            "10.0.29.8"
+          ],
+          [
+            "10.0.29.9",
+            "10.0.29.9"
+          ],
+          [
+            "10.0.29.10",
+            "10.0.29.10"
+          ],
+          [
+            "10.0.29.11",
+            "10.0.29.11"
+          ],
+          [
+            "10.0.29.12",
+            "10.0.29.12"
+          ],
+          [
+            "10.0.29.13",
+            "10.0.29.13"
+          ],
+          [
+            "10.0.29.14",
+            "10.0.29.14"
+          ],
+          [
+            "10.0.29.15",
+            "10.0.29.15"
+          ],
+          [
+            "10.0.29.16",
+            "10.0.29.16"
+          ],
+          [
+            "10.0.29.17",
+            "10.0.29.17"
+          ],
+          [
+            "10.0.29.18",
+            "10.0.29.18"
+          ],
+          [
+            "10.0.29.19",
+            "10.0.29.19"
+          ],
+          [
+            "10.0.29.20",
+            "10.0.29.20"
+          ],
+          [
+            "10.0.29.21",
+            "10.0.29.21"
+          ],
+          [
+            "10.0.29.22",
+            "10.0.29.22"
+          ],
+          [
+            "10.0.29.23",
+            "10.0.29.23"
+          ],
+          [
+            "10.0.29.24",
+            "10.0.29.24"
+          ],
+          [
+            "10.0.29.25",
+            "10.0.29.25"
+          ],
+          [
+            "10.0.29.26",
+            "10.0.29.26"
+          ],
+          [
+            "10.0.29.27",
+            "10.0.29.27"
+          ],
+          [
+            "10.0.29.28",
+            "10.0.29.28"
+          ],
+          [
+            "10.0.29.29",
+            "10.0.29.29"
+          ],
+          [
+            "10.0.29.30",
+            "10.0.29.30"
+          ],
+          [
+            "10.0.29.31",
+            "10.0.29.31"
+          ],
+          [
+            "10.0.30.1",
+            "10.0.30.1"
+          ],
+          [
+            "10.0.30.2",
+            "10.0.30.2"
+          ],
+          [
+            "10.0.30.3",
+            "10.0.30.3"
+          ],
+          [
+            "10.0.30.4",
+            "10.0.30.4"
+          ],
+          [
+            "10.0.30.5",
+            "10.0.30.5"
+          ],
+          [
+            "10.0.30.6",
+            "10.0.30.6"
+          ],
+          [
+            "10.0.30.7",
+            "10.0.30.7"
+          ],
+          [
+            "10.0.30.8",
+            "10.0.30.8"
+          ],
+          [
+            "10.0.30.9",
+            "10.0.30.9"
+          ],
+          [
+            "10.0.30.10",
+            "10.0.30.10"
+          ],
+          [
+            "10.0.30.11",
+            "10.0.30.11"
+          ],
+          [
+            "10.0.30.12",
+            "10.0.30.12"
+          ],
+          [
+            "10.0.30.13",
+            "10.0.30.13"
+          ],
+          [
+            "10.0.30.14",
+            "10.0.30.14"
+          ],
+          [
+            "10.0.30.15",
+            "10.0.30.15"
+          ],
+          [
+            "10.0.30.16",
+            "10.0.30.16"
+          ],
+          [
+            "10.0.30.17",
+            "10.0.30.17"
+          ],
+          [
+            "10.0.30.18",
+            "10.0.30.18"
+          ],
+          [
+            "10.0.30.19",
+            "10.0.30.19"
+          ],
+          [
+            "10.0.30.20",
+            "10.0.30.20"
+          ],
+          [
+            "10.0.30.21",
+            "10.0.30.21"
+          ],
+          [
+            "10.0.30.22",
+            "10.0.30.22"
+          ],
+          [
+            "10.0.30.23",
+            "10.0.30.23"
+          ],
+          [
+            "10.0.30.24",
+            "10.0.30.24"
+          ],
+          [
+            "10.0.30.25",
+            "10.0.30.25"
+          ],
+          [
+            "10.0.30.26",
+            "10.0.30.26"
+          ],
+          [
+            "10.0.30.27",
+            "10.0.30.27"
+          ],
+          [
+            "10.0.30.28",
+            "10.0.30.28"
+          ],
+          [
+            "10.0.30.29",
+            "10.0.30.29"
+          ],
+          [
+            "10.0.30.30",
+            "10.0.30.30"
+          ],
+          [
+            "10.0.30.31",
+            "10.0.30.31"
+          ],
+          [
+            "10.0.31.1",
+            "10.0.31.1"
+          ],
+          [
+            "10.0.31.2",
+            "10.0.31.2"
+          ],
+          [
+            "10.0.31.3",
+            "10.0.31.3"
+          ],
+          [
+            "10.0.31.4",
+            "10.0.31.4"
+          ],
+          [
+            "10.0.31.5",
+            "10.0.31.5"
+          ],
+          [
+            "10.0.31.6",
+            "10.0.31.6"
+          ],
+          [
+            "10.0.31.7",
+            "10.0.31.7"
+          ],
+          [
+            "10.0.31.8",
+            "10.0.31.8"
+          ],
+          [
+            "10.0.31.9",
+            "10.0.31.9"
+          ],
+          [
+            "10.0.31.10",
+            "10.0.31.10"
+          ],
+          [
+            "10.0.31.11",
+            "10.0.31.11"
+          ],
+          [
+            "10.0.31.12",
+            "10.0.31.12"
+          ],
+          [
+            "10.0.31.13",
+            "10.0.31.13"
+          ],
+          [
+            "10.0.31.14",
+            "10.0.31.14"
+          ],
+          [
+            "10.0.31.15",
+            "10.0.31.15"
+          ],
+          [
+            "10.0.31.16",
+            "10.0.31.16"
+          ],
+          [
+            "10.0.31.17",
+            "10.0.31.17"
+          ],
+          [
+            "10.0.31.18",
+            "10.0.31.18"
+          ],
+          [
+            "10.0.31.19",
+            "10.0.31.19"
+          ],
+          [
+            "10.0.31.20",
+            "10.0.31.20"
+          ],
+          [
+            "10.0.31.21",
+            "10.0.31.21"
+          ],
+          [
+            "10.0.31.22",
+            "10.0.31.22"
+          ],
+          [
+            "10.0.31.23",
+            "10.0.31.23"
+          ],
+          [
+            "10.0.31.24",
+            "10.0.31.24"
+          ],
+          [
+            "10.0.31.25",
+            "10.0.31.25"
+          ],
+          [
+            "10.0.31.26",
+            "10.0.31.26"
+          ],
+          [
+            "10.0.31.27",
+            "10.0.31.27"
+          ],
+          [
+            "10.0.31.28",
+            "10.0.31.28"
+          ],
+          [
+            "10.0.31.29",
+            "10.0.31.29"
+          ],
+          [
+            "10.0.31.30",
+            "10.0.31.30"
+          ],
+          [
+            "10.0.31.31",
+            "10.0.31.31"
+          ]
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0003map_add_many_elements_0.nft b/tests/shell/testcases/maps/dumps/0003map_add_many_elements_0.nft
new file mode 100644 (file)
index 0000000..bd6e05d
--- /dev/null
@@ -0,0 +1,966 @@
+table ip x {
+       map y {
+               type ipv4_addr : ipv4_addr
+               elements = { 10.0.1.1 : 10.0.1.1,
+                            10.0.1.2 : 10.0.1.2,
+                            10.0.1.3 : 10.0.1.3,
+                            10.0.1.4 : 10.0.1.4,
+                            10.0.1.5 : 10.0.1.5,
+                            10.0.1.6 : 10.0.1.6,
+                            10.0.1.7 : 10.0.1.7,
+                            10.0.1.8 : 10.0.1.8,
+                            10.0.1.9 : 10.0.1.9,
+                            10.0.1.10 : 10.0.1.10,
+                            10.0.1.11 : 10.0.1.11,
+                            10.0.1.12 : 10.0.1.12,
+                            10.0.1.13 : 10.0.1.13,
+                            10.0.1.14 : 10.0.1.14,
+                            10.0.1.15 : 10.0.1.15,
+                            10.0.1.16 : 10.0.1.16,
+                            10.0.1.17 : 10.0.1.17,
+                            10.0.1.18 : 10.0.1.18,
+                            10.0.1.19 : 10.0.1.19,
+                            10.0.1.20 : 10.0.1.20,
+                            10.0.1.21 : 10.0.1.21,
+                            10.0.1.22 : 10.0.1.22,
+                            10.0.1.23 : 10.0.1.23,
+                            10.0.1.24 : 10.0.1.24,
+                            10.0.1.25 : 10.0.1.25,
+                            10.0.1.26 : 10.0.1.26,
+                            10.0.1.27 : 10.0.1.27,
+                            10.0.1.28 : 10.0.1.28,
+                            10.0.1.29 : 10.0.1.29,
+                            10.0.1.30 : 10.0.1.30,
+                            10.0.1.31 : 10.0.1.31,
+                            10.0.2.1 : 10.0.2.1,
+                            10.0.2.2 : 10.0.2.2,
+                            10.0.2.3 : 10.0.2.3,
+                            10.0.2.4 : 10.0.2.4,
+                            10.0.2.5 : 10.0.2.5,
+                            10.0.2.6 : 10.0.2.6,
+                            10.0.2.7 : 10.0.2.7,
+                            10.0.2.8 : 10.0.2.8,
+                            10.0.2.9 : 10.0.2.9,
+                            10.0.2.10 : 10.0.2.10,
+                            10.0.2.11 : 10.0.2.11,
+                            10.0.2.12 : 10.0.2.12,
+                            10.0.2.13 : 10.0.2.13,
+                            10.0.2.14 : 10.0.2.14,
+                            10.0.2.15 : 10.0.2.15,
+                            10.0.2.16 : 10.0.2.16,
+                            10.0.2.17 : 10.0.2.17,
+                            10.0.2.18 : 10.0.2.18,
+                            10.0.2.19 : 10.0.2.19,
+                            10.0.2.20 : 10.0.2.20,
+                            10.0.2.21 : 10.0.2.21,
+                            10.0.2.22 : 10.0.2.22,
+                            10.0.2.23 : 10.0.2.23,
+                            10.0.2.24 : 10.0.2.24,
+                            10.0.2.25 : 10.0.2.25,
+                            10.0.2.26 : 10.0.2.26,
+                            10.0.2.27 : 10.0.2.27,
+                            10.0.2.28 : 10.0.2.28,
+                            10.0.2.29 : 10.0.2.29,
+                            10.0.2.30 : 10.0.2.30,
+                            10.0.2.31 : 10.0.2.31,
+                            10.0.3.1 : 10.0.3.1,
+                            10.0.3.2 : 10.0.3.2,
+                            10.0.3.3 : 10.0.3.3,
+                            10.0.3.4 : 10.0.3.4,
+                            10.0.3.5 : 10.0.3.5,
+                            10.0.3.6 : 10.0.3.6,
+                            10.0.3.7 : 10.0.3.7,
+                            10.0.3.8 : 10.0.3.8,
+                            10.0.3.9 : 10.0.3.9,
+                            10.0.3.10 : 10.0.3.10,
+                            10.0.3.11 : 10.0.3.11,
+                            10.0.3.12 : 10.0.3.12,
+                            10.0.3.13 : 10.0.3.13,
+                            10.0.3.14 : 10.0.3.14,
+                            10.0.3.15 : 10.0.3.15,
+                            10.0.3.16 : 10.0.3.16,
+                            10.0.3.17 : 10.0.3.17,
+                            10.0.3.18 : 10.0.3.18,
+                            10.0.3.19 : 10.0.3.19,
+                            10.0.3.20 : 10.0.3.20,
+                            10.0.3.21 : 10.0.3.21,
+                            10.0.3.22 : 10.0.3.22,
+                            10.0.3.23 : 10.0.3.23,
+                            10.0.3.24 : 10.0.3.24,
+                            10.0.3.25 : 10.0.3.25,
+                            10.0.3.26 : 10.0.3.26,
+                            10.0.3.27 : 10.0.3.27,
+                            10.0.3.28 : 10.0.3.28,
+                            10.0.3.29 : 10.0.3.29,
+                            10.0.3.30 : 10.0.3.30,
+                            10.0.3.31 : 10.0.3.31,
+                            10.0.4.1 : 10.0.4.1,
+                            10.0.4.2 : 10.0.4.2,
+                            10.0.4.3 : 10.0.4.3,
+                            10.0.4.4 : 10.0.4.4,
+                            10.0.4.5 : 10.0.4.5,
+                            10.0.4.6 : 10.0.4.6,
+                            10.0.4.7 : 10.0.4.7,
+                            10.0.4.8 : 10.0.4.8,
+                            10.0.4.9 : 10.0.4.9,
+                            10.0.4.10 : 10.0.4.10,
+                            10.0.4.11 : 10.0.4.11,
+                            10.0.4.12 : 10.0.4.12,
+                            10.0.4.13 : 10.0.4.13,
+                            10.0.4.14 : 10.0.4.14,
+                            10.0.4.15 : 10.0.4.15,
+                            10.0.4.16 : 10.0.4.16,
+                            10.0.4.17 : 10.0.4.17,
+                            10.0.4.18 : 10.0.4.18,
+                            10.0.4.19 : 10.0.4.19,
+                            10.0.4.20 : 10.0.4.20,
+                            10.0.4.21 : 10.0.4.21,
+                            10.0.4.22 : 10.0.4.22,
+                            10.0.4.23 : 10.0.4.23,
+                            10.0.4.24 : 10.0.4.24,
+                            10.0.4.25 : 10.0.4.25,
+                            10.0.4.26 : 10.0.4.26,
+                            10.0.4.27 : 10.0.4.27,
+                            10.0.4.28 : 10.0.4.28,
+                            10.0.4.29 : 10.0.4.29,
+                            10.0.4.30 : 10.0.4.30,
+                            10.0.4.31 : 10.0.4.31,
+                            10.0.5.1 : 10.0.5.1,
+                            10.0.5.2 : 10.0.5.2,
+                            10.0.5.3 : 10.0.5.3,
+                            10.0.5.4 : 10.0.5.4,
+                            10.0.5.5 : 10.0.5.5,
+                            10.0.5.6 : 10.0.5.6,
+                            10.0.5.7 : 10.0.5.7,
+                            10.0.5.8 : 10.0.5.8,
+                            10.0.5.9 : 10.0.5.9,
+                            10.0.5.10 : 10.0.5.10,
+                            10.0.5.11 : 10.0.5.11,
+                            10.0.5.12 : 10.0.5.12,
+                            10.0.5.13 : 10.0.5.13,
+                            10.0.5.14 : 10.0.5.14,
+                            10.0.5.15 : 10.0.5.15,
+                            10.0.5.16 : 10.0.5.16,
+                            10.0.5.17 : 10.0.5.17,
+                            10.0.5.18 : 10.0.5.18,
+                            10.0.5.19 : 10.0.5.19,
+                            10.0.5.20 : 10.0.5.20,
+                            10.0.5.21 : 10.0.5.21,
+                            10.0.5.22 : 10.0.5.22,
+                            10.0.5.23 : 10.0.5.23,
+                            10.0.5.24 : 10.0.5.24,
+                            10.0.5.25 : 10.0.5.25,
+                            10.0.5.26 : 10.0.5.26,
+                            10.0.5.27 : 10.0.5.27,
+                            10.0.5.28 : 10.0.5.28,
+                            10.0.5.29 : 10.0.5.29,
+                            10.0.5.30 : 10.0.5.30,
+                            10.0.5.31 : 10.0.5.31,
+                            10.0.6.1 : 10.0.6.1,
+                            10.0.6.2 : 10.0.6.2,
+                            10.0.6.3 : 10.0.6.3,
+                            10.0.6.4 : 10.0.6.4,
+                            10.0.6.5 : 10.0.6.5,
+                            10.0.6.6 : 10.0.6.6,
+                            10.0.6.7 : 10.0.6.7,
+                            10.0.6.8 : 10.0.6.8,
+                            10.0.6.9 : 10.0.6.9,
+                            10.0.6.10 : 10.0.6.10,
+                            10.0.6.11 : 10.0.6.11,
+                            10.0.6.12 : 10.0.6.12,
+                            10.0.6.13 : 10.0.6.13,
+                            10.0.6.14 : 10.0.6.14,
+                            10.0.6.15 : 10.0.6.15,
+                            10.0.6.16 : 10.0.6.16,
+                            10.0.6.17 : 10.0.6.17,
+                            10.0.6.18 : 10.0.6.18,
+                            10.0.6.19 : 10.0.6.19,
+                            10.0.6.20 : 10.0.6.20,
+                            10.0.6.21 : 10.0.6.21,
+                            10.0.6.22 : 10.0.6.22,
+                            10.0.6.23 : 10.0.6.23,
+                            10.0.6.24 : 10.0.6.24,
+                            10.0.6.25 : 10.0.6.25,
+                            10.0.6.26 : 10.0.6.26,
+                            10.0.6.27 : 10.0.6.27,
+                            10.0.6.28 : 10.0.6.28,
+                            10.0.6.29 : 10.0.6.29,
+                            10.0.6.30 : 10.0.6.30,
+                            10.0.6.31 : 10.0.6.31,
+                            10.0.7.1 : 10.0.7.1,
+                            10.0.7.2 : 10.0.7.2,
+                            10.0.7.3 : 10.0.7.3,
+                            10.0.7.4 : 10.0.7.4,
+                            10.0.7.5 : 10.0.7.5,
+                            10.0.7.6 : 10.0.7.6,
+                            10.0.7.7 : 10.0.7.7,
+                            10.0.7.8 : 10.0.7.8,
+                            10.0.7.9 : 10.0.7.9,
+                            10.0.7.10 : 10.0.7.10,
+                            10.0.7.11 : 10.0.7.11,
+                            10.0.7.12 : 10.0.7.12,
+                            10.0.7.13 : 10.0.7.13,
+                            10.0.7.14 : 10.0.7.14,
+                            10.0.7.15 : 10.0.7.15,
+                            10.0.7.16 : 10.0.7.16,
+                            10.0.7.17 : 10.0.7.17,
+                            10.0.7.18 : 10.0.7.18,
+                            10.0.7.19 : 10.0.7.19,
+                            10.0.7.20 : 10.0.7.20,
+                            10.0.7.21 : 10.0.7.21,
+                            10.0.7.22 : 10.0.7.22,
+                            10.0.7.23 : 10.0.7.23,
+                            10.0.7.24 : 10.0.7.24,
+                            10.0.7.25 : 10.0.7.25,
+                            10.0.7.26 : 10.0.7.26,
+                            10.0.7.27 : 10.0.7.27,
+                            10.0.7.28 : 10.0.7.28,
+                            10.0.7.29 : 10.0.7.29,
+                            10.0.7.30 : 10.0.7.30,
+                            10.0.7.31 : 10.0.7.31,
+                            10.0.8.1 : 10.0.8.1,
+                            10.0.8.2 : 10.0.8.2,
+                            10.0.8.3 : 10.0.8.3,
+                            10.0.8.4 : 10.0.8.4,
+                            10.0.8.5 : 10.0.8.5,
+                            10.0.8.6 : 10.0.8.6,
+                            10.0.8.7 : 10.0.8.7,
+                            10.0.8.8 : 10.0.8.8,
+                            10.0.8.9 : 10.0.8.9,
+                            10.0.8.10 : 10.0.8.10,
+                            10.0.8.11 : 10.0.8.11,
+                            10.0.8.12 : 10.0.8.12,
+                            10.0.8.13 : 10.0.8.13,
+                            10.0.8.14 : 10.0.8.14,
+                            10.0.8.15 : 10.0.8.15,
+                            10.0.8.16 : 10.0.8.16,
+                            10.0.8.17 : 10.0.8.17,
+                            10.0.8.18 : 10.0.8.18,
+                            10.0.8.19 : 10.0.8.19,
+                            10.0.8.20 : 10.0.8.20,
+                            10.0.8.21 : 10.0.8.21,
+                            10.0.8.22 : 10.0.8.22,
+                            10.0.8.23 : 10.0.8.23,
+                            10.0.8.24 : 10.0.8.24,
+                            10.0.8.25 : 10.0.8.25,
+                            10.0.8.26 : 10.0.8.26,
+                            10.0.8.27 : 10.0.8.27,
+                            10.0.8.28 : 10.0.8.28,
+                            10.0.8.29 : 10.0.8.29,
+                            10.0.8.30 : 10.0.8.30,
+                            10.0.8.31 : 10.0.8.31,
+                            10.0.9.1 : 10.0.9.1,
+                            10.0.9.2 : 10.0.9.2,
+                            10.0.9.3 : 10.0.9.3,
+                            10.0.9.4 : 10.0.9.4,
+                            10.0.9.5 : 10.0.9.5,
+                            10.0.9.6 : 10.0.9.6,
+                            10.0.9.7 : 10.0.9.7,
+                            10.0.9.8 : 10.0.9.8,
+                            10.0.9.9 : 10.0.9.9,
+                            10.0.9.10 : 10.0.9.10,
+                            10.0.9.11 : 10.0.9.11,
+                            10.0.9.12 : 10.0.9.12,
+                            10.0.9.13 : 10.0.9.13,
+                            10.0.9.14 : 10.0.9.14,
+                            10.0.9.15 : 10.0.9.15,
+                            10.0.9.16 : 10.0.9.16,
+                            10.0.9.17 : 10.0.9.17,
+                            10.0.9.18 : 10.0.9.18,
+                            10.0.9.19 : 10.0.9.19,
+                            10.0.9.20 : 10.0.9.20,
+                            10.0.9.21 : 10.0.9.21,
+                            10.0.9.22 : 10.0.9.22,
+                            10.0.9.23 : 10.0.9.23,
+                            10.0.9.24 : 10.0.9.24,
+                            10.0.9.25 : 10.0.9.25,
+                            10.0.9.26 : 10.0.9.26,
+                            10.0.9.27 : 10.0.9.27,
+                            10.0.9.28 : 10.0.9.28,
+                            10.0.9.29 : 10.0.9.29,
+                            10.0.9.30 : 10.0.9.30,
+                            10.0.9.31 : 10.0.9.31,
+                            10.0.10.1 : 10.0.10.1,
+                            10.0.10.2 : 10.0.10.2,
+                            10.0.10.3 : 10.0.10.3,
+                            10.0.10.4 : 10.0.10.4,
+                            10.0.10.5 : 10.0.10.5,
+                            10.0.10.6 : 10.0.10.6,
+                            10.0.10.7 : 10.0.10.7,
+                            10.0.10.8 : 10.0.10.8,
+                            10.0.10.9 : 10.0.10.9,
+                            10.0.10.10 : 10.0.10.10,
+                            10.0.10.11 : 10.0.10.11,
+                            10.0.10.12 : 10.0.10.12,
+                            10.0.10.13 : 10.0.10.13,
+                            10.0.10.14 : 10.0.10.14,
+                            10.0.10.15 : 10.0.10.15,
+                            10.0.10.16 : 10.0.10.16,
+                            10.0.10.17 : 10.0.10.17,
+                            10.0.10.18 : 10.0.10.18,
+                            10.0.10.19 : 10.0.10.19,
+                            10.0.10.20 : 10.0.10.20,
+                            10.0.10.21 : 10.0.10.21,
+                            10.0.10.22 : 10.0.10.22,
+                            10.0.10.23 : 10.0.10.23,
+                            10.0.10.24 : 10.0.10.24,
+                            10.0.10.25 : 10.0.10.25,
+                            10.0.10.26 : 10.0.10.26,
+                            10.0.10.27 : 10.0.10.27,
+                            10.0.10.28 : 10.0.10.28,
+                            10.0.10.29 : 10.0.10.29,
+                            10.0.10.30 : 10.0.10.30,
+                            10.0.10.31 : 10.0.10.31,
+                            10.0.11.1 : 10.0.11.1,
+                            10.0.11.2 : 10.0.11.2,
+                            10.0.11.3 : 10.0.11.3,
+                            10.0.11.4 : 10.0.11.4,
+                            10.0.11.5 : 10.0.11.5,
+                            10.0.11.6 : 10.0.11.6,
+                            10.0.11.7 : 10.0.11.7,
+                            10.0.11.8 : 10.0.11.8,
+                            10.0.11.9 : 10.0.11.9,
+                            10.0.11.10 : 10.0.11.10,
+                            10.0.11.11 : 10.0.11.11,
+                            10.0.11.12 : 10.0.11.12,
+                            10.0.11.13 : 10.0.11.13,
+                            10.0.11.14 : 10.0.11.14,
+                            10.0.11.15 : 10.0.11.15,
+                            10.0.11.16 : 10.0.11.16,
+                            10.0.11.17 : 10.0.11.17,
+                            10.0.11.18 : 10.0.11.18,
+                            10.0.11.19 : 10.0.11.19,
+                            10.0.11.20 : 10.0.11.20,
+                            10.0.11.21 : 10.0.11.21,
+                            10.0.11.22 : 10.0.11.22,
+                            10.0.11.23 : 10.0.11.23,
+                            10.0.11.24 : 10.0.11.24,
+                            10.0.11.25 : 10.0.11.25,
+                            10.0.11.26 : 10.0.11.26,
+                            10.0.11.27 : 10.0.11.27,
+                            10.0.11.28 : 10.0.11.28,
+                            10.0.11.29 : 10.0.11.29,
+                            10.0.11.30 : 10.0.11.30,
+                            10.0.11.31 : 10.0.11.31,
+                            10.0.12.1 : 10.0.12.1,
+                            10.0.12.2 : 10.0.12.2,
+                            10.0.12.3 : 10.0.12.3,
+                            10.0.12.4 : 10.0.12.4,
+                            10.0.12.5 : 10.0.12.5,
+                            10.0.12.6 : 10.0.12.6,
+                            10.0.12.7 : 10.0.12.7,
+                            10.0.12.8 : 10.0.12.8,
+                            10.0.12.9 : 10.0.12.9,
+                            10.0.12.10 : 10.0.12.10,
+                            10.0.12.11 : 10.0.12.11,
+                            10.0.12.12 : 10.0.12.12,
+                            10.0.12.13 : 10.0.12.13,
+                            10.0.12.14 : 10.0.12.14,
+                            10.0.12.15 : 10.0.12.15,
+                            10.0.12.16 : 10.0.12.16,
+                            10.0.12.17 : 10.0.12.17,
+                            10.0.12.18 : 10.0.12.18,
+                            10.0.12.19 : 10.0.12.19,
+                            10.0.12.20 : 10.0.12.20,
+                            10.0.12.21 : 10.0.12.21,
+                            10.0.12.22 : 10.0.12.22,
+                            10.0.12.23 : 10.0.12.23,
+                            10.0.12.24 : 10.0.12.24,
+                            10.0.12.25 : 10.0.12.25,
+                            10.0.12.26 : 10.0.12.26,
+                            10.0.12.27 : 10.0.12.27,
+                            10.0.12.28 : 10.0.12.28,
+                            10.0.12.29 : 10.0.12.29,
+                            10.0.12.30 : 10.0.12.30,
+                            10.0.12.31 : 10.0.12.31,
+                            10.0.13.1 : 10.0.13.1,
+                            10.0.13.2 : 10.0.13.2,
+                            10.0.13.3 : 10.0.13.3,
+                            10.0.13.4 : 10.0.13.4,
+                            10.0.13.5 : 10.0.13.5,
+                            10.0.13.6 : 10.0.13.6,
+                            10.0.13.7 : 10.0.13.7,
+                            10.0.13.8 : 10.0.13.8,
+                            10.0.13.9 : 10.0.13.9,
+                            10.0.13.10 : 10.0.13.10,
+                            10.0.13.11 : 10.0.13.11,
+                            10.0.13.12 : 10.0.13.12,
+                            10.0.13.13 : 10.0.13.13,
+                            10.0.13.14 : 10.0.13.14,
+                            10.0.13.15 : 10.0.13.15,
+                            10.0.13.16 : 10.0.13.16,
+                            10.0.13.17 : 10.0.13.17,
+                            10.0.13.18 : 10.0.13.18,
+                            10.0.13.19 : 10.0.13.19,
+                            10.0.13.20 : 10.0.13.20,
+                            10.0.13.21 : 10.0.13.21,
+                            10.0.13.22 : 10.0.13.22,
+                            10.0.13.23 : 10.0.13.23,
+                            10.0.13.24 : 10.0.13.24,
+                            10.0.13.25 : 10.0.13.25,
+                            10.0.13.26 : 10.0.13.26,
+                            10.0.13.27 : 10.0.13.27,
+                            10.0.13.28 : 10.0.13.28,
+                            10.0.13.29 : 10.0.13.29,
+                            10.0.13.30 : 10.0.13.30,
+                            10.0.13.31 : 10.0.13.31,
+                            10.0.14.1 : 10.0.14.1,
+                            10.0.14.2 : 10.0.14.2,
+                            10.0.14.3 : 10.0.14.3,
+                            10.0.14.4 : 10.0.14.4,
+                            10.0.14.5 : 10.0.14.5,
+                            10.0.14.6 : 10.0.14.6,
+                            10.0.14.7 : 10.0.14.7,
+                            10.0.14.8 : 10.0.14.8,
+                            10.0.14.9 : 10.0.14.9,
+                            10.0.14.10 : 10.0.14.10,
+                            10.0.14.11 : 10.0.14.11,
+                            10.0.14.12 : 10.0.14.12,
+                            10.0.14.13 : 10.0.14.13,
+                            10.0.14.14 : 10.0.14.14,
+                            10.0.14.15 : 10.0.14.15,
+                            10.0.14.16 : 10.0.14.16,
+                            10.0.14.17 : 10.0.14.17,
+                            10.0.14.18 : 10.0.14.18,
+                            10.0.14.19 : 10.0.14.19,
+                            10.0.14.20 : 10.0.14.20,
+                            10.0.14.21 : 10.0.14.21,
+                            10.0.14.22 : 10.0.14.22,
+                            10.0.14.23 : 10.0.14.23,
+                            10.0.14.24 : 10.0.14.24,
+                            10.0.14.25 : 10.0.14.25,
+                            10.0.14.26 : 10.0.14.26,
+                            10.0.14.27 : 10.0.14.27,
+                            10.0.14.28 : 10.0.14.28,
+                            10.0.14.29 : 10.0.14.29,
+                            10.0.14.30 : 10.0.14.30,
+                            10.0.14.31 : 10.0.14.31,
+                            10.0.15.1 : 10.0.15.1,
+                            10.0.15.2 : 10.0.15.2,
+                            10.0.15.3 : 10.0.15.3,
+                            10.0.15.4 : 10.0.15.4,
+                            10.0.15.5 : 10.0.15.5,
+                            10.0.15.6 : 10.0.15.6,
+                            10.0.15.7 : 10.0.15.7,
+                            10.0.15.8 : 10.0.15.8,
+                            10.0.15.9 : 10.0.15.9,
+                            10.0.15.10 : 10.0.15.10,
+                            10.0.15.11 : 10.0.15.11,
+                            10.0.15.12 : 10.0.15.12,
+                            10.0.15.13 : 10.0.15.13,
+                            10.0.15.14 : 10.0.15.14,
+                            10.0.15.15 : 10.0.15.15,
+                            10.0.15.16 : 10.0.15.16,
+                            10.0.15.17 : 10.0.15.17,
+                            10.0.15.18 : 10.0.15.18,
+                            10.0.15.19 : 10.0.15.19,
+                            10.0.15.20 : 10.0.15.20,
+                            10.0.15.21 : 10.0.15.21,
+                            10.0.15.22 : 10.0.15.22,
+                            10.0.15.23 : 10.0.15.23,
+                            10.0.15.24 : 10.0.15.24,
+                            10.0.15.25 : 10.0.15.25,
+                            10.0.15.26 : 10.0.15.26,
+                            10.0.15.27 : 10.0.15.27,
+                            10.0.15.28 : 10.0.15.28,
+                            10.0.15.29 : 10.0.15.29,
+                            10.0.15.30 : 10.0.15.30,
+                            10.0.15.31 : 10.0.15.31,
+                            10.0.16.1 : 10.0.16.1,
+                            10.0.16.2 : 10.0.16.2,
+                            10.0.16.3 : 10.0.16.3,
+                            10.0.16.4 : 10.0.16.4,
+                            10.0.16.5 : 10.0.16.5,
+                            10.0.16.6 : 10.0.16.6,
+                            10.0.16.7 : 10.0.16.7,
+                            10.0.16.8 : 10.0.16.8,
+                            10.0.16.9 : 10.0.16.9,
+                            10.0.16.10 : 10.0.16.10,
+                            10.0.16.11 : 10.0.16.11,
+                            10.0.16.12 : 10.0.16.12,
+                            10.0.16.13 : 10.0.16.13,
+                            10.0.16.14 : 10.0.16.14,
+                            10.0.16.15 : 10.0.16.15,
+                            10.0.16.16 : 10.0.16.16,
+                            10.0.16.17 : 10.0.16.17,
+                            10.0.16.18 : 10.0.16.18,
+                            10.0.16.19 : 10.0.16.19,
+                            10.0.16.20 : 10.0.16.20,
+                            10.0.16.21 : 10.0.16.21,
+                            10.0.16.22 : 10.0.16.22,
+                            10.0.16.23 : 10.0.16.23,
+                            10.0.16.24 : 10.0.16.24,
+                            10.0.16.25 : 10.0.16.25,
+                            10.0.16.26 : 10.0.16.26,
+                            10.0.16.27 : 10.0.16.27,
+                            10.0.16.28 : 10.0.16.28,
+                            10.0.16.29 : 10.0.16.29,
+                            10.0.16.30 : 10.0.16.30,
+                            10.0.16.31 : 10.0.16.31,
+                            10.0.17.1 : 10.0.17.1,
+                            10.0.17.2 : 10.0.17.2,
+                            10.0.17.3 : 10.0.17.3,
+                            10.0.17.4 : 10.0.17.4,
+                            10.0.17.5 : 10.0.17.5,
+                            10.0.17.6 : 10.0.17.6,
+                            10.0.17.7 : 10.0.17.7,
+                            10.0.17.8 : 10.0.17.8,
+                            10.0.17.9 : 10.0.17.9,
+                            10.0.17.10 : 10.0.17.10,
+                            10.0.17.11 : 10.0.17.11,
+                            10.0.17.12 : 10.0.17.12,
+                            10.0.17.13 : 10.0.17.13,
+                            10.0.17.14 : 10.0.17.14,
+                            10.0.17.15 : 10.0.17.15,
+                            10.0.17.16 : 10.0.17.16,
+                            10.0.17.17 : 10.0.17.17,
+                            10.0.17.18 : 10.0.17.18,
+                            10.0.17.19 : 10.0.17.19,
+                            10.0.17.20 : 10.0.17.20,
+                            10.0.17.21 : 10.0.17.21,
+                            10.0.17.22 : 10.0.17.22,
+                            10.0.17.23 : 10.0.17.23,
+                            10.0.17.24 : 10.0.17.24,
+                            10.0.17.25 : 10.0.17.25,
+                            10.0.17.26 : 10.0.17.26,
+                            10.0.17.27 : 10.0.17.27,
+                            10.0.17.28 : 10.0.17.28,
+                            10.0.17.29 : 10.0.17.29,
+                            10.0.17.30 : 10.0.17.30,
+                            10.0.17.31 : 10.0.17.31,
+                            10.0.18.1 : 10.0.18.1,
+                            10.0.18.2 : 10.0.18.2,
+                            10.0.18.3 : 10.0.18.3,
+                            10.0.18.4 : 10.0.18.4,
+                            10.0.18.5 : 10.0.18.5,
+                            10.0.18.6 : 10.0.18.6,
+                            10.0.18.7 : 10.0.18.7,
+                            10.0.18.8 : 10.0.18.8,
+                            10.0.18.9 : 10.0.18.9,
+                            10.0.18.10 : 10.0.18.10,
+                            10.0.18.11 : 10.0.18.11,
+                            10.0.18.12 : 10.0.18.12,
+                            10.0.18.13 : 10.0.18.13,
+                            10.0.18.14 : 10.0.18.14,
+                            10.0.18.15 : 10.0.18.15,
+                            10.0.18.16 : 10.0.18.16,
+                            10.0.18.17 : 10.0.18.17,
+                            10.0.18.18 : 10.0.18.18,
+                            10.0.18.19 : 10.0.18.19,
+                            10.0.18.20 : 10.0.18.20,
+                            10.0.18.21 : 10.0.18.21,
+                            10.0.18.22 : 10.0.18.22,
+                            10.0.18.23 : 10.0.18.23,
+                            10.0.18.24 : 10.0.18.24,
+                            10.0.18.25 : 10.0.18.25,
+                            10.0.18.26 : 10.0.18.26,
+                            10.0.18.27 : 10.0.18.27,
+                            10.0.18.28 : 10.0.18.28,
+                            10.0.18.29 : 10.0.18.29,
+                            10.0.18.30 : 10.0.18.30,
+                            10.0.18.31 : 10.0.18.31,
+                            10.0.19.1 : 10.0.19.1,
+                            10.0.19.2 : 10.0.19.2,
+                            10.0.19.3 : 10.0.19.3,
+                            10.0.19.4 : 10.0.19.4,
+                            10.0.19.5 : 10.0.19.5,
+                            10.0.19.6 : 10.0.19.6,
+                            10.0.19.7 : 10.0.19.7,
+                            10.0.19.8 : 10.0.19.8,
+                            10.0.19.9 : 10.0.19.9,
+                            10.0.19.10 : 10.0.19.10,
+                            10.0.19.11 : 10.0.19.11,
+                            10.0.19.12 : 10.0.19.12,
+                            10.0.19.13 : 10.0.19.13,
+                            10.0.19.14 : 10.0.19.14,
+                            10.0.19.15 : 10.0.19.15,
+                            10.0.19.16 : 10.0.19.16,
+                            10.0.19.17 : 10.0.19.17,
+                            10.0.19.18 : 10.0.19.18,
+                            10.0.19.19 : 10.0.19.19,
+                            10.0.19.20 : 10.0.19.20,
+                            10.0.19.21 : 10.0.19.21,
+                            10.0.19.22 : 10.0.19.22,
+                            10.0.19.23 : 10.0.19.23,
+                            10.0.19.24 : 10.0.19.24,
+                            10.0.19.25 : 10.0.19.25,
+                            10.0.19.26 : 10.0.19.26,
+                            10.0.19.27 : 10.0.19.27,
+                            10.0.19.28 : 10.0.19.28,
+                            10.0.19.29 : 10.0.19.29,
+                            10.0.19.30 : 10.0.19.30,
+                            10.0.19.31 : 10.0.19.31,
+                            10.0.20.1 : 10.0.20.1,
+                            10.0.20.2 : 10.0.20.2,
+                            10.0.20.3 : 10.0.20.3,
+                            10.0.20.4 : 10.0.20.4,
+                            10.0.20.5 : 10.0.20.5,
+                            10.0.20.6 : 10.0.20.6,
+                            10.0.20.7 : 10.0.20.7,
+                            10.0.20.8 : 10.0.20.8,
+                            10.0.20.9 : 10.0.20.9,
+                            10.0.20.10 : 10.0.20.10,
+                            10.0.20.11 : 10.0.20.11,
+                            10.0.20.12 : 10.0.20.12,
+                            10.0.20.13 : 10.0.20.13,
+                            10.0.20.14 : 10.0.20.14,
+                            10.0.20.15 : 10.0.20.15,
+                            10.0.20.16 : 10.0.20.16,
+                            10.0.20.17 : 10.0.20.17,
+                            10.0.20.18 : 10.0.20.18,
+                            10.0.20.19 : 10.0.20.19,
+                            10.0.20.20 : 10.0.20.20,
+                            10.0.20.21 : 10.0.20.21,
+                            10.0.20.22 : 10.0.20.22,
+                            10.0.20.23 : 10.0.20.23,
+                            10.0.20.24 : 10.0.20.24,
+                            10.0.20.25 : 10.0.20.25,
+                            10.0.20.26 : 10.0.20.26,
+                            10.0.20.27 : 10.0.20.27,
+                            10.0.20.28 : 10.0.20.28,
+                            10.0.20.29 : 10.0.20.29,
+                            10.0.20.30 : 10.0.20.30,
+                            10.0.20.31 : 10.0.20.31,
+                            10.0.21.1 : 10.0.21.1,
+                            10.0.21.2 : 10.0.21.2,
+                            10.0.21.3 : 10.0.21.3,
+                            10.0.21.4 : 10.0.21.4,
+                            10.0.21.5 : 10.0.21.5,
+                            10.0.21.6 : 10.0.21.6,
+                            10.0.21.7 : 10.0.21.7,
+                            10.0.21.8 : 10.0.21.8,
+                            10.0.21.9 : 10.0.21.9,
+                            10.0.21.10 : 10.0.21.10,
+                            10.0.21.11 : 10.0.21.11,
+                            10.0.21.12 : 10.0.21.12,
+                            10.0.21.13 : 10.0.21.13,
+                            10.0.21.14 : 10.0.21.14,
+                            10.0.21.15 : 10.0.21.15,
+                            10.0.21.16 : 10.0.21.16,
+                            10.0.21.17 : 10.0.21.17,
+                            10.0.21.18 : 10.0.21.18,
+                            10.0.21.19 : 10.0.21.19,
+                            10.0.21.20 : 10.0.21.20,
+                            10.0.21.21 : 10.0.21.21,
+                            10.0.21.22 : 10.0.21.22,
+                            10.0.21.23 : 10.0.21.23,
+                            10.0.21.24 : 10.0.21.24,
+                            10.0.21.25 : 10.0.21.25,
+                            10.0.21.26 : 10.0.21.26,
+                            10.0.21.27 : 10.0.21.27,
+                            10.0.21.28 : 10.0.21.28,
+                            10.0.21.29 : 10.0.21.29,
+                            10.0.21.30 : 10.0.21.30,
+                            10.0.21.31 : 10.0.21.31,
+                            10.0.22.1 : 10.0.22.1,
+                            10.0.22.2 : 10.0.22.2,
+                            10.0.22.3 : 10.0.22.3,
+                            10.0.22.4 : 10.0.22.4,
+                            10.0.22.5 : 10.0.22.5,
+                            10.0.22.6 : 10.0.22.6,
+                            10.0.22.7 : 10.0.22.7,
+                            10.0.22.8 : 10.0.22.8,
+                            10.0.22.9 : 10.0.22.9,
+                            10.0.22.10 : 10.0.22.10,
+                            10.0.22.11 : 10.0.22.11,
+                            10.0.22.12 : 10.0.22.12,
+                            10.0.22.13 : 10.0.22.13,
+                            10.0.22.14 : 10.0.22.14,
+                            10.0.22.15 : 10.0.22.15,
+                            10.0.22.16 : 10.0.22.16,
+                            10.0.22.17 : 10.0.22.17,
+                            10.0.22.18 : 10.0.22.18,
+                            10.0.22.19 : 10.0.22.19,
+                            10.0.22.20 : 10.0.22.20,
+                            10.0.22.21 : 10.0.22.21,
+                            10.0.22.22 : 10.0.22.22,
+                            10.0.22.23 : 10.0.22.23,
+                            10.0.22.24 : 10.0.22.24,
+                            10.0.22.25 : 10.0.22.25,
+                            10.0.22.26 : 10.0.22.26,
+                            10.0.22.27 : 10.0.22.27,
+                            10.0.22.28 : 10.0.22.28,
+                            10.0.22.29 : 10.0.22.29,
+                            10.0.22.30 : 10.0.22.30,
+                            10.0.22.31 : 10.0.22.31,
+                            10.0.23.1 : 10.0.23.1,
+                            10.0.23.2 : 10.0.23.2,
+                            10.0.23.3 : 10.0.23.3,
+                            10.0.23.4 : 10.0.23.4,
+                            10.0.23.5 : 10.0.23.5,
+                            10.0.23.6 : 10.0.23.6,
+                            10.0.23.7 : 10.0.23.7,
+                            10.0.23.8 : 10.0.23.8,
+                            10.0.23.9 : 10.0.23.9,
+                            10.0.23.10 : 10.0.23.10,
+                            10.0.23.11 : 10.0.23.11,
+                            10.0.23.12 : 10.0.23.12,
+                            10.0.23.13 : 10.0.23.13,
+                            10.0.23.14 : 10.0.23.14,
+                            10.0.23.15 : 10.0.23.15,
+                            10.0.23.16 : 10.0.23.16,
+                            10.0.23.17 : 10.0.23.17,
+                            10.0.23.18 : 10.0.23.18,
+                            10.0.23.19 : 10.0.23.19,
+                            10.0.23.20 : 10.0.23.20,
+                            10.0.23.21 : 10.0.23.21,
+                            10.0.23.22 : 10.0.23.22,
+                            10.0.23.23 : 10.0.23.23,
+                            10.0.23.24 : 10.0.23.24,
+                            10.0.23.25 : 10.0.23.25,
+                            10.0.23.26 : 10.0.23.26,
+                            10.0.23.27 : 10.0.23.27,
+                            10.0.23.28 : 10.0.23.28,
+                            10.0.23.29 : 10.0.23.29,
+                            10.0.23.30 : 10.0.23.30,
+                            10.0.23.31 : 10.0.23.31,
+                            10.0.24.1 : 10.0.24.1,
+                            10.0.24.2 : 10.0.24.2,
+                            10.0.24.3 : 10.0.24.3,
+                            10.0.24.4 : 10.0.24.4,
+                            10.0.24.5 : 10.0.24.5,
+                            10.0.24.6 : 10.0.24.6,
+                            10.0.24.7 : 10.0.24.7,
+                            10.0.24.8 : 10.0.24.8,
+                            10.0.24.9 : 10.0.24.9,
+                            10.0.24.10 : 10.0.24.10,
+                            10.0.24.11 : 10.0.24.11,
+                            10.0.24.12 : 10.0.24.12,
+                            10.0.24.13 : 10.0.24.13,
+                            10.0.24.14 : 10.0.24.14,
+                            10.0.24.15 : 10.0.24.15,
+                            10.0.24.16 : 10.0.24.16,
+                            10.0.24.17 : 10.0.24.17,
+                            10.0.24.18 : 10.0.24.18,
+                            10.0.24.19 : 10.0.24.19,
+                            10.0.24.20 : 10.0.24.20,
+                            10.0.24.21 : 10.0.24.21,
+                            10.0.24.22 : 10.0.24.22,
+                            10.0.24.23 : 10.0.24.23,
+                            10.0.24.24 : 10.0.24.24,
+                            10.0.24.25 : 10.0.24.25,
+                            10.0.24.26 : 10.0.24.26,
+                            10.0.24.27 : 10.0.24.27,
+                            10.0.24.28 : 10.0.24.28,
+                            10.0.24.29 : 10.0.24.29,
+                            10.0.24.30 : 10.0.24.30,
+                            10.0.24.31 : 10.0.24.31,
+                            10.0.25.1 : 10.0.25.1,
+                            10.0.25.2 : 10.0.25.2,
+                            10.0.25.3 : 10.0.25.3,
+                            10.0.25.4 : 10.0.25.4,
+                            10.0.25.5 : 10.0.25.5,
+                            10.0.25.6 : 10.0.25.6,
+                            10.0.25.7 : 10.0.25.7,
+                            10.0.25.8 : 10.0.25.8,
+                            10.0.25.9 : 10.0.25.9,
+                            10.0.25.10 : 10.0.25.10,
+                            10.0.25.11 : 10.0.25.11,
+                            10.0.25.12 : 10.0.25.12,
+                            10.0.25.13 : 10.0.25.13,
+                            10.0.25.14 : 10.0.25.14,
+                            10.0.25.15 : 10.0.25.15,
+                            10.0.25.16 : 10.0.25.16,
+                            10.0.25.17 : 10.0.25.17,
+                            10.0.25.18 : 10.0.25.18,
+                            10.0.25.19 : 10.0.25.19,
+                            10.0.25.20 : 10.0.25.20,
+                            10.0.25.21 : 10.0.25.21,
+                            10.0.25.22 : 10.0.25.22,
+                            10.0.25.23 : 10.0.25.23,
+                            10.0.25.24 : 10.0.25.24,
+                            10.0.25.25 : 10.0.25.25,
+                            10.0.25.26 : 10.0.25.26,
+                            10.0.25.27 : 10.0.25.27,
+                            10.0.25.28 : 10.0.25.28,
+                            10.0.25.29 : 10.0.25.29,
+                            10.0.25.30 : 10.0.25.30,
+                            10.0.25.31 : 10.0.25.31,
+                            10.0.26.1 : 10.0.26.1,
+                            10.0.26.2 : 10.0.26.2,
+                            10.0.26.3 : 10.0.26.3,
+                            10.0.26.4 : 10.0.26.4,
+                            10.0.26.5 : 10.0.26.5,
+                            10.0.26.6 : 10.0.26.6,
+                            10.0.26.7 : 10.0.26.7,
+                            10.0.26.8 : 10.0.26.8,
+                            10.0.26.9 : 10.0.26.9,
+                            10.0.26.10 : 10.0.26.10,
+                            10.0.26.11 : 10.0.26.11,
+                            10.0.26.12 : 10.0.26.12,
+                            10.0.26.13 : 10.0.26.13,
+                            10.0.26.14 : 10.0.26.14,
+                            10.0.26.15 : 10.0.26.15,
+                            10.0.26.16 : 10.0.26.16,
+                            10.0.26.17 : 10.0.26.17,
+                            10.0.26.18 : 10.0.26.18,
+                            10.0.26.19 : 10.0.26.19,
+                            10.0.26.20 : 10.0.26.20,
+                            10.0.26.21 : 10.0.26.21,
+                            10.0.26.22 : 10.0.26.22,
+                            10.0.26.23 : 10.0.26.23,
+                            10.0.26.24 : 10.0.26.24,
+                            10.0.26.25 : 10.0.26.25,
+                            10.0.26.26 : 10.0.26.26,
+                            10.0.26.27 : 10.0.26.27,
+                            10.0.26.28 : 10.0.26.28,
+                            10.0.26.29 : 10.0.26.29,
+                            10.0.26.30 : 10.0.26.30,
+                            10.0.26.31 : 10.0.26.31,
+                            10.0.27.1 : 10.0.27.1,
+                            10.0.27.2 : 10.0.27.2,
+                            10.0.27.3 : 10.0.27.3,
+                            10.0.27.4 : 10.0.27.4,
+                            10.0.27.5 : 10.0.27.5,
+                            10.0.27.6 : 10.0.27.6,
+                            10.0.27.7 : 10.0.27.7,
+                            10.0.27.8 : 10.0.27.8,
+                            10.0.27.9 : 10.0.27.9,
+                            10.0.27.10 : 10.0.27.10,
+                            10.0.27.11 : 10.0.27.11,
+                            10.0.27.12 : 10.0.27.12,
+                            10.0.27.13 : 10.0.27.13,
+                            10.0.27.14 : 10.0.27.14,
+                            10.0.27.15 : 10.0.27.15,
+                            10.0.27.16 : 10.0.27.16,
+                            10.0.27.17 : 10.0.27.17,
+                            10.0.27.18 : 10.0.27.18,
+                            10.0.27.19 : 10.0.27.19,
+                            10.0.27.20 : 10.0.27.20,
+                            10.0.27.21 : 10.0.27.21,
+                            10.0.27.22 : 10.0.27.22,
+                            10.0.27.23 : 10.0.27.23,
+                            10.0.27.24 : 10.0.27.24,
+                            10.0.27.25 : 10.0.27.25,
+                            10.0.27.26 : 10.0.27.26,
+                            10.0.27.27 : 10.0.27.27,
+                            10.0.27.28 : 10.0.27.28,
+                            10.0.27.29 : 10.0.27.29,
+                            10.0.27.30 : 10.0.27.30,
+                            10.0.27.31 : 10.0.27.31,
+                            10.0.28.1 : 10.0.28.1,
+                            10.0.28.2 : 10.0.28.2,
+                            10.0.28.3 : 10.0.28.3,
+                            10.0.28.4 : 10.0.28.4,
+                            10.0.28.5 : 10.0.28.5,
+                            10.0.28.6 : 10.0.28.6,
+                            10.0.28.7 : 10.0.28.7,
+                            10.0.28.8 : 10.0.28.8,
+                            10.0.28.9 : 10.0.28.9,
+                            10.0.28.10 : 10.0.28.10,
+                            10.0.28.11 : 10.0.28.11,
+                            10.0.28.12 : 10.0.28.12,
+                            10.0.28.13 : 10.0.28.13,
+                            10.0.28.14 : 10.0.28.14,
+                            10.0.28.15 : 10.0.28.15,
+                            10.0.28.16 : 10.0.28.16,
+                            10.0.28.17 : 10.0.28.17,
+                            10.0.28.18 : 10.0.28.18,
+                            10.0.28.19 : 10.0.28.19,
+                            10.0.28.20 : 10.0.28.20,
+                            10.0.28.21 : 10.0.28.21,
+                            10.0.28.22 : 10.0.28.22,
+                            10.0.28.23 : 10.0.28.23,
+                            10.0.28.24 : 10.0.28.24,
+                            10.0.28.25 : 10.0.28.25,
+                            10.0.28.26 : 10.0.28.26,
+                            10.0.28.27 : 10.0.28.27,
+                            10.0.28.28 : 10.0.28.28,
+                            10.0.28.29 : 10.0.28.29,
+                            10.0.28.30 : 10.0.28.30,
+                            10.0.28.31 : 10.0.28.31,
+                            10.0.29.1 : 10.0.29.1,
+                            10.0.29.2 : 10.0.29.2,
+                            10.0.29.3 : 10.0.29.3,
+                            10.0.29.4 : 10.0.29.4,
+                            10.0.29.5 : 10.0.29.5,
+                            10.0.29.6 : 10.0.29.6,
+                            10.0.29.7 : 10.0.29.7,
+                            10.0.29.8 : 10.0.29.8,
+                            10.0.29.9 : 10.0.29.9,
+                            10.0.29.10 : 10.0.29.10,
+                            10.0.29.11 : 10.0.29.11,
+                            10.0.29.12 : 10.0.29.12,
+                            10.0.29.13 : 10.0.29.13,
+                            10.0.29.14 : 10.0.29.14,
+                            10.0.29.15 : 10.0.29.15,
+                            10.0.29.16 : 10.0.29.16,
+                            10.0.29.17 : 10.0.29.17,
+                            10.0.29.18 : 10.0.29.18,
+                            10.0.29.19 : 10.0.29.19,
+                            10.0.29.20 : 10.0.29.20,
+                            10.0.29.21 : 10.0.29.21,
+                            10.0.29.22 : 10.0.29.22,
+                            10.0.29.23 : 10.0.29.23,
+                            10.0.29.24 : 10.0.29.24,
+                            10.0.29.25 : 10.0.29.25,
+                            10.0.29.26 : 10.0.29.26,
+                            10.0.29.27 : 10.0.29.27,
+                            10.0.29.28 : 10.0.29.28,
+                            10.0.29.29 : 10.0.29.29,
+                            10.0.29.30 : 10.0.29.30,
+                            10.0.29.31 : 10.0.29.31,
+                            10.0.30.1 : 10.0.30.1,
+                            10.0.30.2 : 10.0.30.2,
+                            10.0.30.3 : 10.0.30.3,
+                            10.0.30.4 : 10.0.30.4,
+                            10.0.30.5 : 10.0.30.5,
+                            10.0.30.6 : 10.0.30.6,
+                            10.0.30.7 : 10.0.30.7,
+                            10.0.30.8 : 10.0.30.8,
+                            10.0.30.9 : 10.0.30.9,
+                            10.0.30.10 : 10.0.30.10,
+                            10.0.30.11 : 10.0.30.11,
+                            10.0.30.12 : 10.0.30.12,
+                            10.0.30.13 : 10.0.30.13,
+                            10.0.30.14 : 10.0.30.14,
+                            10.0.30.15 : 10.0.30.15,
+                            10.0.30.16 : 10.0.30.16,
+                            10.0.30.17 : 10.0.30.17,
+                            10.0.30.18 : 10.0.30.18,
+                            10.0.30.19 : 10.0.30.19,
+                            10.0.30.20 : 10.0.30.20,
+                            10.0.30.21 : 10.0.30.21,
+                            10.0.30.22 : 10.0.30.22,
+                            10.0.30.23 : 10.0.30.23,
+                            10.0.30.24 : 10.0.30.24,
+                            10.0.30.25 : 10.0.30.25,
+                            10.0.30.26 : 10.0.30.26,
+                            10.0.30.27 : 10.0.30.27,
+                            10.0.30.28 : 10.0.30.28,
+                            10.0.30.29 : 10.0.30.29,
+                            10.0.30.30 : 10.0.30.30,
+                            10.0.30.31 : 10.0.30.31,
+                            10.0.31.1 : 10.0.31.1,
+                            10.0.31.2 : 10.0.31.2,
+                            10.0.31.3 : 10.0.31.3,
+                            10.0.31.4 : 10.0.31.4,
+                            10.0.31.5 : 10.0.31.5,
+                            10.0.31.6 : 10.0.31.6,
+                            10.0.31.7 : 10.0.31.7,
+                            10.0.31.8 : 10.0.31.8,
+                            10.0.31.9 : 10.0.31.9,
+                            10.0.31.10 : 10.0.31.10,
+                            10.0.31.11 : 10.0.31.11,
+                            10.0.31.12 : 10.0.31.12,
+                            10.0.31.13 : 10.0.31.13,
+                            10.0.31.14 : 10.0.31.14,
+                            10.0.31.15 : 10.0.31.15,
+                            10.0.31.16 : 10.0.31.16,
+                            10.0.31.17 : 10.0.31.17,
+                            10.0.31.18 : 10.0.31.18,
+                            10.0.31.19 : 10.0.31.19,
+                            10.0.31.20 : 10.0.31.20,
+                            10.0.31.21 : 10.0.31.21,
+                            10.0.31.22 : 10.0.31.22,
+                            10.0.31.23 : 10.0.31.23,
+                            10.0.31.24 : 10.0.31.24,
+                            10.0.31.25 : 10.0.31.25,
+                            10.0.31.26 : 10.0.31.26,
+                            10.0.31.27 : 10.0.31.27,
+                            10.0.31.28 : 10.0.31.28,
+                            10.0.31.29 : 10.0.31.29,
+                            10.0.31.30 : 10.0.31.30,
+                            10.0.31.31 : 10.0.31.31 }
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/0004interval_map_create_once_0.nodump b/tests/shell/testcases/maps/dumps/0004interval_map_create_once_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/maps/dumps/0005interval_map_add_many_elements_0.json-nft b/tests/shell/testcases/maps/dumps/0005interval_map_add_many_elements_0.json-nft
new file mode 100644 (file)
index 0000000..f9ac5bc
--- /dev/null
@@ -0,0 +1,67 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "ipv4_addr",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "prefix": {
+                "addr": "10.1.1.0",
+                "len": 24
+              }
+            },
+            "10.0.1.1"
+          ],
+          [
+            {
+              "prefix": {
+                "addr": "10.1.2.0",
+                "len": 24
+              }
+            },
+            "10.0.1.2"
+          ],
+          [
+            {
+              "prefix": {
+                "addr": "10.2.1.0",
+                "len": 24
+              }
+            },
+            "10.0.2.1"
+          ],
+          [
+            {
+              "prefix": {
+                "addr": "10.2.2.0",
+                "len": 24
+              }
+            },
+            "10.0.2.2"
+          ]
+        ]
+      }
+    }
+  ]
+}
index ab992c4a0618f4731a9daf9ca574e680e6b13696..b1e017bdcae732ae2cc06ca15f6246f4208c2c9a 100644 (file)
@@ -2,7 +2,9 @@ table ip x {
        map y {
                type ipv4_addr : ipv4_addr
                flags interval
-               elements = { 10.1.1.0/24 : 10.0.1.1, 10.1.2.0/24 : 10.0.1.2,
-                            10.2.1.0/24 : 10.0.2.1, 10.2.2.0/24 : 10.0.2.2 }
+               elements = { 10.1.1.0/24 : 10.0.1.1,
+                            10.1.2.0/24 : 10.0.1.2,
+                            10.2.1.0/24 : 10.0.2.1,
+                            10.2.2.0/24 : 10.0.2.2 }
        }
 }
diff --git a/tests/shell/testcases/maps/dumps/0006interval_map_overlap_0.json-nft b/tests/shell/testcases/maps/dumps/0006interval_map_overlap_0.json-nft
new file mode 100644 (file)
index 0000000..d6b32d0
--- /dev/null
@@ -0,0 +1,49 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "ipv4_addr",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "prefix": {
+                "addr": "10.0.1.0",
+                "len": 24
+              }
+            },
+            "10.0.0.1"
+          ],
+          [
+            {
+              "prefix": {
+                "addr": "10.0.2.0",
+                "len": 24
+              }
+            },
+            "10.0.0.2"
+          ]
+        ]
+      }
+    }
+  ]
+}
index 1f5343f4fada7ad9dbafa96f06a723d265bad39e..74380c29490bf1deb86547b83f1fb4e2bf500167 100644 (file)
@@ -2,6 +2,7 @@ table ip x {
        map y {
                type ipv4_addr : ipv4_addr
                flags interval
-               elements = { 10.0.1.0/24 : 10.0.0.1, 10.0.2.0/24 : 10.0.0.2 }
+               elements = { 10.0.1.0/24 : 10.0.0.1,
+                            10.0.2.0/24 : 10.0.0.2 }
        }
 }
diff --git a/tests/shell/testcases/maps/dumps/0007named_ifname_dtype_0.json-nft b/tests/shell/testcases/maps/dumps/0007named_ifname_dtype_0.json-nft
new file mode 100644 (file)
index 0000000..ef57a74
--- /dev/null
@@ -0,0 +1,102 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "m1",
+        "table": "t",
+        "type": "ifname",
+        "handle": 0,
+        "map": "ipv4_addr",
+        "elem": [
+          [
+            "eth0",
+            "1.1.1.1"
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "value": {
+                "map": {
+                  "key": {
+                    "meta": {
+                      "key": "iifname"
+                    }
+                  },
+                  "data": "@m1"
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "value": {
+                "map": {
+                  "key": {
+                    "meta": {
+                      "key": "oifname"
+                    }
+                  },
+                  "data": "@m1"
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0008interval_map_delete_0.json-nft b/tests/shell/testcases/maps/dumps/0008interval_map_delete_0.json-nft
new file mode 100644 (file)
index 0000000..09cb6c8
--- /dev/null
@@ -0,0 +1,157 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "m",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "mark",
+        "flags": "interval",
+        "elem": [
+          [
+            "127.0.0.2",
+            2
+          ],
+          [
+            "127.0.0.3",
+            3
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  "data": "@m"
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "right": 2
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "right": 3
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0008interval_map_delete_0.nft b/tests/shell/testcases/maps/dumps/0008interval_map_delete_0.nft
new file mode 100644 (file)
index 0000000..1b199ff
--- /dev/null
@@ -0,0 +1,16 @@
+table ip filter {
+       map m {
+               type ipv4_addr : mark
+               flags interval
+               elements = { 127.0.0.2 : 0x00000002,
+                            127.0.0.3 : 0x00000003 }
+       }
+
+       chain input {
+               type filter hook input priority filter; policy accept;
+               meta mark set ip daddr map @m
+               meta mark 0x00000002 counter packets 0 bytes 0 accept
+               meta mark 0x00000003 counter packets 0 bytes 0 accept
+               counter packets 0 bytes 0
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/0009vmap_0.json-nft b/tests/shell/testcases/maps/dumps/0009vmap_0.json-nft
new file mode 100644 (file)
index 0000000..345a2c7
--- /dev/null
@@ -0,0 +1,117 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "ssh_input",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "wan_input",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "wan_input",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    22,
+                    {
+                      "jump": {
+                        "target": "ssh_input"
+                      }
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "prerouting",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "meta": {
+                  "key": "iif"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    {
+                      "elem": {
+                        "val": "lo",
+                        "counter": {
+                          "packets": 0,
+                          "bytes": 0
+                        }
+                      }
+                    },
+                    {
+                      "jump": {
+                        "target": "wan_input"
+                      }
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0010concat_map_0.json-nft b/tests/shell/testcases/maps/dumps/0010concat_map_0.json-nft
new file mode 100644 (file)
index 0000000..fcc23bb
--- /dev/null
@@ -0,0 +1,106 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "nat",
+        "hook": "prerouting",
+        "prio": -100,
+        "policy": "accept"
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "z",
+        "table": "x",
+        "type": [
+          "ipv4_addr",
+          "inet_proto",
+          "inet_service"
+        ],
+        "handle": 0,
+        "map": [
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "elem": [
+          [
+            {
+              "concat": [
+                "1.1.1.1",
+                "tcp",
+                20
+              ]
+            },
+            {
+              "concat": [
+                "2.2.2.2",
+                30
+              ]
+            }
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "dnat": {
+              "family": "ip",
+              "addr": {
+                "map": {
+                  "key": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "saddr"
+                        }
+                      },
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "protocol"
+                        }
+                      },
+                      {
+                        "payload": {
+                          "protocol": "tcp",
+                          "field": "dport"
+                        }
+                      }
+                    ]
+                  },
+                  "data": "@z"
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0011vmap_0.json-nft b/tests/shell/testcases/maps/dumps/0011vmap_0.json-nft
new file mode 100644 (file)
index 0000000..8f07378
--- /dev/null
@@ -0,0 +1,145 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "ssh_input",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "wan_input",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "portmap",
+        "table": "filter",
+        "type": "inet_service",
+        "handle": 0,
+        "map": "verdict",
+        "elem": [
+          [
+            {
+              "elem": {
+                "val": 22,
+                "counter": {
+                  "packets": 0,
+                  "bytes": 0
+                }
+              }
+            },
+            {
+              "jump": {
+                "target": "ssh_input"
+              }
+            }
+          ],
+          [
+            {
+              "elem": {
+                "val": "*",
+                "counter": {
+                  "packets": 0,
+                  "bytes": 0
+                }
+              }
+            },
+            {
+              "drop": null
+            }
+          ]
+        ],
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "wan_input",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "data": "@portmap"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "prerouting",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "meta": {
+                  "key": "iif"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    "lo",
+                    {
+                      "jump": {
+                        "target": "wan_input"
+                      }
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index 4a72b5e7ea3866e2053b4b235879ecc540bae350..94b85a61813f376e3bfc01a66f99bf5dbb41e9c3 100644 (file)
@@ -2,7 +2,8 @@ table inet filter {
        map portmap {
                type inet_service : verdict
                counter
-               elements = { 22 counter packets 0 bytes 0 : jump ssh_input, * counter packets 0 bytes 0 : drop }
+               elements = { 22 counter packets 0 bytes 0 : jump ssh_input,
+                            * counter packets 0 bytes 0 : drop }
        }
 
        chain ssh_input {
diff --git a/tests/shell/testcases/maps/dumps/0012map_0.json-nft b/tests/shell/testcases/maps/dumps/0012map_0.json-nft
new file mode 100644 (file)
index 0000000..2892e11
--- /dev/null
@@ -0,0 +1,97 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "z",
+        "table": "x",
+        "type": "ifname",
+        "handle": 0,
+        "map": "verdict",
+        "elem": [
+          [
+            "lo",
+            {
+              "accept": null
+            }
+          ],
+          [
+            "eth0",
+            {
+              "drop": null
+            }
+          ],
+          [
+            "eth1",
+            {
+              "drop": null
+            }
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    "lo",
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    "eth0",
+                    {
+                      "drop": null
+                    }
+                  ],
+                  [
+                    "eth1",
+                    {
+                      "drop": null
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index 895490cffa8c1be6ad780756b921bd522192d3b0..e734fc1c70b9383d436c91abb5c95a0139eaebe4 100644 (file)
@@ -6,20 +6,7 @@ table ip x {
                             "eth1" : drop }
        }
 
-       map w {
-               typeof ip saddr . meta mark : verdict
-               flags interval
-               counter
-               elements = { 127.0.0.1-127.0.0.4 . 0x00123434-0x00b00122 counter packets 0 bytes 0 : accept }
-       }
-
        chain y {
                iifname vmap { "lo" : accept, "eth0" : drop, "eth1" : drop }
        }
-
-       chain k {
-               type filter hook input priority filter + 1; policy accept;
-               meta mark set 0x00123434
-               ip saddr . meta mark vmap @w
-       }
 }
diff --git a/tests/shell/testcases/maps/dumps/0012map_concat_0.json-nft b/tests/shell/testcases/maps/dumps/0012map_concat_0.json-nft
new file mode 100644 (file)
index 0000000..85384c5
--- /dev/null
@@ -0,0 +1,143 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "k",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 1,
+        "policy": "accept"
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "w",
+        "table": "x",
+        "type": {
+          "typeof": {
+            "concat": [
+              {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              {
+                "meta": {
+                  "key": "mark"
+                }
+              }
+            ]
+          }
+        },
+        "handle": 0,
+        "map": "verdict",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "elem": {
+                "val": {
+                  "concat": [
+                    {
+                      "range": [
+                        "127.0.0.1",
+                        "127.0.0.4"
+                      ]
+                    },
+                    {
+                      "range": [
+                        1193012,
+                        11534626
+                      ]
+                    }
+                  ]
+                },
+                "counter": {
+                  "packets": 0,
+                  "bytes": 0
+                }
+              }
+            },
+            {
+              "accept": null
+            }
+          ]
+        ],
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "k",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": 1193012
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "k",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "meta": {
+                      "key": "mark"
+                    }
+                  }
+                ]
+              },
+              "data": "@w"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0012map_concat_0.nft b/tests/shell/testcases/maps/dumps/0012map_concat_0.nft
new file mode 100644 (file)
index 0000000..6649d03
--- /dev/null
@@ -0,0 +1,14 @@
+table ip x {
+       map w {
+               typeof ip saddr . meta mark : verdict
+               flags interval
+               counter
+               elements = { 127.0.0.1-127.0.0.4 . 0x00123434-0x00b00122 counter packets 0 bytes 0 : accept }
+       }
+
+       chain k {
+               type filter hook input priority filter + 1; policy accept;
+               meta mark set 0x00123434
+               ip saddr . meta mark vmap @w
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/0013map_0.json-nft b/tests/shell/testcases/maps/dumps/0013map_0.json-nft
new file mode 100644 (file)
index 0000000..2c8d21b
--- /dev/null
@@ -0,0 +1,126 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "FORWARD",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 0,
+        "policy": "drop"
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "forwport",
+        "table": "filter",
+        "type": [
+          "ipv4_addr",
+          "inet_proto",
+          "inet_service"
+        ],
+        "handle": 0,
+        "map": "verdict",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "elem": {
+                "val": {
+                  "concat": [
+                    "10.133.89.138",
+                    "tcp",
+                    8081
+                  ]
+                },
+                "counter": {
+                  "packets": 0,
+                  "bytes": 0
+                }
+              }
+            },
+            {
+              "accept": null
+            }
+          ]
+        ],
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "enp0s8"
+            }
+          },
+          {
+            "vmap": {
+              "key": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "protocol"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "th",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "data": "@forwport"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0014destroy_0.json-nft b/tests/shell/testcases/maps/dumps/0014destroy_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0014destroy_0.nft b/tests/shell/testcases/maps/dumps/0014destroy_0.nft
new file mode 100644 (file)
index 0000000..5d4d2ca
--- /dev/null
@@ -0,0 +1,2 @@
+table ip x {
+}
diff --git a/tests/shell/testcases/maps/dumps/0016map_leak_0.json-nft b/tests/shell/testcases/maps/dumps/0016map_leak_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0016map_leak_0.nft b/tests/shell/testcases/maps/dumps/0016map_leak_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/maps/dumps/0017_map_variable_0.json-nft b/tests/shell/testcases/maps/dumps/0017_map_variable_0.json-nft
new file mode 100644 (file)
index 0000000..8eacf61
--- /dev/null
@@ -0,0 +1,72 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": {
+          "typeof": {
+            "payload": {
+              "protocol": "ip",
+              "field": "saddr"
+            }
+          }
+        },
+        "handle": 0,
+        "map": "mark",
+        "elem": [
+          [
+            "1.1.1.1",
+            2
+          ],
+          [
+            "*",
+            3
+          ]
+        ]
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "z",
+        "table": "x",
+        "type": {
+          "typeof": {
+            "payload": {
+              "protocol": "ip",
+              "field": "saddr"
+            }
+          }
+        },
+        "handle": 0,
+        "map": "mark",
+        "elem": [
+          [
+            "1.1.1.1",
+            2
+          ],
+          [
+            "*",
+            3
+          ]
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0017_map_variable_0.nft b/tests/shell/testcases/maps/dumps/0017_map_variable_0.nft
new file mode 100644 (file)
index 0000000..f6d7f6a
--- /dev/null
@@ -0,0 +1,13 @@
+table ip x {
+       map y {
+               typeof ip saddr : meta mark
+               elements = { 1.1.1.1 : 0x00000002,
+                            * : 0x00000003 }
+       }
+
+       map z {
+               typeof ip saddr : meta mark
+               elements = { 1.1.1.1 : 0x00000002,
+                            * : 0x00000003 }
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/0018map_leak_timeout_0.json-nft b/tests/shell/testcases/maps/dumps/0018map_leak_timeout_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/0018map_leak_timeout_0.nft b/tests/shell/testcases/maps/dumps/0018map_leak_timeout_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/maps/dumps/0024named_objects_0.json-nft b/tests/shell/testcases/maps/dumps/0024named_objects_0.json-nft
new file mode 100644 (file)
index 0000000..aa2f6f8
--- /dev/null
@@ -0,0 +1,165 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "counter": {
+        "family": "inet",
+        "name": "user123",
+        "table": "x",
+        "handle": 0,
+        "packets": 12,
+        "bytes": 1433
+      }
+    },
+    {
+      "counter": {
+        "family": "inet",
+        "name": "user321",
+        "table": "x",
+        "handle": 0,
+        "packets": 0,
+        "bytes": 0
+      }
+    },
+    {
+      "quota": {
+        "family": "inet",
+        "name": "user123",
+        "table": "x",
+        "handle": 0,
+        "bytes": 2000,
+        "used": 0,
+        "inv": true
+      }
+    },
+    {
+      "quota": {
+        "family": "inet",
+        "name": "user124",
+        "table": "x",
+        "handle": 0,
+        "bytes": 2000,
+        "used": 0,
+        "inv": true
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "test",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "quota",
+        "elem": [
+          [
+            "192.168.2.2",
+            "user124"
+          ],
+          [
+            "192.168.2.3",
+            "user124"
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "map": {
+                "key": {
+                  "payload": {
+                    "protocol": "ip",
+                    "field": "saddr"
+                  }
+                },
+                "data": {
+                  "set": [
+                    [
+                      "1.1.1.1",
+                      "user123"
+                    ],
+                    [
+                      "2.2.2.2",
+                      "user123"
+                    ],
+                    [
+                      "192.168.2.2",
+                      "user123"
+                    ]
+                  ]
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "quota": {
+              "map": {
+                "key": {
+                  "payload": {
+                    "protocol": "ip",
+                    "field": "saddr"
+                  }
+                },
+                "data": "@test"
+              }
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
similarity index 50%
rename from tests/shell/testcases/sets/dumps/0024named_objects_0.nft
rename to tests/shell/testcases/maps/dumps/0024named_objects_0.nft
index 52d1bf64b686638d69ee858e9c3ba81ea3471a53..3188ce2a53a3ffbcd71098119283cc6aac670ee8 100644 (file)
@@ -15,36 +15,19 @@ table inet x {
                over 2000 bytes
        }
 
-       synproxy https-synproxy {
-               mss 1460
-               wscale 7
-               timestamp sack-perm
-       }
-
-       synproxy other-synproxy {
-               mss 1460
-               wscale 5
-       }
-
        set y {
                type ipv4_addr
        }
 
        map test {
                type ipv4_addr : quota
-               elements = { 192.168.2.2 : "user124", 192.168.2.3 : "user124" }
-       }
-
-       map test2 {
-               type ipv4_addr : synproxy
-               flags interval
-               elements = { 192.168.1.0/24 : "https-synproxy", 192.168.2.0/24 : "other-synproxy" }
+               elements = { 192.168.2.2 : "user124",
+                            192.168.2.3 : "user124" }
        }
 
        chain y {
                type filter hook input priority filter; policy accept;
                counter name ip saddr map { 1.1.1.1 : "user123", 2.2.2.2 : "user123", 192.168.2.2 : "user123" }
-               synproxy name ip saddr map { 192.168.1.0/24 : "https-synproxy", 192.168.2.0/24 : "other-synproxy" }
                quota name ip saddr map @test drop
        }
 }
diff --git a/tests/shell/testcases/maps/dumps/0024named_objects_2.nodump b/tests/shell/testcases/maps/dumps/0024named_objects_2.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/maps/dumps/anon_objmap_concat.json-nft b/tests/shell/testcases/maps/dumps/anon_objmap_concat.json-nft
new file mode 100644 (file)
index 0000000..6420984
--- /dev/null
@@ -0,0 +1,116 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "ct helper": {
+        "family": "inet",
+        "name": "sip-5060u",
+        "table": "filter",
+        "handle": 0,
+        "type": "sip",
+        "protocol": "udp",
+        "l3proto": "ip"
+      }
+    },
+    {
+      "ct helper": {
+        "family": "inet",
+        "name": "sip-5060t",
+        "table": "filter",
+        "handle": 0,
+        "type": "sip",
+        "protocol": "tcp",
+        "l3proto": "ip"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "ct helper": {
+              "map": {
+                "key": {
+                  "concat": [
+                    {
+                      "payload": {
+                        "protocol": "ip",
+                        "field": "protocol"
+                      }
+                    },
+                    {
+                      "payload": {
+                        "protocol": "th",
+                        "field": "dport"
+                      }
+                    }
+                  ]
+                },
+                "data": {
+                  "set": [
+                    [
+                      {
+                        "concat": [
+                          "udp",
+                          {
+                            "range": [
+                              10000,
+                              20000
+                            ]
+                          }
+                        ]
+                      },
+                      "sip-5060u"
+                    ],
+                    [
+                      {
+                        "concat": [
+                          "tcp",
+                          {
+                            "range": [
+                              10000,
+                              20000
+                            ]
+                          }
+                        ]
+                      },
+                      "sip-5060t"
+                    ]
+                  ]
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/anonymous_snat_map_0.json-nft b/tests/shell/testcases/maps/dumps/anonymous_snat_map_0.json-nft
new file mode 100644 (file)
index 0000000..f4c5570
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "nat",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "nat",
+        "name": "postrouting",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "nat",
+        "chain": "postrouting",
+        "handle": 0,
+        "expr": [
+          {
+            "snat": {
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        "1.1.1.1",
+                        "2.2.2.2"
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/anonymous_snat_map_2.nodump b/tests/shell/testcases/maps/dumps/anonymous_snat_map_2.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/maps/dumps/delete_element.nft b/tests/shell/testcases/maps/dumps/delete_element.nft
new file mode 100644 (file)
index 0000000..5275b4d
--- /dev/null
@@ -0,0 +1,12 @@
+table ip x {
+       map m {
+               typeof ct bytes : meta priority
+               flags interval
+               elements = { 2048001-4000000 : 1:2 }
+       }
+
+       chain y {
+               type filter hook output priority filter; policy accept;
+               meta priority set ct bytes map @m
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/delete_element_catchall.nft b/tests/shell/testcases/maps/dumps/delete_element_catchall.nft
new file mode 100644 (file)
index 0000000..14054f4
--- /dev/null
@@ -0,0 +1,12 @@
+table ip x {
+       map m {
+               typeof ct bytes : meta priority
+               flags interval
+               elements = { * : 1:3 }
+       }
+
+       chain y {
+               type filter hook output priority filter; policy accept;
+               meta priority set ct bytes map @m
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/different_map_types_1.json-nft b/tests/shell/testcases/maps/dumps/different_map_types_1.json-nft
new file mode 100644 (file)
index 0000000..ed0ce0e
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "output",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/different_map_types_1.nft b/tests/shell/testcases/maps/dumps/different_map_types_1.nft
new file mode 100644 (file)
index 0000000..3c18b5c
--- /dev/null
@@ -0,0 +1,5 @@
+table ip filter {
+       chain output {
+               type filter hook output priority filter; policy accept;
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/map_catchall_double_deactivate.json-nft b/tests/shell/testcases/maps/dumps/map_catchall_double_deactivate.json-nft
new file mode 100644 (file)
index 0000000..49b8bb2
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "testchain",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/map_catchall_double_deactivate.nft b/tests/shell/testcases/maps/dumps/map_catchall_double_deactivate.nft
new file mode 100644 (file)
index 0000000..37c48bf
--- /dev/null
@@ -0,0 +1,4 @@
+table ip test {
+       chain testchain {
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/map_catchall_double_free.nodump b/tests/shell/testcases/maps/dumps/map_catchall_double_free.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/maps/dumps/map_catchall_double_free_2.json-nft b/tests/shell/testcases/maps/dumps/map_catchall_double_free_2.json-nft
new file mode 100644 (file)
index 0000000..a9d4c8e
--- /dev/null
@@ -0,0 +1,46 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "testchain",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "testmap",
+        "table": "test",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "verdict",
+        "elem": [
+          [
+            "*",
+            {
+              "jump": {
+                "target": "testchain"
+              }
+            }
+          ]
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/map_catchall_double_free_2.nft b/tests/shell/testcases/maps/dumps/map_catchall_double_free_2.nft
new file mode 100644 (file)
index 0000000..68958c4
--- /dev/null
@@ -0,0 +1,9 @@
+table ip test {
+       map testmap {
+               type ipv4_addr : verdict
+               elements = { * : jump testchain }
+       }
+
+       chain testchain {
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/map_with_flags_0.json-nft b/tests/shell/testcases/maps/dumps/map_with_flags_0.json-nft
new file mode 100644 (file)
index 0000000..94ec5f7
--- /dev/null
@@ -0,0 +1,29 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "ipv4_addr",
+        "flags": "timeout"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/named_ct_objects.nft b/tests/shell/testcases/maps/dumps/named_ct_objects.nft
new file mode 100644 (file)
index 0000000..59f1893
--- /dev/null
@@ -0,0 +1,71 @@
+table inet t {
+       ct expectation exp1 {
+               protocol tcp
+               dport 9876
+               timeout 1m
+               size 12
+               l3proto ip
+       }
+
+       ct expectation exp2 {
+               protocol tcp
+               dport 9876
+               timeout 3s
+               size 13
+               l3proto ip6
+       }
+
+       ct helper myftp {
+               type "ftp" protocol tcp
+               l3proto inet
+       }
+
+       ct timeout dns {
+               protocol tcp
+               l3proto ip
+               policy = { established : 3s, close : 1s }
+       }
+
+       map exp {
+               typeof ip saddr : ct expectation
+               elements = { 192.168.2.2 : "exp1" }
+       }
+
+       map exp6 {
+               typeof ip6 saddr : ct expectation
+               flags interval
+               elements = { dead:beef::/64 : "exp2" }
+       }
+
+       map helpobj {
+               typeof ip6 saddr : ct helper
+               flags interval
+               elements = { dead:beef::/64 : "myftp" }
+       }
+
+       map timeoutmap {
+               typeof ip daddr : ct timeout
+               elements = { 192.168.0.1 : "dns" }
+       }
+
+       set helpname {
+               typeof ct helper
+               elements = { "sip",
+                            "ftp" }
+       }
+
+       chain y {
+               ct expectation set ip saddr map @exp
+               ct expectation set ip6 saddr map { dead::beef : "exp2" }
+               ct expectation set ip6 daddr map { dead::beef : "exp2", feed::17 : "exp2" }
+               ct expectation set ip6 daddr . tcp dport map { feed::17 . 512 : "exp2", dead::beef . 123 : "exp2" }
+               ct helper set ip6 saddr map { 1c3::c01d : "myftp", dead::beef : "myftp" }
+               ct helper set ip6 saddr map @helpobj
+               ct timeout set ip daddr map @timeoutmap
+               ct timeout set ip daddr map { 1.2.3.4 : "dns", 5.6.7.8 : "dns", 192.168.8.0/24 : "dns" }
+               ct timeout set ip daddr map { 1.2.3.4-1.2.3.8 : "dns" }
+               ct timeout set ip6 daddr map { 1ce::/64 : "dns", dead::beef : "dns" }
+               ct helper @helpname accept
+               ip saddr 192.168.1.1 ct timeout set "dns"
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/named_limits.json-nft b/tests/shell/testcases/maps/dumps/named_limits.json-nft
new file mode 100644 (file)
index 0000000..07e2892
--- /dev/null
@@ -0,0 +1,363 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "limit": {
+        "family": "inet",
+        "name": "tarpit-pps",
+        "table": "filter",
+        "handle": 0,
+        "rate": 1,
+        "per": "second",
+        "burst": 5
+      }
+    },
+    {
+      "limit": {
+        "family": "inet",
+        "name": "tarpit-bps",
+        "table": "filter",
+        "handle": 0,
+        "rate": 1,
+        "per": "second",
+        "rate_unit": "kbytes"
+      }
+    },
+    {
+      "limit": {
+        "family": "inet",
+        "name": "http-bulk-rl-1m",
+        "table": "filter",
+        "handle": 0,
+        "rate": 1,
+        "per": "second",
+        "rate_unit": "mbytes"
+      }
+    },
+    {
+      "limit": {
+        "family": "inet",
+        "name": "http-bulk-rl-10m",
+        "table": "filter",
+        "handle": 0,
+        "rate": 10,
+        "per": "second",
+        "rate_unit": "mbytes"
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "tarpit4",
+        "table": "filter",
+        "type": {
+          "typeof": {
+            "payload": {
+              "protocol": "ip",
+              "field": "saddr"
+            }
+          }
+        },
+        "handle": 0,
+        "size": 10000,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ],
+        "timeout": 60
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "tarpit6",
+        "table": "filter",
+        "type": {
+          "typeof": {
+            "payload": {
+              "protocol": "ip6",
+              "field": "saddr"
+            }
+          }
+        },
+        "handle": 0,
+        "size": 10000,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ],
+        "timeout": 60
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "addr4limit",
+        "table": "filter",
+        "type": {
+          "typeof": {
+            "concat": [
+              {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "sport"
+                }
+              }
+            ]
+          }
+        },
+        "handle": 0,
+        "map": "limit",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "concat": [
+                "tcp",
+                {
+                  "prefix": {
+                    "addr": "192.168.0.0",
+                    "len": 16
+                  }
+                },
+                {
+                  "range": [
+                    1,
+                    65535
+                  ]
+                }
+              ]
+            },
+            "tarpit-bps"
+          ],
+          [
+            {
+              "concat": [
+                "udp",
+                {
+                  "prefix": {
+                    "addr": "192.168.0.0",
+                    "len": 16
+                  }
+                },
+                {
+                  "range": [
+                    1,
+                    65535
+                  ]
+                }
+              ]
+            },
+            "tarpit-pps"
+          ],
+          [
+            {
+              "concat": [
+                "tcp",
+                {
+                  "range": [
+                    "127.0.0.1",
+                    "127.1.2.3"
+                  ]
+                },
+                {
+                  "range": [
+                    1,
+                    1024
+                  ]
+                }
+              ]
+            },
+            "tarpit-pps"
+          ],
+          [
+            {
+              "concat": [
+                "tcp",
+                {
+                  "range": [
+                    "10.0.0.1",
+                    "10.0.0.255"
+                  ]
+                },
+                80
+              ]
+            },
+            "http-bulk-rl-1m"
+          ],
+          [
+            {
+              "concat": [
+                "tcp",
+                {
+                  "range": [
+                    "10.0.0.1",
+                    "10.0.0.255"
+                  ]
+                },
+                443
+              ]
+            },
+            "http-bulk-rl-1m"
+          ],
+          [
+            {
+              "concat": [
+                "tcp",
+                {
+                  "prefix": {
+                    "addr": "10.0.1.0",
+                    "len": 24
+                  }
+                },
+                {
+                  "range": [
+                    1024,
+                    65535
+                  ]
+                }
+              ]
+            },
+            "http-bulk-rl-10m"
+          ],
+          [
+            {
+              "concat": [
+                "tcp",
+                "10.0.2.1",
+                22
+              ]
+            },
+            "http-bulk-rl-10m"
+          ]
+        ]
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "saddr6limit",
+        "table": "filter",
+        "type": {
+          "typeof": {
+            "payload": {
+              "protocol": "ip6",
+              "field": "saddr"
+            }
+          }
+        },
+        "handle": 0,
+        "map": "limit",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "range": [
+                "dead::beef",
+                "dead::1:aced"
+              ]
+            },
+            "tarpit-pps"
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "limit": {
+              "map": {
+                "key": {
+                  "concat": [
+                    {
+                      "meta": {
+                        "key": "l4proto"
+                      }
+                    },
+                    {
+                      "payload": {
+                        "protocol": "ip",
+                        "field": "saddr"
+                      }
+                    },
+                    {
+                      "payload": {
+                        "protocol": "th",
+                        "field": "sport"
+                      }
+                    }
+                  ]
+                },
+                "data": "@addr4limit"
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "limit": {
+              "map": {
+                "key": {
+                  "payload": {
+                    "protocol": "ip6",
+                    "field": "saddr"
+                  }
+                },
+                "data": "@saddr6limit"
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/named_limits.nft b/tests/shell/testcases/maps/dumps/named_limits.nft
new file mode 100644 (file)
index 0000000..214df20
--- /dev/null
@@ -0,0 +1,55 @@
+table inet filter {
+       limit tarpit-pps {
+               rate 1/second
+       }
+
+       limit tarpit-bps {
+               rate 1 kbytes/second
+       }
+
+       limit http-bulk-rl-1m {
+               rate 1 mbytes/second
+       }
+
+       limit http-bulk-rl-10m {
+               rate 10 mbytes/second
+       }
+
+       set tarpit4 {
+               typeof ip saddr
+               size 10000
+               flags dynamic,timeout
+               timeout 1m
+       }
+
+       set tarpit6 {
+               typeof ip6 saddr
+               size 10000
+               flags dynamic,timeout
+               timeout 1m
+       }
+
+       map addr4limit {
+               typeof meta l4proto . ip saddr . tcp sport : limit
+               flags interval
+               elements = { tcp . 192.168.0.0/16 . 1-65535 : "tarpit-bps",
+                            udp . 192.168.0.0/16 . 1-65535 : "tarpit-pps",
+                            tcp . 127.0.0.1-127.1.2.3 . 1-1024 : "tarpit-pps",
+                            tcp . 10.0.0.1-10.0.0.255 . 80 : "http-bulk-rl-1m",
+                            tcp . 10.0.0.1-10.0.0.255 . 443 : "http-bulk-rl-1m",
+                            tcp . 10.0.1.0/24 . 1024-65535 : "http-bulk-rl-10m",
+                            tcp . 10.0.2.1 . 22 : "http-bulk-rl-10m" }
+       }
+
+       map saddr6limit {
+               typeof ip6 saddr : limit
+               flags interval
+               elements = { dead::beef-dead::1:aced : "tarpit-pps" }
+       }
+
+       chain input {
+               type filter hook input priority filter; policy accept;
+               limit name meta l4proto . ip saddr . th sport map @addr4limit
+               limit name ip6 saddr map @saddr6limit
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/named_snat_map_0.json-nft b/tests/shell/testcases/maps/dumps/named_snat_map_0.json-nft
new file mode 100644 (file)
index 0000000..ad9eb36
--- /dev/null
@@ -0,0 +1,67 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "nat",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "nat",
+        "name": "postrouting",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "m",
+        "table": "nat",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "ipv4_addr",
+        "elem": [
+          [
+            "1.1.1.1",
+            "2.2.2.2"
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "nat",
+        "chain": "postrouting",
+        "handle": 0,
+        "expr": [
+          {
+            "snat": {
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "data": "@m"
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/pipapo_double_flush.json-nft b/tests/shell/testcases/maps/dumps/pipapo_double_flush.json-nft
new file mode 100644 (file)
index 0000000..dc793a6
--- /dev/null
@@ -0,0 +1,40 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "m",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "ipv4_addr"
+        ],
+        "handle": 0,
+        "map": "verdict",
+        "flags": "interval"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/pipapo_double_flush.nft b/tests/shell/testcases/maps/dumps/pipapo_double_flush.nft
new file mode 100644 (file)
index 0000000..cca569e
--- /dev/null
@@ -0,0 +1,9 @@
+table inet t {
+       map m {
+               type ipv4_addr . ipv4_addr : verdict
+               flags interval
+       }
+
+       chain c {
+       }
+}
index 330415574c95b594ecef5315b3618721571773dd..19c24febffcc5bd803251db80d7fb655c83b2a31 100644 (file)
@@ -13,8 +13,8 @@ table inet t {
        }
 
        chain c {
-               udp length . @ih,32,32 vmap @m1
-               udp length . @ih,32,32 vmap @m2
+               udp length . @nh,32,32 vmap @m1
+               udp length . @nh,32,32 vmap @m2
                udp length . @th,160,128 vmap { 47-63 . 0xe373135363130333131303735353203 : accept }
        }
 }
index a5c0a60927a7b2757c1f68e35dc0e008f6462d88..e0efabab3b5509516cebaeb4b2ea5d6625d54b31 100644 (file)
@@ -6,7 +6,8 @@ table inet t {
 
        map m2 {
                typeof vlan id : meta mark
-               elements = { 1 : 0x00000001, 4095 : 0x00004095 }
+               elements = { 1 : 0x00000001,
+                            4095 : 0x00004095 }
        }
 
        map m3 {
diff --git a/tests/shell/testcases/maps/dumps/typeof_maps_add_delete.json-nft b/tests/shell/testcases/maps/dumps/typeof_maps_add_delete.json-nft
new file mode 100644 (file)
index 0000000..8b18a78
--- /dev/null
@@ -0,0 +1,288 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "dynset",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "dynset",
+        "name": "test_ping",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "dynset",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "dynmark",
+        "table": "dynset",
+        "type": {
+          "typeof": {
+            "payload": {
+              "protocol": "ip",
+              "field": "daddr"
+            }
+          }
+        },
+        "handle": 0,
+        "map": "mark",
+        "size": 64,
+        "flags": "timeout",
+        "timeout": 300,
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "dynset",
+        "chain": "test_ping",
+        "handle": 0,
+        "comment": "should not increment",
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@dynmark"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "dynset",
+        "chain": "test_ping",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "!=",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@dynmark"
+            }
+          },
+          {
+            "map": {
+              "op": "add",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": 1,
+              "map": "@dynmark"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "dynset",
+        "chain": "test_ping",
+        "handle": 0,
+        "comment": "should increment",
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@dynmark"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "dynset",
+        "chain": "test_ping",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@dynmark"
+            }
+          },
+          {
+            "map": {
+              "op": "delete",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": 1,
+              "map": "@dynmark"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "dynset",
+        "chain": "test_ping",
+        "handle": 0,
+        "comment": "delete should be instant but might fail under memory pressure",
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@dynmark"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "dynset",
+        "chain": "input",
+        "handle": 0,
+        "comment": "also check timeout-gc",
+        "expr": [
+          {
+            "map": {
+              "op": "add",
+              "elem": {
+                "elem": {
+                  "val": "10.2.3.4",
+                  "timeout": 2
+                }
+              },
+              "data": 2,
+              "map": "@dynmark"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "dynset",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "icmp"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "127.0.0.42"
+            }
+          },
+          {
+            "jump": {
+              "target": "test_ping"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/typeof_maps_add_delete.nft b/tests/shell/testcases/maps/dumps/typeof_maps_add_delete.nft
new file mode 100644 (file)
index 0000000..e80366b
--- /dev/null
@@ -0,0 +1,22 @@
+table ip dynset {
+       map dynmark {
+               typeof ip daddr : meta mark
+               size 64
+               counter
+               timeout 5m
+       }
+
+       chain test_ping {
+               ip saddr @dynmark counter packets 0 bytes 0 comment "should not increment"
+               ip saddr != @dynmark add @dynmark { ip saddr : 0x00000001 } counter packets 1 bytes 84
+               ip saddr @dynmark counter packets 1 bytes 84 comment "should increment"
+               ip saddr @dynmark delete @dynmark { ip saddr : 0x00000001 }
+               ip saddr @dynmark counter packets 0 bytes 0 comment "delete should be instant but might fail under memory pressure"
+       }
+
+       chain input {
+               type filter hook input priority filter; policy accept;
+               add @dynmark { 10.2.3.4 timeout 2s : 0x00000002 } comment "also check timeout-gc"
+               meta l4proto icmp ip daddr 127.0.0.42 jump test_ping
+       }
+}
diff --git a/tests/shell/testcases/maps/dumps/typeof_maps_update_0.json-nft b/tests/shell/testcases/maps/dumps/typeof_maps_update_0.json-nft
new file mode 100644 (file)
index 0000000..b79237d
--- /dev/null
@@ -0,0 +1,113 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "kube-nfproxy-v4",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "kube-nfproxy-v4",
+        "name": "k8s-nfproxy-sep-TMVEFT7EX55F4T62",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "kube-nfproxy-v4",
+        "name": "k8s-nfproxy-sep-GMVEFT7EX55F4T62",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "sticky-set-svc-M53CN2XYVUHRQ7UB",
+        "table": "kube-nfproxy-v4",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "mark",
+        "size": 65535,
+        "flags": "timeout",
+        "timeout": 360
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "sticky-set-svc-153CN2XYVUHRQ7UB",
+        "table": "kube-nfproxy-v4",
+        "type": {
+          "typeof": {
+            "payload": {
+              "protocol": "ip",
+              "field": "daddr"
+            }
+          }
+        },
+        "handle": 0,
+        "map": "mark",
+        "size": 65535,
+        "flags": "timeout",
+        "timeout": 60
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "kube-nfproxy-v4",
+        "chain": "k8s-nfproxy-sep-TMVEFT7EX55F4T62",
+        "handle": 0,
+        "expr": [
+          {
+            "map": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": 2,
+              "map": "@sticky-set-svc-M53CN2XYVUHRQ7UB"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "kube-nfproxy-v4",
+        "chain": "k8s-nfproxy-sep-GMVEFT7EX55F4T62",
+        "handle": 0,
+        "expr": [
+          {
+            "map": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": 3,
+              "map": "@sticky-set-svc-153CN2XYVUHRQ7UB"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index e876425b2bc62581f107a9b0380a4553eba19943..476169f2943b4ce3ea6bf785374b6b56dae18a3c 100644 (file)
@@ -7,7 +7,7 @@ table ip x {
        }
 
        chain y {
-               ip saddr . @ih,32,32 vmap @y
-               ip saddr . @ih,32,32 vmap { 4.4.4.4 . 0x34 : accept, 5.5.5.5 . 0x45 : drop }
+               ip saddr . @nh,32,32 vmap @y
+               ip saddr . @nh,32,32 vmap { 4.4.4.4 . 0x34 : accept, 5.5.5.5 . 0x45 : drop }
        }
 }
diff --git a/tests/shell/testcases/maps/dumps/vmap_mark_bitwise_0.json-nft b/tests/shell/testcases/maps/dumps/vmap_mark_bitwise_0.json-nft
new file mode 100644 (file)
index 0000000..df15641
--- /dev/null
@@ -0,0 +1,158 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "sctm_o0_0",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "sctm_o0_1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "SET_ctmark_RPLYroute",
+        "handle": 0
+      }
+    },
+    {
+      "counter": {
+        "family": "ip",
+        "name": "c_o0_0",
+        "table": "x",
+        "handle": 0,
+        "packets": 0,
+        "bytes": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "sctm_o0",
+        "table": "x",
+        "type": "mark",
+        "handle": 0,
+        "map": "verdict",
+        "elem": [
+          [
+            0,
+            {
+              "jump": {
+                "target": "sctm_o0_0"
+              }
+            }
+          ],
+          [
+            1,
+            {
+              "jump": {
+                "target": "sctm_o0_1"
+              }
+            }
+          ]
+        ]
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "sctm_o1",
+        "table": "x",
+        "type": "mark",
+        "handle": 0,
+        "map": "counter",
+        "elem": [
+          [
+            0,
+            "c_o0_0"
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "SET_ctmark_RPLYroute",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "&": [
+                  {
+                    ">>": [
+                      {
+                        "meta": {
+                          "key": "mark"
+                        }
+                      },
+                      8
+                    ]
+                  },
+                  15
+                ]
+              },
+              "data": "@sctm_o0"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "SET_ctmark_RPLYroute",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "map": {
+                "key": {
+                  "&": [
+                    {
+                      ">>": [
+                        {
+                          "meta": {
+                            "key": "mark"
+                          }
+                        },
+                        8
+                      ]
+                    },
+                    15
+                  ]
+                },
+                "data": "@sctm_o1"
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index beb5ffb098f5948378eae127b951f281a16e56c4..6891e8611081b3555c6d70c2ee61435b952e59e8 100644 (file)
@@ -5,7 +5,8 @@ table ip x {
 
        map sctm_o0 {
                type mark : verdict
-               elements = { 0x00000000 : jump sctm_o0_0, 0x00000001 : jump sctm_o0_1 }
+               elements = { 0x00000000 : jump sctm_o0_0,
+                            0x00000001 : jump sctm_o0_1 }
        }
 
        map sctm_o1 {
diff --git a/tests/shell/testcases/maps/dumps/vmap_timeout.json-nft b/tests/shell/testcases/maps/dumps/vmap_timeout.json-nft
new file mode 100644 (file)
index 0000000..2d7d8cc
--- /dev/null
@@ -0,0 +1,239 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "ssh_input",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "log_and_drop",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "other_input",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "wan_input",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -300,
+        "policy": "accept"
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "portmap",
+        "table": "filter",
+        "type": "inet_service",
+        "handle": 0,
+        "map": "verdict",
+        "flags": "timeout",
+        "gc-interval": 10,
+        "elem": [
+          [
+            22,
+            {
+              "jump": {
+                "target": "ssh_input"
+              }
+            }
+          ]
+        ]
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "portaddrmap",
+        "table": "filter",
+        "type": {
+          "typeof": {
+            "concat": [
+              {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              {
+                "payload": {
+                  "protocol": "th",
+                  "field": "dport"
+                }
+              }
+            ]
+          }
+        },
+        "handle": 0,
+        "map": "verdict",
+        "flags": "timeout",
+        "gc-interval": 10,
+        "elem": [
+          [
+            {
+              "concat": [
+                "1.2.3.4",
+                22
+              ]
+            },
+            {
+              "jump": {
+                "target": "ssh_input"
+              }
+            }
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "log_and_drop",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "other_input",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "log_and_drop"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "wan_input",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "data": "@portaddrmap"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "wan_input",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "data": "@portmap"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "prerouting",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "meta": {
+                  "key": "iif"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    "lo",
+                    {
+                      "jump": {
+                        "target": "wan_input"
+                      }
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/maps/dumps/vmap_timeout.nft b/tests/shell/testcases/maps/dumps/vmap_timeout.nft
new file mode 100644 (file)
index 0000000..095f894
--- /dev/null
@@ -0,0 +1,36 @@
+table inet filter {
+       map portmap {
+               type inet_service : verdict
+               flags timeout
+               gc-interval 10s
+               elements = { 22 : jump ssh_input }
+       }
+
+       map portaddrmap {
+               typeof ip daddr . th dport : verdict
+               flags timeout
+               gc-interval 10s
+               elements = { 1.2.3.4 . 22 : jump ssh_input }
+       }
+
+       chain ssh_input {
+       }
+
+       chain log_and_drop {
+               drop
+       }
+
+       chain other_input {
+               goto log_and_drop
+       }
+
+       chain wan_input {
+               ip daddr . tcp dport vmap @portaddrmap
+               tcp dport vmap @portmap
+       }
+
+       chain prerouting {
+               type filter hook prerouting priority raw; policy accept;
+               iif vmap { "lo" : jump wan_input }
+       }
+}
diff --git a/tests/shell/testcases/maps/map_catchall_double_deactivate b/tests/shell/testcases/maps/map_catchall_double_deactivate
new file mode 100755 (executable)
index 0000000..651c08a
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_catchall_element)
+
+$NFT "add table ip test ;
+     add map ip test testmap { type ipv4_addr : verdict; };
+     add chain ip test testchain;
+     add element ip test testmap { * : jump testchain }" || exit 1
+
+$NFT "flush map ip test testmap; delete map ip test testmap; delete map ip test testmap" 2>/dev/null && exit 1
+$NFT "flush map ip test testmap; delete map ip test testmap; delete element ip test testmap { * : jump testchain }" 2>/dev/null && exit 1
+
+$NFT "flush map ip test testmap; delete map ip test testmap" || exit 1
diff --git a/tests/shell/testcases/maps/map_catchall_double_free b/tests/shell/testcases/maps/map_catchall_double_free
new file mode 100755 (executable)
index 0000000..d101256
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_catchall_element)
+
+$NFT "add table ip test ;
+     add map ip test testmap { type ipv4_addr . ipv4_addr: verdict; flags interval,timeout; timeout 1s;};
+     add chain ip test testchain;
+     add element ip test testmap { * : jump testchain }" || exit 1
+
+sleep 2
+$NFT "add element ip test testmap { 1.2.3.4 . 5.6.7.8: jump testchain }" || exit 1
+sleep 2
+$NFT "add element ip test testmap { 2.3.4.5 . 6.7.8.9 timeout 1m: jump testchain }" || exit 1
diff --git a/tests/shell/testcases/maps/map_catchall_double_free_2 b/tests/shell/testcases/maps/map_catchall_double_free_2
new file mode 100755 (executable)
index 0000000..5842fcb
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_catchall_element)
+
+$NFT -f /dev/stdin <<EOF
+table ip test {
+       map testmap {
+               type ipv4_addr : verdict
+               elements = { * : jump testchain }
+       }
+
+       chain testchain { }
+}
+EOF
+
+# second attempt to delete the catchall element
+# musts trigger transaction abort
+$NFT -f /dev/stdin <<EOF
+delete element ip test testmap { * }
+delete element ip test testmap { * }
+EOF
+
+if [ $? -eq 1 ]; then
+       exit 0
+fi
+
+exit 1
diff --git a/tests/shell/testcases/maps/named_ct_objects b/tests/shell/testcases/maps/named_ct_objects
new file mode 100755 (executable)
index 0000000..518140b
--- /dev/null
@@ -0,0 +1,95 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_cttimeout)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_ctexpect)
+
+$NFT -f /dev/stdin <<EOF || exit 1
+table inet t {
+       ct expectation exp1 {
+               protocol tcp
+               dport 9876
+               timeout 1m
+               size 12
+               l3proto ip
+       }
+
+       ct expectation exp2 {
+               protocol tcp
+               dport 9876
+               timeout 3s
+               size 13
+               l3proto ip6
+       }
+
+       ct helper myftp {
+               type "ftp" protocol tcp
+       }
+
+       ct timeout dns {
+               protocol tcp
+               l3proto ip
+               policy = { established : 3, close : 1 }
+       }
+
+       map exp {
+               typeof ip saddr : ct expectation
+               elements = { 192.168.2.2 : "exp1" }
+       }
+
+       map exp6 {
+               typeof ip6 saddr : ct expectation
+               flags interval
+               elements = { dead:beef::/64 : "exp2" }
+       }
+
+       map helpobj {
+               typeof ip6 saddr : ct helper
+               flags interval
+               elements = { dead:beef::/64 : "myftp" }
+       }
+
+       map timeoutmap {
+               typeof ip daddr : ct timeout
+               elements = { 192.168.0.1 : "dns" }
+       }
+
+       set helpname {
+               typeof ct helper
+               elements = { "ftp", "sip" }
+       }
+
+       chain y {
+               ct expectation set ip saddr map @exp
+               ct expectation set ip6 saddr map { dead::beef : "exp2" }
+               ct expectation set ip6 daddr map { dead::beef : "exp2", feed::17 : "exp2" }
+               ct expectation set ip6 daddr . tcp dport map { dead::beef . 123 : "exp2", feed::17 . 512 : "exp2" }
+               ct helper set ip6 saddr map { dead::beef : "myftp", 1c3::c01d : "myftp" }
+               ct helper set ip6 saddr map @helpobj
+               ct timeout set ip daddr map @timeoutmap
+               ct timeout set ip daddr map { 1.2.3.4 : "dns", 5.6.7.8 : "dns", 192.168.8.0/24 : "dns" }
+               ct timeout set ip daddr map { 1.2.3.4-1.2.3.8 : "dns" }
+               ct timeout set ip6 daddr map { dead::beef : "dns", 1ce::/64 : "dns" }
+               ct helper @helpname accept
+       }
+}
+EOF
+
+must_fail()
+{
+       echo "Command should have failed: $1"
+       exit 111
+}
+
+
+must_work()
+{
+       echo "Command should have succeeded: $1"
+       exit 111
+}
+
+$NFT 'add rule inet t y ip saddr 192.168.1.1 ct timeout set "dns"' || must_work "dns timeout"
+
+$NFT 'add rule inet t y ct helper set ip saddr map @helpobj' && must_fail "helper assignment, map key is ipv6_addr"
+$NFT 'add rule inet t y ct helper set ip6 saddr map @helpname' && must_fail "helper assignment, not a map with objects"
+
+exit 0
diff --git a/tests/shell/testcases/maps/named_limits b/tests/shell/testcases/maps/named_limits
new file mode 100755 (executable)
index 0000000..ac8e434
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
+dumpfile=$(dirname $0)/dumps/$(basename $0).nft
+
+$NFT -f "$dumpfile" || exit 1
+
+add_add_then_create()
+{
+       cmd="$@"
+
+       $NFT "add element inet filter $cmd" || exit 2
+
+       # again, kernel should suppress -EEXIST
+       $NFT "add element inet filter $cmd" || exit 3
+
+       # AGAIN, kernel should report -EEXIST
+       $NFT "create element inet filter $cmd" && echo "$cmd worked" 1>&2 && exit 4
+}
+
+add_create_dupe()
+{
+       cmd="$@"
+
+       $NFT "add element inet filter $cmd" && echo "$cmd worked" 1>&2 && exit 10
+       $NFT "create element inet filter $cmd" && echo "$cmd worked" 1>&2 && exit 11
+}
+
+delete()
+{
+       cmd="$@"
+
+       $NFT "delete element inet filter $cmd" || exit 30
+       $NFT "delete element inet filter $cmd" && echo "$cmd worked" 1>&2 && exit 31
+
+       # destroy should NOT report an error
+#      $NFT "destroy element inet filter $cmd" || exit 40
+}
+
+add_add_then_create 'saddr6limit { fee1::dead : "tarpit-pps" }'
+add_add_then_create 'saddr6limit { c01a::/64 : "tarpit-bps" }'
+
+# test same with a diffent set type (concat + interval)
+add_add_then_create 'addr4limit { udp . 1.2.3.4 . 42 : "tarpit-pps", tcp . 1.2.3.4 . 42 : "tarpit-pps" }'
+
+# now test duplicate key with *DIFFERENT* limiter, should fail
+add_create_dupe 'saddr6limit { fee1::dead : "tarpit-bps" }'
+
+add_create_dupe 'addr4limit { udp . 1.2.3.4 . 42 : "tarpit-pps", tcp . 1.2.3.4 . 42 : "http-bulk-rl-10m" }'
+add_create_dupe 'addr4limit { udp . 1.2.3.4 . 43 : "tarpit-pps", tcp . 1.2.3.4 . 42 : "http-bulk-rl-10m" }'
+add_create_dupe 'addr4limit { udp . 1.2.3.5 . 42 : "tarpit-pps", tcp . 1.2.3.4 . 42 : "http-bulk-rl-10m" }'
+add_create_dupe 'addr4limit { udp . 1.2.3.4 . 42 : "tarpit-bps", tcp . 1.2.3.4 . 42 : "tarpit-pps" }'
+
+# delete keys again
+delete 'addr4limit { udp . 1.2.3.4 . 42 : "tarpit-pps", tcp . 1.2.3.4 . 42 :"tarpit-pps" }'
+
+delete 'saddr6limit { fee1::dead : "tarpit-pps" }'
+delete 'saddr6limit { c01a::/64 : "tarpit-bps" }'
+
+exit 0
index 2804d48ca406234e705355c1648f85af8d04dc9c..703a2ad9d4311a833be65db3707bc33a293736d4 100755 (executable)
@@ -84,6 +84,11 @@ $NFT add rule 'ip6 ip6foo c ip6 saddr f0:0b::a3 dnat to [1c::3]:42' && exit 1
 # should fail: rule has no test for l4 protocol, but map has inet_service
 $NFT add rule 'ip6 ip6foo c dnat to ip daddr map @y' && exit 1
 
+if [ "$NFT_TEST_HAVE_inet_nat" = n ]; then
+       echo "Test partially skipped due to NFT_TEST_HAVE_inet_nat=n"
+       exit 77
+fi
+
 # skeleton inet
 $NFT -f /dev/stdin <<EOF || exit 1
 table inet inetfoo {
diff --git a/tests/shell/testcases/maps/pipapo_double_flush b/tests/shell/testcases/maps/pipapo_double_flush
new file mode 100755 (executable)
index 0000000..35ad096
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
+set -e
+
+$NFT add table inet t
+$NFT add chain inet t c
+$NFT 'add map inet t m { type ipv4_addr . ipv4_addr : verdict; flags interval;}'
+
+for i in $(seq 1 10); do
+       $NFT "add element inet t m { 10.0.0.1 . 1.2.$i.1 - 1.2.$i.10 : jump c }"
+done
+
+$NFT -f /dev/stdin <<EOF
+add element inet t m { 10.1.1.1 . 1.1.1.4 : accept }
+add element inet t m { 10.1.1.6 . 1.1.1.4 : drop  }
+add element inet t m { 10.1.1.7 . 1.1.1.4 : jump c  }
+flush map inet t m
+add element inet t m { 10.1.1.1 . 1.1.1.4 : accept }
+add element inet t m { 10.1.1.6 . 1.1.1.4 : drop  }
+add element inet t m { 10.1.1.7 . 1.1.1.4 : jump c  }
+flush map inet t m
+flush map inet t m
+EOF
index d51510af9073350db90f471eac8730119138a135..e93604e849c74970157851e858a55977805ed6d1 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 EXPECTED="table inet t {
        map m1 {
                typeof udp length . @ih,32,32 : verdict
@@ -13,8 +15,8 @@ EXPECTED="table inet t {
        }
 
        chain c {
-               udp length . @ih,32,32 vmap @m1
-               udp length . @ih,32,32 vmap @m2
+               udp length . @nh,32,32 vmap @m1
+               udp length . @nh,32,32 vmap @m2
                udp length . @th,160,128 vmap { 47-63 . 0xe373135363130333131303735353203 : accept }
        }
 }"
index 5cf5dddeb1d61bdac4472d81fb37551e986c3e1c..8f629c5dadf42ad4f5f320799c562cfc6b8599b4 100755 (executable)
@@ -4,10 +4,25 @@
 # without typeof, this is 'type string' and 'type integer',
 # but neither could be used because it lacks size information.
 
-EXPECTED="table inet t {
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_ipsec)
+
+set -e
+
+die() {
+       printf '%s\n' "$*"
+       exit 1
+}
+
+INPUT_OSF_CT="
+               ct mark set osf name map @m1"
+if [ "$NFT_TEST_HAVE_osf" = n ] ; then
+       INPUT_OSF_CT=
+fi
+
+INPUT="table inet t {
        map m1 {
                typeof osf name : ct mark
-               elements = { "Linux" : 0x00000001 }
+               elements = { Linux : 0x00000001 }
        }
 
        map m2 {
@@ -32,8 +47,7 @@ EXPECTED="table inet t {
                elements = { 23 . eth0 : accept }
        }
 
-       chain c {
-               ct mark set osf name map @m1
+       chain c {$INPUT_OSF_CT
                ether type vlan meta mark set vlan id map @m2
                meta mark set ip saddr . ip daddr map @m3
                iifname . ip protocol . th dport vmap @m4
@@ -42,6 +56,49 @@ EXPECTED="table inet t {
        }
 }"
 
-set -e
-$NFT -f - <<< $EXPECTED
+EXPECTED="table inet t {
+       map m1 {
+               typeof osf name : ct mark
+               elements = { \"Linux\" : 0x00000001 }
+       }
+
+       map m2 {
+               typeof vlan id : meta mark
+               elements = { 1 : 0x00000001,
+                            4095 : 0x00004095 }
+       }
+
+       map m3 {
+               typeof ip saddr . ip daddr : meta mark
+               elements = { 1.2.3.4 . 5.6.7.8 : 0x00000001,
+                            2.3.4.5 . 6.7.8.9 : 0x00000002 }
+       }
+
+       map m4 {
+               typeof iifname . ip protocol . th dport : verdict
+               elements = { \"eth0\" . tcp . 22 : accept }
+       }
+
+       map m5 {
+               typeof ipsec in reqid . iifname : verdict
+               elements = { 23 . \"eth0\" : accept }
+       }
+
+       chain c {$INPUT_OSF_CT
+               meta mark set vlan id map @m2
+               meta mark set ip saddr . ip daddr map @m3
+               iifname . ip protocol . th dport vmap @m4
+               iifname . ip protocol . th dport vmap { \"eth0\" . tcp . 22 : accept, \"eth1\" . udp . 67 : drop }
+               ipsec in reqid . iifname vmap @m5
+       }
+}"
+
+$NFT -f - <<< "$INPUT" || die $'nft command failed to process input:\n'">$INPUT<"
+
+$DIFF -u <($NFT list ruleset) - <<<"$EXPECTED" || die $'diff failed between ruleset and expected data.\nExpected:\n'">$EXPECTED<"
+
 
+if [ "$NFT_TEST_HAVE_osf" = n ] ; then
+    echo "Partial test due to NFT_TEST_HAVE_osf=n. Skip"
+    exit 77
+fi
diff --git a/tests/shell/testcases/maps/typeof_maps_add_delete b/tests/shell/testcases/maps/typeof_maps_add_delete
new file mode 100755 (executable)
index 0000000..2d718c5
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_dynset_op_delete)
+
+CONDMATCH="ip saddr @dynmark"
+NCONDMATCH="ip saddr != @dynmark"
+
+# use reduced feature set
+if [ "$NFT_TEST_HAVE_map_lookup" = n ] ; then
+       CONDMATCH=""
+       NCONDMATCH=""
+fi
+
+EXPECTED="table ip dynset {
+       map dynmark {
+               typeof ip daddr : meta mark
+               counter
+               size 64
+               timeout 5m
+       }
+
+       chain test_ping {
+               $CONDMATCH counter comment \"should not increment\"
+               $NCONDMATCH add @dynmark { ip saddr : 0x1 } counter
+               $CONDMATCH counter comment \"should increment\"
+               $CONDMATCH delete @dynmark { ip saddr : 0x1 }
+               $CONDMATCH counter comment \"delete should be instant but might fail under memory pressure\"
+       }
+
+       chain input {
+               type filter hook input priority 0; policy accept;
+
+               add @dynmark { 10.2.3.4 timeout 2s : 0x2 } comment \"also check timeout-gc\"
+               meta l4proto icmp ip daddr 127.0.0.42 jump test_ping
+       }
+}"
+
+set -e
+$NFT -f - <<< $EXPECTED
+$NFT list ruleset
+
+ip link set lo up
+ping -c 1 127.0.0.42
+
+$NFT get element ip dynset dynmark { 10.2.3.4 }
+
+# wait so that 10.2.3.4 times out.
+sleep 3
+
+set +e
+$NFT get element ip dynset dynmark { 10.2.3.4 } && exit 1
+
+if [ "$NFT_TEST_HAVE_map_lookup" = n ] ; then
+       echo "Only tested a subset due to NFT_TEST_HAVE_map_lookup=n. Skipped."
+       exit 77
+fi
index e3da7825cb7bfd482cd28f3cd24c4d25d90d7180..bcd2c6d8c5024f10c4383917584049dca040bdb6 100755 (executable)
@@ -7,8 +7,8 @@ EXPECTED="table ip x {
        }
 
        chain y {
-               ip saddr . @ih,32,32 vmap @y
-               ip saddr . @ih,32,32 vmap { 4.4.4.4 . 0x34 : accept, 5.5.5.5 . 0x45 : drop}
+               ip saddr . @nh,32,32 vmap @y
+               ip saddr . @nh,32,32 vmap { 4.4.4.4 . 0x34 : accept, 5.5.5.5 . 0x45 : drop}
        }
 }"
 
index 0d933553e6b87d292a5234293958ab7051dee1af..2f305b27bc3334820b790823ddf37bceb00e63db 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
 set -e
 
 RULESET="table ip x {
diff --git a/tests/shell/testcases/maps/vmap_timeout b/tests/shell/testcases/maps/vmap_timeout
new file mode 100755 (executable)
index 0000000..8ac7e8e
--- /dev/null
@@ -0,0 +1,92 @@
+#!/bin/bash
+
+# NFT_TEST_SKIP(NFT_TEST_SKIP_slow)
+
+set -e
+
+dumpfile=$(dirname $0)/dumps/$(basename $0).nft
+$NFT -f $dumpfile
+
+port=23
+for i in $(seq 1 100) ; do
+       timeout=$((RANDOM % 5 + 1))
+       expire=$((RANDOM%timeout))
+       j=1
+
+       batched="{ $port timeout 3s : jump other_input "
+       ubatched="$batched"
+
+       timeout_str="timeout ${timeout}s"
+       expire_str=""
+       if [ "$expire" -gt 0 ]; then
+               expire_str="expires ${expire}s"
+       fi
+
+       batched_addr="{ 10.0.$((i%256)).$j . $port ${timeout_str} ${expire_str} : jump other_input "
+       ubatched_addr="$batched_addr"
+
+       port=$((port + 1))
+       for j in $(seq 2 400); do
+               timeout=$((RANDOM % 5 + 1))
+               expire=$((RANDOM%timeout))
+               utimeout=$((RANDOM % 5 + 1))
+
+               timeout_str="timeout ${timeout}s"
+               expire_str=""
+               if [ "$expire" -gt 0 ]; then
+                       expire_str="expires ${expire}s"
+               fi
+
+               batched="$batched, $port ${timeout_str} ${expire_str} : jump other_input "
+               batched_addr="$batched_addr, 10.0.$((i%256)).$((j%256)) . $port ${timeout_str} ${expire_str} : jump other_input "
+               port=$((port + 1))
+
+               timeout_str="timeout ${utimeout}s"
+               expire=$((RANDOM%utimeout))
+
+               expire_str=""
+               if [ "$expires" -gt 0 ]; then
+                       expire_str="expires ${expire}s"
+               fi
+
+               update=$((RANDOM%2))
+               if [ "$update" -ne 0 ]; then
+                       ubatched="$batched, $port ${timeout_str} ${expire_str} : jump other_input "
+                       ubatched_addr="$batched_addr, 10.0.$((i%256)).$((j%256)) . $port ${timeout_str} ${expire_str} : jump other_input "
+               fi
+       done
+
+       fail_addr="$batched_addr, 1.2.3.4 . 23 timeout 5m : jump other_input,
+                                 1.2.3.4 . 23 timeout 3m : jump other_input }"
+       fail="$batched, 23 timeout 1m : jump other_input, 23 : jump other_input }"
+
+       batched="$batched }"
+       batched_addr="$batched_addr }"
+
+       if [ $i -gt 90 ]; then
+               # must fail, we create and $fail/$fail_addr contain one element twice.
+               $NFT create element inet filter portmap "$fail" && exit 111
+               $NFT create element inet filter portaddrmap "$fail_addr" && exit 112
+       fi
+
+       $NFT add element inet filter portmap "$batched"
+       $NFT add element inet filter portaddrmap "$batched_addr"
+
+       update=$((RANDOM%2))
+       if [ "$update" -ne 0 ]; then
+               ubatched="$ubatched }"
+               ubatched_addr="$ubatched_addr }"
+               $NFT add element inet filter portmap "$ubatched"
+               $NFT add element inet filter portaddrmap "$ubatched_addr"
+       fi
+done
+
+if [ "$NFT_TEST_HAVE_catchall_element" = n ] ; then
+       echo "Partial test due to NFT_TEST_HAVE_catchall_element=n."
+else
+       $NFT add element inet filter portaddrmap { "* timeout 2s : drop" }
+       $NFT add element inet filter portmap { "* timeout 3s : drop" }
+fi
+
+# wait for elements to time out
+sleep 5
index 4038d1c109ffce1902d97bd8387f2833067c9d48..f4e1f01215ec95c12987b52297bb0a7286fd512e 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 set -e
 
 RULESET="table ip filter {
diff --git a/tests/shell/testcases/netns/dumps/0001nft-f_0.json-nft b/tests/shell/testcases/netns/dumps/0001nft-f_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/netns/dumps/0001nft-f_0.nft b/tests/shell/testcases/netns/dumps/0001nft-f_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/netns/dumps/0002loosecommands_0.json-nft b/tests/shell/testcases/netns/dumps/0002loosecommands_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/netns/dumps/0002loosecommands_0.nft b/tests/shell/testcases/netns/dumps/0002loosecommands_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/netns/dumps/0003many_0.json-nft b/tests/shell/testcases/netns/dumps/0003many_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/netns/dumps/0003many_0.nft b/tests/shell/testcases/netns/dumps/0003many_0.nft
new file mode 100644 (file)
index 0000000..e69de29
index 84664f46af5084044085ad98cafbd1af860b9fa8..aac0670602f6cd3b5c5e8c2336ef383786c58f1e 100755 (executable)
@@ -4,6 +4,15 @@
 
 HOWMANY=20000
 
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+       # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for
+       # the test.
+       #
+       # Run only a subset of the test and mark as skipped at the end.
+       HOWMANY=2000
+fi
+
+
 tmpfile=$(mktemp)
 if [ ! -w $tmpfile ] ; then
        echo "Failed to create tmp file" >&2
@@ -35,3 +44,10 @@ table t {
 
 set -e
 $NFT -f $tmpfile
+
+if [ "$HOWMANY" != 20000 ] ; then
+       echo "NFT_TEST_HAS_SOCKET_LIMITS indicates that the socket limit for"
+       echo "/proc/sys/net/core/wmem_max is too small for this test. Mark as SKIPPED"
+       echo "You may bump the limit and rerun with \`NFT_TEST_HAS_SOCKET_LIMITS=n\`."
+       exit 77
+fi
index 4f407793b23bac2af5d4943ac05d5188d6d5f39e..cfb789501beaf1d99d8631e394ce6c2eddb4ffd8 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_cttimeout)
+
 EXPECTED='table ip filter {
        ct timeout cttime{
                protocol tcp
index 4f9872f631304ee205dee6e50e23d667bce00666..b288457c726ee73c96cb4e1f285cf571d6596d0d 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_ctexpect)
+
 EXPECTED='table ip filter {
        ct expectation ctexpect{
                protocol tcp
index b66c802f8536963aa808cd3d7963300a7a07632f..fbdb57931ed09f371afa0fa5e40be61c7434afdc 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+set -e
+
 RULESET="table ip foo {
                set inflows {
                 type ipv4_addr . inet_service . ifname . ipv4_addr . inet_service
@@ -20,3 +22,9 @@ RULESET="table ip foo {
 }"
 
 $NFT -f - <<< "$RULESET"
+
+# inflows_ratelimit will be dumped without 'limit rate .. counter' on old kernels.
+if [ "$NFT_TEST_HAVE_set_with_two_expressions" = n ]; then
+       echo "Partial test due to NFT_TEST_HAVE_set_with_two_expressions=n."
+       exit 77
+fi
diff --git a/tests/shell/testcases/nft-f/0032pknock_0 b/tests/shell/testcases/nft-f/0032pknock_0
new file mode 100755 (executable)
index 0000000..94fc840
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+set -e
+
+RULESET="define guarded_ports = {ssh}
+
+table inet portknock {
+        set clients_ipv4 {
+                type ipv4_addr
+                flags timeout
+        }
+
+        set candidates_ipv4 {
+                type ipv4_addr . inet_service
+                flags timeout
+        }
+
+        chain input {
+                type filter hook input priority -10; policy accept;
+
+                tcp dport 10001 add @candidates_ipv4 {ip  saddr . 10002 timeout 1s}
+                tcp dport 10002 ip  saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 {ip  saddr . 10003 timeout 1s}
+                tcp dport 10003 ip  saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 {ip  saddr . 10004 timeout 1s}
+                tcp dport 10004 ip  saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 {ip  saddr . 10005 timeout 1s}
+                tcp dport 10005 ip  saddr . tcp dport @candidates_ipv4 add @clients_ipv4 {ip  saddr timeout 600s} log prefix \"Successful portknock: \"
+
+                tcp dport \$guarded_ports ip  saddr @clients_ipv4 counter accept
+                tcp dport \$guarded_ports ct state established,related counter accept
+
+                tcp dport \$guarded_ports reject with tcp reset
+        }
+}"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/nft-f/dumps/0001define_slash_0.json-nft b/tests/shell/testcases/nft-f/dumps/0001define_slash_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0001define_slash_0.nft b/tests/shell/testcases/nft-f/dumps/0001define_slash_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0002rollback_rule_0.json-nft b/tests/shell/testcases/nft-f/dumps/0002rollback_rule_0.json-nft
new file mode 100644 (file)
index 0000000..99b0b28
--- /dev/null
@@ -0,0 +1,134 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "other",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "t",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  22222,
+                  33333
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@t"
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "other"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0003rollback_jump_0.json-nft b/tests/shell/testcases/nft-f/dumps/0003rollback_jump_0.json-nft
new file mode 100644 (file)
index 0000000..99b0b28
--- /dev/null
@@ -0,0 +1,134 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "other",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "t",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  22222,
+                  33333
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@t"
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "other"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0004rollback_set_0.json-nft b/tests/shell/testcases/nft-f/dumps/0004rollback_set_0.json-nft
new file mode 100644 (file)
index 0000000..99b0b28
--- /dev/null
@@ -0,0 +1,134 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "other",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "t",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  22222,
+                  33333
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@t"
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "other"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0005rollback_map_0.json-nft b/tests/shell/testcases/nft-f/dumps/0005rollback_map_0.json-nft
new file mode 100644 (file)
index 0000000..99b0b28
--- /dev/null
@@ -0,0 +1,134 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "other",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "t",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  22222,
+                  33333
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@t"
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "other"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0006action_object_0.json-nft b/tests/shell/testcases/nft-f/dumps/0006action_object_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0006action_object_0.nft b/tests/shell/testcases/nft-f/dumps/0006action_object_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.json-nft b/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.nft b/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0008split_tables_0.json-nft b/tests/shell/testcases/nft-f/dumps/0008split_tables_0.json-nft
new file mode 100644 (file)
index 0000000..05ebed5
--- /dev/null
@@ -0,0 +1,67 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "ssh",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 1,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "ssh",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0009variable_0.json-nft b/tests/shell/testcases/nft-f/dumps/0009variable_0.json-nft
new file mode 100644 (file)
index 0000000..41236db
--- /dev/null
@@ -0,0 +1,44 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "forward",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "concat-set-variable",
+        "table": "forward",
+        "type": [
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "elem": [
+          {
+            "concat": [
+              "10.10.10.10",
+              25
+            ]
+          },
+          {
+            "concat": [
+              "10.10.10.10",
+              143
+            ]
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0010variable_0.json-nft b/tests/shell/testcases/nft-f/dumps/0010variable_0.json-nft
new file mode 100644 (file)
index 0000000..4b4ec4f
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "whitelist_v4",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0011manydefines_0.nodump b/tests/shell/testcases/nft-f/dumps/0011manydefines_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0013defines_1.json-nft b/tests/shell/testcases/nft-f/dumps/0013defines_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0013defines_1.nft b/tests/shell/testcases/nft-f/dumps/0013defines_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0014defines_1.json-nft b/tests/shell/testcases/nft-f/dumps/0014defines_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0014defines_1.nft b/tests/shell/testcases/nft-f/dumps/0014defines_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0015defines_1.json-nft b/tests/shell/testcases/nft-f/dumps/0015defines_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0015defines_1.nft b/tests/shell/testcases/nft-f/dumps/0015defines_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0016redefines_1.json-nft b/tests/shell/testcases/nft-f/dumps/0016redefines_1.json-nft
new file mode 100644 (file)
index 0000000..40cdb00
--- /dev/null
@@ -0,0 +1,80 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "1.1.1.1",
+                  "2.2.2.2"
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "3.3.3.3",
+                  "4.4.4.4"
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0016redefines_1.nft b/tests/shell/testcases/nft-f/dumps/0016redefines_1.nft
new file mode 100644 (file)
index 0000000..65b7f49
--- /dev/null
@@ -0,0 +1,6 @@
+table ip x {
+       chain y {
+               ip saddr { 1.1.1.1, 2.2.2.2 }
+               ip saddr { 3.3.3.3, 4.4.4.4 }
+       }
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.json-nft b/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.json-nft
new file mode 100644 (file)
index 0000000..b56240e
--- /dev/null
@@ -0,0 +1,53 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "ct timeout": {
+        "family": "ip",
+        "name": "cttime",
+        "table": "filter",
+        "handle": 0,
+        "protocol": "tcp",
+        "l3proto": "ip",
+        "policy": {
+          "established": 123,
+          "close": 12
+        }
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "ct timeout": "cttime"
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.json-nft b/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.json-nft
new file mode 100644 (file)
index 0000000..21c9797
--- /dev/null
@@ -0,0 +1,52 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "ct expectation": {
+        "family": "ip",
+        "name": "ctexpect",
+        "table": "filter",
+        "handle": 0,
+        "protocol": "tcp",
+        "dport": 9876,
+        "timeout": 60000,
+        "size": 12,
+        "l3proto": "ip"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "ct expectation": "ctexpect"
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.nft b/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.nft
new file mode 100644 (file)
index 0000000..396185e
--- /dev/null
@@ -0,0 +1,13 @@
+table ip filter {
+       ct expectation ctexpect {
+               protocol tcp
+               dport 9876
+               timeout 1m
+               size 12
+               l3proto ip
+       }
+
+       chain c {
+               ct expectation set "ctexpect"
+       }
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.json-nft b/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.json-nft
new file mode 100644 (file)
index 0000000..f62b48a
--- /dev/null
@@ -0,0 +1,49 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "foo",
+        "name": "bar",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "foo",
+        "name": "ber",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "ber"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.json-nft b/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.nft b/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.json-nft b/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.nft b/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0021list_ruleset_0.json-nft b/tests/shell/testcases/nft-f/dumps/0021list_ruleset_0.json-nft
new file mode 100644 (file)
index 0000000..f41b1b0
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -50,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0022variables_0.json-nft b/tests/shell/testcases/nft-f/dumps/0022variables_0.json-nft
new file mode 100644 (file)
index 0000000..09a4c1e
--- /dev/null
@@ -0,0 +1,115 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "z",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "z",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "set": "@y"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "z",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "timeout": 30
+                }
+              },
+              "set": "@y"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "z",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@y"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0023check_1.json-nft b/tests/shell/testcases/nft-f/dumps/0023check_1.json-nft
new file mode 100644 (file)
index 0000000..ddb2a05
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "foo",
+        "name": "bar",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0023check_1.nft b/tests/shell/testcases/nft-f/dumps/0023check_1.nft
new file mode 100644 (file)
index 0000000..04b9e70
--- /dev/null
@@ -0,0 +1,5 @@
+table ip foo {
+       chain bar {
+               type filter hook prerouting priority filter; policy accept;
+       }
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0024priority_0.json-nft b/tests/shell/testcases/nft-f/dumps/0024priority_0.json-nft
new file mode 100644 (file)
index 0000000..cdc4b9d
--- /dev/null
@@ -0,0 +1,95 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "statelessnat",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "statelessnat",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -100,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "statelessnat",
+        "name": "postrouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "postrouting",
+        "prio": 100,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "statelessnat",
+        "chain": "prerouting",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "value": {
+                "map": {
+                  "key": {
+                    "numgen": {
+                      "mode": "inc",
+                      "mod": 16,
+                      "offset": 0
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        {
+                          "range": [
+                            0,
+                            7
+                          ]
+                        },
+                        "10.0.1.1"
+                      ],
+                      [
+                        {
+                          "range": [
+                            8,
+                            15
+                          ]
+                        },
+                        "10.0.1.2"
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.json-nft b/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.json-nft
new file mode 100644 (file)
index 0000000..63d6764
--- /dev/null
@@ -0,0 +1,105 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "inflows",
+        "table": "foo",
+        "type": [
+          "ipv4_addr",
+          "inet_service",
+          "ifname",
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "flags": "dynamic",
+        "elem": [
+          {
+            "elem": {
+              "val": {
+                "concat": [
+                  "10.1.0.3",
+                  39466,
+                  "veth1",
+                  "10.3.0.99",
+                  5201
+                ]
+              },
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "inflows6",
+        "table": "foo",
+        "type": [
+          "ipv6_addr",
+          "inet_service",
+          "ifname",
+          "ipv6_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "inflows_ratelimit",
+        "table": "foo",
+        "type": [
+          "ipv4_addr",
+          "inet_service",
+          "ifname",
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "flags": "dynamic",
+        "elem": [
+          {
+            "elem": {
+              "val": {
+                "concat": [
+                  "10.1.0.3",
+                  39466,
+                  "veth1",
+                  "10.3.0.99",
+                  5201
+                ]
+              },
+              "limit": {
+                "rate": 1,
+                "burst": 5,
+                "per": "second"
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0026listing_0.json-nft b/tests/shell/testcases/nft-f/dumps/0026listing_0.json-nft
new file mode 100644 (file)
index 0000000..8acdcdf
--- /dev/null
@@ -0,0 +1,56 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "A",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "A",
+        "name": "B",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "A",
+        "chain": "B",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  1,
+                  2
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0026listing_0.nft b/tests/shell/testcases/nft-f/dumps/0026listing_0.nft
new file mode 100644 (file)
index 0000000..fd0bb68
--- /dev/null
@@ -0,0 +1,5 @@
+table ip A {
+       chain B {
+               tcp dport { 1, 2 } accept
+       }
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0027split_chains_0.json-nft b/tests/shell/testcases/nft-f/dumps/0027split_chains_0.json-nft
new file mode 100644 (file)
index 0000000..bda8bfc
--- /dev/null
@@ -0,0 +1,53 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "x"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0028variable_cmdline_0.json-nft b/tests/shell/testcases/nft-f/dumps/0028variable_cmdline_0.json-nft
new file mode 100644 (file)
index 0000000..69d826d
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "whitelist_v4",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1",
+          "2.2.2.2",
+          "3.3.3.3",
+          "4.4.4.4",
+          "5.5.5.5"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0029split_file_0.json-nft b/tests/shell/testcases/nft-f/dumps/0029split_file_0.json-nft
new file mode 100644 (file)
index 0000000..ab680af
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "whitelist_v4",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "prerouting",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "@whitelist_v4"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0029split_file_0.nft b/tests/shell/testcases/nft-f/dumps/0029split_file_0.nft
new file mode 100644 (file)
index 0000000..32d5c0e
--- /dev/null
@@ -0,0 +1,10 @@
+table inet filter {
+       set whitelist_v4 {
+               type ipv4_addr
+       }
+
+       chain prerouting {
+               type filter hook prerouting priority filter; policy accept;
+               ip daddr @whitelist_v4
+       }
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0030variable_reuse_0.json-nft b/tests/shell/testcases/nft-f/dumps/0030variable_reuse_0.json-nft
new file mode 100644 (file)
index 0000000..e0704b7
--- /dev/null
@@ -0,0 +1,44 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1",
+          "2.2.2.2"
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "z",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1",
+          "3.3.3.3"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.json-nft b/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.nft b/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-f/dumps/0032pknock_0.json-nft b/tests/shell/testcases/nft-f/dumps/0032pknock_0.json-nft
new file mode 100644 (file)
index 0000000..4c7d2bb
--- /dev/null
@@ -0,0 +1,484 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "portknock",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "portknock",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": -10,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "clients_ipv4",
+        "table": "portknock",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "candidates_ipv4",
+        "table": "portknock",
+        "type": [
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "size": 65535,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "portknock",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 10001
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "saddr"
+                        }
+                      },
+                      10002
+                    ]
+                  },
+                  "timeout": 1
+                }
+              },
+              "set": "@candidates_ipv4"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "portknock",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 10002
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "right": "@candidates_ipv4"
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "saddr"
+                        }
+                      },
+                      10003
+                    ]
+                  },
+                  "timeout": 1
+                }
+              },
+              "set": "@candidates_ipv4"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "portknock",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 10003
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "right": "@candidates_ipv4"
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "saddr"
+                        }
+                      },
+                      10004
+                    ]
+                  },
+                  "timeout": 1
+                }
+              },
+              "set": "@candidates_ipv4"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "portknock",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 10004
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "right": "@candidates_ipv4"
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "saddr"
+                        }
+                      },
+                      10005
+                    ]
+                  },
+                  "timeout": 1
+                }
+              },
+              "set": "@candidates_ipv4"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "portknock",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 10005
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "right": "@candidates_ipv4"
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "timeout": 600
+                }
+              },
+              "set": "@clients_ipv4"
+            }
+          },
+          {
+            "log": {
+              "prefix": "Successful portknock: "
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "portknock",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@clients_ipv4"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "portknock",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "established",
+                "related"
+              ]
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "portknock",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "reject": {
+              "type": "tcp reset"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0032pknock_0.nft b/tests/shell/testcases/nft-f/dumps/0032pknock_0.nft
new file mode 100644 (file)
index 0000000..f29dfb2
--- /dev/null
@@ -0,0 +1,25 @@
+table inet portknock {
+       set clients_ipv4 {
+               type ipv4_addr
+               size 65535
+               flags dynamic,timeout
+       }
+
+       set candidates_ipv4 {
+               type ipv4_addr . inet_service
+               size 65535
+               flags dynamic,timeout
+       }
+
+       chain input {
+               type filter hook input priority filter - 10; policy accept;
+               tcp dport 10001 add @candidates_ipv4 { ip saddr . 10002 timeout 1s }
+               tcp dport 10002 ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 { ip saddr . 10003 timeout 1s }
+               tcp dport 10003 ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 { ip saddr . 10004 timeout 1s }
+               tcp dport 10004 ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 { ip saddr . 10005 timeout 1s }
+               tcp dport 10005 ip saddr . tcp dport @candidates_ipv4 add @clients_ipv4 { ip saddr timeout 10m } log prefix "Successful portknock: "
+               tcp dport 22 ip saddr @clients_ipv4 counter packets 0 bytes 0 accept
+               tcp dport 22 ct state established,related counter packets 0 bytes 0 accept
+               tcp dport 22 reject with tcp reset
+       }
+}
diff --git a/tests/shell/testcases/nft-f/sample-ruleset b/tests/shell/testcases/nft-f/sample-ruleset
new file mode 100755 (executable)
index 0000000..763e41a
--- /dev/null
@@ -0,0 +1,262 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_chain_binding)
+
+$NFT -f /dev/stdin <<"EOF"
+define public_if = eth0
+define trusted_if = eth1
+define voip_if = eth2.10
+define guest_if = eth2.20
+define home_if = { $trusted_if, $voip_if, $guest_if }
+define home_ipv6_if = { $trusted_if, $voip_if, $guest_if }
+
+define masq_ip = { 192.168.1.0/24, 192.168.2.0/24, 192.168.3.0/24, 192.168.4.0/24 }
+define masq_if = $public_if
+
+define host1_ip = 192.168.1.10
+define host2_ip = 192.168.2.20
+define host3_ip = 192.168.3.30
+define host4_ip = 192.168.4.40
+
+define proxy_port = 8443
+
+define private_ip = { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
+define private_ip6 = { fe80::/64, fd00::/8 }
+define bogons_ip = { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 }
+define bogons_ip6 = { ::/3, 2001:0002::/48, 2001:0003::/32, 2001:10::/28, 2001:20::/28, 2001::/32, 2001:db8::/32, 2002::/16, 3000::/4, 4000::/2, 8000::/1 }
+
+define sip_whitelist_ip6 = { 2001:db8::1/128, 2001:db8::2/128 }
+define smtps_whitelist_ip = 10.0.0.1
+define protocol_whitelist = { tcp, udp, icmp, ipv6-icmp }
+
+table inet filter {
+       map if_input {
+               type ifname : verdict;
+               elements = { $public_if : jump public_input, $trusted_if : jump home_input, $voip_if : jump home_input, $guest_if : jump home_input }
+       }
+       map if_forward {
+               type ifname : verdict;
+               elements = { $public_if : jump public_forward, $trusted_if : jump trusted_forward, $voip_if : jump voip_forward, $guest_if : jump guest_forward }
+       }
+       map if_output {
+               type ifname : verdict;
+               elements = { $public_if : jump public_output, $trusted_if : jump home_output, $voip_if : jump home_output, $guest_if : jump home_output }
+       }
+
+       set ipv4_blacklist { type ipv4_addr; flags interval; auto-merge; }
+       set ipv6_blacklist { type ipv6_addr; flags interval; auto-merge; }
+       set limit_src_ip { type ipv4_addr; flags dynamic, timeout; size 1024; }
+       set limit_src_ip6 { type ipv6_addr; flags dynamic, timeout; size 1024; }
+
+       chain PREROUTING_RAW {
+               type filter hook prerouting priority raw;
+
+               meta l4proto != $protocol_whitelist counter drop
+               tcp flags syn jump {
+                       tcp option maxseg size 1-500 counter drop
+                       tcp sport 0 counter drop
+               }
+               rt type 0 counter drop
+       }
+
+       chain PREROUTING_MANGLE {
+               type filter hook prerouting priority mangle;
+
+               ct state vmap { invalid : jump ct_invalid_pre, untracked : jump ct_untracked_pre, new : jump ct_new_pre, related : jump rpfilter }
+       }
+       chain ct_invalid_pre {
+               counter drop
+       }
+       chain ct_untracked_pre {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld-listener-query, mld2-listener-report } return
+               counter drop
+       }
+       chain ct_new_pre {
+               jump rpfilter
+
+               tcp flags & (fin|syn|rst|ack) != syn counter drop
+
+               iifname $public_if meta nfproto vmap { ipv4 : jump blacklist_input_ipv4, ipv6 : jump blacklist_input_ipv6 }
+       }
+       chain rpfilter {
+               ip saddr 0.0.0.0 ip daddr 255.255.255.255 udp sport bootpc udp dport bootps return
+               ip6 saddr ::/128 ip6 daddr . icmpv6 type { ff02::1:ff00:0/104 . nd-neighbor-solicit, ff02::16 . mld2-listener-report } return
+
+               fib saddr . iif oif eq 0 counter drop
+       }
+       chain blacklist_input_ipv4{
+               ip saddr $bogons_ip counter drop
+               ip saddr @ipv4_blacklist counter drop
+       }
+       chain blacklist_input_ipv6{
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 return
+               udp sport dhcpv6-server ip6 saddr fe80::/64 return
+
+               ip6 saddr $bogons_ip6 counter drop
+               ip6 saddr @ipv6_blacklist counter drop
+       }
+
+       chain INPUT {
+               type filter hook input priority filter; policy drop;
+
+               iif lo accept
+
+               ct state established,related accept
+
+               iifname vmap @if_input
+
+               log prefix "NFT REJECT IN " flags ether flags ip options limit rate 5/second burst 10 packets reject
+       }
+       chain public_input {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 ip6 hoplimit 255 accept
+
+               udp sport dhcpv6-server udp dport dhcpv6-client ip6 saddr fe80::/64 accept
+               fib daddr type { broadcast, multicast, anycast } counter drop
+
+               counter drop
+       }
+       chain home_input {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+               icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+
+               udp sport bootpc udp dport bootps accept
+               udp sport dhcpv6-client udp dport dhcpv6-server iifname $home_ipv6_if accept
+
+               fib daddr type { broadcast, multicast, anycast } counter drop
+
+               icmp type echo-request accept
+               icmpv6 type echo-request accept
+
+               tcp dport ssh iifname $trusted_if accept
+
+               meta l4proto { tcp, udp } th dport domain jump {
+                       ip6 saddr != $private_ip6 counter reject
+                       accept
+               }
+
+               udp dport ntp accept
+
+               tcp dport $proxy_port accept
+       }
+
+       chain FORWARD_MANGLE {
+               type filter hook forward priority mangle;
+
+               oifname $public_if jump {
+                       ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 }
+                       tcp flags & (syn|rst) == syn tcp option maxseg size set rt mtu
+               }
+       }
+       chain blacklist_output_ipv4 {
+               ip daddr $bogons_ip goto log_blacklist
+               ip daddr @ipv4_blacklist goto log_blacklist
+       }
+       chain blacklist_output_ipv6 {
+               icmpv6 type . ip6 daddr { nd-router-solicit . ff02::2/128, nd-neighbor-solicit . ff02::1:ff00:0/104, nd-neighbor-advert . fe80::/64, nd-neighbor-advert . ff02::1/128, nd-neighbor-advert . ff02::1:ff00:0/104, mld2-listener-report . ff02::16/128 } return
+               udp dport dhcpv6-server ip6 daddr ff02::1:2 return
+
+               ip6 daddr $bogons_ip6 goto log_blacklist
+               ip6 daddr @ipv6_blacklist goto log_blacklist
+       }
+       chain log_blacklist {
+               log prefix "NFT BLACKLIST " flags ether flags ip options limit rate 5/minute burst 10 packets drop
+               counter drop
+       }
+
+       chain FORWARD {
+               type filter hook forward priority filter; policy drop;
+
+               ct state established,related accept
+
+               fib daddr type { broadcast, multicast, anycast } counter drop
+
+               iifname vmap @if_forward
+
+               log prefix "NFT REJECT FWD " flags ether flags ip options limit rate 5/second burst 10 packets reject
+       }
+       chain public_forward {
+               udp dport { 5060, 7078-7097 } oifname $voip_if jump {
+                       ip6 saddr $sip_whitelist_ip6 accept
+                       meta nfproto ipv6 log prefix "NFT DROP SIP " flags ether flags ip options limit rate 5/second burst 10 packets drop
+               }
+
+               counter drop
+       }
+       chain trusted_forward {
+               oifname $public_if accept
+
+               icmp type echo-request accept
+               icmpv6 type echo-request accept
+
+               ip daddr { $host3_ip, $host4_ip } tcp dport vmap { ssh : accept, https : accept, http : drop }
+
+               ip daddr $host2_ip jump {
+                       tcp dport { http, https, printer, ipp, 9100 } accept
+                       udp dport snmp accept
+               }
+       }
+       chain voip_forward {
+               icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } oifname $public_if accept
+
+               ip6 daddr $sip_whitelist_ip6 jump {
+                       udp dport { 3478, 5060 } accept
+                       udp sport { 7078-7097 } accept
+                       tcp dport 5061 accept
+               }
+
+               tcp dport 587 ip daddr $smtps_whitelist_ip accept
+               tcp dport http oifname $public_if counter reject
+       }
+       chain guest_forward {
+               oifname $public_if accept
+       }
+
+       chain OUTPUT {
+               type filter hook output priority filter; policy drop;
+
+               oif lo accept
+
+               ct state vmap { established : accept, related : accept, invalid : jump ct_invalid_out, untracked : jump ct_untracked_out }
+
+               oifname vmap @if_output
+
+               log prefix "NFT REJECT OUT " flags ether flags ip options limit rate 5/second burst 10 packets reject
+       }
+       chain ct_invalid_out {
+               counter drop
+       }
+       chain ct_untracked_out {
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld-listener-query, mld2-listener-report } return
+               counter drop
+       }
+       chain public_output {
+               ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 }
+
+               icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+               icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+
+               udp dport dhcpv6-server ip6 saddr fe80::/64 ip6 daddr ff02::1:2 accept
+
+               udp dport { domain, ntp } accept
+               tcp dport { https, 587, domain-s } accept
+       }
+       chain home_output {
+               icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept
+               icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
+               icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept
+
+               udp sport dhcpv6-server udp dport dhcpv6-client ip6 saddr fe80::/64 oifname $home_ipv6_if accept
+               udp sport bootps udp dport bootpc ip saddr $private_ip accept
+               tcp dport ssh ip daddr $host1_ip accept
+       }
+
+       chain POSTROUTING_SRCNAT {
+               type nat hook postrouting priority srcnat;
+
+               meta nfproto ipv4 ip saddr $masq_ip oifname $masq_if masquerade
+       }
+}
+EOF
diff --git a/tests/shell/testcases/nft-i/dumps/0001define_0.json-nft b/tests/shell/testcases/nft-i/dumps/0001define_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/nft-i/dumps/0001define_0.nft b/tests/shell/testcases/nft-i/dumps/0001define_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/nft-i/dumps/index_0.nft b/tests/shell/testcases/nft-i/dumps/index_0.nft
new file mode 100644 (file)
index 0000000..abcd1b7
--- /dev/null
@@ -0,0 +1,8 @@
+table inet foo {
+       chain bar {
+               type filter hook input priority filter; policy accept;
+               accept
+               accept
+               accept
+       }
+}
diff --git a/tests/shell/testcases/nft-i/dumps/set_0.nft b/tests/shell/testcases/nft-i/dumps/set_0.nft
new file mode 100644 (file)
index 0000000..d3377d6
--- /dev/null
@@ -0,0 +1,7 @@
+table inet foo {
+       set bar {
+               type ipv4_addr
+               flags interval
+               elements = { 10.1.1.1, 10.1.1.2 }
+       }
+}
diff --git a/tests/shell/testcases/nft-i/index_0 b/tests/shell/testcases/nft-i/index_0
new file mode 100755 (executable)
index 0000000..f885fde
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+RULESET="add table inet foo
+add chain inet foo bar { type filter hook input priority filter; }
+add rule inet foo bar accept
+insert rule inet foo bar index 0 accept
+add rule inet foo bar index 0 accept"
+
+$NFT -i <<< "$RULESET"
diff --git a/tests/shell/testcases/nft-i/set_0 b/tests/shell/testcases/nft-i/set_0
new file mode 100755 (executable)
index 0000000..e87eef1
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+set -e
+
+RULESET="add table inet foo
+add set inet foo bar { type ipv4_addr; flags interval; }; add element inet foo bar { 10.1.1.1/32 }
+add element inet foo bar { 10.1.1.2/32 }"
+
+$NFT -i <<< "$RULESET"
diff --git a/tests/shell/testcases/optimizations/dumps/dependency_kill.json-nft b/tests/shell/testcases/optimizations/dumps/dependency_kill.json-nft
new file mode 100644 (file)
index 0000000..712182e
--- /dev/null
@@ -0,0 +1,776 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "bridge",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "bridge",
+        "table": "foo",
+        "name": "bar",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "bridge",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "protocol"
+                }
+              },
+              "right": "ip"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "bridge",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "protocol"
+                }
+              },
+              "right": "ip6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "bridge",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "type"
+                }
+              },
+              "right": "ip"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "bridge",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "type"
+                }
+              },
+              "right": "ip6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "foo",
+        "name": "bar",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "protocol"
+                }
+              },
+              "right": "ip6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "type"
+                }
+              },
+              "right": "ip6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "foo",
+        "name": "bar",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "protocol"
+                }
+              },
+              "right": "ip"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "type"
+                }
+              },
+              "right": "ip"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "foo",
+        "name": "bar",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "netdev",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "protocol"
+                }
+              },
+              "right": "ip"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "netdev",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "protocol"
+                }
+              },
+              "right": "ip6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "netdev",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "type"
+                }
+              },
+              "right": "ip"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "netdev",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "type"
+                }
+              },
+              "right": "ip6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "foo",
+        "name": "bar",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "protocol"
+                }
+              },
+              "right": "ip"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "protocol"
+                }
+              },
+              "right": "ip6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "type"
+                }
+              },
+              "right": "ip"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "type"
+                }
+              },
+              "right": "ip6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "nfproto"
+                }
+              },
+              "right": "ipv4"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "foo",
+        "chain": "bar",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "nfproto"
+                }
+              },
+              "right": "ipv6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 67
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat.json-nft b/tests/shell/testcases/optimizations/dumps/merge_nat.json-nft
new file mode 100644 (file)
index 0000000..a6cf1bf
--- /dev/null
@@ -0,0 +1,379 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test1",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test1",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test1",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "dnat": {
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        "4.4.4.4",
+                        "1.1.1.1"
+                      ],
+                      [
+                        "5.5.5.5",
+                        "2.2.2.2"
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test2",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test2",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test2",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "dnat": {
+              "family": "ip",
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        80,
+                        {
+                          "concat": [
+                            "1.1.1.1",
+                            8001
+                          ]
+                        }
+                      ],
+                      [
+                        81,
+                        {
+                          "concat": [
+                            "2.2.2.2",
+                            9001
+                          ]
+                        }
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test2",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": {
+                "set": [
+                  {
+                    "prefix": {
+                      "addr": "10.141.11.0",
+                      "len": 24
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "10.141.13.0",
+                      "len": 24
+                    }
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "masquerade": null
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test4",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test4",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test4",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test4",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "dnat": {
+              "family": "ip",
+              "addr": {
+                "map": {
+                  "key": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "daddr"
+                        }
+                      },
+                      {
+                        "payload": {
+                          "protocol": "tcp",
+                          "field": "dport"
+                        }
+                      }
+                    ]
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        {
+                          "concat": [
+                            "1.1.1.1",
+                            80
+                          ]
+                        },
+                        {
+                          "concat": [
+                            "4.4.4.4",
+                            8000
+                          ]
+                        }
+                      ],
+                      [
+                        {
+                          "concat": [
+                            "2.2.2.2",
+                            81
+                          ]
+                        },
+                        {
+                          "concat": [
+                            "3.3.3.3",
+                            9000
+                          ]
+                        }
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test4",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "redirect": {
+              "port": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        83,
+                        8083
+                      ],
+                      [
+                        84,
+                        8084
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test4",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 85
+            }
+          },
+          {
+            "redirect": null
+          }
+        ]
+      }
+    }
+  ]
+}
index 48d18a676ee0cc47f5ac510fc03548d38c474d07..f6c119eca8108a274c1d11301902ad777169f5b7 100644 (file)
@@ -11,14 +11,6 @@ table ip test2 {
                ip saddr { 10.141.11.0/24, 10.141.13.0/24 } masquerade
        }
 }
-table ip test3 {
-       chain y {
-               oif "lo" accept
-               snat to ip saddr . tcp sport map { 1.1.1.1 . 1024-65535 : 3.3.3.3, 2.2.2.2 . 1024-65535 : 4.4.4.4 }
-               oifname "enp2s0" snat ip to ip saddr map { 10.1.1.0/24 : 72.2.3.66-72.2.3.78 }
-               tcp dport { 8888, 9999 } redirect
-       }
-}
 table ip test4 {
        chain y {
                oif "lo" accept
@@ -27,14 +19,3 @@ table ip test4 {
                tcp dport 85 redirect
        }
 }
-table inet nat {
-       chain prerouting {
-               oif "lo" accept
-               dnat ip to iifname . ip daddr . tcp dport map { "enp2s0" . 72.2.3.70 . 80 : 10.1.1.52 . 80, "enp2s0" . 72.2.3.66 . 53122 : 10.1.1.10 . 22, "enp2s0" . 72.2.3.66 . 443 : 10.1.1.52 . 443 }
-       }
-
-       chain postrouting {
-               oif "lo" accept
-               snat ip to ip daddr map { 72.2.3.66 : 10.2.2.2, 72.2.3.67 : 10.2.3.3 }
-       }
-}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat_concat.json-nft b/tests/shell/testcases/optimizations/dumps/merge_nat_concat.json-nft
new file mode 100644 (file)
index 0000000..dc67fee
--- /dev/null
@@ -0,0 +1,200 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test3",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test3",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test3",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test3",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "snat": {
+              "addr": {
+                "map": {
+                  "key": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "saddr"
+                        }
+                      },
+                      {
+                        "payload": {
+                          "protocol": "tcp",
+                          "field": "sport"
+                        }
+                      }
+                    ]
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        {
+                          "concat": [
+                            "1.1.1.1",
+                            {
+                              "range": [
+                                1024,
+                                65535
+                              ]
+                            }
+                          ]
+                        },
+                        "3.3.3.3"
+                      ],
+                      [
+                        {
+                          "concat": [
+                            "2.2.2.2",
+                            {
+                              "range": [
+                                1024,
+                                65535
+                              ]
+                            }
+                          ]
+                        },
+                        "4.4.4.4"
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test3",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "enp2s0"
+            }
+          },
+          {
+            "snat": {
+              "family": "ip",
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        {
+                          "prefix": {
+                            "addr": "10.1.1.0",
+                            "len": 24
+                          }
+                        },
+                        {
+                          "range": [
+                            "72.2.3.66",
+                            "72.2.3.78"
+                          ]
+                        }
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test3",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  8888,
+                  9999
+                ]
+              }
+            }
+          },
+          {
+            "redirect": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat_concat.nft b/tests/shell/testcases/optimizations/dumps/merge_nat_concat.nft
new file mode 100644 (file)
index 0000000..0faddfd
--- /dev/null
@@ -0,0 +1,8 @@
+table ip test3 {
+       chain y {
+               oif "lo" accept
+               snat to ip saddr . tcp sport map { 1.1.1.1 . 1024-65535 : 3.3.3.3, 2.2.2.2 . 1024-65535 : 4.4.4.4 }
+               oifname "enp2s0" snat ip to ip saddr map { 10.1.1.0/24 : 72.2.3.66-72.2.3.78 }
+               tcp dport { 8888, 9999 } redirect
+       }
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat_inet.json-nft b/tests/shell/testcases/optimizations/dumps/merge_nat_inet.json-nft
new file mode 100644 (file)
index 0000000..99930f1
--- /dev/null
@@ -0,0 +1,208 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "nat",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "nat",
+        "name": "prerouting",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "nat",
+        "name": "postrouting",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "nat",
+        "chain": "prerouting",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "nat",
+        "chain": "prerouting",
+        "handle": 0,
+        "expr": [
+          {
+            "dnat": {
+              "family": "ip",
+              "addr": {
+                "map": {
+                  "key": {
+                    "concat": [
+                      {
+                        "meta": {
+                          "key": "iifname"
+                        }
+                      },
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "daddr"
+                        }
+                      },
+                      {
+                        "payload": {
+                          "protocol": "tcp",
+                          "field": "dport"
+                        }
+                      }
+                    ]
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        {
+                          "concat": [
+                            "enp2s0",
+                            "72.2.3.70",
+                            80
+                          ]
+                        },
+                        {
+                          "concat": [
+                            "10.1.1.52",
+                            80
+                          ]
+                        }
+                      ],
+                      [
+                        {
+                          "concat": [
+                            "enp2s0",
+                            "72.2.3.66",
+                            53122
+                          ]
+                        },
+                        {
+                          "concat": [
+                            "10.1.1.10",
+                            22
+                          ]
+                        }
+                      ],
+                      [
+                        {
+                          "concat": [
+                            "enp2s0",
+                            "72.2.3.66",
+                            443
+                          ]
+                        },
+                        {
+                          "concat": [
+                            "10.1.1.52",
+                            443
+                          ]
+                        }
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "nat",
+        "chain": "postrouting",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "nat",
+        "chain": "postrouting",
+        "handle": 0,
+        "expr": [
+          {
+            "snat": {
+              "family": "ip",
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        "72.2.3.66",
+                        "10.2.2.2"
+                      ],
+                      [
+                        "72.2.3.67",
+                        "10.2.3.3"
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat_inet.nft b/tests/shell/testcases/optimizations/dumps/merge_nat_inet.nft
new file mode 100644 (file)
index 0000000..a1a1135
--- /dev/null
@@ -0,0 +1,11 @@
+table inet nat {
+       chain prerouting {
+               oif "lo" accept
+               dnat ip to iifname . ip daddr . tcp dport map { "enp2s0" . 72.2.3.70 . 80 : 10.1.1.52 . 80, "enp2s0" . 72.2.3.66 . 53122 : 10.1.1.10 . 22, "enp2s0" . 72.2.3.66 . 443 : 10.1.1.52 . 443 }
+       }
+
+       chain postrouting {
+               oif "lo" accept
+               snat ip to ip daddr map { 72.2.3.66 : 10.2.2.2, 72.2.3.67 : 10.2.3.3 }
+       }
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_reject.json-nft b/tests/shell/testcases/optimizations/dumps/merge_reject.json-nft
new file mode 100644 (file)
index 0000000..46ed067
--- /dev/null
@@ -0,0 +1,320 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "172.30.33.70"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 3306
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "meta": {
+                      "key": "l4proto"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "right": {
+                "set": [
+                  {
+                    "concat": [
+                      "tcp",
+                      "172.30.238.117",
+                      8080
+                    ]
+                  },
+                  {
+                    "concat": [
+                      "tcp",
+                      "172.30.33.71",
+                      3306
+                    ]
+                  },
+                  {
+                    "concat": [
+                      "tcp",
+                      "172.30.254.251",
+                      3306
+                    ]
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "reject": {
+              "type": "icmp",
+              "expr": "port-unreachable"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "172.30.254.252"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 3306
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "reject": {
+              "type": "tcp reset"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "meta": {
+                      "key": "l4proto"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "ip6",
+                      "field": "daddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "right": {
+                "set": [
+                  {
+                    "concat": [
+                      "tcp",
+                      "aaaa::3",
+                      8080
+                    ]
+                  },
+                  {
+                    "concat": [
+                      "tcp",
+                      "aaaa::2",
+                      3306
+                    ]
+                  },
+                  {
+                    "concat": [
+                      "tcp",
+                      "aaaa::4",
+                      3306
+                    ]
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "reject": {
+              "type": "icmpv6",
+              "expr": "port-unreachable"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": "aaaa::5"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 3306
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "reject": {
+              "type": "tcp reset"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_stmts.json-nft b/tests/shell/testcases/optimizations/dumps/merge_stmts.json-nft
new file mode 100644 (file)
index 0000000..c392b76
--- /dev/null
@@ -0,0 +1,63 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "192.168.0.1",
+                  "192.168.0.2",
+                  "192.168.0.3"
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_stmts_concat_vmap.json-nft b/tests/shell/testcases/optimizations/dumps/merge_stmts_concat_vmap.json-nft
new file mode 100644 (file)
index 0000000..5dfa40a
--- /dev/null
@@ -0,0 +1,167 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "x",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "concat": [
+                  {
+                    "meta": {
+                      "key": "pkttype"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "udp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "data": {
+                "set": [
+                  [
+                    {
+                      "concat": [
+                        "broadcast",
+                        547
+                      ]
+                    },
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    {
+                      "concat": [
+                        "broadcast",
+                        67
+                      ]
+                    },
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    {
+                      "concat": [
+                        "multicast",
+                        1900
+                      ]
+                    },
+                    {
+                      "drop": null
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  }
+                ]
+              },
+              "data": {
+                "set": [
+                  [
+                    {
+                      "concat": [
+                        "1.1.1.1",
+                        "2.2.2.2"
+                      ]
+                    },
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    {
+                      "concat": [
+                        "2.2.2.2",
+                        "3.3.3.3"
+                      ]
+                    },
+                    {
+                      "drop": null
+                    }
+                  ],
+                  [
+                    {
+                      "concat": [
+                        "4.4.4.4",
+                        "5.5.5.5"
+                      ]
+                    },
+                    {
+                      "accept": null
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_stmts_vmap.json-nft b/tests/shell/testcases/optimizations/dumps/merge_stmts_vmap.json-nft
new file mode 100644 (file)
index 0000000..17d57b8
--- /dev/null
@@ -0,0 +1,182 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "z",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "w",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    "invalid",
+                    {
+                      "drop": null
+                    }
+                  ],
+                  [
+                    "established",
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    "related",
+                    {
+                      "accept": null
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "z",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    1,
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    {
+                      "range": [
+                        2,
+                        3
+                      ]
+                    },
+                    {
+                      "drop": null
+                    }
+                  ],
+                  [
+                    4,
+                    {
+                      "accept": null
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "w",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    {
+                      "elem": {
+                        "val": "1.1.1.1",
+                        "counter": {
+                          "packets": 0,
+                          "bytes": 0
+                        }
+                      }
+                    },
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    {
+                      "elem": {
+                        "val": "1.1.1.2",
+                        "counter": {
+                          "packets": 0,
+                          "bytes": 0
+                        }
+                      }
+                    },
+                    {
+                      "drop": null
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_vmap_raw.json-nft b/tests/shell/testcases/optimizations/dumps/merge_vmap_raw.json-nft
new file mode 100644 (file)
index 0000000..b8ad126
--- /dev/null
@@ -0,0 +1,438 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "nat_dns_dnstc",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "nat_dns_this_5301",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "nat_dns_saturn_5301",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "nat_dns_saturn_5302",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "nat_dns_saturn_5303",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "nat_dns_acme",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_dnstc",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "udp"
+            }
+          },
+          {
+            "redirect": {
+              "port": 5300
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_dnstc",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_this_5301",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "udp"
+            }
+          },
+          {
+            "redirect": {
+              "port": 5301
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_this_5301",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_saturn_5301",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "nfproto"
+                }
+              },
+              "right": "ipv4"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "udp"
+            }
+          },
+          {
+            "dnat": {
+              "family": "ip",
+              "addr": "240.0.1.2",
+              "port": 5301
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_saturn_5301",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_saturn_5302",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "nfproto"
+                }
+              },
+              "right": "ipv4"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "udp"
+            }
+          },
+          {
+            "dnat": {
+              "family": "ip",
+              "addr": "240.0.1.2",
+              "port": 5302
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_saturn_5302",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_saturn_5303",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "nfproto"
+                }
+              },
+              "right": "ipv4"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": "udp"
+            }
+          },
+          {
+            "dnat": {
+              "family": "ip",
+              "addr": "240.0.1.2",
+              "port": 5303
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_saturn_5303",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_acme",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "udp",
+                      "field": "length"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "base": "th",
+                      "offset": 160,
+                      "len": 128
+                    }
+                  }
+                ]
+              },
+              "data": {
+                "set": [
+                  [
+                    {
+                      "concat": [
+                        {
+                          "range": [
+                            47,
+                            63
+                          ]
+                        },
+                        "0xe373135363130333131303735353203"
+                      ]
+                    },
+                    {
+                      "goto": {
+                        "target": "nat_dns_dnstc"
+                      }
+                    }
+                  ],
+                  [
+                    {
+                      "concat": [
+                        {
+                          "range": [
+                            62,
+                            78
+                          ]
+                        },
+                        "0xe31393032383939353831343037320e"
+                      ]
+                    },
+                    {
+                      "goto": {
+                        "target": "nat_dns_this_5301"
+                      }
+                    }
+                  ],
+                  [
+                    {
+                      "concat": [
+                        {
+                          "range": [
+                            62,
+                            78
+                          ]
+                        },
+                        "0xe31363436323733373931323934300e"
+                      ]
+                    },
+                    {
+                      "goto": {
+                        "target": "nat_dns_saturn_5301"
+                      }
+                    }
+                  ],
+                  [
+                    {
+                      "concat": [
+                        {
+                          "range": [
+                            62,
+                            78
+                          ]
+                        },
+                        "0xe32393535373539353636383732310e"
+                      ]
+                    },
+                    {
+                      "goto": {
+                        "target": "nat_dns_saturn_5302"
+                      }
+                    }
+                  ],
+                  [
+                    {
+                      "concat": [
+                        {
+                          "range": [
+                            62,
+                            78
+                          ]
+                        },
+                        "0xe38353439353637323038363633390e"
+                      ]
+                    },
+                    {
+                      "goto": {
+                        "target": "nat_dns_saturn_5303"
+                      }
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "nat_dns_acme",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/merge_vmaps.json-nft b/tests/shell/testcases/optimizations/dumps/merge_vmaps.json-nft
new file mode 100644 (file)
index 0000000..f058d6f
--- /dev/null
@@ -0,0 +1,203 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "filter_in_tcp",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "filter_in_udp",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "set": "@s",
+              "stmt": [
+                {
+                  "limit": {
+                    "rate": 12,
+                    "burst": 30,
+                    "per": "minute"
+                  }
+                }
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    80,
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    81,
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    443,
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    {
+                      "range": [
+                        8000,
+                        8100
+                      ]
+                    },
+                    {
+                      "accept": null
+                    }
+                  ],
+                  [
+                    {
+                      "range": [
+                        24000,
+                        25000
+                      ]
+                    },
+                    {
+                      "accept": null
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    "tcp",
+                    {
+                      "goto": {
+                        "target": "filter_in_tcp"
+                      }
+                    }
+                  ],
+                  [
+                    "udp",
+                    {
+                      "goto": {
+                        "target": "filter_in_udp"
+                      }
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "log": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/not_mergeable.json-nft b/tests/shell/testcases/optimizations/dumps/not_mergeable.json-nft
new file mode 100644 (file)
index 0000000..8e64ba1
--- /dev/null
@@ -0,0 +1,140 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "t1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "t2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "t3",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "t4",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "jump": {
+              "target": "t1"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "jump": {
+              "target": "t2"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "version"
+                }
+              },
+              "data": {
+                "set": [
+                  [
+                    4,
+                    {
+                      "jump": {
+                        "target": "t3"
+                      }
+                    }
+                  ],
+                  [
+                    6,
+                    {
+                      "jump": {
+                        "target": "t4"
+                      }
+                    }
+                  ]
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/ruleset.json-nft b/tests/shell/testcases/optimizations/dumps/ruleset.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/ruleset.nft b/tests/shell/testcases/optimizations/dumps/ruleset.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/optimizations/dumps/single_anon_set.json-nft b/tests/shell/testcases/optimizations/dumps/single_anon_set.json-nft
new file mode 100644 (file)
index 0000000..2663413
--- /dev/null
@@ -0,0 +1,360 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "127.0.0.1"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iif"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "!=",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": {
+                "prefix": {
+                  "addr": "127.0.0.0",
+                  "len": 8
+                }
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": {
+                "range": [
+                  "127.0.0.1",
+                  "192.168.7.3"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "sport"
+                }
+              },
+              "right": {
+                "range": [
+                  1,
+                  1023
+                ]
+              }
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "192.168.7.1",
+                  "192.168.7.5"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  80,
+                  443
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "right": {
+                "set": [
+                  {
+                    "concat": [
+                      "192.168.0.1",
+                      22
+                    ]
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        "192.168.0.1",
+                        1
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": {
+                "set": [
+                  "established",
+                  "related"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
index 3f703034d80f6a8cafd9d744a746614bf4c9da5a..35e3f36e1a548fe859f0a7ee65fae4ac0dcce689 100644 (file)
@@ -11,6 +11,5 @@ table ip test {
                ip daddr . tcp dport { 192.168.0.1 . 22 } accept
                meta mark set ip daddr map { 192.168.0.1 : 0x00000001 }
                ct state { established, related } accept
-               meta mark { 0x0000000a counter packets 0 bytes 0 }
        }
 }
diff --git a/tests/shell/testcases/optimizations/dumps/single_anon_set.nft.input b/tests/shell/testcases/optimizations/dumps/single_anon_set.nft.input
deleted file mode 100644 (file)
index ecc5691..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-table ip test {
-       chain test {
-               # Test cases where anon set can be removed:
-               ip saddr { 127.0.0.1 } accept
-               iif { "lo" } accept
-
-               # negation, can change to != 22.
-               tcp dport != { 22 } drop
-
-               # single prefix, can remove anon set.
-               ip saddr { 127.0.0.0/8 } accept
-
-               # range, can remove anon set.
-               ip saddr { 127.0.0.1-192.168.7.3 } accept
-               tcp sport { 1-1023 } drop
-
-               # Test cases where anon set must be kept.
-
-               # 2 elements, cannot remove the anon set.
-               ip daddr { 192.168.7.1, 192.168.7.5 } accept
-               tcp dport { 80, 443 } accept
-
-               # single element, but concatenation which is not
-               # supported outside of set/map context at this time.
-               ip daddr . tcp dport { 192.168.0.1 . 22 } accept
-
-               # single element, but a map.
-               meta mark set ip daddr map { 192.168.0.1 : 1 }
-
-               # 2 elements.  This could be converted because
-               # ct state cannot be both established and related
-               # at the same time, but this needs extra work.
-               ct state { established, related } accept
-
-               # with stateful statement
-               meta mark { 0x0000000a counter }
-       }
-}
diff --git a/tests/shell/testcases/optimizations/dumps/single_anon_set_expr.json-nft b/tests/shell/testcases/optimizations/dumps/single_anon_set_expr.json-nft
new file mode 100644 (file)
index 0000000..c8adddb
--- /dev/null
@@ -0,0 +1,59 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "right": {
+                "set": [
+                  {
+                    "elem": {
+                      "val": 10,
+                      "counter": {
+                        "packets": 0,
+                        "bytes": 0
+                      }
+                    }
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/single_anon_set_expr.nft b/tests/shell/testcases/optimizations/dumps/single_anon_set_expr.nft
new file mode 100644 (file)
index 0000000..54880b9
--- /dev/null
@@ -0,0 +1,5 @@
+table ip test {
+       chain test {
+               meta mark { 0x0000000a counter packets 0 bytes 0 }
+       }
+}
diff --git a/tests/shell/testcases/optimizations/dumps/skip_merge.json-nft b/tests/shell/testcases/optimizations/dumps/skip_merge.json-nft
new file mode 100644 (file)
index 0000000..7bb6c65
--- /dev/null
@@ -0,0 +1,235 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "udp_input",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "tcp_input",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "udp_accepted",
+        "table": "filter",
+        "type": "inet_service",
+        "handle": 0,
+        "elem": [
+          500,
+          4500
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "tcp_accepted",
+        "table": "filter",
+        "type": "inet_service",
+        "handle": 0,
+        "elem": [
+          80,
+          443
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "udp_input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "range": [
+                  1,
+                  128
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "udp_input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": "@udp_accepted"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "udp_input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 53
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "tcp_input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  {
+                    "range": [
+                      1,
+                      128
+                    ]
+                  },
+                  {
+                    "range": [
+                      8888,
+                      9999
+                    ]
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "tcp_input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": "@tcp_accepted"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "tcp_input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "range": [
+                  1024,
+                  65535
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/skip_non_eq.json-nft b/tests/shell/testcases/optimizations/dumps/skip_non_eq.json-nft
new file mode 100644 (file)
index 0000000..19296d0
--- /dev/null
@@ -0,0 +1,108 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "eth0"
+            }
+          },
+          {
+            "match": {
+              "op": "!=",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "eth0"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "eth0"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "eth0"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/skip_unsupported.json-nft b/tests/shell/testcases/optimizations/dumps/skip_unsupported.json-nft
new file mode 100644 (file)
index 0000000..bf5a8ce
--- /dev/null
@@ -0,0 +1,254 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "GEOIP_CC_wan-lan_120",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "1.32.128.0",
+              "len": 18
+            }
+          },
+          {
+            "range": [
+              "1.32.200.0",
+              "1.32.204.128"
+            ]
+          },
+          {
+            "prefix": {
+              "addr": "1.32.207.0",
+              "len": 24
+            }
+          },
+          {
+            "range": [
+              "1.32.216.118",
+              "1.32.216.255"
+            ]
+          },
+          {
+            "range": [
+              "1.32.219.0",
+              "1.32.222.255"
+            ]
+          },
+          {
+            "prefix": {
+              "addr": "1.32.226.0",
+              "len": 23
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.32.231.0",
+              "len": 24
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.32.233.0",
+              "len": 24
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.32.238.0",
+              "len": 23
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.32.240.0",
+              "len": 24
+            }
+          },
+          {
+            "prefix": {
+              "addr": "223.223.220.0",
+              "len": 22
+            }
+          },
+          {
+            "prefix": {
+              "addr": "223.255.254.0",
+              "len": 24
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "1.2.3.4"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 80
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": 10
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "1.2.3.4"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 81
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": 11
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "right": {
+                "set": [
+                  {
+                    "concat": [
+                      "1.2.3.5",
+                      81
+                    ]
+                  },
+                  {
+                    "concat": [
+                      "1.2.3.5",
+                      82
+                    ]
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/variables.json-nft b/tests/shell/testcases/optimizations/dumps/variables.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optimizations/dumps/variables.nft b/tests/shell/testcases/optimizations/dumps/variables.nft
new file mode 100644 (file)
index 0000000..e69de29
index 3a57d9402301b7b9958c342cce8373cda180ccd5..3ffcbd5766915cb9753808e448670e6680940a4c 100755 (executable)
@@ -24,19 +24,6 @@ RULESET="table ip test2 {
 
 $NFT -o -f - <<< $RULESET
 
-RULESET="table ip test3 {
-        chain y {
-                oif lo accept
-                ip saddr 1.1.1.1 tcp sport 1024-65535 snat to 3.3.3.3
-                ip saddr 2.2.2.2 tcp sport 1024-65535 snat to 4.4.4.4
-                oifname enp2s0 snat ip to ip saddr map { 10.1.1.0/24 : 72.2.3.66-72.2.3.78 }
-                tcp dport 8888 redirect
-                tcp dport 9999 redirect
-        }
-}"
-
-$NFT -o -f - <<< $RULESET
-
 RULESET="table ip test4 {
         chain y {
                 oif lo accept
@@ -49,19 +36,3 @@ RULESET="table ip test4 {
 }"
 
 $NFT -o -f - <<< $RULESET
-
-RULESET="table inet nat {
-       chain prerouting {
-               oif lo accept
-               iifname enp2s0 ip daddr 72.2.3.66 tcp dport 53122 dnat to 10.1.1.10:22
-               iifname enp2s0 ip daddr 72.2.3.66 tcp dport 443 dnat to 10.1.1.52:443
-               iifname enp2s0 ip daddr 72.2.3.70 tcp dport 80 dnat to 10.1.1.52:80
-       }
-       chain postrouting {
-               oif lo accept
-               ip daddr 72.2.3.66 snat to 10.2.2.2
-               ip daddr 72.2.3.67 snat to 10.2.3.3
-       }
-}"
-
-$NFT -o -f - <<< $RULESET
diff --git a/tests/shell/testcases/optimizations/merge_nat_concat b/tests/shell/testcases/optimizations/merge_nat_concat
new file mode 100755 (executable)
index 0000000..2e0a91a
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
+set -e
+
+RULESET="table ip test3 {
+        chain y {
+                oif lo accept
+                ip saddr 1.1.1.1 tcp sport 1024-65535 snat to 3.3.3.3
+                ip saddr 2.2.2.2 tcp sport 1024-65535 snat to 4.4.4.4
+                oifname enp2s0 snat ip to ip saddr map { 10.1.1.0/24 : 72.2.3.66-72.2.3.78 }
+                tcp dport 8888 redirect
+                tcp dport 9999 redirect
+        }
+}"
+
+$NFT -o -f - <<< $RULESET
diff --git a/tests/shell/testcases/optimizations/merge_nat_inet b/tests/shell/testcases/optimizations/merge_nat_inet
new file mode 100755 (executable)
index 0000000..ff1916d
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_inet_nat)
+
+set -e
+
+RULESET="table inet nat {
+       chain prerouting {
+               oif lo accept
+               iifname enp2s0 ip daddr 72.2.3.66 tcp dport 53122 dnat to 10.1.1.10:22
+               iifname enp2s0 ip daddr 72.2.3.66 tcp dport 443 dnat to 10.1.1.52:443
+               iifname enp2s0 ip daddr 72.2.3.70 tcp dport 80 dnat to 10.1.1.52:80
+       }
+       chain postrouting {
+               oif lo accept
+               ip daddr 72.2.3.66 snat to 10.2.2.2
+               ip daddr 72.2.3.67 snat to 10.2.3.3
+       }
+}"
+
+$NFT -o -f - <<< $RULESET
index 1fd1a3031fb50e07fecc74e6bc3ba1a4c7f4562c..bae54e3665e02f00f2ccca8ee441864f1a181566 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 set -e
 
 RULESET="table ip x {
index 6e0f0762b7bb4dc616a045b4f8d602035f6f33c1..e5357c0f66b6fa2f4ff468d1f8fe63dac4f5fe7b 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
 set -e
 
 RULESET="table ip x {
index f3dc0721b94ffb52c7b53a32b59d8f11c813b7a2..eb04bec3ae6972c2c8304c033da371336ce85ecb 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 set -e
 
 RULESET="table inet x {
index ef2652dbeae8e3f6f6daee942f48a3a494f26000..f7c3b74702baa96d4563fb9bf9dfd4fd96746337 100755 (executable)
@@ -1,5 +1,8 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_prerouting_reject)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_inet_nat)
+
 RULESET="table inet uni {
        chain gtfo {
                reject with icmpx type host-unreachable
index 7275e3606900c6c4bd63bacd9c547b0a6b634c3a..632e965f37a798ffe6c00317f81a55a6b86ccde2 100755 (executable)
@@ -2,12 +2,52 @@
 
 set -e
 
+test -d "$NFT_TEST_TESTTMPDIR"
+
 # Input file contains rules with anon sets that contain
 # one element, plus extra rule with two elements (that should be
 # left alone).
 
 # Dump file has the simplified rules where anon sets have been
 # replaced by equality tests where possible.
-dumpfile=$(dirname $0)/dumps/$(basename $0).nft
+file_input1="$NFT_TEST_TESTTMPDIR/input1.nft"
+
+cat <<EOF > "$file_input1"
+table ip test {
+       chain test {
+               # Test cases where anon set can be removed:
+               ip saddr { 127.0.0.1 } accept
+               iif { "lo" } accept
+
+               # negation, can change to != 22.
+               tcp dport != { 22 } drop
+
+               # single prefix, can remove anon set.
+               ip saddr { 127.0.0.0/8 } accept
+
+               # range, can remove anon set.
+               ip saddr { 127.0.0.1-192.168.7.3 } accept
+               tcp sport { 1-1023 } drop
+
+               # Test cases where anon set must be kept.
+
+               # 2 elements, cannot remove the anon set.
+               ip daddr { 192.168.7.1, 192.168.7.5 } accept
+               tcp dport { 80, 443 } accept
+
+               # single element, but concatenation which is not
+               # supported outside of set/map context at this time.
+               ip daddr . tcp dport { 192.168.0.1 . 22 } accept
+
+               # single element, but a map.
+               meta mark set ip daddr map { 192.168.0.1 : 1 }
+
+               # 2 elements.  This could be converted because
+               # ct state cannot be both established and related
+               # at the same time, but this needs extra work.
+               ct state { established, related } accept
+       }
+}
+EOF
 
-$NFT -f "$dumpfile".input
+$NFT -f "$file_input1"
diff --git a/tests/shell/testcases/optimizations/single_anon_set_expr b/tests/shell/testcases/optimizations/single_anon_set_expr
new file mode 100755 (executable)
index 0000000..81b7ceb
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
+set -e
+
+test -d "$NFT_TEST_TESTTMPDIR"
+
+# Input file contains rules with anon sets that contain
+# one element, plus extra rule with two elements (that should be
+# left alone).
+
+# Dump file has the simplified rules where anon sets have been
+# replaced by equality tests where possible.
+file_input1="$NFT_TEST_TESTTMPDIR/input1.nft"
+
+cat <<EOF > "$file_input1"
+table ip test {
+       chain test {
+               # with stateful statement
+               meta mark { 0x0000000a counter }
+       }
+}
+EOF
+
+$NFT -f "$file_input1"
index fba961c76841f8df0ed71d29981461cf583ab63f..1a84cfa67a2a0420fb77de4e70292ffec65fa266 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_comment)
+
 EXPECTED='table ip test_table {
        chain test_chain {
                comment "test"
index 7437c77beb0b47ab35c9c2af07f4896bb28d297b..28041ebd2a43ef1261d92146c9bd2f43df06122f 100755 (executable)
@@ -1,9 +1,25 @@
 #!/bin/bash
 
-EXPECTED='table ip filter {
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_comment)
+
+set -e
+
+COMMENT128="12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"
+
+# test for pass with comment that is 128 bytes long.
+rc=0
+$NFT add table ip filter \{ quota foo1 \{ comment "\"${COMMENT128}\"" \}\; \}\; || rc="$?"
+test "$rc" = 0
+
+# test for failure with comment that is 128+1 bytes long.
+rc=0
+$NFT add table ip filter \{ quota foo2 \{ comment "\"${COMMENT128}x\"" \}\; \}\; || rc="$?"
+test "$rc" = 1
+
+RULESET='table ip filter {
        quota q {
                over 1200 bytes
-               comment "test1"
+               comment "'"$COMMENT128"'"
        }
 
        counter c {
@@ -39,6 +55,4 @@ EXPECTED='table ip filter {
 }
 '
 
-set -e
-
-$NFT -f - <<< "$EXPECTED"
+$NFT -f - <<< "$RULESET"
index a0dfd74946617576c669f7882b66f25048b49adb..56bb206bddcf8155ab8f273a76759c07c0a4af5d 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_comment)
+
 # comments are shown
 
 $NFT add table test { comment \"test_comment\"\; }
diff --git a/tests/shell/testcases/optionals/dumps/comments_0.json-nft b/tests/shell/testcases/optionals/dumps/comments_0.json-nft
new file mode 100644 (file)
index 0000000..aef4b3e
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "comment": "test_comment",
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/comments_chain_0.json-nft b/tests/shell/testcases/optionals/dumps/comments_chain_0.json-nft
new file mode 100644 (file)
index 0000000..4c752e8
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test_table",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test_table",
+        "name": "test_chain",
+        "handle": 0,
+        "comment": "test"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/comments_handles_0.json-nft b/tests/shell/testcases/optionals/dumps/comments_handles_0.json-nft
new file mode 100644 (file)
index 0000000..aef4b3e
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "comment": "test_comment",
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/comments_objects_0.json-nft b/tests/shell/testcases/optionals/dumps/comments_objects_0.json-nft
new file mode 100644 (file)
index 0000000..b5359d8
--- /dev/null
@@ -0,0 +1,102 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "quota": {
+        "family": "ip",
+        "name": "foo1",
+        "table": "filter",
+        "handle": 0,
+        "comment": "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678",
+        "bytes": 0,
+        "used": 0,
+        "inv": false
+      }
+    },
+    {
+      "quota": {
+        "family": "ip",
+        "name": "q",
+        "table": "filter",
+        "handle": 0,
+        "comment": "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678",
+        "bytes": 1200,
+        "used": 0,
+        "inv": true
+      }
+    },
+    {
+      "counter": {
+        "family": "ip",
+        "name": "c",
+        "table": "filter",
+        "handle": 0,
+        "comment": "test2",
+        "packets": 0,
+        "bytes": 0
+      }
+    },
+    {
+      "ct helper": {
+        "family": "ip",
+        "name": "h",
+        "table": "filter",
+        "handle": 0,
+        "comment": "test3",
+        "type": "sip",
+        "protocol": "tcp",
+        "l3proto": "ip"
+      }
+    },
+    {
+      "ct expectation": {
+        "family": "ip",
+        "name": "e",
+        "table": "filter",
+        "handle": 0,
+        "comment": "test4",
+        "protocol": "tcp",
+        "dport": 666,
+        "timeout": 100,
+        "size": 96,
+        "l3proto": "ip"
+      }
+    },
+    {
+      "limit": {
+        "family": "ip",
+        "name": "l",
+        "table": "filter",
+        "handle": 0,
+        "comment": "test5",
+        "rate": 400,
+        "per": "hour",
+        "burst": 5
+      }
+    },
+    {
+      "synproxy": {
+        "family": "ip",
+        "name": "s",
+        "table": "filter",
+        "handle": 0,
+        "comment": "test6",
+        "mss": 1460,
+        "wscale": 2
+      }
+    }
+  ]
+}
index b760ced6042407aa2e6c1f1da086c8198dade455..13822209ebabc16215e39a492b2bfe2010433a0b 100644 (file)
@@ -1,6 +1,11 @@
 table ip filter {
+       quota foo1 {
+               comment "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"
+               0 bytes
+       }
+
        quota q {
-               comment "test1"
+               comment "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"
                over 1200 bytes
        }
 
diff --git a/tests/shell/testcases/optionals/dumps/comments_objects_dup_0.json-nft b/tests/shell/testcases/optionals/dumps/comments_objects_dup_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/comments_objects_dup_0.nft b/tests/shell/testcases/optionals/dumps/comments_objects_dup_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/optionals/dumps/comments_table_0.json-nft b/tests/shell/testcases/optionals/dumps/comments_table_0.json-nft
new file mode 100644 (file)
index 0000000..8512c7d
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0,
+        "comment": "test_comment"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/delete_object_handles_0.json-nft b/tests/shell/testcases/optionals/dumps/delete_object_handles_0.json-nft
new file mode 100644 (file)
index 0000000..583ce52
--- /dev/null
@@ -0,0 +1,67 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test-ip",
+        "handle": 0
+      }
+    },
+    {
+      "quota": {
+        "family": "ip",
+        "name": "https-quota",
+        "table": "test-ip",
+        "handle": 0,
+        "bytes": 26214400,
+        "used": 0,
+        "inv": false
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "ports",
+        "table": "test-ip",
+        "type": "inet_service",
+        "handle": 0,
+        "map": "quota"
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test-ip6",
+        "handle": 0
+      }
+    },
+    {
+      "quota": {
+        "family": "ip6",
+        "name": "http-quota",
+        "table": "test-ip6",
+        "handle": 0,
+        "bytes": 26214400,
+        "used": 0,
+        "inv": true
+      }
+    },
+    {
+      "counter": {
+        "family": "ip6",
+        "name": "http-traffic",
+        "table": "test-ip6",
+        "handle": 0,
+        "packets": 0,
+        "bytes": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/delete_object_handles_0.nft b/tests/shell/testcases/optionals/dumps/delete_object_handles_0.nft
new file mode 100644 (file)
index 0000000..aac03cc
--- /dev/null
@@ -0,0 +1,18 @@
+table ip test-ip {
+       quota https-quota {
+               25 mbytes
+       }
+
+       map ports {
+               type inet_service : quota
+       }
+}
+table ip6 test-ip6 {
+       quota http-quota {
+               over 25 mbytes
+       }
+
+       counter http-traffic {
+               packets 0 bytes 0
+       }
+}
diff --git a/tests/shell/testcases/optionals/dumps/handles_0.json-nft b/tests/shell/testcases/optionals/dumps/handles_0.json-nft
new file mode 100644 (file)
index 0000000..ff06af3
--- /dev/null
@@ -0,0 +1,57 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/handles_1.json-nft b/tests/shell/testcases/optionals/dumps/handles_1.json-nft
new file mode 100644 (file)
index 0000000..ff06af3
--- /dev/null
@@ -0,0 +1,57 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/handles_1.nft b/tests/shell/testcases/optionals/dumps/handles_1.nft
new file mode 100644 (file)
index 0000000..085c6cf
--- /dev/null
@@ -0,0 +1,5 @@
+table ip test {
+       chain test {
+               tcp dport 22 counter packets 0 bytes 0 accept
+       }
+}
diff --git a/tests/shell/testcases/optionals/dumps/log_prefix_0.json-nft b/tests/shell/testcases/optionals/dumps/log_prefix_0.json-nft
new file mode 100644 (file)
index 0000000..161a58d
--- /dev/null
@@ -0,0 +1,52 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "invalid"
+            }
+          },
+          {
+            "log": {
+              "prefix": "invalid state match, logging:"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/update_object_handles_0.json-nft b/tests/shell/testcases/optionals/dumps/update_object_handles_0.json-nft
new file mode 100644 (file)
index 0000000..ba78f8d
--- /dev/null
@@ -0,0 +1,39 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test-ip",
+        "handle": 0
+      }
+    },
+    {
+      "counter": {
+        "family": "ip",
+        "name": "traffic-counter",
+        "table": "test-ip",
+        "handle": 0,
+        "packets": 0,
+        "bytes": 0
+      }
+    },
+    {
+      "quota": {
+        "family": "ip",
+        "name": "traffic-quota",
+        "table": "test-ip",
+        "handle": 0,
+        "bytes": 52428800,
+        "used": 0,
+        "inv": false
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/optionals/dumps/update_object_handles_0.nft b/tests/shell/testcases/optionals/dumps/update_object_handles_0.nft
new file mode 100644 (file)
index 0000000..f391b63
--- /dev/null
@@ -0,0 +1,9 @@
+table ip test-ip {
+       counter traffic-counter {
+               packets 0 bytes 0
+       }
+
+       quota traffic-quota {
+               50 mbytes
+       }
+}
index 8b12b8c57cd8bb4f7b33f802cc0297e01ff71e83..ccd96779d9b331f409ac1ae723d34ef90089c524 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_stateful_object_update)
+
 set -e
 $NFT add table test-ip
 $NFT add counter test-ip traffic-counter
index 8b7a551cc69e9af005a0a3a11b12a53114aa4760..c07e8d6a0ab9a919530b88c6e892b5a5f0da2f44 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_table_flag_owner)
+
 set -e
 
 $NFT -f - <<EOF
diff --git a/tests/shell/testcases/owner/0002-persist b/tests/shell/testcases/owner/0002-persist
new file mode 100755 (executable)
index 0000000..700f00e
--- /dev/null
@@ -0,0 +1,79 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_table_flag_owner)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_table_flag_persist)
+
+die() {
+       echo "$@"
+       exit 1
+}
+
+$NFT -f - <<EOF
+table ip t {
+       flags owner, persist
+}
+EOF
+[[ $? -eq 0 ]] || {
+       die "table add failed"
+}
+
+$NFT list ruleset | grep -q 'table ip t' || {
+       die "table does not persist"
+}
+$NFT list ruleset | grep -q 'flags persist$' || {
+       die "unexpected flags in orphaned table"
+}
+
+$NFT -f - <<EOF
+table ip t {
+       flags owner, persist
+}
+EOF
+[[ $? -eq 0 ]] || {
+       die "retake ownership failed"
+}
+
+EXPECT="table ip t {
+       flags persist
+}"
+diff -u <(echo "$EXPECT") <($NFT list ruleset) || {
+       die "unexpected ruleset before coproc setup"
+}
+
+coproc $NFT -i
+sleep 1
+
+cat >&"${COPROC[1]}" <<EOF
+add table ip t { flags owner, persist; }
+EOF
+
+COMM=$(</proc/${COPROC_PID}/comm)
+EXPECT="table ip t { # progname $COMM
+       flags owner,persist
+}"
+diff -u <(echo "$EXPECT") <($NFT list ruleset) || {
+       die "unexpected ruleset after coproc setup"
+}
+
+$NFT flush ruleset
+$NFT list ruleset | grep -q 'table ip t' || {
+       die "flushed owned table"
+}
+
+$NFT add table 'ip t { flags owner, persist; }' && {
+       die "stole owned table"
+}
+
+cat >&"${COPROC[1]}" <<EOF
+delete table ip t
+EOF
+
+[[ -z $($NFT list ruleset) ]] || {
+       die "owner should be able to delete the table"
+}
+
+eval "exec ${COPROC[1]}>&-"
+wait $COPROC_PID
+
+
+exit 0
diff --git a/tests/shell/testcases/owner/dumps/0001-flowtable-uaf.json-nft b/tests/shell/testcases/owner/dumps/0001-flowtable-uaf.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/owner/dumps/0001-flowtable-uaf.nft b/tests/shell/testcases/owner/dumps/0001-flowtable-uaf.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/owner/dumps/0002-persist.json-nft b/tests/shell/testcases/owner/dumps/0002-persist.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/owner/dumps/0002-persist.nft b/tests/shell/testcases/owner/dumps/0002-persist.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/packetpath/cgroupv2 b/tests/shell/testcases/packetpath/cgroupv2
new file mode 100755 (executable)
index 0000000..0a6199f
--- /dev/null
@@ -0,0 +1,143 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_socat)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_cgroupsv2)
+
+doit="$1"
+rc=0
+
+# Create hierarchy:
+# / -> nft-test1a/nft-test2a
+# |              `nft-test2b
+# `--> nft-test1b/nft-test2a
+# test1b/nft-test2a will remain empty and
+# should never match, it only exists so we
+# can create cgroupv2 match rules.
+
+if [ ! -r /sys/fs/cgroup/cgroup.procs ] ;then
+       echo "cgroup filesystem not available"
+       exit 77
+fi
+
+cleanup()
+{
+       echo $$ > "/sys/fs/cgroup/cgroup.procs"
+
+       rmdir "/sys/fs/cgroup/nft-test1a/nft-test2a"
+       rmdir "/sys/fs/cgroup/nft-test1a/nft-test2b"
+       rmdir "/sys/fs/cgroup/nft-test1b/nft-test2a"
+       rmdir "/sys/fs/cgroup/nft-test1a"
+       rmdir "/sys/fs/cgroup/nft-test1b"
+
+       # nft list is broken after cgroupv2 removal, as nft
+       # can't find the human-readable names anymore.
+       $NFT delete table inet testcgrpv2
+}
+
+do_initial_setup()
+{
+       trap cleanup EXIT
+       ip link set lo up
+
+       mkdir -p "/sys/fs/cgroup/nft-test1a/nft-test2a" || exit 1
+       mkdir -p "/sys/fs/cgroup/nft-test1b/nft-test2a" || exit 1
+
+       mkdir "/sys/fs/cgroup/nft-test1a/nft-test2b" || exit 1
+
+       # After this, we can create cgroupv2 rules for the these cgroups.
+       # test1a and test2a should match while test1b/test2b should not:
+$NFT -f - <<EOF
+table inet testcgrpv2 {
+       counter nft-test1a {}
+       counter nft-test1a2a {}
+       counter nft-test1a2b {}
+       counter nft-test1b {}
+       counter nft-test1b2a {}
+
+       chain output {
+               type filter hook output priority 0;
+
+               socket cgroupv2 level 1 "nft-test1a" counter name "nft-test1a"
+               socket cgroupv2 level 2 "nft-test1a/nft-test2a" counter name "nft-test1a2a"
+
+               # Next must never match
+               socket cgroupv2 level 2 "nft-test1a/nft-test2b" counter name "nft-test1a2b"
+
+               # Must never match
+               socket cgroupv2 level 1 "nft-test1b" counter name "nft-test1b"
+               # Same, must not match.
+               socket cgroupv2 level 2 "nft-test1b/nft-test2a" counter name "nft-test1b2a"
+       }
+}
+EOF
+}
+
+test_counters()
+{
+       local subtest="$1"
+
+       local t1a="$2"
+       local t1a2a="$3"
+
+       $NFT list ruleset
+
+       $NFT reset counter inet testcgrpv2 nft-test1a | grep -q "packets $t1a" || rc=1
+       $NFT reset counter inet testcgrpv2 nft-test1a2a | grep -q "packets $t1a2a" || rc=2
+
+       # dummy cgroup counters, must not match.
+       $NFT reset counter inet testcgrpv2 nft-test1a2b | grep -q 'packets 0' || rc=3
+       $NFT reset counter inet testcgrpv2 nft-test1b   | grep -q 'packets 0' || rc=4
+       $NFT reset counter inet testcgrpv2 nft-test1b2a | grep -q 'packets 0' || rc=5
+
+       if [ $rc -ne 0 ]; then
+               echo "Counters did not match expected values fur subtest $subtest, return $rc"
+               exit $rc
+       fi
+}
+
+run_test()
+{
+       echo $$ > "/sys/fs/cgroup/nft-test1a/nft-test2a/cgroup.procs" || exit 2
+       socat -u STDIN TCP:127.0.0.1:8880,connect-timeout=4 < /dev/null > /dev/null
+
+       test_counters "a1,a2" 1 1
+
+       echo $$ > "/sys/fs/cgroup/nft-test1a/cgroup.procs" || exit 2
+       socat -u STDIN TCP:127.0.0.1:8880,connect-timeout=4 < /dev/null > /dev/null
+       test_counters "a1 only" 1 0
+}
+
+
+if [ "$doit" != "setup-done" ];then
+       mkdir -p "/sys/fs/cgroup/nft-test1a" || exit 77
+
+       do_initial_setup
+       run_test
+
+       if [ $rc -ne 0 ]; then
+               exit $rc
+       fi
+
+       echo "Re-running test with changed cgroup root"
+       echo $$ > "/sys/fs/cgroup/nft-test1a/cgroup.procs" || exit 2
+       unshare --fork --pid --mount -n -C $0 "setup-done"
+       rc=$?
+else
+       want_inode=$(stat --printf=%i "/sys/fs/cgroup/nft-test1a/")
+       mount --bind /sys/fs/cgroup/nft-test1a/ /sys/fs/cgroup/
+
+       # /sys/fs/cgroup/  should now match "/sys/fs/cgroup/nft-test1a/cgroup.procs"
+       rootinode=$(stat --printf=%i "/sys/fs/cgroup/")
+
+       if [ $want_inode -ne $rootinode ] ;then
+               echo "Failed to remount cgroupv2 fs, wanted inode $want_inode as root node, but got $rootinode"
+               exit 77
+       fi
+
+       do_initial_setup
+       run_test
+
+       umount /sys/fs/group/
+fi
+
+exit $rc
diff --git a/tests/shell/testcases/packetpath/dumps/cgroupv2.nodump b/tests/shell/testcases/packetpath/dumps/cgroupv2.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/packetpath/dumps/flowtables.nodump b/tests/shell/testcases/packetpath/dumps/flowtables.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/packetpath/dumps/payload.nodump b/tests/shell/testcases/packetpath/dumps/payload.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/packetpath/dumps/policy.json-nft b/tests/shell/testcases/packetpath/dumps/policy.json-nft
new file mode 100644 (file)
index 0000000..26e8a05
--- /dev/null
@@ -0,0 +1,121 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "underflow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "drop"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-reply"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "127.0.0.1"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "127.0.0.2"
+            }
+          },
+          {
+            "counter": {
+              "packets": 3,
+              "bytes": 252
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "underflow"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/packetpath/dumps/policy.nft b/tests/shell/testcases/packetpath/dumps/policy.nft
new file mode 100644 (file)
index 0000000..e625ea6
--- /dev/null
@@ -0,0 +1,11 @@
+table inet filter {
+       chain underflow {
+       }
+
+       chain input {
+               type filter hook input priority filter; policy drop;
+               icmp type echo-reply accept
+               ip saddr 127.0.0.1 ip daddr 127.0.0.2 counter packets 3 bytes 252 accept
+               goto underflow
+       }
+}
diff --git a/tests/shell/testcases/packetpath/dumps/set_lookups.json-nft b/tests/shell/testcases/packetpath/dumps/set_lookups.json-nft
new file mode 100644 (file)
index 0000000..23f4b17
--- /dev/null
@@ -0,0 +1,696 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "iface_index"
+        ],
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "concat": [
+              "127.0.0.1",
+              "lo"
+            ]
+          },
+          {
+            "concat": [
+              "127.0.0.2",
+              "lo"
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s2",
+        "table": "t",
+        "type": {
+          "typeof": {
+            "concat": [
+              {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              {
+                "meta": {
+                  "key": "iif"
+                }
+              }
+            ]
+          }
+        },
+        "handle": 0,
+        "elem": [
+          {
+            "concat": [
+              "127.0.0.1",
+              "lo"
+            ]
+          },
+          {
+            "concat": [
+              "127.0.0.2",
+              "lo"
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s3",
+        "table": "t",
+        "type": "iface_index",
+        "handle": 0,
+        "elem": [
+          "lo"
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s4",
+        "table": "t",
+        "type": "iface_index",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          "lo"
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "nomatch",
+        "table": "t",
+        "type": {
+          "typeof": {
+            "concat": [
+              {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              {
+                "meta": {
+                  "key": "iif"
+                }
+              }
+            ]
+          }
+        },
+        "handle": 0,
+        "elem": [
+          {
+            "concat": [
+              "127.0.0.3",
+              "lo"
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "nomatch2",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "iface_index"
+        ],
+        "handle": 0,
+        "elem": [
+          {
+            "concat": [
+              "127.0.0.2",
+              "90000"
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "meta": {
+                      "key": "iif"
+                    }
+                  }
+                ]
+              },
+              "right": "@s"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "lo"
+                ]
+              },
+              "right": "@s"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "lo"
+                ]
+              },
+              "right": "@s"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "meta": {
+                      "key": "iif"
+                    }
+                  }
+                ]
+              },
+              "right": "@s2"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "lo"
+                ]
+              },
+              "right": "@s2"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "lo"
+                ]
+              },
+              "right": "@s2"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  "lo"
+                ]
+              },
+              "right": "@s"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  "lo"
+                ]
+              },
+              "right": "@s2"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iif"
+                }
+              },
+              "right": "@s3"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": "echo-request"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iif"
+                }
+              },
+              "right": "@s4"
+            }
+          },
+          {
+            "counter": {
+              "packets": 1,
+              "bytes": 84
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  "lo"
+                ]
+              },
+              "right": "@nomatch"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  {
+                    "meta": {
+                      "key": "iif"
+                    }
+                  }
+                ]
+              },
+              "right": "@nomatch2"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/packetpath/dumps/set_lookups.nft b/tests/shell/testcases/packetpath/dumps/set_lookups.nft
new file mode 100644 (file)
index 0000000..7566f55
--- /dev/null
@@ -0,0 +1,51 @@
+table ip t {
+       set s {
+               type ipv4_addr . iface_index
+               flags interval
+               elements = { 127.0.0.1 . "lo",
+                            127.0.0.2 . "lo" }
+       }
+
+       set s2 {
+               typeof ip saddr . iif
+               elements = { 127.0.0.1 . "lo",
+                            127.0.0.2 . "lo" }
+       }
+
+       set s3 {
+               type iface_index
+               elements = { "lo" }
+       }
+
+       set s4 {
+               type iface_index
+               flags interval
+               elements = { "lo" }
+       }
+
+       set nomatch {
+               typeof ip saddr . iif
+               elements = { 127.0.0.3 . "lo" }
+       }
+
+       set nomatch2 {
+               type ipv4_addr . iface_index
+               elements = { 127.0.0.2 . 90000 }
+       }
+
+       chain c {
+               type filter hook input priority filter; policy accept;
+               icmp type echo-request ip saddr . iif @s counter packets 1 bytes 84
+               icmp type echo-request ip saddr . "lo" @s counter packets 1 bytes 84
+               icmp type echo-request ip saddr . "lo" @s counter packets 1 bytes 84
+               icmp type echo-request ip saddr . iif @s2 counter packets 1 bytes 84
+               icmp type echo-request ip saddr . "lo" @s2 counter packets 1 bytes 84
+               icmp type echo-request ip saddr . "lo" @s2 counter packets 1 bytes 84
+               icmp type echo-request ip daddr . "lo" @s counter packets 1 bytes 84
+               icmp type echo-request ip daddr . "lo" @s2 counter packets 1 bytes 84
+               icmp type echo-request iif @s3 counter packets 1 bytes 84
+               icmp type echo-request iif @s4 counter packets 1 bytes 84
+               ip daddr . "lo" @nomatch counter packets 0 bytes 0 drop
+               ip daddr . iif @nomatch2 counter packets 0 bytes 0 drop
+       }
+}
diff --git a/tests/shell/testcases/packetpath/dumps/tcp_reset.json-nft b/tests/shell/testcases/packetpath/dumps/tcp_reset.json-nft
new file mode 100644 (file)
index 0000000..e1367cc
--- /dev/null
@@ -0,0 +1,168 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "output",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "nftrace"
+                }
+              },
+              "value": 1
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "127.0.0.1"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 5555
+            }
+          },
+          {
+            "reject": {
+              "type": "tcp reset"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": "::1"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 5555
+            }
+          },
+          {
+            "reject": {
+              "type": "tcp reset"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 5555
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/packetpath/dumps/tcp_reset.nft b/tests/shell/testcases/packetpath/dumps/tcp_reset.nft
new file mode 100644 (file)
index 0000000..fb3df1a
--- /dev/null
@@ -0,0 +1,13 @@
+table inet filter {
+       chain input {
+               type filter hook input priority filter; policy accept;
+               meta nftrace set 1
+               ip daddr 127.0.0.1 tcp dport 5555 reject with tcp reset
+               ip6 daddr ::1 tcp dport 5555 reject with tcp reset
+               tcp dport 5555 counter packets 0 bytes 0
+       }
+
+       chain output {
+               type filter hook output priority filter; policy accept;
+       }
+}
diff --git a/tests/shell/testcases/packetpath/dumps/vlan_8021ad_tag.nodump b/tests/shell/testcases/packetpath/dumps/vlan_8021ad_tag.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/packetpath/dumps/vlan_mangling.nodump b/tests/shell/testcases/packetpath/dumps/vlan_mangling.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/packetpath/dumps/vlan_qinq.nodump b/tests/shell/testcases/packetpath/dumps/vlan_qinq.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/packetpath/flowtables b/tests/shell/testcases/packetpath/flowtables
new file mode 100755 (executable)
index 0000000..b68c5dd
--- /dev/null
@@ -0,0 +1,122 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_socat)
+# NFT_TEST_SKIP(NFT_TEST_SKIP_slow)
+
+rnd=$(mktemp -u XXXXXXXX)
+R="flowtable-router-$rnd"
+C="flowtable-client-$rnd"
+S="flowtbale-server-$rnd"
+
+cleanup()
+{
+       for i in $R $C $S;do
+               kill $(ip netns pid $i) 2>/dev/null
+               ip netns del $i
+       done
+}
+trap cleanup EXIT
+
+assert_pass()
+{
+       local ret=$?
+       if [ $ret != 0 ]
+       then
+               echo "FAIL: ${@}"
+               ip netns exec $R cat /proc/net/nf_conntrack
+               exit 1
+       else
+               echo "PASS: ${@}"
+       fi
+}
+assert_fail()
+{
+       local ret=$?
+       if [ $ret == 0 ]
+       then
+               echo "FAIL: ${@}"
+               ip netns exec $R cat /proc/net/nf_conntrack
+               exit 1
+       else
+               echo "PASS: ${@}"
+       fi
+}
+
+ip netns add $R
+ip netns add $S
+ip netns add $C
+
+ip link add s_r netns $S type veth peer name r_s netns $R
+ip netns exec $S ip link set s_r up
+ip netns exec $R ip link set r_s up
+ip link add c_r netns $C type veth peer name r_c netns $R
+ip netns exec $R ip link set r_c up
+ip netns exec $C ip link set c_r up
+
+ip netns exec $S ip -6 addr add 2001:db8:ffff:22::1/64 dev s_r
+ip netns exec $C ip -6 addr add 2001:db8:ffff:21::2/64 dev c_r
+ip netns exec $R ip -6 addr add 2001:db8:ffff:22::fffe/64 dev r_s
+ip netns exec $R ip -6 addr add 2001:db8:ffff:21::fffe/64 dev r_c
+ip netns exec $R sysctl -wq net.ipv6.conf.all.forwarding=1
+ip netns exec $C ip route add 2001:db8:ffff:22::/64 via 2001:db8:ffff:21::fffe dev c_r
+ip netns exec $S ip route add 2001:db8:ffff:21::/64 via 2001:db8:ffff:22::fffe dev s_r
+ip netns exec $S ethtool -K s_r tso off
+ip netns exec $C ethtool -K c_r tso off
+sleep 3
+
+ip netns exec $C ping -q -6 2001:db8:ffff:22::1 -c1
+assert_pass "topo initialization"
+
+ip netns exec $R nft -f - <<EOF
+table ip6 filter {
+        flowtable f1 {
+                hook ingress priority -100
+                devices = { r_c, r_s }
+        }
+
+        chain forward {
+                type filter hook forward priority filter; policy accept;
+                ip6 nexthdr tcp ct state established,related counter packets 0 bytes 0 flow add @f1 counter packets 0 bytes 0
+                ip6 nexthdr tcp ct state invalid counter packets 0 bytes 0 drop
+                tcp flags fin,rst counter packets 0 bytes 0 accept
+                meta l4proto tcp meta length < 100 counter packets 0 bytes 0 accept
+                ip6 nexthdr tcp counter packets 0 bytes 0 log drop
+        }
+}
+EOF
+assert_pass "apply nft ruleset"
+
+if [ ! -r /proc/net/nf_conntrack ]
+then
+       echo "E: nf_conntrack unreadable, skipping" >&2 
+       exit 77
+fi
+
+ip netns exec $R sysctl -wq net.netfilter.nf_flowtable_tcp_timeout=5
+assert_pass "set net.netfilter.nf_flowtable_tcp_timeout=5"
+
+ip netns exec $R sysctl -wq net.netfilter.nf_conntrack_tcp_timeout_established=86400
+assert_pass "set net.netfilter.nf_conntrack_tcp_timeout_established=86400"
+
+# A trick to control the timing to send a packet
+ip netns exec $S socat TCP6-LISTEN:10001 GOPEN:/tmp/socat-$rnd,ignoreeof &
+sleep 1
+ip netns exec $C socat -b 2048 PIPE:/tmp/pipefile-$rnd 'TCP:[2001:db8:ffff:22::1]:10001' &
+sleep 1
+ip netns exec $C echo "send sth" >> /tmp/pipefile-$rnd        ; assert_pass "send a packet"
+ip netns exec $R grep -q 'OFFLOAD' /proc/net/nf_conntrack     ; assert_pass "check [OFFLOAD] tag"
+sleep 6
+ip netns exec $R grep -q 'OFFLOAD' /proc/net/nf_conntrack     ; assert_fail "CT OFFLOAD timeout, back to the classical path"
+ip netns exec $R grep -q '863[89][0-9]' /proc/net/nf_conntrack; assert_pass "check timeout adopt nf_conntrack_tcp_timeout_established"
+ip netns exec $C echo "send sth" >> /tmp/pipefile-$rnd        ; assert_pass "send a packet"
+ip netns exec $R grep -q 'OFFLOAD' /proc/net/nf_conntrack     ; assert_pass "packet detected, back to the OFFLOAD path"
+
+i=3; while ((i--))
+do
+       sleep 3
+       ip netns exec $C echo "send sth" >> /tmp/pipefile-$rnd; assert_pass "send a packet"
+       sleep 3
+       ip netns exec $R grep -q 'OFFLOAD' /proc/net/nf_conntrack
+       assert_pass "Traffic seen in 5s (nf_flowtable_tcp_timeout), should stay in OFFLOAD"
+done
+exit 0
diff --git a/tests/shell/testcases/packetpath/match_l4proto b/tests/shell/testcases/packetpath/match_l4proto
new file mode 100755 (executable)
index 0000000..e61524e
--- /dev/null
@@ -0,0 +1,150 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netdev_egress)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_socat)
+
+rnd=$(mktemp -u XXXXXXXX)
+ns1="nft1payload-$rnd"
+ns2="nft2payload-$rnd"
+
+cleanup()
+{
+       ip netns del "$ns1"
+       ip netns del "$ns2"
+}
+
+trap cleanup EXIT
+
+run_test()
+{
+       ns1_addr=$2
+       ns2_addr=$3
+       cidr=$4
+
+       # socat needs square brackets, ie. [abcd::2]
+       if [ $1 -eq 6 ]; then
+               nsx1_addr="["$ns1_addr"]"
+               nsx2_addr="["$ns2_addr"]"
+       else
+               nsx1_addr="$ns1_addr"
+               nsx2_addr="$ns2_addr"
+       fi
+
+       ip netns add "$ns1" || exit 111
+       ip netns add "$ns2" || exit 111
+
+       ip -net "$ns1" link set lo up
+       ip -net "$ns2" link set lo up
+
+       ip link add veth0 netns $ns1 type veth peer name veth0 netns $ns2
+
+       ip -net "$ns1" link set veth0 up
+       ip -net "$ns2" link set veth0 up
+       ip -net "$ns1" addr add $ns1_addr/$cidr dev veth0
+       ip -net "$ns2" addr add $ns2_addr/$cidr dev veth0
+
+       sleep 5
+
+RULESET="table netdev payload_netdev {
+       counter ingress {}
+       counter ingress_2 {}
+       counter egress {}
+       counter egress_2 {}
+
+       chain ingress {
+               type filter hook ingress device veth0 priority 0;
+               udp dport 7777 counter name ingress
+               meta l4proto udp counter name ingress_2
+       }
+
+       chain egress {
+               type filter hook egress device veth0 priority 0;
+               udp dport 7777 counter name egress
+               meta l4proto udp counter name egress_2
+       }
+}"
+
+       ip netns exec "$ns1" $NFT -f - <<< "$RULESET" || exit 1
+
+       ip netns exec "$ns1" bash -c "echo 'A' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+       ip netns exec "$ns1" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+       ip netns exec "$ns1" bash -c "echo 'AAA' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+       ip netns exec "$ns1" bash -c "echo 'AAAA' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+       ip netns exec "$ns1" bash -c "echo 'AAAAA' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+
+       ip netns exec "$ns2" bash -c "echo 'A' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+       ip netns exec "$ns2" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+       ip netns exec "$ns2" bash -c "echo 'AAA' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+       ip netns exec "$ns2" bash -c "echo 'AAAA' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+       ip netns exec "$ns2" bash -c "echo 'AAAAA' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+
+       ip netns exec "$ns1" $NFT list ruleset
+
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev ingress | grep "packets 5" > /dev/null || exit 1
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev ingress_2 | grep "packets 5" > /dev/null || exit 1
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev egress | grep "packets 5" > /dev/null || exit 1
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev egress_2| grep "packets 5" > /dev/null || exit 1
+
+       #
+       # ... next stage
+       #
+       ip netns exec "$ns1" $NFT flush ruleset
+
+       #
+       # bridge
+       #
+
+       ip -net "$ns1" addr del $ns1_addr/$cidr dev veth0
+
+       ip -net "$ns1" link add name br0 type bridge
+       ip -net "$ns1" link set veth0 master br0
+       ip -net "$ns1" addr add $ns1_addr/$cidr dev br0
+       ip -net "$ns1" link set up dev br0
+
+       sleep 5
+
+RULESET="table bridge payload_bridge {
+       counter input {}
+       counter output {}
+       counter input_2 {}
+       counter output_2 {}
+
+       chain in {
+               type filter hook input priority 0;
+               udp dport 7777 counter name input
+               meta l4proto udp counter name input_2
+       }
+
+       chain out {
+               type filter hook output priority 0;
+               udp dport 7777 counter name output
+               meta l4proto udp counter name output_2
+        }
+}"
+
+       ip netns exec "$ns1" $NFT -f - <<< "$RULESET" || exit 1
+
+       ip netns exec "$ns1" bash -c "echo 'A' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+       ip netns exec "$ns1" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+       ip netns exec "$ns1" bash -c "echo 'AAA' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+       ip netns exec "$ns1" bash -c "echo 'AAAA' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+       ip netns exec "$ns1" bash -c "echo 'AAAAA' | socat -u STDIN UDP:$nsx2_addr:7777 > /dev/null"
+
+       ip netns exec "$ns2" bash -c "echo 'A' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+       ip netns exec "$ns2" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+       ip netns exec "$ns2" bash -c "echo 'AAA' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+       ip netns exec "$ns2" bash -c "echo 'AAAA' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+       ip netns exec "$ns2" bash -c "echo 'AAAAA' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+
+       ip netns exec "$ns1" $NFT list ruleset
+
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge input | grep "packets 5" > /dev/null || exit 1
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge input_2 | grep "packets 5" > /dev/null || exit 1
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge output | grep "packets 5" > /dev/null || exit 1
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge output_2 | grep "packets 5" > /dev/null || exit 1
+}
+
+run_test "4" "10.141.10.2" "10.141.10.3" "24"
+cleanup
+run_test "6" "abcd::2" "abcd::3" "64"
+# trap calls cleanup
diff --git a/tests/shell/testcases/packetpath/nat_ftp b/tests/shell/testcases/packetpath/nat_ftp
new file mode 100755 (executable)
index 0000000..327047b
--- /dev/null
@@ -0,0 +1,178 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_tcpdump)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_curl)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_vsftpd)
+
+cleanup()
+{
+       for i in $R $C $S;do
+               kill $(ip netns pid $i) 2>/dev/null
+               ip netns del $i
+       done
+       rm -rf $WORKDIR
+}
+trap cleanup EXIT
+
+assert_pass()
+{
+       local ret=$?
+       if [ $ret != 0 ]
+       then
+               echo "FAIL: ${@}"
+               ip netns exec $R nft list ruleset
+               tcpdump -nnr ${PCAP}
+               test -r /proc/net/nf_conntrack && ip netns exec $R cat /proc/net/nf_conntrack
+               ip netns exec $R conntrack -S
+               ip netns exec $R conntrack -L
+               ip netns exec $S ss -nitepal
+               exit 1
+       else
+               echo "PASS: ${@}"
+       fi
+}
+
+rnd=$(mktemp -u XXXXXXXX)
+R="natftp-router-$rnd"
+C="natftp-client-$rnd"
+S="natftp-server-$rnd"
+
+WORKDIR="/tmp/nat_ftp_test-$rnd"
+FTPCONF="$WORKDIR/ftp-conf"
+INFILE="$WORKDIR/infile"
+OUTFILE="$WORKDIR/outfile"
+PCAP="$WORKDIR/tcpdump.pcap"
+
+mkdir -p $WORKDIR
+assert_pass "mkdir $WORKDIR"
+
+modprobe nf_nat_ftp
+assert_pass "modprobe nf_nat_ftp. Needed for DNAT of data connection and active mode PORT change with SNAT"
+
+ip_sr=2001:db8:ffff:22::1
+ip_cr=2001:db8:ffff:21::2
+ip_rs=2001:db8:ffff:22::fffe
+ip_rc=2001:db8:ffff:21::fffe
+
+ip netns add $R
+ip netns add $S
+ip netns add $C
+ip -net $S link set lo up
+ip -net $R link set lo up
+ip -net $C link set lo up
+ip netns exec $R sysctl -wq net.ipv6.conf.all.forwarding=1
+
+ip link add s_r netns $S type veth peer name r_s netns $R
+ip link add c_r netns $C type veth peer name r_c netns $R
+ip -net $S link set s_r up
+ip -net $R link set r_s up
+ip -net $R link set r_c up
+ip -net $C link set c_r up
+
+ip -net $S addr add ${ip_sr}/64 dev s_r nodad
+ip -net $C addr add ${ip_cr}/64 dev c_r nodad
+ip -net $R addr add ${ip_rs}/64 dev r_s nodad
+ip -net $R addr add ${ip_rc}/64 dev r_c nodad
+ip -net $C route add ${ip_rs}/64 via ${ip_rc} dev c_r
+ip -net $S route add ${ip_rc}/64 via ${ip_rs} dev s_r
+
+ip netns exec $C ping -q -6 ${ip_sr} -c1 > /dev/null
+assert_pass "topo initialization"
+
+reload_ruleset()
+{
+       ip netns exec $R conntrack -F 2> /dev/null
+       ip netns exec $R nft -f - <<-EOF
+       flush ruleset
+       table ip6 ftp_helper_nat_test {
+               ct helper ftp-standard {
+                       type "ftp" protocol tcp;
+               }
+
+               chain PRE-dnat {
+                       type nat hook prerouting priority dstnat; policy accept;
+                       # Dnat the control connection, data connection will be automaticly NATed.
+                       ip6 daddr ${ip_rc} counter ip6 nexthdr tcp tcp dport 2121 counter dnat ip6 to [${ip_sr}]:21
+               }
+
+               chain PRE-aftnat {
+                       type filter hook prerouting priority 350; policy drop;
+                       iifname r_c tcp dport 21 ct state new ct helper set "ftp-standard" counter accept
+
+                       ip6 nexthdr tcp ct state related counter accept
+                       ip6 nexthdr tcp ct state established counter accept
+
+                       ip6 nexthdr icmpv6 counter accept
+
+                       counter log
+               }
+
+               chain forward {
+                       type filter hook forward priority filter; policy drop;
+                       ip6 daddr ${ip_sr} counter tcp dport 21 ct state new counter accept
+                       ip6 nexthdr tcp ct state established counter accept
+                       ip6 nexthdr tcp ct state related     counter log accept
+               }
+
+               chain POST-srcnat {
+                       type nat hook postrouting priority srcnat; policy accept;
+                       ip6 daddr ${ip_sr} ip6 nexthdr tcp tcp dport 21 counter snat ip6 to [${ip_rs}]:16500
+               }
+       }
+       EOF
+       assert_pass "apply ftp helper ruleset"
+}
+
+dd if=/dev/urandom of="$INFILE" bs=4096 count=1 2>/dev/null
+chmod 755 $INFILE
+assert_pass "Prepare the file for FTP transmission"
+
+cat > ${FTPCONF} <<-EOF
+anonymous_enable=YES
+anon_root=${WORKDIR}
+local_enable=YES
+connect_from_port_20=YES
+listen=NO
+listen_ipv6=YES
+pam_service_name=vsftpd
+background=YES
+EOF
+ip netns exec $S vsftpd ${FTPCONF}
+sleep 1
+ip netns exec $S ss -6ltnp | grep -q '*:21'
+assert_pass "start vsftpd server"
+
+
+# test passive mode
+reload_ruleset
+ip netns exec $S tcpdump -q --immediate-mode -Ui s_r -w ${PCAP} 2> /dev/null &
+pid=$!
+sleep 1
+ip netns exec $C curl --no-progress-meter --connect-timeout 5 ftp://[${ip_rc}]:2121/$(basename $INFILE) -o $OUTFILE
+assert_pass "curl ftp passive mode "
+
+cmp "$INFILE" "$OUTFILE"
+assert_pass "FTP Passive mode: The input and output files remain the same when traffic passes through NAT."
+
+kill $pid; sync
+tcpdump -nnr ${PCAP} src ${ip_rs} and dst ${ip_sr} 2>&1 |grep -q FTP
+assert_pass "assert FTP traffic NATed"
+
+
+# test active mode
+reload_ruleset
+
+ip netns exec $S tcpdump -q --immediate-mode -Ui s_r -w ${PCAP} 2> /dev/null &
+pid=$!
+ip netns exec $C curl --no-progress-meter -P - --connect-timeout 5 ftp://[${ip_rc}]:2121/$(basename $INFILE) -o $OUTFILE
+assert_pass "curl ftp active mode "
+
+cmp "$INFILE" "$OUTFILE"
+assert_pass "FTP Active mode: in and output files remain the same when FTP traffic passes through NAT."
+
+kill $pid; sync
+tcpdump -nnr ${PCAP} src ${ip_rs} and dst ${ip_sr} 2>&1 |grep -q FTP
+assert_pass "assert FTP traffic NATed"
+
+# trap calls cleanup
+exit 0
diff --git a/tests/shell/testcases/packetpath/payload b/tests/shell/testcases/packetpath/payload
new file mode 100755 (executable)
index 0000000..1e6b5a5
--- /dev/null
@@ -0,0 +1,252 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netdev_egress)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_socat)
+
+rnd=$(mktemp -u XXXXXXXX)
+ns1="nft1payload-$rnd"
+ns2="nft2payload-$rnd"
+
+cleanup()
+{
+       ip netns del "$ns1"
+       ip netns del "$ns2"
+}
+
+trap cleanup EXIT
+
+run_test()
+{
+       ns1_addr=$2
+       ns2_addr=$3
+       cidr=$4
+       mode=$5
+
+       case $mode in
+       "udp")
+               l4proto="udp"
+               udp_checksum="udp checksum != 0"
+               udp_zero_checksum=""
+               ;;
+       "udp-zero-checksum")
+               l4proto="udp"
+               udp_checksum="udp checksum 0"
+               udp_zero_checksum="udp checksum set 0"
+               ;;
+       "tcp")
+               l4proto="tcp"
+               udp_checksum=""
+               udp_zero_checksum=""
+               ;;
+       *)
+               echo "unexpected, incorrect mode"
+               exit 0
+       esac
+
+       # socat needs square brackets, ie. [abcd::2]
+       if [ $1 -eq 6 ]; then
+               nsx1_addr="["$ns1_addr"]"
+               nsx2_addr="["$ns2_addr"]"
+       else
+               nsx1_addr="$ns1_addr"
+               nsx2_addr="$ns2_addr"
+       fi
+
+       ip netns add "$ns1" || exit 111
+       ip netns add "$ns2" || exit 111
+
+       ip -net "$ns1" link set lo up
+       ip -net "$ns2" link set lo up
+
+       ip link add veth0 netns $ns1 type veth peer name veth0 netns $ns2
+
+       ip -net "$ns1" link set veth0 up
+       ip -net "$ns2" link set veth0 up
+       ip -net "$ns1" addr add $ns1_addr/$cidr dev veth0
+       ip -net "$ns2" addr add $ns2_addr/$cidr dev veth0
+
+       sleep 3
+
+RULESET="table netdev payload_netdev {
+       counter ingress {}
+       counter egress {}
+       counter mangle_ingress {}
+       counter mangle_egress {}
+       counter mangle_ingress_match {}
+       counter mangle_egress_match {}
+
+       chain ingress {
+               type filter hook ingress device veth0 priority 0;
+               $udp_zero_checksum
+               $l4proto dport 7777 counter name ingress
+               $l4proto dport 7778 $l4proto dport set 7779 $udp_checksum counter name mangle_ingress
+               $l4proto dport 7779 counter name mangle_ingress_match
+       }
+
+       chain egress {
+               type filter hook egress device veth0 priority 0;
+               $udp_zero_checksum
+               $l4proto dport 8887 counter name egress
+               $l4proto dport 8888 $l4proto dport set 8889 $udp_checksum counter name mangle_egress
+               $l4proto dport 8889 counter name mangle_egress_match
+       }
+}
+
+table inet payload_inet {
+       counter input {}
+       counter output {}
+       counter mangle_input {}
+       counter mangle_output {}
+       counter mangle_input_match {}
+       counter mangle_output_match {}
+
+       chain in {
+               type filter hook input priority 0;
+               $udp_zero_checksum
+               $l4proto dport 7770 counter name input
+               $l4proto dport 7771 $l4proto dport set 7772 $udp_checksum counter name mangle_input
+               $l4proto dport 7772 counter name mangle_input_match
+       }
+
+       chain out {
+               type filter hook output priority 0;
+               $udp_zero_checksum
+               $l4proto dport 8880 counter name output
+               $l4proto dport 8881 $l4proto dport set 8882 $udp_checksum counter name mangle_output
+               $l4proto dport 8882 counter name mangle_output_match
+        }
+}"
+
+       ip netns exec "$ns1" $NFT -f - <<< "$RULESET" || exit 1
+
+       case $l4proto in
+       "tcp")
+               ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8887,connect-timeout=4 < /dev/null > /dev/null
+               ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8888,connect-timeout=4 < /dev/null > /dev/null
+
+               ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8880,connect-timeout=4 < /dev/null > /dev/null
+               ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8881,connect-timeout=4 < /dev/null > /dev/null
+
+               ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7777,connect-timeout=4 < /dev/null > /dev/null
+               ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7778,connect-timeout=4 < /dev/null > /dev/null
+
+               ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7770,connect-timeout=4 < /dev/null > /dev/null
+               ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7771,connect-timeout=4 < /dev/null > /dev/null
+               ;;
+       "udp")
+               ip netns exec "$ns1" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx2_addr:8887 > /dev/null"
+               ip netns exec "$ns1" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx2_addr:8888 > /dev/null"
+
+               ip netns exec "$ns1" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx2_addr:8880 > /dev/null"
+               ip netns exec "$ns1" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx2_addr:8881 > /dev/null"
+
+               ip netns exec "$ns2" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx1_addr:7777 > /dev/null"
+               ip netns exec "$ns2" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx1_addr:7778 > /dev/null"
+
+               ip netns exec "$ns2" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx1_addr:7770 > /dev/null"
+               ip netns exec "$ns2" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx1_addr:7771 > /dev/null"
+               ;;
+       esac
+
+       ip netns exec "$ns1" $NFT list ruleset
+
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev ingress | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev mangle_ingress | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev mangle_ingress_match | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev egress | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev mangle_egress | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter netdev payload_netdev mangle_egress_match | grep -q "packets 0" && exit 1
+
+       ip netns exec "$ns1" $NFT list counter inet payload_inet input | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter inet payload_inet mangle_input | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter inet payload_inet mangle_input_match | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter inet payload_inet output | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter inet payload_inet mangle_output | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter inet payload_inet mangle_output_match | grep -q "packets 0" && exit 1
+
+       #
+       # ... next stage
+       #
+
+       ip netns exec "$ns1" $NFT flush ruleset
+
+       #
+       # bridge
+       #
+
+       ip -net "$ns1" addr del $ns1_addr/$cidr dev veth0
+
+       ip -net "$ns1" link add name br0 type bridge
+       ip -net "$ns1" link set veth0 master br0
+       ip -net "$ns1" addr add $ns1_addr/$cidr dev br0
+       ip -net "$ns1" link set up dev br0
+
+       sleep 3
+
+RULESET="table bridge payload_bridge {
+       counter input {}
+       counter output {}
+       counter mangle_input {}
+       counter mangle_output {}
+       counter mangle_input_match {}
+       counter mangle_output_match {}
+
+       chain in {
+               type filter hook input priority 0;
+               $udp_zero_checksum
+               $l4proto dport 7770 counter name input
+               $l4proto dport 7771 $l4proto dport set 7772 $udp_checksum counter name mangle_input
+               $l4proto dport 7772 counter name mangle_input_match
+       }
+
+       chain out {
+               type filter hook output priority 0;
+               $udp_zero_checksum
+               $l4proto dport 8880 counter name output
+               $l4proto dport 8881 $l4proto dport set 8882 $udp_checksum counter name mangle_output
+               $l4proto dport 8882 counter name mangle_output_match
+        }
+}"
+
+       ip netns exec "$ns1" $NFT -f - <<< "$RULESET" || exit 1
+
+       case $l4proto in
+       "tcp")
+               ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8880,connect-timeout=4 < /dev/null > /dev/null
+               ip netns exec "$ns1" socat -u STDIN TCP:$nsx2_addr:8881,connect-timeout=4 < /dev/null > /dev/null
+
+               ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7770,connect-timeout=4 < /dev/null > /dev/null
+               ip netns exec "$ns2" socat -u STDIN TCP:$nsx1_addr:7771,connect-timeout=4 < /dev/null > /dev/null
+               ;;
+       "udp")
+               ip netns exec "$ns1" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx2_addr:8880 > /dev/null"
+               ip netns exec "$ns1" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx2_addr:8881 > /dev/null"
+
+               ip netns exec "$ns2" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx1_addr:7770 > /dev/null"
+               ip netns exec "$ns2" bash -c "echo 'AA' | socat -u STDIN UDP:$nsx1_addr:7771 > /dev/null"
+               ;;
+       esac
+
+       ip netns exec "$ns1" $NFT list ruleset
+
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge input | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge mangle_input | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge mangle_input_match | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge output | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge mangle_output | grep -q "packets 0" && exit 1
+       ip netns exec "$ns1" $NFT list counter bridge payload_bridge mangle_output_match | grep -q "packets 0" && exit 1
+}
+
+run_test "4" "10.141.10.2" "10.141.10.3" "24" "tcp"
+cleanup
+run_test 6 "abcd::2" "abcd::3" "64" "tcp"
+cleanup
+run_test "4" "10.141.10.2" "10.141.10.3" "24" "udp"
+cleanup
+run_test 6 "abcd::2" "abcd::3" "64" "udp"
+cleanup
+run_test "4" "10.141.10.2" "10.141.10.3" "24" "udp-zero-checksum"
+cleanup
+run_test 6 "abcd::2" "abcd::3" "64" "udp-zero-checksum"
+# trap calls cleanup
+exit 0
diff --git a/tests/shell/testcases/packetpath/policy b/tests/shell/testcases/packetpath/policy
new file mode 100755 (executable)
index 0000000..0bb42a5
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+ip link set lo up
+
+$NFT -f - <<EOF
+table inet filter {
+ chain underflow { }
+
+  chain input {
+    type filter hook input priority filter; policy accept;
+    icmp type echo-reply accept
+    ip saddr 127.0.0.1 ip daddr 127.0.0.2 counter accept
+    goto underflow
+    }
+}
+EOF
+[ $? -ne 0 ] && exit 1
+
+ping -q -c 1 127.0.0.2 >/dev/null || exit 2
+
+# should work, polict is accept.
+ping -q -c 1 127.0.0.1 >/dev/null || exit 1
+
+$NFT -f - <<EOF
+table inet filter {
+  chain input {
+    type filter hook input priority filter; policy drop;
+  }
+}
+EOF
+[ $? -ne 0 ] && exit 1
+
+$NFT list ruleset
+
+ping -W 1 -q -c 1 127.0.0.2
+
+ping -q -c 1 127.0.0.2 >/dev/null || exit 2
+
+# should fail, policy is set to drop
+ping -W 1 -q -c 1 127.0.0.1 >/dev/null 2>&1 && exit 1
+
+exit 0
diff --git a/tests/shell/testcases/packetpath/set_lookups b/tests/shell/testcases/packetpath/set_lookups
new file mode 100755 (executable)
index 0000000..8515985
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
+set -e
+
+$NFT -f /dev/stdin <<"EOF"
+table ip t {
+       set s {
+               type ipv4_addr . iface_index
+               flags interval
+               elements = { 127.0.0.1 . 1 }
+       }
+
+       set s2 {
+               typeof ip saddr . meta iif
+               elements = { 127.0.0.1 . 1 }
+       }
+
+       set s3 {
+               type iface_index
+               elements = { "lo" }
+       }
+
+       set s4 {
+               type iface_index
+               flags interval
+               elements = { "lo" }
+       }
+
+       set nomatch {
+               typeof ip saddr . meta iif
+               elements = { 127.0.0.3 . 1 }
+       }
+
+       set nomatch2 {
+               type ipv4_addr . iface_index
+               elements = { 127.0.0.2 . 90000 }
+       }
+
+       chain c {
+               type filter hook input priority filter;
+               icmp type echo-request ip saddr . meta iif @s counter
+               icmp type echo-request ip saddr . 1 @s counter
+               icmp type echo-request ip saddr . "lo" @s counter
+               icmp type echo-request ip saddr . meta iif @s2 counter
+               icmp type echo-request ip saddr . 1 @s2 counter
+               icmp type echo-request ip saddr . "lo" @s2 counter
+
+               icmp type echo-request ip daddr . "lo" @s counter
+               icmp type echo-request ip daddr . "lo" @s2 counter
+
+               icmp type echo-request meta iif @s3 counter
+               icmp type echo-request meta iif @s4 counter
+
+               ip daddr . 1 @nomatch counter drop
+               ip daddr . meta iif @nomatch2 counter drop
+       }
+}
+EOF
+
+$NFT add element t s { 127.0.0.2 . 1 }
+$NFT add element t s2 { 127.0.0.2 . "lo" }
+
+ip link set lo up
+ping -q -c 1 127.0.0.2 > /dev/null
index 88552226ee3ad6d749f7fec4c28a32e41843af7a..88c095ff66dec5db74bde83c79c1cc8f250ea760 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 
-have_socat="no"
-socat -h > /dev/null && have_socat="yes"
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_reset_tcp_options)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_socat)
 
 ip link set lo up
 
@@ -31,11 +31,6 @@ if [ $? -ne 0 ]; then
        exit 1
 fi
 
-if [ $have_socat != "yes" ]; then
-       echo "Ran partial test, socat not available (skipped)"
-       exit 77
-fi
-
 # This will fail (drop in output -> connect fails with eperm)
 socat -u STDIN TCP:127.0.0.1:22345,connect-timeout=1 < /dev/null > /dev/null
 
diff --git a/tests/shell/testcases/packetpath/tcp_reset b/tests/shell/testcases/packetpath/tcp_reset
new file mode 100755 (executable)
index 0000000..559260a
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_socat)
+
+# regression check for kernel commit
+# netfilter: nf_reject: init skb->dev for reset packet
+
+ip link set lo up
+
+$NFT -f - <<EOF
+table inet filter {
+  chain input {
+    type filter hook input priority filter; policy accept;
+    meta nftrace set 1
+    ip daddr 127.0.0.1 tcp dport 5555 reject with tcp reset
+    ip6 daddr ::1 tcp dport 5555 reject with tcp reset
+    tcp dport 5555 counter
+   }
+   chain output {
+    type filter hook output priority filter; policy accept;
+    # empty chain, so nf_hook_slow is called from ip_local_out.
+   }
+}
+EOF
+[ $? -ne 0 ] && exit 1
+
+socat -u STDIN TCP:127.0.0.1:5555,connect-timeout=2 < /dev/null > /dev/null
+socat -u STDIN TCP:[::1]:5555,connect-timeout=2 < /dev/null > /dev/null
+
+$NFT list ruleset |grep -q 'counter packets 0 bytes 0' || exit 1
+exit 0
diff --git a/tests/shell/testcases/packetpath/vlan_8021ad_tag b/tests/shell/testcases/packetpath/vlan_8021ad_tag
new file mode 100755 (executable)
index 0000000..379a571
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+rnd=$(mktemp -u XXXXXXXX)
+ns1="nft1ifname-$rnd"
+ns2="nft2ifname-$rnd"
+
+cleanup()
+{
+       ip netns del "$ns1"
+       ip netns del "$ns2"
+}
+
+trap cleanup EXIT
+
+set -e
+
+ip netns add "$ns1"
+ip netns add "$ns2"
+ip -net "$ns1" link set lo up
+ip -net "$ns2" link set lo up
+
+ip link add veth0 netns $ns1 type veth peer name veth0 netns $ns2
+
+ip -net "$ns1" link set veth0 addr da:d3:00:01:02:03
+
+ip -net "$ns1" link add vlan123 link veth0 type vlan id 123 proto 802.1ad
+ip -net "$ns2" link add vlan123 link veth0 type vlan id 123 proto 802.1ad
+
+
+for dev in veth0 vlan123; do
+       ip -net "$ns1" link set $dev up
+       ip -net "$ns2" link set $dev up
+done
+
+ip -net "$ns1" addr add 10.1.1.1/24 dev vlan123
+ip -net "$ns2" addr add 10.1.1.2/24 dev vlan123
+
+ip netns exec "$ns2" $NFT -f /dev/stdin <<"EOF"
+table netdev t {
+       chain c {
+               type filter hook ingress device veth0 priority filter;
+               ether saddr da:d3:00:01:02:03 ether type 8021ad vlan id 123 ip daddr 10.1.1.2 icmp type echo-request counter
+       }
+}
+EOF
+
+ip netns exec "$ns1" ping -c 1 10.1.1.2
+
+ip netns exec "$ns2" $NFT list ruleset
+ip netns exec "$ns2" $NFT list chain netdev t c | grep 'counter packets 1 bytes 84'
diff --git a/tests/shell/testcases/packetpath/vlan_mangling b/tests/shell/testcases/packetpath/vlan_mangling
new file mode 100755 (executable)
index 0000000..3fc2ebb
--- /dev/null
@@ -0,0 +1,79 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netdev_egress)
+
+rnd=$(mktemp -u XXXXXXXX)
+ns1="nft1ifname-$rnd"
+ns2="nft2ifname-$rnd"
+
+cleanup()
+{
+       ip netns del "$ns1"
+       ip netns del "$ns2"
+}
+
+trap cleanup EXIT
+
+set -e
+
+ip netns add "$ns1"
+ip netns add "$ns2"
+ip -net "$ns1" link set lo up
+ip -net "$ns2" link set lo up
+
+ip link add veth0 netns $ns1 type veth peer name veth0 netns $ns2
+
+ip -net "$ns1" link set veth0 addr da:d3:00:01:02:03
+
+ip -net "$ns1" link add vlan123 link veth0 type vlan id 123
+ip -net "$ns2" link add vlan321 link veth0 type vlan id 321
+
+
+for dev in veth0 ; do
+       ip -net "$ns1" link set $dev up
+       ip -net "$ns2" link set $dev up
+done
+ip -net "$ns1" link set vlan123 up
+ip -net "$ns2" link set vlan321 up
+
+ip -net "$ns1" addr add 10.1.1.1/24 dev vlan123
+ip -net "$ns2" addr add 10.1.1.2/24 dev vlan321
+
+ip netns exec "$ns2" $NFT -f /dev/stdin <<"EOF"
+table netdev t {
+       chain in_update_vlan {
+               vlan type arp vlan id set 321 counter
+               ip saddr 10.1.1.1 icmp type echo-request vlan id set 321 counter
+       }
+
+       chain in {
+               type filter hook ingress device veth0 priority filter;
+               vlan pcp 0 counter
+               ether saddr da:d3:00:01:02:03 vlan id 123 jump in_update_vlan
+       }
+
+       chain out_update_vlan {
+               vlan type arp vlan id set 123 counter
+               ip daddr 10.1.1.1 icmp type echo-reply vlan id set 123 counter
+               vlan pcp set 6 counter
+       }
+
+       chain out {
+               type filter hook egress device veth0 priority filter;
+               ether daddr da:d3:00:01:02:03 vlan id 321 jump out_update_vlan
+       }
+}
+EOF
+
+ip netns exec "$ns1" ping -c 1 10.1.1.2
+
+set +e
+
+ip netns exec "$ns2" $NFT list ruleset
+ip netns exec "$ns2" $NFT list table netdev t | grep 'counter packets' | grep 'counter packets 0 bytes 0'
+if [ $? -eq 1 ]
+then
+       exit 0
+fi
+
+exit 1
diff --git a/tests/shell/testcases/packetpath/vlan_qinq b/tests/shell/testcases/packetpath/vlan_qinq
new file mode 100755 (executable)
index 0000000..2865576
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+rnd=$(mktemp -u XXXXXXXX)
+ns1="nft1ifname-$rnd"
+ns2="nft2ifname-$rnd"
+
+cleanup()
+{
+       ip netns del "$ns1"
+       ip netns del "$ns2"
+}
+
+trap cleanup EXIT
+
+set -e
+
+ip netns add "$ns1"
+ip netns add "$ns2"
+ip -net "$ns1" link set lo up
+ip -net "$ns2" link set lo up
+
+ip link add veth0 netns $ns1 type veth peer name veth0 netns $ns2
+
+ip -net "$ns1" link set veth0 addr da:d3:00:01:02:03
+
+ip -net "$ns1" link add link veth0 name vlan10 type vlan proto 802.1ad id 10
+ip -net "$ns1" link add link vlan10 name vlan10.100 type vlan proto 802.1q id 100
+
+ip -net "$ns2" link add link veth0 name vlan10 type vlan proto 802.1ad id 10
+ip -net "$ns2" link add link vlan10 name vlan10.100 type vlan proto 802.1q id 100
+
+for dev in veth0 vlan10 vlan10.100; do
+       ip -net "$ns1" link set $dev up
+       ip -net "$ns2" link set $dev up
+done
+
+ip -net "$ns1" addr add 10.1.1.1/24 dev vlan10.100
+ip -net "$ns2" addr add 10.1.1.2/24 dev vlan10.100
+
+ip netns exec "$ns2" $NFT -f /dev/stdin <<"EOF"
+table netdev t {
+       chain c1 {
+               type filter hook ingress device veth0 priority filter;
+               ether type 8021ad vlan id 10 vlan type 8021q vlan id 100 vlan type ip counter
+       }
+
+       chain c2 {
+               type filter hook ingress device vlan10 priority filter;
+               vlan id 100 ip daddr 10.1.1.2 counter
+       }
+
+       chain c3 {
+               type filter hook ingress device vlan10.100 priority filter;
+               ip daddr 10.1.1.2 counter
+       }
+}
+EOF
+
+ip netns exec "$ns1" ping -c 1 10.1.1.2
+ip netns exec "$ns2" $NFT list ruleset
+
+set +e
+
+ip netns exec "$ns2" $NFT list chain netdev t c1 | grep 'counter packets 0 bytes 0'
+[[ $? -eq 0 ]] && exit 1
+
+ip netns exec "$ns2" $NFT list chain netdev t c2 | grep 'counter packets 0 bytes 0'
+[[ $? -eq 0 ]] && exit 1
+
+ip netns exec "$ns2" $NFT list chain netdev t c3 | grep 'counter packets 0 bytes 0'
+[[ $? -eq 0 ]] && exit 1
+
+exit 0
diff --git a/tests/shell/testcases/parsing/dumps/describe.json-nft b/tests/shell/testcases/parsing/dumps/describe.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/parsing/dumps/describe.nft b/tests/shell/testcases/parsing/dumps/describe.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/parsing/dumps/large_rule_pipe.json-nft b/tests/shell/testcases/parsing/dumps/large_rule_pipe.json-nft
new file mode 100644 (file)
index 0000000..bf5dc65
--- /dev/null
@@ -0,0 +1,4079 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "firewalld",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PREROUTING",
+        "handle": 0,
+        "type": "nat",
+        "hook": "prerouting",
+        "prio": -90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PREROUTING_ZONES_SOURCE",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PREROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING",
+        "handle": 0,
+        "type": "nat",
+        "hook": "postrouting",
+        "prio": 110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING_ZONES_SOURCE",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_home",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_home_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_home_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_home_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_home",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_home_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_home_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_home_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PREROUTING_ZONES_SOURCE"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PREROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "enp0s25"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_PRE_home"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "nat_PRE_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POSTROUTING_ZONES_SOURCE"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POSTROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "enp0s25"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_POST_home"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "nat_POST_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_home_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_home_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_home_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_home_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_home_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_home_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "firewalld",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PREROUTING",
+        "handle": 0,
+        "type": "nat",
+        "hook": "prerouting",
+        "prio": -90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PREROUTING_ZONES_SOURCE",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PREROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING",
+        "handle": 0,
+        "type": "nat",
+        "hook": "postrouting",
+        "prio": 110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING_ZONES_SOURCE",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_home",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_home_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_home_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_home_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_home",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_home_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_home_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_home_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PREROUTING_ZONES_SOURCE"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PREROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "enp0s25"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_PRE_home"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "nat_PRE_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POSTROUTING_ZONES_SOURCE"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POSTROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "enp0s25"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_POST_home"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "nat_POST_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_home_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_home_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_home_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_home_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_home_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_home_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "firewalld",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PREROUTING",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PREROUTING_ZONES_SOURCE",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PREROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PREROUTING",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PREROUTING_ZONES_SOURCE",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PREROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_INPUT",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FORWARD",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_INPUT_ZONES_SOURCE",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_INPUT_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FORWARD_IN_ZONES_SOURCE",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FORWARD_IN_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FORWARD_OUT_ZONES_SOURCE",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FORWARD_OUT_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_home",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_home_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_home_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_home_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_home",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_home_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_home_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_home_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_home",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_home_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_home_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_home_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_home",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_home_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_home_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_home_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_home",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_home_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_home_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_home_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmpv6",
+                  "field": "type"
+                }
+              },
+              "right": {
+                "set": [
+                  "nd-router-advert",
+                  "nd-neighbor-solicit"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "nfproto"
+                }
+              },
+              "right": "ipv6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "fib": {
+                  "result": "oif",
+                  "flags": [
+                    "saddr",
+                    "iif"
+                  ]
+                }
+              },
+              "right": false
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PREROUTING_ZONES_SOURCE"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PREROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "enp0s25"
+            }
+          },
+          {
+            "goto": {
+              "target": "raw_PRE_home"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "raw_PRE_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PREROUTING_ZONES_SOURCE"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PREROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "enp0s25"
+            }
+          },
+          {
+            "goto": {
+              "target": "mangle_PRE_home"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "mangle_PRE_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "established",
+                "related"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_INPUT_ZONES_SOURCE"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_INPUT_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "invalid"
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "reject": {
+              "type": "icmpx",
+              "expr": "admin-prohibited"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "established",
+                "related"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FORWARD_IN_ZONES_SOURCE"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FORWARD_IN_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FORWARD_OUT_ZONES_SOURCE"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FORWARD_OUT_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "invalid"
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "reject": {
+              "type": "icmpx",
+              "expr": "admin-prohibited"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "enp0s25"
+            }
+          },
+          {
+            "goto": {
+              "target": "filter_IN_home"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "filter_IN_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_IN_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "enp0s25"
+            }
+          },
+          {
+            "goto": {
+              "target": "filter_FWDI_home"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_IN_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "filter_FWDI_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_OUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "enp0s25"
+            }
+          },
+          {
+            "goto": {
+              "target": "filter_FWDO_home"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_OUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "filter_FWDO_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "prefix": {
+                  "addr": "fe80::",
+                  "len": 64
+                }
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 546
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_home_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_home_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_home_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 137
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "ct": {
+                  "key": "helper"
+                }
+              },
+              "right": "netbios-ns"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_home_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_home_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_home_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "224.0.0.251"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 5353
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": "ff02::fb"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 5353
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "range": [
+                  1714,
+                  1764
+                ]
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "range": [
+                  1714,
+                  1764
+                ]
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "prefix": {
+                  "addr": "fe80::",
+                  "len": 64
+                }
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 546
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 137
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 138
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 139
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_home_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 445
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_home_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_home_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_home_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_home",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_home_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_home_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_home_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_home_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_home_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_home",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_home_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "prefix": {
+                  "addr": "fe80::",
+                  "len": 64
+                }
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 546
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "new",
+                "untracked"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_work_allow"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/parsing/dumps/large_rule_pipe.nft b/tests/shell/testcases/parsing/dumps/large_rule_pipe.nft
new file mode 100644 (file)
index 0000000..1583275
--- /dev/null
@@ -0,0 +1,561 @@
+table ip firewalld {
+       chain nat_PREROUTING {
+               type nat hook prerouting priority dstnat + 10; policy accept;
+               jump nat_PREROUTING_ZONES_SOURCE
+               jump nat_PREROUTING_ZONES
+       }
+
+       chain nat_PREROUTING_ZONES_SOURCE {
+       }
+
+       chain nat_PREROUTING_ZONES {
+               iifname "enp0s25" goto nat_PRE_home
+               goto nat_PRE_public
+       }
+
+       chain nat_POSTROUTING {
+               type nat hook postrouting priority srcnat + 10; policy accept;
+               jump nat_POSTROUTING_ZONES_SOURCE
+               jump nat_POSTROUTING_ZONES
+       }
+
+       chain nat_POSTROUTING_ZONES_SOURCE {
+       }
+
+       chain nat_POSTROUTING_ZONES {
+               oifname "enp0s25" goto nat_POST_home
+               goto nat_POST_public
+       }
+
+       chain nat_PRE_public {
+               jump nat_PRE_public_log
+               jump nat_PRE_public_deny
+               jump nat_PRE_public_allow
+       }
+
+       chain nat_PRE_public_log {
+       }
+
+       chain nat_PRE_public_deny {
+       }
+
+       chain nat_PRE_public_allow {
+       }
+
+       chain nat_POST_public {
+               jump nat_POST_public_log
+               jump nat_POST_public_deny
+               jump nat_POST_public_allow
+       }
+
+       chain nat_POST_public_log {
+       }
+
+       chain nat_POST_public_deny {
+       }
+
+       chain nat_POST_public_allow {
+       }
+
+       chain nat_PRE_home {
+               jump nat_PRE_home_log
+               jump nat_PRE_home_deny
+               jump nat_PRE_home_allow
+       }
+
+       chain nat_PRE_home_log {
+       }
+
+       chain nat_PRE_home_deny {
+       }
+
+       chain nat_PRE_home_allow {
+       }
+
+       chain nat_POST_home {
+               jump nat_POST_home_log
+               jump nat_POST_home_deny
+               jump nat_POST_home_allow
+       }
+
+       chain nat_POST_home_log {
+       }
+
+       chain nat_POST_home_deny {
+       }
+
+       chain nat_POST_home_allow {
+       }
+
+       chain nat_PRE_work {
+               jump nat_PRE_work_log
+               jump nat_PRE_work_deny
+               jump nat_PRE_work_allow
+       }
+
+       chain nat_PRE_work_log {
+       }
+
+       chain nat_PRE_work_deny {
+       }
+
+       chain nat_PRE_work_allow {
+       }
+
+       chain nat_POST_work {
+               jump nat_POST_work_log
+               jump nat_POST_work_deny
+               jump nat_POST_work_allow
+       }
+
+       chain nat_POST_work_log {
+       }
+
+       chain nat_POST_work_deny {
+       }
+
+       chain nat_POST_work_allow {
+       }
+}
+table ip6 firewalld {
+       chain nat_PREROUTING {
+               type nat hook prerouting priority dstnat + 10; policy accept;
+               jump nat_PREROUTING_ZONES_SOURCE
+               jump nat_PREROUTING_ZONES
+       }
+
+       chain nat_PREROUTING_ZONES_SOURCE {
+       }
+
+       chain nat_PREROUTING_ZONES {
+               iifname "enp0s25" goto nat_PRE_home
+               goto nat_PRE_public
+       }
+
+       chain nat_POSTROUTING {
+               type nat hook postrouting priority srcnat + 10; policy accept;
+               jump nat_POSTROUTING_ZONES_SOURCE
+               jump nat_POSTROUTING_ZONES
+       }
+
+       chain nat_POSTROUTING_ZONES_SOURCE {
+       }
+
+       chain nat_POSTROUTING_ZONES {
+               oifname "enp0s25" goto nat_POST_home
+               goto nat_POST_public
+       }
+
+       chain nat_PRE_public {
+               jump nat_PRE_public_log
+               jump nat_PRE_public_deny
+               jump nat_PRE_public_allow
+       }
+
+       chain nat_PRE_public_log {
+       }
+
+       chain nat_PRE_public_deny {
+       }
+
+       chain nat_PRE_public_allow {
+       }
+
+       chain nat_POST_public {
+               jump nat_POST_public_log
+               jump nat_POST_public_deny
+               jump nat_POST_public_allow
+       }
+
+       chain nat_POST_public_log {
+       }
+
+       chain nat_POST_public_deny {
+       }
+
+       chain nat_POST_public_allow {
+       }
+
+       chain nat_PRE_home {
+               jump nat_PRE_home_log
+               jump nat_PRE_home_deny
+               jump nat_PRE_home_allow
+       }
+
+       chain nat_PRE_home_log {
+       }
+
+       chain nat_PRE_home_deny {
+       }
+
+       chain nat_PRE_home_allow {
+       }
+
+       chain nat_POST_home {
+               jump nat_POST_home_log
+               jump nat_POST_home_deny
+               jump nat_POST_home_allow
+       }
+
+       chain nat_POST_home_log {
+       }
+
+       chain nat_POST_home_deny {
+       }
+
+       chain nat_POST_home_allow {
+       }
+
+       chain nat_PRE_work {
+               jump nat_PRE_work_log
+               jump nat_PRE_work_deny
+               jump nat_PRE_work_allow
+       }
+
+       chain nat_PRE_work_log {
+       }
+
+       chain nat_PRE_work_deny {
+       }
+
+       chain nat_PRE_work_allow {
+       }
+
+       chain nat_POST_work {
+               jump nat_POST_work_log
+               jump nat_POST_work_deny
+               jump nat_POST_work_allow
+       }
+
+       chain nat_POST_work_log {
+       }
+
+       chain nat_POST_work_deny {
+       }
+
+       chain nat_POST_work_allow {
+       }
+}
+table inet firewalld {
+       chain raw_PREROUTING {
+               type filter hook prerouting priority raw + 10; policy accept;
+               icmpv6 type { nd-router-advert, nd-neighbor-solicit } accept
+               meta nfproto ipv6 fib saddr . iif oif missing drop
+               jump raw_PREROUTING_ZONES_SOURCE
+               jump raw_PREROUTING_ZONES
+       }
+
+       chain raw_PREROUTING_ZONES_SOURCE {
+       }
+
+       chain raw_PREROUTING_ZONES {
+               iifname "enp0s25" goto raw_PRE_home
+               goto raw_PRE_public
+       }
+
+       chain mangle_PREROUTING {
+               type filter hook prerouting priority mangle + 10; policy accept;
+               jump mangle_PREROUTING_ZONES_SOURCE
+               jump mangle_PREROUTING_ZONES
+       }
+
+       chain mangle_PREROUTING_ZONES_SOURCE {
+       }
+
+       chain mangle_PREROUTING_ZONES {
+               iifname "enp0s25" goto mangle_PRE_home
+               goto mangle_PRE_public
+       }
+
+       chain filter_INPUT {
+               type filter hook input priority filter + 10; policy accept;
+               ct state established,related accept
+               iifname "lo" accept
+               jump filter_INPUT_ZONES_SOURCE
+               jump filter_INPUT_ZONES
+               ct state invalid drop
+               reject with icmpx admin-prohibited
+       }
+
+       chain filter_FORWARD {
+               type filter hook forward priority filter + 10; policy accept;
+               ct state established,related accept
+               iifname "lo" accept
+               jump filter_FORWARD_IN_ZONES_SOURCE
+               jump filter_FORWARD_IN_ZONES
+               jump filter_FORWARD_OUT_ZONES_SOURCE
+               jump filter_FORWARD_OUT_ZONES
+               ct state invalid drop
+               reject with icmpx admin-prohibited
+       }
+
+       chain filter_INPUT_ZONES_SOURCE {
+       }
+
+       chain filter_INPUT_ZONES {
+               iifname "enp0s25" goto filter_IN_home
+               goto filter_IN_public
+       }
+
+       chain filter_FORWARD_IN_ZONES_SOURCE {
+       }
+
+       chain filter_FORWARD_IN_ZONES {
+               iifname "enp0s25" goto filter_FWDI_home
+               goto filter_FWDI_public
+       }
+
+       chain filter_FORWARD_OUT_ZONES_SOURCE {
+       }
+
+       chain filter_FORWARD_OUT_ZONES {
+               oifname "enp0s25" goto filter_FWDO_home
+               goto filter_FWDO_public
+       }
+
+       chain raw_PRE_public {
+               jump raw_PRE_public_log
+               jump raw_PRE_public_deny
+               jump raw_PRE_public_allow
+       }
+
+       chain raw_PRE_public_log {
+       }
+
+       chain raw_PRE_public_deny {
+       }
+
+       chain raw_PRE_public_allow {
+       }
+
+       chain filter_IN_public {
+               jump filter_IN_public_log
+               jump filter_IN_public_deny
+               jump filter_IN_public_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_IN_public_log {
+       }
+
+       chain filter_IN_public_deny {
+       }
+
+       chain filter_IN_public_allow {
+               tcp dport 22 ct state new,untracked accept
+               ip6 daddr fe80::/64 udp dport 546 ct state new,untracked accept
+       }
+
+       chain filter_FWDI_public {
+               jump filter_FWDI_public_log
+               jump filter_FWDI_public_deny
+               jump filter_FWDI_public_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_FWDI_public_log {
+       }
+
+       chain filter_FWDI_public_deny {
+       }
+
+       chain filter_FWDI_public_allow {
+       }
+
+       chain mangle_PRE_public {
+               jump mangle_PRE_public_log
+               jump mangle_PRE_public_deny
+               jump mangle_PRE_public_allow
+       }
+
+       chain mangle_PRE_public_log {
+       }
+
+       chain mangle_PRE_public_deny {
+       }
+
+       chain mangle_PRE_public_allow {
+       }
+
+       chain filter_FWDO_public {
+               jump filter_FWDO_public_log
+               jump filter_FWDO_public_deny
+               jump filter_FWDO_public_allow
+       }
+
+       chain filter_FWDO_public_log {
+       }
+
+       chain filter_FWDO_public_deny {
+       }
+
+       chain filter_FWDO_public_allow {
+       }
+
+       chain raw_PRE_home {
+               jump raw_PRE_home_log
+               jump raw_PRE_home_deny
+               jump raw_PRE_home_allow
+       }
+
+       chain raw_PRE_home_log {
+       }
+
+       chain raw_PRE_home_deny {
+       }
+
+       chain raw_PRE_home_allow {
+               udp dport 137 ct helper "netbios-ns"
+       }
+
+       chain filter_IN_home {
+               jump filter_IN_home_log
+               jump filter_IN_home_deny
+               jump filter_IN_home_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_IN_home_log {
+       }
+
+       chain filter_IN_home_deny {
+       }
+
+       chain filter_IN_home_allow {
+               tcp dport 22 ct state new,untracked accept
+               ip daddr 224.0.0.251 udp dport 5353 ct state new,untracked accept
+               ip6 daddr ff02::fb udp dport 5353 ct state new,untracked accept
+               udp dport 1714-1764 ct state new,untracked accept
+               tcp dport 1714-1764 ct state new,untracked accept
+               ip6 daddr fe80::/64 udp dport 546 ct state new,untracked accept
+               udp dport 137 ct state new,untracked accept
+               udp dport 138 ct state new,untracked accept
+               tcp dport 139 ct state new,untracked accept
+               tcp dport 445 ct state new,untracked accept
+       }
+
+       chain filter_FWDI_home {
+               jump filter_FWDI_home_log
+               jump filter_FWDI_home_deny
+               jump filter_FWDI_home_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_FWDI_home_log {
+       }
+
+       chain filter_FWDI_home_deny {
+       }
+
+       chain filter_FWDI_home_allow {
+       }
+
+       chain mangle_PRE_home {
+               jump mangle_PRE_home_log
+               jump mangle_PRE_home_deny
+               jump mangle_PRE_home_allow
+       }
+
+       chain mangle_PRE_home_log {
+       }
+
+       chain mangle_PRE_home_deny {
+       }
+
+       chain mangle_PRE_home_allow {
+       }
+
+       chain filter_FWDO_home {
+               jump filter_FWDO_home_log
+               jump filter_FWDO_home_deny
+               jump filter_FWDO_home_allow
+       }
+
+       chain filter_FWDO_home_log {
+       }
+
+       chain filter_FWDO_home_deny {
+       }
+
+       chain filter_FWDO_home_allow {
+       }
+
+       chain raw_PRE_work {
+               jump raw_PRE_work_log
+               jump raw_PRE_work_deny
+               jump raw_PRE_work_allow
+       }
+
+       chain raw_PRE_work_log {
+       }
+
+       chain raw_PRE_work_deny {
+       }
+
+       chain raw_PRE_work_allow {
+       }
+
+       chain filter_IN_work {
+               jump filter_IN_work_log
+               jump filter_IN_work_deny
+               jump filter_IN_work_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_IN_work_log {
+       }
+
+       chain filter_IN_work_deny {
+       }
+
+       chain filter_IN_work_allow {
+               tcp dport 22 ct state new,untracked accept
+               ip6 daddr fe80::/64 udp dport 546 ct state new,untracked accept
+       }
+
+       chain filter_FWDI_work {
+               jump filter_FWDI_work_log
+               jump filter_FWDI_work_deny
+               jump filter_FWDI_work_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_FWDI_work_log {
+       }
+
+       chain filter_FWDI_work_deny {
+       }
+
+       chain filter_FWDI_work_allow {
+       }
+
+       chain mangle_PRE_work {
+               jump mangle_PRE_work_log
+               jump mangle_PRE_work_deny
+               jump mangle_PRE_work_allow
+       }
+
+       chain mangle_PRE_work_log {
+       }
+
+       chain mangle_PRE_work_deny {
+       }
+
+       chain mangle_PRE_work_allow {
+       }
+
+       chain filter_FWDO_work {
+               jump filter_FWDO_work_log
+               jump filter_FWDO_work_deny
+               jump filter_FWDO_work_allow
+       }
+
+       chain filter_FWDO_work_log {
+       }
+
+       chain filter_FWDO_work_deny {
+       }
+
+       chain filter_FWDO_work_allow {
+       }
+}
diff --git a/tests/shell/testcases/parsing/dumps/log.json-nft b/tests/shell/testcases/parsing/dumps/log.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/parsing/dumps/log.nft b/tests/shell/testcases/parsing/dumps/log.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/parsing/dumps/octal.json-nft b/tests/shell/testcases/parsing/dumps/octal.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/parsing/dumps/octal.nft b/tests/shell/testcases/parsing/dumps/octal.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/parsing/large_rule_pipe b/tests/shell/testcases/parsing/large_rule_pipe
new file mode 100755 (executable)
index 0000000..b6760c0
--- /dev/null
@@ -0,0 +1,571 @@
+#!/bin/bash
+
+set -e
+
+RULESET="#!/sbin/nft -f
+flush ruleset;
+table ip firewalld {
+       chain nat_PREROUTING {
+               type nat hook prerouting priority -90; policy accept;
+               jump nat_PREROUTING_ZONES_SOURCE
+               jump nat_PREROUTING_ZONES
+       }
+
+       chain nat_PREROUTING_ZONES_SOURCE {
+       }
+
+       chain nat_PREROUTING_ZONES {
+               iifname "enp0s25" goto nat_PRE_home
+               goto nat_PRE_public
+       }
+
+       chain nat_POSTROUTING {
+               type nat hook postrouting priority 110; policy accept;
+               jump nat_POSTROUTING_ZONES_SOURCE
+               jump nat_POSTROUTING_ZONES
+       }
+
+       chain nat_POSTROUTING_ZONES_SOURCE {
+       }
+
+       chain nat_POSTROUTING_ZONES {
+               oifname "enp0s25" goto nat_POST_home
+               goto nat_POST_public
+       }
+
+       chain nat_PRE_public {
+               jump nat_PRE_public_log
+               jump nat_PRE_public_deny
+               jump nat_PRE_public_allow
+       }
+
+       chain nat_PRE_public_log {
+       }
+
+       chain nat_PRE_public_deny {
+       }
+
+       chain nat_PRE_public_allow {
+       }
+
+       chain nat_POST_public {
+               jump nat_POST_public_log
+               jump nat_POST_public_deny
+               jump nat_POST_public_allow
+       }
+
+       chain nat_POST_public_log {
+       }
+
+       chain nat_POST_public_deny {
+       }
+
+       chain nat_POST_public_allow {
+       }
+
+       chain nat_PRE_home {
+               jump nat_PRE_home_log
+               jump nat_PRE_home_deny
+               jump nat_PRE_home_allow
+       }
+
+       chain nat_PRE_home_log {
+       }
+
+       chain nat_PRE_home_deny {
+       }
+
+       chain nat_PRE_home_allow {
+       }
+
+       chain nat_POST_home {
+               jump nat_POST_home_log
+               jump nat_POST_home_deny
+               jump nat_POST_home_allow
+       }
+
+       chain nat_POST_home_log {
+       }
+
+       chain nat_POST_home_deny {
+       }
+
+       chain nat_POST_home_allow {
+       }
+
+       chain nat_PRE_work {
+               jump nat_PRE_work_log
+               jump nat_PRE_work_deny
+               jump nat_PRE_work_allow
+       }
+
+       chain nat_PRE_work_log {
+       }
+
+       chain nat_PRE_work_deny {
+       }
+
+       chain nat_PRE_work_allow {
+       }
+
+       chain nat_POST_work {
+               jump nat_POST_work_log
+               jump nat_POST_work_deny
+               jump nat_POST_work_allow
+       }
+
+       chain nat_POST_work_log {
+       }
+
+       chain nat_POST_work_deny {
+       }
+
+       chain nat_POST_work_allow {
+       }
+}
+table ip6 firewalld {
+       chain nat_PREROUTING {
+               type nat hook prerouting priority -90; policy accept;
+               jump nat_PREROUTING_ZONES_SOURCE
+               jump nat_PREROUTING_ZONES
+       }
+
+       chain nat_PREROUTING_ZONES_SOURCE {
+       }
+
+       chain nat_PREROUTING_ZONES {
+               iifname "enp0s25" goto nat_PRE_home
+               goto nat_PRE_public
+       }
+
+       chain nat_POSTROUTING {
+               type nat hook postrouting priority 110; policy accept;
+               jump nat_POSTROUTING_ZONES_SOURCE
+               jump nat_POSTROUTING_ZONES
+       }
+
+       chain nat_POSTROUTING_ZONES_SOURCE {
+       }
+
+       chain nat_POSTROUTING_ZONES {
+               oifname "enp0s25" goto nat_POST_home
+               goto nat_POST_public
+       }
+
+       chain nat_PRE_public {
+               jump nat_PRE_public_log
+               jump nat_PRE_public_deny
+               jump nat_PRE_public_allow
+       }
+
+       chain nat_PRE_public_log {
+       }
+
+       chain nat_PRE_public_deny {
+       }
+
+       chain nat_PRE_public_allow {
+       }
+
+       chain nat_POST_public {
+               jump nat_POST_public_log
+               jump nat_POST_public_deny
+               jump nat_POST_public_allow
+       }
+
+       chain nat_POST_public_log {
+       }
+
+       chain nat_POST_public_deny {
+       }
+
+       chain nat_POST_public_allow {
+       }
+
+       chain nat_PRE_home {
+               jump nat_PRE_home_log
+               jump nat_PRE_home_deny
+               jump nat_PRE_home_allow
+       }
+
+       chain nat_PRE_home_log {
+       }
+
+       chain nat_PRE_home_deny {
+       }
+
+       chain nat_PRE_home_allow {
+       }
+
+       chain nat_POST_home {
+               jump nat_POST_home_log
+               jump nat_POST_home_deny
+               jump nat_POST_home_allow
+       }
+
+       chain nat_POST_home_log {
+       }
+
+       chain nat_POST_home_deny {
+       }
+
+       chain nat_POST_home_allow {
+       }
+
+       chain nat_PRE_work {
+               jump nat_PRE_work_log
+               jump nat_PRE_work_deny
+               jump nat_PRE_work_allow
+       }
+
+       chain nat_PRE_work_log {
+       }
+
+       chain nat_PRE_work_deny {
+       }
+
+       chain nat_PRE_work_allow {
+       }
+
+       chain nat_POST_work {
+               jump nat_POST_work_log
+               jump nat_POST_work_deny
+               jump nat_POST_work_allow
+       }
+
+       chain nat_POST_work_log {
+       }
+
+       chain nat_POST_work_deny {
+       }
+
+       chain nat_POST_work_allow {
+       }
+}
+table inet firewalld {
+       chain raw_PREROUTING {
+               type filter hook prerouting priority -290; policy accept;
+               icmpv6 type { nd-router-advert, nd-neighbor-solicit } accept
+               meta nfproto ipv6 fib saddr . iif oif missing drop
+               jump raw_PREROUTING_ZONES_SOURCE
+               jump raw_PREROUTING_ZONES
+       }
+
+       chain raw_PREROUTING_ZONES_SOURCE {
+       }
+
+       chain raw_PREROUTING_ZONES {
+               iifname "enp0s25" goto raw_PRE_home
+               goto raw_PRE_public
+       }
+
+       chain mangle_PREROUTING {
+               type filter hook prerouting priority -140; policy accept;
+               jump mangle_PREROUTING_ZONES_SOURCE
+               jump mangle_PREROUTING_ZONES
+       }
+
+       chain mangle_PREROUTING_ZONES_SOURCE {
+       }
+
+       chain mangle_PREROUTING_ZONES {
+               iifname "enp0s25" goto mangle_PRE_home
+               goto mangle_PRE_public
+       }
+
+       chain filter_INPUT {
+               type filter hook input priority 10; policy accept;
+               ct state established,related accept
+               iifname "lo" accept
+               jump filter_INPUT_ZONES_SOURCE
+               jump filter_INPUT_ZONES
+               ct state invalid drop
+               reject with icmpx type admin-prohibited
+       }
+
+       chain filter_FORWARD {
+               type filter hook forward priority 10; policy accept;
+               ct state established,related accept
+               iifname "lo" accept
+               jump filter_FORWARD_IN_ZONES_SOURCE
+               jump filter_FORWARD_IN_ZONES
+               jump filter_FORWARD_OUT_ZONES_SOURCE
+               jump filter_FORWARD_OUT_ZONES
+               ct state invalid drop
+               reject with icmpx type admin-prohibited
+       }
+
+       chain filter_INPUT_ZONES_SOURCE {
+       }
+
+       chain filter_INPUT_ZONES {
+               iifname "enp0s25" goto filter_IN_home
+               goto filter_IN_public
+       }
+
+       chain filter_FORWARD_IN_ZONES_SOURCE {
+       }
+
+       chain filter_FORWARD_IN_ZONES {
+               iifname "enp0s25" goto filter_FWDI_home
+               goto filter_FWDI_public
+       }
+
+       chain filter_FORWARD_OUT_ZONES_SOURCE {
+       }
+
+       chain filter_FORWARD_OUT_ZONES {
+               oifname "enp0s25" goto filter_FWDO_home
+               goto filter_FWDO_public
+       }
+
+       chain raw_PRE_public {
+               jump raw_PRE_public_log
+               jump raw_PRE_public_deny
+               jump raw_PRE_public_allow
+       }
+
+       chain raw_PRE_public_log {
+       }
+
+       chain raw_PRE_public_deny {
+       }
+
+       chain raw_PRE_public_allow {
+       }
+
+       chain filter_IN_public {
+               jump filter_IN_public_log
+               jump filter_IN_public_deny
+               jump filter_IN_public_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_IN_public_log {
+       }
+
+       chain filter_IN_public_deny {
+       }
+
+       chain filter_IN_public_allow {
+               tcp dport ssh ct state new,untracked accept
+               ip6 daddr fe80::/64 udp dport dhcpv6-client ct state new,untracked accept
+       }
+
+       chain filter_FWDI_public {
+               jump filter_FWDI_public_log
+               jump filter_FWDI_public_deny
+               jump filter_FWDI_public_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_FWDI_public_log {
+       }
+
+       chain filter_FWDI_public_deny {
+       }
+
+       chain filter_FWDI_public_allow {
+       }
+
+       chain mangle_PRE_public {
+               jump mangle_PRE_public_log
+               jump mangle_PRE_public_deny
+               jump mangle_PRE_public_allow
+       }
+
+       chain mangle_PRE_public_log {
+       }
+
+       chain mangle_PRE_public_deny {
+       }
+
+       chain mangle_PRE_public_allow {
+       }
+
+       chain filter_FWDO_public {
+               jump filter_FWDO_public_log
+               jump filter_FWDO_public_deny
+               jump filter_FWDO_public_allow
+       }
+
+       chain filter_FWDO_public_log {
+       }
+
+       chain filter_FWDO_public_deny {
+       }
+
+       chain filter_FWDO_public_allow {
+       }
+
+       chain raw_PRE_home {
+               jump raw_PRE_home_log
+               jump raw_PRE_home_deny
+               jump raw_PRE_home_allow
+       }
+
+       chain raw_PRE_home_log {
+       }
+
+       chain raw_PRE_home_deny {
+       }
+
+       chain raw_PRE_home_allow {
+               udp dport netbios-ns ct helper "netbios-ns"
+       }
+
+       chain filter_IN_home {
+               jump filter_IN_home_log
+               jump filter_IN_home_deny
+               jump filter_IN_home_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_IN_home_log {
+       }
+
+       chain filter_IN_home_deny {
+       }
+
+       chain filter_IN_home_allow {
+               tcp dport ssh ct state new,untracked accept
+               ip daddr 224.0.0.251 udp dport mdns ct state new,untracked accept
+               ip6 daddr ff02::fb udp dport mdns ct state new,untracked accept
+               udp dport 1714-1764 ct state new,untracked accept
+               tcp dport 1714-1764 ct state new,untracked accept
+               ip6 daddr fe80::/64 udp dport dhcpv6-client ct state new,untracked accept
+               udp dport netbios-ns ct state new,untracked accept
+               udp dport netbios-dgm ct state new,untracked accept
+               tcp dport netbios-ssn ct state new,untracked accept
+               tcp dport microsoft-ds ct state new,untracked accept
+       }
+
+       chain filter_FWDI_home {
+               jump filter_FWDI_home_log
+               jump filter_FWDI_home_deny
+               jump filter_FWDI_home_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_FWDI_home_log {
+       }
+
+       chain filter_FWDI_home_deny {
+       }
+
+       chain filter_FWDI_home_allow {
+       }
+
+       chain mangle_PRE_home {
+               jump mangle_PRE_home_log
+               jump mangle_PRE_home_deny
+               jump mangle_PRE_home_allow
+       }
+
+       chain mangle_PRE_home_log {
+       }
+
+       chain mangle_PRE_home_deny {
+       }
+
+       chain mangle_PRE_home_allow {
+       }
+
+       chain filter_FWDO_home {
+               jump filter_FWDO_home_log
+               jump filter_FWDO_home_deny
+               jump filter_FWDO_home_allow
+       }
+
+       chain filter_FWDO_home_log {
+       }
+
+       chain filter_FWDO_home_deny {
+       }
+
+       chain filter_FWDO_home_allow {
+       }
+
+       chain raw_PRE_work {
+               jump raw_PRE_work_log
+               jump raw_PRE_work_deny
+               jump raw_PRE_work_allow
+       }
+
+       chain raw_PRE_work_log {
+       }
+
+       chain raw_PRE_work_deny {
+       }
+
+       chain raw_PRE_work_allow {
+       }
+
+       chain filter_IN_work {
+               jump filter_IN_work_log
+               jump filter_IN_work_deny
+               jump filter_IN_work_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_IN_work_log {
+       }
+
+       chain filter_IN_work_deny {
+       }
+
+       chain filter_IN_work_allow {
+               tcp dport ssh ct state new,untracked accept
+               ip6 daddr fe80::/64 udp dport dhcpv6-client ct state new,untracked accept
+       }
+
+       chain filter_FWDI_work {
+               jump filter_FWDI_work_log
+               jump filter_FWDI_work_deny
+               jump filter_FWDI_work_allow
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_FWDI_work_log {
+       }
+
+       chain filter_FWDI_work_deny {
+       }
+
+       chain filter_FWDI_work_allow {
+       }
+
+       chain mangle_PRE_work {
+               jump mangle_PRE_work_log
+               jump mangle_PRE_work_deny
+               jump mangle_PRE_work_allow
+       }
+
+       chain mangle_PRE_work_log {
+       }
+
+       chain mangle_PRE_work_deny {
+       }
+
+       chain mangle_PRE_work_allow {
+       }
+
+       chain filter_FWDO_work {
+               jump filter_FWDO_work_log
+               jump filter_FWDO_work_deny
+               jump filter_FWDO_work_allow
+       }
+
+       chain filter_FWDO_work_log {
+       }
+
+       chain filter_FWDO_work_deny {
+       }
+
+       chain filter_FWDO_work_allow {
+       }
+}"
+
+( echo "flush ruleset;"; echo "${RULESET}" ) | $NFT -f -
+
+exit 0
index c3329af500d3864354748c95e1937e29d66c88a4..18dc4a9fe30bde8431bdf4e90df9c35635ea6e8e 100755 (executable)
@@ -6,5 +6,9 @@
 set -e
 $NFT add table t
 $NFT add chain t c
-$NFT add rule t c accept       # should have handle 2
-$NFT replace rule t c handle 2 drop
+$NFT 'add set t s1 { type ipv4_addr; }'
+$NFT 'add set t s2 { type ipv4_addr; flags interval; }'
+$NFT add rule t c accept        # should have handle 4
+$NFT replace rule t c handle 4 drop
+$NFT replace rule t c handle 4 ip saddr { 1.1.1.1, 2.2.2.2 }
+$NFT replace rule t c handle 4 ip saddr @s2 ip daddr { 3.3.3.3, 4.4.4.4 }
index 251cebb26ec080a566d1e80240c1414e20f1daaf..cd69a89d986109c17bbdc353d9b49d25cc118608 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 # test for kernel commit ca08987885a147643817d02bf260bc4756ce8cd4
 # ("netfilter: nf_tables: deactivate expressions in rule replecement routine")
diff --git a/tests/shell/testcases/rule_management/0011reset_0 b/tests/shell/testcases/rule_management/0011reset_0
new file mode 100755 (executable)
index 0000000..2004b17
--- /dev/null
@@ -0,0 +1,187 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_reset_rule)
+
+set -e
+
+echo "loading ruleset with anonymous set"
+$NFT -f - <<EOF
+table t {
+        chain dns-nat-pre {
+                type nat hook prerouting priority filter; policy accept;
+                meta l4proto { tcp, udp } th dport 53 ip saddr 10.24.0.0/24 ip daddr != 10.25.0.1 counter packets 1000 bytes 1000 dnat to 10.25.0.1
+        }
+}
+EOF
+
+echo "resetting ruleset with anonymous set"
+$NFT reset rules
+EXPECT='table ip t {
+       chain dns-nat-pre {
+               type nat hook prerouting priority filter; policy accept;
+               meta l4proto { tcp, udp } th dport 53 ip saddr 10.24.0.0/24 ip daddr != 10.25.0.1 counter packets 0 bytes 0 dnat to 10.25.0.1
+       }
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT list ruleset)
+$NFT flush ruleset
+
+echo "loading ruleset"
+$NFT -f - <<EOF
+table ip t {
+       set s {
+               type ipv4_addr
+               counter
+               elements = { 1.1.1.1 counter packets 1 bytes 11 }
+       }
+       chain c {
+               counter packets 1 bytes 11 update @s { ip saddr } accept
+               counter packets 2 bytes 12 drop
+       }
+
+       chain c2 {
+               counter packets 3 bytes 13 accept
+               counter packets 4 bytes 14 drop
+       }
+}
+table inet t {
+       chain c {
+               counter packets 5 bytes 15 accept
+               counter packets 6 bytes 16 drop
+       }
+}
+table ip t2 {
+       chain c2 {
+               counter packets 7 bytes 17 accept
+               counter packets 8 bytes 18 drop
+       }
+}
+EOF
+
+echo "resetting specific rule"
+handle=$($NFT -a list chain t c | sed -n 's/.*accept # handle \([0-9]*\)$/\1/p')
+$NFT reset rule t c handle $handle
+EXPECT='table ip t {
+       set s {
+               type ipv4_addr
+               size 65535
+               flags dynamic
+               counter
+               elements = { 1.1.1.1 counter packets 1 bytes 11 }
+       }
+
+       chain c {
+               counter packets 0 bytes 0 update @s { ip saddr } accept
+               counter packets 2 bytes 12 drop
+       }
+
+       chain c2 {
+               counter packets 3 bytes 13 accept
+               counter packets 4 bytes 14 drop
+       }
+}
+table inet t {
+       chain c {
+               counter packets 5 bytes 15 accept
+               counter packets 6 bytes 16 drop
+       }
+}
+table ip t2 {
+       chain c2 {
+               counter packets 7 bytes 17 accept
+               counter packets 8 bytes 18 drop
+       }
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT list ruleset)
+
+echo "resetting specific chain"
+EXPECT='table ip t {
+       chain c2 {
+               counter packets 3 bytes 13 accept
+               counter packets 4 bytes 14 drop
+       }
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT reset rules chain t c2)
+
+echo "resetting specific table"
+EXPECT='table ip t {
+       set s {
+               type ipv4_addr
+               size 65535
+               flags dynamic
+               counter
+               elements = { 1.1.1.1 counter packets 1 bytes 11 }
+       }
+
+       chain c {
+               counter packets 0 bytes 0 update @s { ip saddr } accept
+               counter packets 2 bytes 12 drop
+       }
+
+       chain c2 {
+               counter packets 0 bytes 0 accept
+               counter packets 0 bytes 0 drop
+       }
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT reset rules table t)
+
+echo "resetting specific family"
+EXPECT='table ip t {
+       set s {
+               type ipv4_addr
+               size 65535
+               flags dynamic
+               counter
+               elements = { 1.1.1.1 counter packets 1 bytes 11 }
+       }
+
+       chain c {
+               counter packets 0 bytes 0 update @s { ip saddr } accept
+               counter packets 0 bytes 0 drop
+       }
+
+       chain c2 {
+               counter packets 0 bytes 0 accept
+               counter packets 0 bytes 0 drop
+       }
+}
+table ip t2 {
+       chain c2 {
+               counter packets 7 bytes 17 accept
+               counter packets 8 bytes 18 drop
+       }
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT reset rules ip)
+
+echo "resetting whole ruleset"
+EXPECT='table ip t {
+       set s {
+               type ipv4_addr
+               size 65535
+               flags dynamic
+               counter
+               elements = { 1.1.1.1 counter packets 1 bytes 11 }
+       }
+
+       chain c {
+               counter packets 0 bytes 0 update @s { ip saddr } accept
+               counter packets 0 bytes 0 drop
+       }
+
+       chain c2 {
+               counter packets 0 bytes 0 accept
+               counter packets 0 bytes 0 drop
+       }
+}
+table inet t {
+       chain c {
+               counter packets 5 bytes 15 accept
+               counter packets 6 bytes 16 drop
+       }
+}
+table ip t2 {
+       chain c2 {
+               counter packets 0 bytes 0 accept
+               counter packets 0 bytes 0 drop
+       }
+}'
+$DIFF -u <(echo "$EXPECT") <($NFT reset rules)
diff --git a/tests/shell/testcases/rule_management/0012destroy_0 b/tests/shell/testcases/rule_management/0012destroy_0
new file mode 100755 (executable)
index 0000000..a058150
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash -e
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_destroy)
+
+$NFT add table t
+$NFT add chain t c
+
+# pass for non-existent rule
+$NFT destroy rule t c handle 3333
+
+# successfully delete existing rule
+handle=$($NFT -a -e insert rule t c accept | \
+       sed -n 's/.*handle \([0-9]*\)$/\1/p')
+$NFT destroy rule t c handle "$handle"
diff --git a/tests/shell/testcases/rule_management/dumps/0001addinsertposition_0.json-nft b/tests/shell/testcases/rule_management/dumps/0001addinsertposition_0.json-nft
new file mode 100644 (file)
index 0000000..83dfee0
--- /dev/null
@@ -0,0 +1,65 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0001addinsertposition_0.nft b/tests/shell/testcases/rule_management/dumps/0001addinsertposition_0.nft
new file mode 100644 (file)
index 0000000..527d79d
--- /dev/null
@@ -0,0 +1,7 @@
+table ip t {
+       chain c {
+               drop
+               accept
+               accept
+       }
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0002addinsertlocation_1.json-nft b/tests/shell/testcases/rule_management/dumps/0002addinsertlocation_1.json-nft
new file mode 100644 (file)
index 0000000..b3808ce
--- /dev/null
@@ -0,0 +1,52 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0002addinsertlocation_1.nft b/tests/shell/testcases/rule_management/dumps/0002addinsertlocation_1.nft
new file mode 100644 (file)
index 0000000..b76cd93
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       chain c {
+               accept
+               accept
+       }
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0003insert_0.json-nft b/tests/shell/testcases/rule_management/dumps/0003insert_0.json-nft
new file mode 100644 (file)
index 0000000..9216cab
--- /dev/null
@@ -0,0 +1,102 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "sport"
+                }
+              },
+              "right": {
+                "set": [
+                  {
+                    "range": [
+                      3478,
+                      3497
+                    ]
+                  },
+                  {
+                    "range": [
+                      16384,
+                      16387
+                    ]
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "masquerade": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0004replace_0.json-nft b/tests/shell/testcases/rule_management/dumps/0004replace_0.json-nft
new file mode 100644 (file)
index 0000000..811cb73
--- /dev/null
@@ -0,0 +1,84 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s1",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s2",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@s2"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "3.3.3.3",
+                  "4.4.4.4"
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index e20952ef573e96afdbd73591d512db8ada8e7dc7..803c0debb7376f1efe5b46d5ea3c086cd3e0dfad 100644 (file)
@@ -1,5 +1,14 @@
 table ip t {
+       set s1 {
+               type ipv4_addr
+       }
+
+       set s2 {
+               type ipv4_addr
+               flags interval
+       }
+
        chain c {
-               drop
+               ip saddr @s2 ip daddr { 3.3.3.3, 4.4.4.4 }
        }
 }
diff --git a/tests/shell/testcases/rule_management/dumps/0005replace_1.json-nft b/tests/shell/testcases/rule_management/dumps/0005replace_1.json-nft
new file mode 100644 (file)
index 0000000..db64cdb
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0005replace_1.nft b/tests/shell/testcases/rule_management/dumps/0005replace_1.nft
new file mode 100644 (file)
index 0000000..1e0d1d6
--- /dev/null
@@ -0,0 +1,4 @@
+table ip t {
+       chain c {
+       }
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0006replace_1.json-nft b/tests/shell/testcases/rule_management/dumps/0006replace_1.json-nft
new file mode 100644 (file)
index 0000000..db64cdb
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0006replace_1.nft b/tests/shell/testcases/rule_management/dumps/0006replace_1.nft
new file mode 100644 (file)
index 0000000..1e0d1d6
--- /dev/null
@@ -0,0 +1,4 @@
+table ip t {
+       chain c {
+       }
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0007delete_0.json-nft b/tests/shell/testcases/rule_management/dumps/0007delete_0.json-nft
new file mode 100644 (file)
index 0000000..5d0b7d0
--- /dev/null
@@ -0,0 +1,39 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0008delete_1.json-nft b/tests/shell/testcases/rule_management/dumps/0008delete_1.json-nft
new file mode 100644 (file)
index 0000000..db64cdb
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0008delete_1.nft b/tests/shell/testcases/rule_management/dumps/0008delete_1.nft
new file mode 100644 (file)
index 0000000..1e0d1d6
--- /dev/null
@@ -0,0 +1,4 @@
+table ip t {
+       chain c {
+       }
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0009delete_1.json-nft b/tests/shell/testcases/rule_management/dumps/0009delete_1.json-nft
new file mode 100644 (file)
index 0000000..db64cdb
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0009delete_1.nft b/tests/shell/testcases/rule_management/dumps/0009delete_1.nft
new file mode 100644 (file)
index 0000000..1e0d1d6
--- /dev/null
@@ -0,0 +1,4 @@
+table ip t {
+       chain c {
+       }
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0010replace_0.json-nft b/tests/shell/testcases/rule_management/dumps/0010replace_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0010replace_0.nft b/tests/shell/testcases/rule_management/dumps/0010replace_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/rule_management/dumps/0011reset_0.json-nft b/tests/shell/testcases/rule_management/dumps/0011reset_0.json-nft
new file mode 100644 (file)
index 0000000..e57dee7
--- /dev/null
@@ -0,0 +1,255 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic",
+        "elem": [
+          {
+            "elem": {
+              "val": "1.1.1.1",
+              "counter": {
+                "packets": 1,
+                "bytes": 11
+              }
+            }
+          }
+        ],
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "set": "@s"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c2",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c2",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t2",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t2",
+        "chain": "c2",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t2",
+        "chain": "c2",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0011reset_0.nft b/tests/shell/testcases/rule_management/dumps/0011reset_0.nft
new file mode 100644 (file)
index 0000000..3b4f5a1
--- /dev/null
@@ -0,0 +1,31 @@
+table ip t {
+       set s {
+               type ipv4_addr
+               size 65535
+               flags dynamic
+               counter
+               elements = { 1.1.1.1 counter packets 1 bytes 11 }
+       }
+
+       chain c {
+               counter packets 0 bytes 0 update @s { ip saddr } accept
+               counter packets 0 bytes 0 drop
+       }
+
+       chain c2 {
+               counter packets 0 bytes 0 accept
+               counter packets 0 bytes 0 drop
+       }
+}
+table inet t {
+       chain c {
+               counter packets 0 bytes 0 accept
+               counter packets 0 bytes 0 drop
+       }
+}
+table ip t2 {
+       chain c2 {
+               counter packets 0 bytes 0 accept
+               counter packets 0 bytes 0 drop
+       }
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0012destroy_0.json-nft b/tests/shell/testcases/rule_management/dumps/0012destroy_0.json-nft
new file mode 100644 (file)
index 0000000..db64cdb
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/rule_management/dumps/0012destroy_0.nft b/tests/shell/testcases/rule_management/dumps/0012destroy_0.nft
new file mode 100644 (file)
index 0000000..1e0d1d6
--- /dev/null
@@ -0,0 +1,4 @@
+table ip t {
+       chain c {
+       }
+}
index ba23f90f2328478a2275297186de02a8efe39ea4..c37b2f0dfa2e7ccfd5d5d2918820dd1b2e5f82a4 100755 (executable)
@@ -3,6 +3,14 @@
 # test adding many sets elements
 
 HOWMANY=255
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+       # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for
+       # the test.
+       #
+       # Run only a subset of the test and mark as skipped at the end.
+       HOWMANY=30
+fi
+
 
 tmpfile=$(mktemp)
 if [ ! -w $tmpfile ] ; then
@@ -30,3 +38,10 @@ add element x y $(generate)" > $tmpfile
 
 set -e
 $NFT -f $tmpfile
+
+if [ "$HOWMANY" != 255 ] ; then
+       echo "NFT_TEST_HAS_SOCKET_LIMITS indicates that the socket limit for"
+       echo "/proc/sys/net/core/wmem_max is too small for this test. Mark as SKIPPED"
+       echo "You may bump the limit and rerun with \`NFT_TEST_HAS_SOCKET_LIMITS=n\`."
+       exit 77
+fi
index 7e7beebd207394503b93b02727605cec278d5e1e..64451604c3d12c13644ab5721cb3881bf2941b65 100755 (executable)
@@ -3,6 +3,13 @@
 # test adding and deleting many sets elements
 
 HOWMANY=255
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+       # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for
+       # the test.
+       #
+       # Run only a subset of the test and mark as skipped at the end.
+       HOWMANY=30
+fi
 
 tmpfile=$(mktemp)
 if [ ! -w $tmpfile ] ; then
@@ -31,3 +38,10 @@ delete element x y $(generate)" > $tmpfile
 
 set -e
 $NFT -f $tmpfile
+
+if [ "$HOWMANY" != 255 ] ; then
+       echo "NFT_TEST_HAS_SOCKET_LIMITS indicates that the socket limit for"
+       echo "/proc/sys/net/core/wmem_max is too small for this test. Mark as SKIPPED"
+       echo "You may bump the limit and rerun with \`NFT_TEST_HAS_SOCKET_LIMITS=n\`."
+       exit 77
+fi
index 5774317b6b630db197d2d76a4a2df303345e0b45..c0925dd57b4720fc2736708bf274ca9e1c6d0865 100755 (executable)
@@ -3,6 +3,13 @@
 # test adding and deleting many sets elements in two nft -f runs.
 
 HOWMANY=255
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+       # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for
+       # the test.
+       #
+       # Run only a subset of the test and mark as skipped at the end.
+       HOWMANY=30
+fi
 
 tmpfile=$(mktemp)
 if [ ! -w $tmpfile ] ; then
@@ -32,3 +39,10 @@ add element x y $(generate)" > $tmpfile
 $NFT -f $tmpfile
 echo "delete element x y $(generate)" > $tmpfile
 $NFT -f $tmpfile
+
+if [ "$HOWMANY" != 255 ] ; then
+       echo "NFT_TEST_HAS_SOCKET_LIMITS indicates that the socket limit for"
+       echo "/proc/sys/net/core/wmem_max is too small for this test. Mark as SKIPPED"
+       echo "You may bump the limit and rerun with \`NFT_TEST_HAS_SOCKET_LIMITS=n\`."
+       exit 77
+fi
index 44d451a8ad3a3483a0649b2b67e1b39839a53092..1df38326ab571c74e69c92a4a4ffdddc7af5d5ca 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_comment)
+
 # Test that comments are added to set elements in standard sets.
 # Explicitly test bitmap backend set implementation.
 
index 6062913b52729a16581fce98fdd39d75d3fe3b2d..48f6875bf459fda9dd10e11c90f3381dfdf4c36d 100755 (executable)
@@ -16,7 +16,7 @@ $NFT -f - <<< "$RULESET"
 # Commands that should be invalid
 
 declare -a cmds=(
-               "flush set t m" "flush set t f"
+               "flush set t m"
                "flush map t s" "flush map t f"
                "flush meter t s" "flush meter t m"
                )
diff --git a/tests/shell/testcases/sets/0024synproxy_0 b/tests/shell/testcases/sets/0024synproxy_0
new file mode 100755 (executable)
index 0000000..0c7da57
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_synproxy)
+
+# * creating valid named objects
+# * referencing them from a valid rule
+
+RULESET="
+table inet x {
+       synproxy https-synproxy {
+               mss 1460
+               wscale 7
+               timestamp sack-perm
+       }
+       synproxy other-synproxy {
+               mss 1460
+               wscale 5
+       }
+       map test2 {
+               type ipv4_addr : synproxy
+               flags interval
+               elements = { 192.168.1.0/24 : "https-synproxy", 192.168.2.0/24 : "other-synproxy" }
+       }
+       chain y {
+               type filter hook input priority 0; policy accept;
+               synproxy name ip saddr map { 192.168.1.0/24 : "https-synproxy", 192.168.2.0/24 : "other-synproxy" }
+       }
+}"
+
+set -e
+$NFT -f - <<< "$RULESET"
index 059ade9aa30cfaac66a21be0fc1e1f0c5e309783..32a705bf2c81968087e0bd7081a14da59b7fa5f9 100755 (executable)
@@ -1,6 +1,13 @@
 #!/bin/bash
 
 HOWMANY=255
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+       # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for
+       # the test.
+       #
+       # Run only a subset of the test and mark as skipped at the end.
+       HOWMANY=30
+fi
 
 tmpfile=$(mktemp)
 if [ ! -w $tmpfile ] ; then
@@ -28,3 +35,10 @@ add element x y $(generate)" > $tmpfile
 
 set -e
 $NFT -f $tmpfile
+
+if [ "$HOWMANY" != 255 ] ; then
+       echo "NFT_TEST_HAS_SOCKET_LIMITS indicates that the socket limit for"
+       echo "/proc/sys/net/core/wmem_max is too small for this test. Mark as SKIPPED"
+       echo "You may bump the limit and rerun with \`NFT_TEST_HAS_SOCKET_LIMITS=n\`."
+       exit 77
+fi
index 3343529b8ffa73bbb4380cac391638e592d75051..32375b9f50c2cfe0a9cd4bcfcd416fb3872fa464 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 RC=0
 
 check() { # (set, elems, expected)
index 3097d077506cad5e6819138dbcbfcac07fbac959..d961ffd4cdcdb02a278efa4350fa89f05bac7cf6 100755 (executable)
@@ -1,15 +1,25 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_setelem_expiration)
+
 set -e
 
+drop_seconds() {
+       sed -E 's/m[0-9]*s([0-9]*ms)?/m/g'
+}
+
 RULESET="add table ip x
+add set ip x y { type ipv4_addr; flags dynamic,timeout; }
+add element ip x y { 1.1.1.1 timeout 30m expires 15m59s }"
+
+EXPECTED="add table ip x
 add set ip x y { type ipv4_addr; flags dynamic,timeout; } 
-add element ip x y { 1.1.1.1 timeout 30s expires 15s }"
+add element ip x y { 1.1.1.1 timeout 30m expires 15m }"
 
-test_output=$($NFT -e -f - <<< "$RULESET" 2>&1 | grep -v '# new generation')
+test_output=$($NFT -e -f - <<< "$RULESET" 2>&1 | grep -v '# new generation' | drop_seconds)
 
-if [ "$test_output" != "$RULESET" ] ; then
-       $DIFF -u <(echo "$test_output") <(echo "$RULESET")
+if [ "$test_output" != "$EXPECTED" ] ; then
+       $DIFF -u <(echo "$test_output") <(echo "$EXPECTED")
        exit 1
 fi
 
index e9e0f6fb02b14f28779b902f8b6f84232afea5df..7c37c1d81131bb90eb4721c85c33b9a77d00885b 100755 (executable)
@@ -14,7 +14,12 @@ RULESET="
 "
 
 expected_output="table ip t {
-       meter m {
+       set s {
+               type ipv4_addr
+               size 256
+               flags dynamic,timeout
+       }
+       set m {
                type ipv4_addr
                size 128
                flags dynamic
index 8d3dacf6e38ad8241fd4f6814ea856651d18f5ff..a3dbf5bf28ba38df55c9284d124fc527bb8ecf81 100755 (executable)
@@ -1,4 +1,7 @@
-#!/bin/sh -e
+#!/bin/bash -e
+#
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+# NFT_TEST_SKIP(NFT_TEST_SKIP_slow)
 #
 # 0043concatenated_ranges_0 - Add, get, list, timeout for concatenated ranges
 #
 # - delete them
 # - make sure they can't be deleted again
 
-if [ "$(ps -o comm= $PPID)" = "run-tests.sh" ]; then
-       # Skip some permutations on a full test suite run to keep it quick
-       TYPES="ipv4_addr ipv6_addr ether_addr inet_service"
-else
-       TYPES="ipv4_addr ipv6_addr ether_addr inet_proto inet_service mark"
-fi
+TYPES="ipv4_addr ipv6_addr ether_addr inet_proto inet_service mark"
 
 RULESPEC_ipv4_addr="ip saddr"
 ELEMS_ipv4_addr="192.0.2.1 198.51.100.0/25 203.0.113.0-203.0.113.129"
index bab189c56d8c436bef86fb228d656dbd797ed732..bb3bf6b27ea76099bb940e3aafe15a2539637c3c 100755 (executable)
@@ -1,7 +1,9 @@
-#!/bin/sh -e
+#!/bin/bash -e
 #
 # 0043concatenated_ranges_1 - Insert and list subnets of different sizes
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 check() {
        $NFT add element "${1}" t s "{ ${2} . ${3} }"
        [ "$( $NFT list set "${1}" t s | grep -c "${2} . ${3}" )" = 1 ]
index face90f2e9ae2ac4aa4aba1bdc9e86720c8a9194..b0f51cc8873b4e4d4010c626df15f4c21e97f593 100755 (executable)
@@ -1,4 +1,6 @@
-#!/bin/sh -e
+#!/bin/bash -e
+#
+# NFT_TEST_SKIP(NFT_TEST_SKIP_slow)
 #
 # 0044interval_overlap_0 - Add overlapping and non-overlapping intervals
 #
@@ -115,7 +117,11 @@ add_elements() {
        IFS='   
 '
        for t in ${intervals_simple} switch ${intervals_concat}; do
+if [ "$NFT_TEST_HAVE_pipapo" = y ] ; then
                [ "${t}" = "switch" ] && set="c"         && continue
+else
+               break
+fi
                [ -z "${pass}" ]      && pass="${t}"     && continue
                [ -z "${interval}" ]  && interval="${t}" && continue
                unset IFS
@@ -146,7 +152,9 @@ add_elements() {
 
 $NFT add table t
 $NFT add set t s '{ type inet_service ; flags interval ; }'
-$NFT add set t c '{ type inet_service . inet_service ; flags interval ; }'
+if [ "$NFT_TEST_HAVE_pipapo" = y ] ; then
+       $NFT add set t c '{ type inet_service . inet_service ; flags interval ; }'
+fi
 add_elements
 
 $NFT flush ruleset
@@ -155,7 +163,9 @@ estimate_timeout
 $NFT flush ruleset
 $NFT add table t
 $NFT add set t s "{ type inet_service ; flags interval,timeout; timeout ${timeout}s; gc-interval ${timeout}s; }"
-$NFT add set t c "{ type inet_service . inet_service ; flags interval,timeout ; timeout ${timeout}s; gc-interval ${timeout}s; }"
+if [ "$NFT_TEST_HAVE_pipapo" = y ] ; then
+       $NFT add set t c "{ type inet_service . inet_service ; flags interval,timeout ; timeout ${timeout}s; gc-interval ${timeout}s; }"
+fi
 add_elements
 
 sleep $((timeout * 3 / 2))
index eeea1943ee55b0f9bb9a80ad5ee530dfa4b402bc..cdd0c8446f1b2e84b5d55a9b3e208aa2250a7203 100755 (executable)
@@ -1,4 +1,6 @@
-#!/bin/sh -e
+#!/bin/bash -e
+#
+# NFT_TEST_SKIP(NFT_TEST_SKIP_slow)
 #
 # 0044interval_overlap_1 - Single-sized intervals can never overlap partially
 #
index 60bda4017c5999f11bc1956a40290850d4077ad9..7533623e7f7baa90f8dc3fef98290a6897a1c39f 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_netmap)
+
 EXPECTED="table ip x {
             chain y {
                     type nat hook postrouting priority srcnat; policy accept;
index 4e53b7b8e8c81cd0db0a6aa8cc5c7d39dfcdfed1..757605ee34928480115591a89480187b4380169e 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 EXPECTED="table ip x {
             map y {
                     type ipv4_addr : interval ipv4_addr
index e62d25df799c838510c11de8ac9e175778e4d8ed..95babdc9ca5ffadc972e5015a51a52efb1aec71d 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
 set -e
 
 EXPECTED="table ip x {
index ea90e264bfcc487ca73755d8cdcbb29ea3093b08..6e67a43c577a98ca63575992a22ecae88359f989 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
 set -e
 
 EXPECTED="table ip x {
index 107bfb87093223d9dbda0829fb571f9b76d1feab..2aeba2c5d227949ad44783e61845a605c55861d1 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_with_two_expressions)
+
 RULESET="table x {
        set y {
                type ipv4_addr
index 6bd147c3540c9e34b39258f67f1edbf93106072a..8e17444e9ec5a3a3a3973d06d65fb1921b02ff42 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_with_two_expressions)
+
 RULESET="table x {
        set y {
                type ipv4_addr
index 1652668a2fec560867ae6db4131cf08b3954da1f..04ef047caa52d003ffa7c391cd6b4bb3e9fb742e 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_with_two_expressions)
+
 RULESET="table x {
        set y {
                type ipv4_addr
index 48d589fe68cc3b90b46e331200ffb06a669382bf..48aa6fce5c31b9b985a8d8636c509a40190bc5ff 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
 set -e
 
 RULESET="table ip x {
@@ -24,3 +26,6 @@ RULESET="table ip x {
 }"
 
 $NFT -f - <<< $RULESET
+
+$NFT flush set ip x est-connlimit
+$NFT flush set ip x new-connlimit
index faca56a18dc5273afeda4b9cb7fafd92b355e51d..edd015d09b21d3e0af8e1ace02d465b6e63555cf 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_catchall_element)
+
 set -e
 
 RULESET="table ip x {
index 436851604e34555eee9cd3222d2c3b2b9b91e65d..fd289372df18d93565aeaf477112768710156da0 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_catchall_element)
+
 set -e
 
 RULESET="table ip x {
index 55cc0d4b43dfd63973428fff88d3019b66e1b92e..816219573870a7a74b5be9887169945a7d896880 100755 (executable)
@@ -1,21 +1,8 @@
 #!/bin/bash
 
-set -e
-
-EXPECTED="table ip nat {
-       map ipportmap {
-                type ipv4_addr : interval ipv4_addr . inet_service
-                flags interval
-                elements = { 192.168.1.2 : 10.141.10.1-10.141.10.3 . 8888-8999 }
-       }
-       chain prerouting {
-                type nat hook prerouting priority dstnat; policy accept;
-                ip protocol tcp dnat ip to ip saddr map @ipportmap
-       }
-}"
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
 
-$NFT -f - <<< $EXPECTED
-$NFT add element ip nat ipportmap { 192.168.2.0/24 : 10.141.11.5-10.141.11.20 . 8888-8999 }
+set -e
 
 EXPECTED="table ip nat {
         map ipportmap2 {
diff --git a/tests/shell/testcases/sets/0067nat_interval_0 b/tests/shell/testcases/sets/0067nat_interval_0
new file mode 100755 (executable)
index 0000000..c90203d
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+set -e
+
+EXPECTED="table ip nat {
+       map ipportmap {
+                type ipv4_addr : interval ipv4_addr . inet_service
+                flags interval
+                elements = { 192.168.1.2 : 10.141.10.1-10.141.10.3 . 8888-8999 }
+       }
+       chain prerouting {
+                type nat hook prerouting priority dstnat; policy accept;
+                ip protocol tcp dnat ip to ip saddr map @ipportmap
+       }
+}"
+
+$NFT -f - <<< $EXPECTED
+$NFT add element ip nat ipportmap { 192.168.2.0/24 : 10.141.11.5-10.141.11.20 . 8888-8999 }
index 2cbc986802644a96e5a51eabeb328099421d3195..e61010c7e126053d82beccf1a03e75f29c25925a 100755 (executable)
@@ -6,9 +6,18 @@ ruleset_file=$(mktemp)
 
 trap 'rm -f "$ruleset_file"' EXIT
 
+HOWMANY=255
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+       # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for
+       # the test.
+       #
+       # Run only a subset of the test and mark as skipped at the end.
+       HOWMANY=30
+fi
+
 {
        echo 'define big_set = {'
-       for ((i = 1; i < 255; i++)); do
+       for ((i = 1; i < $HOWMANY; i++)); do
                for ((j = 1; j < 255; j++)); do
                        echo "10.0.$i.$j,"
                done
@@ -27,3 +36,10 @@ table inet test68_table {
 EOF
 
 ( ulimit -s 400 && $NFT -f "$ruleset_file" )
+
+if [ "$HOWMANY" != 255 ] ; then
+       echo "NFT_TEST_HAS_SOCKET_LIMITS indicates that the socket limit for"
+       echo "/proc/sys/net/core/wmem_max is too small for this test. Mark as SKIPPED"
+       echo "You may bump the limit and rerun with \`NFT_TEST_HAS_SOCKET_LIMITS=n\`."
+       exit 77
+fi
diff --git a/tests/shell/testcases/sets/0072destroy_0 b/tests/shell/testcases/sets/0072destroy_0
new file mode 100755 (executable)
index 0000000..9886a9b
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash -e
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_destroy)
+
+$NFT add table x
+
+# pass for non-existent set
+$NFT destroy set x s
+
+# successfully delete existing set
+$NFT add set x s '{type ipv4_addr; size 2;}'
+$NFT destroy set x s
diff --git a/tests/shell/testcases/sets/0073flat_interval_set b/tests/shell/testcases/sets/0073flat_interval_set
new file mode 100755 (executable)
index 0000000..0630595
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+EXPECTED="flush ruleset
+add table inet filter
+add map inet filter testmap { type ipv4_addr : counter; flags interval;}
+add counter inet filter TEST
+add element inet filter testmap { 192.168.0.0/24 : \"TEST\" }"
+
+$NFT -f - <<< "$EXPECTED"
diff --git a/tests/shell/testcases/sets/0074nested_interval_set b/tests/shell/testcases/sets/0074nested_interval_set
new file mode 100755 (executable)
index 0000000..e7f65fc
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+set -e
+
+dumpfile=$(dirname $0)/dumps/$(basename $0).nft
+$NFT -f "$dumpfile"
index c9fb609571fa8e74c51e949f797a8ed433222cab..1dbac0b7cdbd541eb04f24da2cb53f4cf0e5f230 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_SKIP(NFT_TEST_SKIP_slow)
+
 set -e
 
 RULESET="table inet x {
@@ -10,14 +12,23 @@ RULESET="table inet x {
        }
 }"
 
+HOWMANY=65535
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+       # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for
+       # the test.
+       #
+       # Run only a subset of the test and mark as skipped at the end.
+       HOWMANY=5000
+fi
+
 $NFT -f - <<< $RULESET
 
 tmpfile=$(mktemp)
 echo -n "add element inet x y { " > $tmpfile
-for ((i=0;i<65535;i+=2))
+for ((i=0;i<$HOWMANY;i+=2))
 do
        echo -n "$i, " >> $tmpfile
-       if [ $i -eq 65534 ]
+       if [ $i -eq $((HOWMANY-1)) ]
        then
                echo -n "$i" >> $tmpfile
        fi
@@ -27,23 +38,28 @@ echo "}" >> $tmpfile
 $NFT -f $tmpfile
 
 tmpfile2=$(mktemp)
-for ((i=1;i<65535;i+=2))
+for ((i=1;i<$HOWMANY;i+=2))
 do
        echo "$i" >> $tmpfile2
 done
 
 tmpfile3=$(mktemp)
-shuf $tmpfile2 > $tmpfile3
+shuf "$tmpfile2" --random-source=<("$NFT_TEST_BASEDIR/helpers/random-source.sh" "automerge-shuf-tmpfile2" "$NFT_TEST_RANDOM_SEED") > "$tmpfile3"
 i=0
 cat $tmpfile3 | while read line && [ $i -lt 10 ]
 do
        $NFT add element inet x y { $line }
+       if [ $? -ne 0 ]
+       then
+               echo "failed to add $line"
+               exit 1
+       fi
        i=$((i+1))
 done
 
 for ((i=0;i<10;i++))
 do
-       from=$(($RANDOM%65535))
+       from=$(($RANDOM%$HOWMANY))
        to=$(($from+100))
        $NFT add element inet x y { $from-$to }
        if [ $? -ne 0 ]
@@ -51,14 +67,65 @@ do
                echo "failed to add $from-$to"
                exit 1
        fi
-       $NFT get element inet x y { $from-$to }
+
+       $NFT get element inet x y { $from-$to } 1>/dev/null
        if [ $? -ne 0 ]
        then
                echo "failed to get $from-$to"
                exit 1
        fi
+
+       # partial removals in the previous random range
+       from2=$(($from+10))
+       to2=$(($to-10))
+       $NFT delete element inet x y { $from, $to, $from2-$to2 }
+       if [ $? -ne 0 ]
+       then
+               echo "failed to delete $from, $to, $from2-$to2"
+               exit 1
+       fi
+
+       # check deletions are correct
+       from=$(($from+1))
+       $NFT get element inet x y { $from } 1>/dev/null
+       if [ $? -ne 0 ]
+       then
+               echo "failed to get $from"
+               exit 1
+       fi
+
+       to=$(($to-1))
+       $NFT get element inet x y { $to } 1>/dev/null
+       if [ $? -ne 0 ]
+       then
+               echo "failed to get $to"
+               exit 1
+       fi
+
+       from2=$(($from2-1))
+       $NFT get element inet x y { $from2 } 1>/dev/null
+       if [ $? -ne 0 ]
+       then
+               echo "failed to get $from2"
+               exit 1
+       fi
+       to2=$(($to2+1))
+
+       $NFT get element inet x y { $to2 } 1>/dev/null
+       if [ $? -ne 0 ]
+       then
+               echo "failed to get $to2"
+               exit 1
+       fi
 done
 
 rm -f $tmpfile
 rm -f $tmpfile2
 rm -f $tmpfile3
+
+if [ "$HOWMANY" != 65535 ] ; then
+       echo "NFT_TEST_HAS_SOCKET_LIMITS indicates that the socket limit for"
+       echo "/proc/sys/net/core/wmem_max is too small for this test. Mark as SKIPPED"
+       echo "You may bump the limit and rerun with \`NFT_TEST_HAS_SOCKET_LIMITS=n\`."
+       exit 77
+fi
index 7699e9da3e75dd0dc27321ccb2f6a5b9ca589ddd..52a42c2f7305f56f6cb235fefeb2a8218ad8638d 100755 (executable)
@@ -17,3 +17,9 @@ add element ip a x { 2 }
 add element ip6 a x { 2 }"
 
 $NFT -f - <<< $RULESET
+
+RULESET="define m = { 3, 4 }
+add element ip a x \$m
+add element ip a x { 5 }"
+
+$NFT -f - <<< $RULESET
index 4d90af9a65579e5719e46f13618a24d441dc4073..36138ae0de786e4b35435de1901958f41c015064 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 set -e
 
 RULESET="table ip t {
diff --git a/tests/shell/testcases/sets/dumps/0001named_interval_0.json-nft b/tests/shell/testcases/sets/dumps/0001named_interval_0.json-nft
new file mode 100644 (file)
index 0000000..9200154
--- /dev/null
@@ -0,0 +1,253 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s1",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "range": [
+              "10.0.0.0",
+              "11.0.0.0"
+            ]
+          },
+          {
+            "prefix": {
+              "addr": "172.16.0.0",
+              "len": 16
+            }
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s2",
+        "table": "t",
+        "type": "ipv6_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "fe00::",
+              "len": 64
+            }
+          },
+          {
+            "range": [
+              "fe11::",
+              "fe22::"
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s3",
+        "table": "t",
+        "type": "inet_proto",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "range": [
+              10,
+              20
+            ]
+          },
+          {
+            "range": [
+              50,
+              60
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s4",
+        "table": "t",
+        "type": "inet_service",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "range": [
+              0,
+              1024
+            ]
+          },
+          {
+            "range": [
+              8080,
+              8082
+            ]
+          },
+          {
+            "range": [
+              10000,
+              40000
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@s1"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": "@s2"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "protocol"
+                }
+              },
+              "right": "@s3"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "nexthdr"
+                }
+              },
+              "right": "@s3"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": "@s4"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0002named_interval_automerging_0.json-nft b/tests/shell/testcases/sets/dumps/0002named_interval_automerging_0.json-nft
new file mode 100644 (file)
index 0000000..b083ecb
--- /dev/null
@@ -0,0 +1,42 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "192.168.0.0",
+              "len": 24
+            }
+          },
+          {
+            "prefix": {
+              "addr": "192.168.1.0",
+              "len": 24
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0003named_interval_missing_flag_0.json-nft b/tests/shell/testcases/sets/dumps/0003named_interval_missing_flag_0.json-nft
new file mode 100644 (file)
index 0000000..b6173e9
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0004named_interval_shadow_0.json-nft b/tests/shell/testcases/sets/dumps/0004named_interval_shadow_0.json-nft
new file mode 100644 (file)
index 0000000..c79d9ba
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s",
+        "table": "t",
+        "type": "ipv6_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "fe00::",
+              "len": 64
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0005named_interval_shadow_0.json-nft b/tests/shell/testcases/sets/dumps/0005named_interval_shadow_0.json-nft
new file mode 100644 (file)
index 0000000..464661e
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s",
+        "table": "t",
+        "type": "ipv6_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "fe00::",
+              "len": 48
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0006create_set_0.json-nft b/tests/shell/testcases/sets/dumps/0006create_set_0.json-nft
new file mode 100644 (file)
index 0000000..b6173e9
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0007create_element_0.json-nft b/tests/shell/testcases/sets/dumps/0007create_element_0.json-nft
new file mode 100644 (file)
index 0000000..f5a9ac1
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0008comments_interval_0.json-nft b/tests/shell/testcases/sets/dumps/0008comments_interval_0.json-nft
new file mode 100644 (file)
index 0000000..e715241
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "elem": {
+              "val": "1.1.1.1",
+              "comment": "test"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0008create_verdict_map_0.json-nft b/tests/shell/testcases/sets/dumps/0008create_verdict_map_0.json-nft
new file mode 100644 (file)
index 0000000..fa5dcb2
--- /dev/null
@@ -0,0 +1,78 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "postrouting",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "sourcemap",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "verdict",
+        "elem": [
+          [
+            "100.123.10.2",
+            {
+              "jump": {
+                "target": "c"
+              }
+            }
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "postrouting",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": "@sourcemap"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0009comments_timeout_0.json-nft b/tests/shell/testcases/sets/dumps/0009comments_timeout_0.json-nft
new file mode 100644 (file)
index 0000000..a67a067
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "timeout",
+        "elem": [
+          {
+            "elem": {
+              "val": "1.1.1.1",
+              "comment": "test"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0010comments_0.json-nft b/tests/shell/testcases/sets/dumps/0010comments_0.json-nft
new file mode 100644 (file)
index 0000000..7ea3c60
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s",
+        "table": "t",
+        "type": "ipv6_addr",
+        "handle": 0,
+        "elem": [
+          {
+            "elem": {
+              "val": "::1",
+              "comment": "test"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0011add_many_elements_0.nodump b/tests/shell/testcases/sets/dumps/0011add_many_elements_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/0012add_delete_many_elements_0.json-nft b/tests/shell/testcases/sets/dumps/0012add_delete_many_elements_0.json-nft
new file mode 100644 (file)
index 0000000..c1b7639
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0013add_delete_many_elements_0.json-nft b/tests/shell/testcases/sets/dumps/0013add_delete_many_elements_0.json-nft
new file mode 100644 (file)
index 0000000..c1b7639
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0014malformed_set_is_not_defined_0.json-nft b/tests/shell/testcases/sets/dumps/0014malformed_set_is_not_defined_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0014malformed_set_is_not_defined_0.nft b/tests/shell/testcases/sets/dumps/0014malformed_set_is_not_defined_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/0015rulesetflush_0.json-nft b/tests/shell/testcases/sets/dumps/0015rulesetflush_0.json-nft
new file mode 100644 (file)
index 0000000..86d7eb6
--- /dev/null
@@ -0,0 +1,51 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "blacklist_v4",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "192.168.0.0",
+              "len": 24
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0016element_leak_0.json-nft b/tests/shell/testcases/sets/dumps/0016element_leak_0.json-nft
new file mode 100644 (file)
index 0000000..96b9714
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 2,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0017add_after_flush_0.json-nft b/tests/shell/testcases/sets/dumps/0017add_after_flush_0.json-nft
new file mode 100644 (file)
index 0000000..96b9714
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 2,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0018set_check_size_1.json-nft b/tests/shell/testcases/sets/dumps/0018set_check_size_1.json-nft
new file mode 100644 (file)
index 0000000..d226811
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 2,
+        "elem": [
+          "1.1.1.1",
+          "1.1.1.2"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0018set_check_size_1.nft b/tests/shell/testcases/sets/dumps/0018set_check_size_1.nft
new file mode 100644 (file)
index 0000000..8cd3707
--- /dev/null
@@ -0,0 +1,7 @@
+table ip x {
+       set s {
+               type ipv4_addr
+               size 2
+               elements = { 1.1.1.1, 1.1.1.2 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0019set_check_size_0.json-nft b/tests/shell/testcases/sets/dumps/0019set_check_size_0.json-nft
new file mode 100644 (file)
index 0000000..d226811
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 2,
+        "elem": [
+          "1.1.1.1",
+          "1.1.1.2"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0020comments_0.json-nft b/tests/shell/testcases/sets/dumps/0020comments_0.json-nft
new file mode 100644 (file)
index 0000000..401a8f2
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s",
+        "table": "t",
+        "type": "inet_service",
+        "handle": 0,
+        "elem": [
+          {
+            "elem": {
+              "val": 22,
+              "comment": "test"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0021nesting_0.json-nft b/tests/shell/testcases/sets/dumps/0021nesting_0.json-nft
new file mode 100644 (file)
index 0000000..5ed089d
--- /dev/null
@@ -0,0 +1,69 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": {
+                "set": [
+                  {
+                    "prefix": {
+                      "addr": "1.1.1.0",
+                      "len": 24
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2.2.2.0",
+                      "len": 24
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "3.3.3.0",
+                      "len": 24
+                    }
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0022type_selective_flush_0.json-nft b/tests/shell/testcases/sets/dumps/0022type_selective_flush_0.json-nft
new file mode 100644 (file)
index 0000000..dcb62eb
--- /dev/null
@@ -0,0 +1,99 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "m",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "inet_service"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "f",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 1024,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 80
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "set": "@f",
+              "stmt": [
+                {
+                  "limit": {
+                    "rate": 10,
+                    "burst": 5,
+                    "per": "second"
+                  }
+                }
+              ]
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index 0a4cb0a54d73030ba46eb4d687c2cd78667e0485..38987ded39e0d3699bb2d94047c594d523b641e4 100644 (file)
@@ -7,7 +7,13 @@ table ip t {
                type ipv4_addr : inet_service
        }
 
+       set f {
+               type ipv4_addr
+               size 1024
+               flags dynamic
+       }
+
        chain c {
-               tcp dport 80 meter f size 1024 { ip saddr limit rate 10/second burst 5 packets }
+               tcp dport 80 add @f { ip saddr limit rate 10/second burst 5 packets }
        }
 }
diff --git a/tests/shell/testcases/sets/dumps/0023incomplete_add_set_command_0.json-nft b/tests/shell/testcases/sets/dumps/0023incomplete_add_set_command_0.json-nft
new file mode 100644 (file)
index 0000000..e0e56fe
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0024named_objects_0.json-nft b/tests/shell/testcases/sets/dumps/0024named_objects_0.json-nft
new file mode 100644 (file)
index 0000000..b452133
--- /dev/null
@@ -0,0 +1,165 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "counter": {
+        "family": "inet",
+        "name": "user123",
+        "table": "x",
+        "handle": 0,
+        "packets": 12,
+        "bytes": 1433
+      }
+    },
+    {
+      "counter": {
+        "family": "inet",
+        "name": "user321",
+        "table": "x",
+        "handle": 0,
+        "packets": 0,
+        "bytes": 0
+      }
+    },
+    {
+      "quota": {
+        "family": "inet",
+        "name": "user123",
+        "table": "x",
+        "handle": 0,
+        "bytes": 2000,
+        "used": 0,
+        "inv": true
+      }
+    },
+    {
+      "quota": {
+        "family": "inet",
+        "name": "user124",
+        "table": "x",
+        "handle": 0,
+        "bytes": 2000,
+        "used": 0,
+        "inv": true
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "test",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "quota",
+        "elem": [
+          [
+            "192.168.2.2",
+            "user124"
+          ],
+          [
+            "192.168.2.3",
+            "user124"
+          ]
+        ]
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "counter": {
+              "map": {
+                "key": {
+                  "payload": {
+                    "protocol": "ip",
+                    "field": "saddr"
+                  }
+                },
+                "data": {
+                  "set": [
+                    [
+                      "1.1.1.1",
+                      "user123"
+                    ],
+                    [
+                      "2.2.2.2",
+                      "user123"
+                    ],
+                    [
+                      "192.168.2.2",
+                      "user123"
+                    ]
+                  ]
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "quota": {
+              "map": {
+                "key": {
+                  "payload": {
+                    "protocol": "ip",
+                    "field": "saddr"
+                  }
+                },
+                "data": "@test"
+              }
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0024synproxy_0.json-nft b/tests/shell/testcases/sets/dumps/0024synproxy_0.json-nft
new file mode 100644 (file)
index 0000000..dd71bb3
--- /dev/null
@@ -0,0 +1,129 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "synproxy": {
+        "family": "inet",
+        "name": "https-synproxy",
+        "table": "x",
+        "handle": 0,
+        "mss": 1460,
+        "wscale": 7,
+        "flags": [
+          "timestamp",
+          "sack-perm"
+        ]
+      }
+    },
+    {
+      "synproxy": {
+        "family": "inet",
+        "name": "other-synproxy",
+        "table": "x",
+        "handle": 0,
+        "mss": 1460,
+        "wscale": 5
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "test2",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "synproxy",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "prefix": {
+                "addr": "192.168.1.0",
+                "len": 24
+              }
+            },
+            "https-synproxy"
+          ],
+          [
+            {
+              "prefix": {
+                "addr": "192.168.2.0",
+                "len": 24
+              }
+            },
+            "other-synproxy"
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "synproxy": {
+              "map": {
+                "key": {
+                  "payload": {
+                    "protocol": "ip",
+                    "field": "saddr"
+                  }
+                },
+                "data": {
+                  "set": [
+                    [
+                      {
+                        "prefix": {
+                          "addr": "192.168.1.0",
+                          "len": 24
+                        }
+                      },
+                      "https-synproxy"
+                    ],
+                    [
+                      {
+                        "prefix": {
+                          "addr": "192.168.2.0",
+                          "len": 24
+                        }
+                      },
+                      "other-synproxy"
+                    ]
+                  ]
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0024synproxy_0.nft b/tests/shell/testcases/sets/dumps/0024synproxy_0.nft
new file mode 100644 (file)
index 0000000..dd9a112
--- /dev/null
@@ -0,0 +1,24 @@
+table inet x {
+       synproxy https-synproxy {
+               mss 1460
+               wscale 7
+               timestamp sack-perm
+       }
+
+       synproxy other-synproxy {
+               mss 1460
+               wscale 5
+       }
+
+       map test2 {
+               type ipv4_addr : synproxy
+               flags interval
+               elements = { 192.168.1.0/24 : "https-synproxy",
+                            192.168.2.0/24 : "other-synproxy" }
+       }
+
+       chain y {
+               type filter hook input priority filter; policy accept;
+               synproxy name ip saddr map { 192.168.1.0/24 : "https-synproxy", 192.168.2.0/24 : "other-synproxy" }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0025anonymous_set_0.json-nft b/tests/shell/testcases/sets/dumps/0025anonymous_set_0.json-nft
new file mode 100644 (file)
index 0000000..9d56d02
--- /dev/null
@@ -0,0 +1,102 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "set": [
+                  "192.168.0.1",
+                  "192.168.0.2",
+                  "192.168.0.3"
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "doesntexist"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  22,
+                  23
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0026named_limit_0.json-nft b/tests/shell/testcases/sets/dumps/0026named_limit_0.json-nft
new file mode 100644 (file)
index 0000000..5d21f26
--- /dev/null
@@ -0,0 +1,75 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "limit": {
+        "family": "ip",
+        "name": "http-traffic",
+        "table": "filter",
+        "handle": 0,
+        "rate": 1,
+        "per": "second",
+        "burst": 5
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "limit": {
+              "map": {
+                "key": {
+                  "payload": {
+                    "protocol": "tcp",
+                    "field": "dport"
+                  }
+                },
+                "data": {
+                  "set": [
+                    [
+                      80,
+                      "http-traffic"
+                    ],
+                    [
+                      443,
+                      "http-traffic"
+                    ]
+                  ]
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0027ipv6_maps_ipv4_0.json-nft b/tests/shell/testcases/sets/dumps/0027ipv6_maps_ipv4_0.json-nft
new file mode 100644 (file)
index 0000000..75d8b46
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s",
+        "table": "t",
+        "type": "ipv6_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "::ffff:0.0.0.0",
+              "len": 96
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0028autoselect_0.json-nft b/tests/shell/testcases/sets/dumps/0028autoselect_0.json-nft
new file mode 100644 (file)
index 0000000..05fc072
--- /dev/null
@@ -0,0 +1,162 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s1",
+        "table": "t",
+        "type": "inet_proto",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s2",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s3",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 1024,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "foobar"
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "protocol"
+                }
+              },
+              "set": "@s1"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "foobar"
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "set": "@s2"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "foobar"
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "set": "@s3"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0028autoselect_0.nft b/tests/shell/testcases/sets/dumps/0028autoselect_0.nft
new file mode 100644 (file)
index 0000000..0c60492
--- /dev/null
@@ -0,0 +1,26 @@
+table ip t {
+       set s1 {
+               type inet_proto
+               size 65535
+               flags dynamic
+       }
+
+       set s2 {
+               type ipv4_addr
+               size 65535
+               flags dynamic
+       }
+
+       set s3 {
+               type ipv4_addr
+               size 1024
+               flags dynamic
+       }
+
+       chain c {
+               type filter hook input priority filter; policy accept;
+               iifname "foobar" add @s1 { ip protocol }
+               iifname "foobar" add @s2 { ip daddr }
+               iifname "foobar" add @s3 { ip daddr }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0028delete_handle_0.json-nft b/tests/shell/testcases/sets/dumps/0028delete_handle_0.json-nft
new file mode 100644 (file)
index 0000000..9e5f708
--- /dev/null
@@ -0,0 +1,51 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test-ip",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "x",
+        "table": "test-ip",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "test-ip",
+        "type": "inet_service",
+        "handle": 0,
+        "flags": "timeout",
+        "timeout": 10845
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "z",
+        "table": "test-ip",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": [
+          "constant",
+          "interval"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0028delete_handle_0.nft b/tests/shell/testcases/sets/dumps/0028delete_handle_0.nft
new file mode 100644 (file)
index 0000000..0f25c76
--- /dev/null
@@ -0,0 +1,15 @@
+table ip test-ip {
+       set x {
+               type ipv4_addr
+       }
+
+       set y {
+               type inet_service
+               timeout 3h45s
+       }
+
+       set z {
+               type ipv4_addr
+               flags constant,interval
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0030add_many_elements_interval_0.nodump b/tests/shell/testcases/sets/dumps/0030add_many_elements_interval_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/0031set_timeout_size_0.nodump b/tests/shell/testcases/sets/dumps/0031set_timeout_size_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/0032restore_set_simple_0.json-nft b/tests/shell/testcases/sets/dumps/0032restore_set_simple_0.json-nft
new file mode 100644 (file)
index 0000000..7a72315
--- /dev/null
@@ -0,0 +1,45 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "setA",
+        "table": "filter",
+        "type": [
+          "ipv4_addr",
+          "inet_service",
+          "ipv4_addr"
+        ],
+        "handle": 0,
+        "flags": "timeout"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "setB",
+        "table": "filter",
+        "type": [
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "flags": "timeout"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0033add_set_simple_flat_0.json-nft b/tests/shell/testcases/sets/dumps/0033add_set_simple_flat_0.json-nft
new file mode 100644 (file)
index 0000000..5697652
--- /dev/null
@@ -0,0 +1,45 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "setA",
+        "table": "x",
+        "type": [
+          "ipv4_addr",
+          "inet_service",
+          "ipv4_addr"
+        ],
+        "handle": 0,
+        "flags": "timeout"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "setB",
+        "table": "x",
+        "type": [
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "flags": "timeout"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0033add_set_simple_flat_0.nft b/tests/shell/testcases/sets/dumps/0033add_set_simple_flat_0.nft
new file mode 100644 (file)
index 0000000..d6174c5
--- /dev/null
@@ -0,0 +1,11 @@
+table ip x {
+       set setA {
+               type ipv4_addr . inet_service . ipv4_addr
+               flags timeout
+       }
+
+       set setB {
+               type ipv4_addr . inet_service
+               flags timeout
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0034get_element_0.json-nft b/tests/shell/testcases/sets/dumps/0034get_element_0.json-nft
new file mode 100644 (file)
index 0000000..4f5ba0a
--- /dev/null
@@ -0,0 +1,134 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "inet_service",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          10,
+          {
+            "range": [
+              20,
+              30
+            ]
+          },
+          40,
+          {
+            "range": [
+              50,
+              60
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "ips",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          "10.0.0.1",
+          {
+            "range": [
+              "10.0.0.5",
+              "10.0.0.8"
+            ]
+          },
+          {
+            "prefix": {
+              "addr": "10.0.0.128",
+              "len": 25
+            }
+          },
+          {
+            "prefix": {
+              "addr": "10.0.1.0",
+              "len": 24
+            }
+          },
+          {
+            "range": [
+              "10.0.2.3",
+              "10.0.2.12"
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "cs",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "concat": [
+              "10.0.0.1",
+              22
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "10.1.0.0",
+                  "len": 16
+                }
+              },
+              {
+                "range": [
+                  1,
+                  1024
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "range": [
+                  "10.2.0.1",
+                  "10.2.0.8"
+                ]
+              },
+              {
+                "range": [
+                  1024,
+                  65535
+                ]
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0034get_element_0.nft b/tests/shell/testcases/sets/dumps/0034get_element_0.nft
new file mode 100644 (file)
index 0000000..1c1dd97
--- /dev/null
@@ -0,0 +1,23 @@
+table ip t {
+       set s {
+               type inet_service
+               flags interval
+               elements = { 10, 20-30, 40, 50-60 }
+       }
+
+       set ips {
+               type ipv4_addr
+               flags interval
+               elements = { 10.0.0.1, 10.0.0.5-10.0.0.8,
+                            10.0.0.128/25, 10.0.1.0/24,
+                            10.0.2.3-10.0.2.12 }
+       }
+
+       set cs {
+               type ipv4_addr . inet_service
+               flags interval
+               elements = { 10.0.0.1 . 22,
+                            10.1.0.0/16 . 1-1024,
+                            10.2.0.1-10.2.0.8 . 1024-65535 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0035add_set_elements_flat_0.json-nft b/tests/shell/testcases/sets/dumps/0035add_set_elements_flat_0.json-nft
new file mode 100644 (file)
index 0000000..f9fe4e6
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0035add_set_elements_flat_0.nft b/tests/shell/testcases/sets/dumps/0035add_set_elements_flat_0.nft
new file mode 100644 (file)
index 0000000..ca69cee
--- /dev/null
@@ -0,0 +1,6 @@
+table ip x {
+       set y {
+               type ipv4_addr
+               flags interval
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0036add_set_element_expiration_0.nodump b/tests/shell/testcases/sets/dumps/0036add_set_element_expiration_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/0037_set_with_inet_service_0.json-nft b/tests/shell/testcases/sets/dumps/0037_set_with_inet_service_0.json-nft
new file mode 100644 (file)
index 0000000..1c3b559
--- /dev/null
@@ -0,0 +1,159 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "forward",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 0,
+        "policy": "drop"
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "myset",
+        "table": "filter",
+        "type": [
+          "ipv4_addr",
+          "inet_proto",
+          "inet_service"
+        ],
+        "handle": 0,
+        "elem": [
+          {
+            "concat": [
+              "192.168.0.113",
+              "tcp",
+              22
+            ]
+          },
+          {
+            "concat": [
+              "192.168.0.12",
+              "tcp",
+              53
+            ]
+          },
+          {
+            "concat": [
+              "192.168.0.12",
+              "udp",
+              53
+            ]
+          },
+          {
+            "concat": [
+              "192.168.0.12",
+              "tcp",
+              80
+            ]
+          },
+          {
+            "concat": [
+              "192.168.0.13",
+              "tcp",
+              80
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "forward",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": [
+                "established",
+                "related"
+              ]
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "forward",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "protocol"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "th",
+                      "field": "dport"
+                    }
+                  }
+                ]
+              },
+              "right": "@myset"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0038meter_list_0.json-nft b/tests/shell/testcases/sets/dumps/0038meter_list_0.json-nft
new file mode 100644 (file)
index 0000000..6f6555d
--- /dev/null
@@ -0,0 +1,94 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 256,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "m",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 128,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 80
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "set": "@m",
+              "stmt": [
+                {
+                  "limit": {
+                    "rate": 10,
+                    "burst": 5,
+                    "per": "second"
+                  }
+                }
+              ]
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index f274086b5285431462f7651c00010cb90b23ab96..8037dfa502b4d491a31119ca1171bd31d2547c1a 100644 (file)
@@ -5,7 +5,13 @@ table ip t {
                flags dynamic,timeout
        }
 
+       set m {
+               type ipv4_addr
+               size 128
+               flags dynamic
+       }
+
        chain c {
-               tcp dport 80 meter m size 128 { ip saddr limit rate 10/second burst 5 packets }
+               tcp dport 80 add @m { ip saddr limit rate 10/second burst 5 packets }
        }
 }
diff --git a/tests/shell/testcases/sets/dumps/0039delete_interval_0.json-nft b/tests/shell/testcases/sets/dumps/0039delete_interval_0.json-nft
new file mode 100644 (file)
index 0000000..afa8195
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "range": [
+              "192.168.1.0",
+              "192.168.1.254"
+            ]
+          },
+          "192.168.1.255"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0039delete_interval_0.nft b/tests/shell/testcases/sets/dumps/0039delete_interval_0.nft
new file mode 100644 (file)
index 0000000..1fc7657
--- /dev/null
@@ -0,0 +1,7 @@
+table ip t {
+       set s {
+               type ipv4_addr
+               flags interval
+               elements = { 192.168.1.0-192.168.1.254, 192.168.1.255 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0040get_host_endian_elements_0.json-nft b/tests/shell/testcases/sets/dumps/0040get_host_endian_elements_0.json-nft
new file mode 100644 (file)
index 0000000..486ca45
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "mark",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "range": [
+              35,
+              66
+            ]
+          },
+          4919
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0040get_host_endian_elements_0.nft b/tests/shell/testcases/sets/dumps/0040get_host_endian_elements_0.nft
new file mode 100644 (file)
index 0000000..f580c38
--- /dev/null
@@ -0,0 +1,7 @@
+table ip t {
+       set s {
+               type mark
+               flags interval
+               elements = { 0x00000023-0x00000042, 0x00001337 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0041interval_0.json-nft b/tests/shell/testcases/sets/dumps/0041interval_0.json-nft
new file mode 100644 (file)
index 0000000..c59a65a
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          "192.168.2.196"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0041interval_0.nft b/tests/shell/testcases/sets/dumps/0041interval_0.nft
new file mode 100644 (file)
index 0000000..222d4d7
--- /dev/null
@@ -0,0 +1,7 @@
+table ip t {
+       set s {
+               type ipv4_addr
+               flags interval
+               elements = { 192.168.2.196 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0042update_set_0.json-nft b/tests/shell/testcases/sets/dumps/0042update_set_0.json-nft
new file mode 100644 (file)
index 0000000..3f98e12
--- /dev/null
@@ -0,0 +1,85 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "set1",
+        "table": "t",
+        "type": "ether_addr",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "set2",
+        "table": "t",
+        "type": "ether_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "daddr"
+                }
+              },
+              "right": "@set1"
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "payload": {
+                  "protocol": "ether",
+                  "field": "daddr"
+                }
+              },
+              "set": "@set2",
+              "stmt": [
+                {
+                  "counter": null
+                }
+              ]
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0042update_set_0.nft b/tests/shell/testcases/sets/dumps/0042update_set_0.nft
new file mode 100644 (file)
index 0000000..56cc875
--- /dev/null
@@ -0,0 +1,15 @@
+table ip t {
+       set set1 {
+               type ether_addr
+       }
+
+       set set2 {
+               type ether_addr
+               size 65535
+               flags dynamic
+       }
+
+       chain c {
+               ether daddr @set1 add @set2 { ether daddr counter }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0043concatenated_ranges_0.json-nft b/tests/shell/testcases/sets/dumps/0043concatenated_ranges_0.json-nft
new file mode 100644 (file)
index 0000000..ffb76e2
--- /dev/null
@@ -0,0 +1,98 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "output",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "test",
+        "table": "filter",
+        "type": [
+          "mark",
+          "inet_service",
+          "inet_proto"
+        ],
+        "handle": 0,
+        "map": "mark",
+        "flags": [
+          "interval",
+          "timeout"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "output",
+        "handle": 0,
+        "expr": [
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": {
+                "map": {
+                  "key": {
+                    "concat": [
+                      {
+                        "meta": {
+                          "key": "mark"
+                        }
+                      },
+                      {
+                        "payload": {
+                          "protocol": "tcp",
+                          "field": "dport"
+                        }
+                      },
+                      {
+                        "meta": {
+                          "key": "l4proto"
+                        }
+                      }
+                    ]
+                  },
+                  "data": "@test"
+                }
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0043concatenated_ranges_0.nft b/tests/shell/testcases/sets/dumps/0043concatenated_ranges_0.nft
new file mode 100644 (file)
index 0000000..f2077b9
--- /dev/null
@@ -0,0 +1,11 @@
+table inet filter {
+       map test {
+               type mark . inet_service . inet_proto : mark
+               flags interval,timeout
+       }
+
+       chain output {
+               type filter hook output priority filter; policy accept;
+               meta mark set meta mark . tcp dport . meta l4proto map @test counter packets 0 bytes 0
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0043concatenated_ranges_1.json-nft b/tests/shell/testcases/sets/dumps/0043concatenated_ranges_1.json-nft
new file mode 100644 (file)
index 0000000..5ce063d
--- /dev/null
@@ -0,0 +1,1719 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip6",
+        "name": "s",
+        "table": "t",
+        "type": [
+          "ipv6_addr",
+          "ipv6_addr"
+        ],
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 32
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:20::",
+                  "2001:db8:20::20:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 33
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:21::",
+                  "2001:db8:21::21:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 34
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:22::",
+                  "2001:db8:22::22:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 35
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:23::",
+                  "2001:db8:23::23:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 36
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:24::",
+                  "2001:db8:24::24:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 37
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:25::",
+                  "2001:db8:25::25:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 38
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:26::",
+                  "2001:db8:26::26:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 39
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:27::",
+                  "2001:db8:27::27:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 40
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:28::",
+                  "2001:db8:28::28:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 41
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:29::",
+                  "2001:db8:29::29:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 42
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:2a::",
+                  "2001:db8:2a::2a:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 43
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:2b::",
+                  "2001:db8:2b::2b:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 44
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:2c::",
+                  "2001:db8:2c::2c:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 45
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:2d::",
+                  "2001:db8:2d::2d:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 46
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:2e::",
+                  "2001:db8:2e::2e:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 47
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:2f::",
+                  "2001:db8:2f::2f:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 48
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:30::",
+                  "2001:db8:30::30:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 49
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:31::",
+                  "2001:db8:31::31:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 50
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:32::",
+                  "2001:db8:32::32:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 51
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:33::",
+                  "2001:db8:33::33:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 52
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:34::",
+                  "2001:db8:34::34:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 53
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:35::",
+                  "2001:db8:35::35:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 54
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:36::",
+                  "2001:db8:36::36:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 55
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:37::",
+                  "2001:db8:37::37:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 56
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:38::",
+                  "2001:db8:38::38:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 57
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:39::",
+                  "2001:db8:39::39:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 58
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:3a::",
+                  "2001:db8:3a::3a:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 59
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:3b::",
+                  "2001:db8:3b::3b:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 60
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:3c::",
+                  "2001:db8:3c::3c:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 61
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:3d::",
+                  "2001:db8:3d::3d:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 62
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:3e::",
+                  "2001:db8:3e::3e:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 63
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:3f::",
+                  "2001:db8:3f::3f:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 64
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:40::",
+                  "2001:db8:40::40:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 65
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:41::",
+                  "2001:db8:41::41:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 66
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:42::",
+                  "2001:db8:42::42:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 67
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:43::",
+                  "2001:db8:43::43:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 68
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:44::",
+                  "2001:db8:44::44:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 69
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:45::",
+                  "2001:db8:45::45:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 70
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:46::",
+                  "2001:db8:46::46:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 71
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:47::",
+                  "2001:db8:47::47:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 72
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:48::",
+                  "2001:db8:48::48:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 73
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:49::",
+                  "2001:db8:49::49:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 74
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:4a::",
+                  "2001:db8:4a::4a:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 75
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:4b::",
+                  "2001:db8:4b::4b:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 76
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:4c::",
+                  "2001:db8:4c::4c:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 77
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:4d::",
+                  "2001:db8:4d::4d:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 78
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:4e::",
+                  "2001:db8:4e::4e:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 79
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:4f::",
+                  "2001:db8:4f::4f:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 80
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:50::",
+                  "2001:db8:50::50:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 81
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:51::",
+                  "2001:db8:51::51:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 82
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:52::",
+                  "2001:db8:52::52:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 83
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:53::",
+                  "2001:db8:53::53:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 84
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:54::",
+                  "2001:db8:54::54:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 85
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:55::",
+                  "2001:db8:55::55:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 86
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:56::",
+                  "2001:db8:56::56:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 87
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:57::",
+                  "2001:db8:57::57:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 88
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:58::",
+                  "2001:db8:58::58:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 89
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:59::",
+                  "2001:db8:59::59:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 90
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:5a::",
+                  "2001:db8:5a::5a:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 91
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:5b::",
+                  "2001:db8:5b::5b:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 92
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:5c::",
+                  "2001:db8:5c::5c:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 93
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:5d::",
+                  "2001:db8:5d::5d:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 94
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:5e::",
+                  "2001:db8:5e::5e:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 95
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:5f::",
+                  "2001:db8:5f::5f:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 96
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:60::",
+                  "2001:db8:60::60:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 97
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:61::",
+                  "2001:db8:61::61:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 98
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:62::",
+                  "2001:db8:62::62:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 99
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:63::",
+                  "2001:db8:63::63:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 100
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:64::",
+                  "2001:db8:64::64:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 101
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:65::",
+                  "2001:db8:65::65:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 102
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:66::",
+                  "2001:db8:66::66:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 103
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:67::",
+                  "2001:db8:67::67:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 104
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:68::",
+                  "2001:db8:68::68:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 105
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:69::",
+                  "2001:db8:69::69:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 106
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:6a::",
+                  "2001:db8:6a::6a:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 107
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:6b::",
+                  "2001:db8:6b::6b:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 108
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:6c::",
+                  "2001:db8:6c::6c:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 109
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:6d::",
+                  "2001:db8:6d::6d:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 110
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:6e::",
+                  "2001:db8:6e::6e:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 111
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:6f::",
+                  "2001:db8:6f::6f:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 112
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:70::",
+                  "2001:db8:70::70:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 113
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:71::",
+                  "2001:db8:71::71:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 114
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:72::",
+                  "2001:db8:72::72:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 115
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:73::",
+                  "2001:db8:73::73:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 116
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:74::",
+                  "2001:db8:74::74:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 117
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:75::",
+                  "2001:db8:75::75:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 118
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:76::",
+                  "2001:db8:76::76:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 119
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:77::",
+                  "2001:db8:77::77:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 120
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:78::",
+                  "2001:db8:78::78:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 121
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:79::",
+                  "2001:db8:79::79:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 122
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:7a::",
+                  "2001:db8:7a::7a:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 123
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:7b::",
+                  "2001:db8:7b::7b:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 124
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:7c::",
+                  "2001:db8:7c::7c:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 125
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:7d::",
+                  "2001:db8:7d::7d:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 126
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:7e::",
+                  "2001:db8:7e::7e:1"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "2001:db8::",
+                  "len": 127
+                }
+              },
+              {
+                "range": [
+                  "2001:db8:7f::",
+                  "2001:db8:7f::7f:1"
+                ]
+              }
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "ipv4_addr"
+        ],
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "192.0.2.0",
+                  "len": 24
+                }
+              },
+              {
+                "range": [
+                  "192.0.2.72",
+                  "192.0.2.74"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "192.0.2.0",
+                  "len": 25
+                }
+              },
+              {
+                "range": [
+                  "192.0.2.75",
+                  "192.0.2.77"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "192.0.2.0",
+                  "len": 26
+                }
+              },
+              {
+                "range": [
+                  "192.0.2.78",
+                  "192.0.2.80"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "192.0.2.0",
+                  "len": 27
+                }
+              },
+              {
+                "range": [
+                  "192.0.2.81",
+                  "192.0.2.83"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "192.0.2.0",
+                  "len": 28
+                }
+              },
+              {
+                "range": [
+                  "192.0.2.84",
+                  "192.0.2.86"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "192.0.2.0",
+                  "len": 29
+                }
+              },
+              {
+                "range": [
+                  "192.0.2.87",
+                  "192.0.2.89"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "192.0.2.0",
+                  "len": 30
+                }
+              },
+              {
+                "range": [
+                  "192.0.2.90",
+                  "192.0.2.92"
+                ]
+              }
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "192.0.2.0",
+                  "len": 31
+                }
+              },
+              {
+                "range": [
+                  "192.0.2.93",
+                  "192.0.2.95"
+                ]
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0043concatenated_ranges_1.nft b/tests/shell/testcases/sets/dumps/0043concatenated_ranges_1.nft
new file mode 100644 (file)
index 0000000..19d08d3
--- /dev/null
@@ -0,0 +1,116 @@
+table ip6 t {
+       set s {
+               type ipv6_addr . ipv6_addr
+               flags interval
+               elements = { 2001:db8::/32 . 2001:db8:20::-2001:db8:20::20:1,
+                            2001:db8::/33 . 2001:db8:21::-2001:db8:21::21:1,
+                            2001:db8::/34 . 2001:db8:22::-2001:db8:22::22:1,
+                            2001:db8::/35 . 2001:db8:23::-2001:db8:23::23:1,
+                            2001:db8::/36 . 2001:db8:24::-2001:db8:24::24:1,
+                            2001:db8::/37 . 2001:db8:25::-2001:db8:25::25:1,
+                            2001:db8::/38 . 2001:db8:26::-2001:db8:26::26:1,
+                            2001:db8::/39 . 2001:db8:27::-2001:db8:27::27:1,
+                            2001:db8::/40 . 2001:db8:28::-2001:db8:28::28:1,
+                            2001:db8::/41 . 2001:db8:29::-2001:db8:29::29:1,
+                            2001:db8::/42 . 2001:db8:2a::-2001:db8:2a::2a:1,
+                            2001:db8::/43 . 2001:db8:2b::-2001:db8:2b::2b:1,
+                            2001:db8::/44 . 2001:db8:2c::-2001:db8:2c::2c:1,
+                            2001:db8::/45 . 2001:db8:2d::-2001:db8:2d::2d:1,
+                            2001:db8::/46 . 2001:db8:2e::-2001:db8:2e::2e:1,
+                            2001:db8::/47 . 2001:db8:2f::-2001:db8:2f::2f:1,
+                            2001:db8::/48 . 2001:db8:30::-2001:db8:30::30:1,
+                            2001:db8::/49 . 2001:db8:31::-2001:db8:31::31:1,
+                            2001:db8::/50 . 2001:db8:32::-2001:db8:32::32:1,
+                            2001:db8::/51 . 2001:db8:33::-2001:db8:33::33:1,
+                            2001:db8::/52 . 2001:db8:34::-2001:db8:34::34:1,
+                            2001:db8::/53 . 2001:db8:35::-2001:db8:35::35:1,
+                            2001:db8::/54 . 2001:db8:36::-2001:db8:36::36:1,
+                            2001:db8::/55 . 2001:db8:37::-2001:db8:37::37:1,
+                            2001:db8::/56 . 2001:db8:38::-2001:db8:38::38:1,
+                            2001:db8::/57 . 2001:db8:39::-2001:db8:39::39:1,
+                            2001:db8::/58 . 2001:db8:3a::-2001:db8:3a::3a:1,
+                            2001:db8::/59 . 2001:db8:3b::-2001:db8:3b::3b:1,
+                            2001:db8::/60 . 2001:db8:3c::-2001:db8:3c::3c:1,
+                            2001:db8::/61 . 2001:db8:3d::-2001:db8:3d::3d:1,
+                            2001:db8::/62 . 2001:db8:3e::-2001:db8:3e::3e:1,
+                            2001:db8::/63 . 2001:db8:3f::-2001:db8:3f::3f:1,
+                            2001:db8::/64 . 2001:db8:40::-2001:db8:40::40:1,
+                            2001:db8::/65 . 2001:db8:41::-2001:db8:41::41:1,
+                            2001:db8::/66 . 2001:db8:42::-2001:db8:42::42:1,
+                            2001:db8::/67 . 2001:db8:43::-2001:db8:43::43:1,
+                            2001:db8::/68 . 2001:db8:44::-2001:db8:44::44:1,
+                            2001:db8::/69 . 2001:db8:45::-2001:db8:45::45:1,
+                            2001:db8::/70 . 2001:db8:46::-2001:db8:46::46:1,
+                            2001:db8::/71 . 2001:db8:47::-2001:db8:47::47:1,
+                            2001:db8::/72 . 2001:db8:48::-2001:db8:48::48:1,
+                            2001:db8::/73 . 2001:db8:49::-2001:db8:49::49:1,
+                            2001:db8::/74 . 2001:db8:4a::-2001:db8:4a::4a:1,
+                            2001:db8::/75 . 2001:db8:4b::-2001:db8:4b::4b:1,
+                            2001:db8::/76 . 2001:db8:4c::-2001:db8:4c::4c:1,
+                            2001:db8::/77 . 2001:db8:4d::-2001:db8:4d::4d:1,
+                            2001:db8::/78 . 2001:db8:4e::-2001:db8:4e::4e:1,
+                            2001:db8::/79 . 2001:db8:4f::-2001:db8:4f::4f:1,
+                            2001:db8::/80 . 2001:db8:50::-2001:db8:50::50:1,
+                            2001:db8::/81 . 2001:db8:51::-2001:db8:51::51:1,
+                            2001:db8::/82 . 2001:db8:52::-2001:db8:52::52:1,
+                            2001:db8::/83 . 2001:db8:53::-2001:db8:53::53:1,
+                            2001:db8::/84 . 2001:db8:54::-2001:db8:54::54:1,
+                            2001:db8::/85 . 2001:db8:55::-2001:db8:55::55:1,
+                            2001:db8::/86 . 2001:db8:56::-2001:db8:56::56:1,
+                            2001:db8::/87 . 2001:db8:57::-2001:db8:57::57:1,
+                            2001:db8::/88 . 2001:db8:58::-2001:db8:58::58:1,
+                            2001:db8::/89 . 2001:db8:59::-2001:db8:59::59:1,
+                            2001:db8::/90 . 2001:db8:5a::-2001:db8:5a::5a:1,
+                            2001:db8::/91 . 2001:db8:5b::-2001:db8:5b::5b:1,
+                            2001:db8::/92 . 2001:db8:5c::-2001:db8:5c::5c:1,
+                            2001:db8::/93 . 2001:db8:5d::-2001:db8:5d::5d:1,
+                            2001:db8::/94 . 2001:db8:5e::-2001:db8:5e::5e:1,
+                            2001:db8::/95 . 2001:db8:5f::-2001:db8:5f::5f:1,
+                            2001:db8::/96 . 2001:db8:60::-2001:db8:60::60:1,
+                            2001:db8::/97 . 2001:db8:61::-2001:db8:61::61:1,
+                            2001:db8::/98 . 2001:db8:62::-2001:db8:62::62:1,
+                            2001:db8::/99 . 2001:db8:63::-2001:db8:63::63:1,
+                            2001:db8::/100 . 2001:db8:64::-2001:db8:64::64:1,
+                            2001:db8::/101 . 2001:db8:65::-2001:db8:65::65:1,
+                            2001:db8::/102 . 2001:db8:66::-2001:db8:66::66:1,
+                            2001:db8::/103 . 2001:db8:67::-2001:db8:67::67:1,
+                            2001:db8::/104 . 2001:db8:68::-2001:db8:68::68:1,
+                            2001:db8::/105 . 2001:db8:69::-2001:db8:69::69:1,
+                            2001:db8::/106 . 2001:db8:6a::-2001:db8:6a::6a:1,
+                            2001:db8::/107 . 2001:db8:6b::-2001:db8:6b::6b:1,
+                            2001:db8::/108 . 2001:db8:6c::-2001:db8:6c::6c:1,
+                            2001:db8::/109 . 2001:db8:6d::-2001:db8:6d::6d:1,
+                            2001:db8::/110 . 2001:db8:6e::-2001:db8:6e::6e:1,
+                            2001:db8::/111 . 2001:db8:6f::-2001:db8:6f::6f:1,
+                            2001:db8::/112 . 2001:db8:70::-2001:db8:70::70:1,
+                            2001:db8::/113 . 2001:db8:71::-2001:db8:71::71:1,
+                            2001:db8::/114 . 2001:db8:72::-2001:db8:72::72:1,
+                            2001:db8::/115 . 2001:db8:73::-2001:db8:73::73:1,
+                            2001:db8::/116 . 2001:db8:74::-2001:db8:74::74:1,
+                            2001:db8::/117 . 2001:db8:75::-2001:db8:75::75:1,
+                            2001:db8::/118 . 2001:db8:76::-2001:db8:76::76:1,
+                            2001:db8::/119 . 2001:db8:77::-2001:db8:77::77:1,
+                            2001:db8::/120 . 2001:db8:78::-2001:db8:78::78:1,
+                            2001:db8::/121 . 2001:db8:79::-2001:db8:79::79:1,
+                            2001:db8::/122 . 2001:db8:7a::-2001:db8:7a::7a:1,
+                            2001:db8::/123 . 2001:db8:7b::-2001:db8:7b::7b:1,
+                            2001:db8::/124 . 2001:db8:7c::-2001:db8:7c::7c:1,
+                            2001:db8::/125 . 2001:db8:7d::-2001:db8:7d::7d:1,
+                            2001:db8::/126 . 2001:db8:7e::-2001:db8:7e::7e:1,
+                            2001:db8::/127 . 2001:db8:7f::-2001:db8:7f::7f:1 }
+       }
+}
+table ip t {
+       set s {
+               type ipv4_addr . ipv4_addr
+               flags interval
+               elements = { 192.0.2.0/24 . 192.0.2.72-192.0.2.74,
+                            192.0.2.0/25 . 192.0.2.75-192.0.2.77,
+                            192.0.2.0/26 . 192.0.2.78-192.0.2.80,
+                            192.0.2.0/27 . 192.0.2.81-192.0.2.83,
+                            192.0.2.0/28 . 192.0.2.84-192.0.2.86,
+                            192.0.2.0/29 . 192.0.2.87-192.0.2.89,
+                            192.0.2.0/30 . 192.0.2.90-192.0.2.92,
+                            192.0.2.0/31 . 192.0.2.93-192.0.2.95 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0044interval_overlap_0.nodump b/tests/shell/testcases/sets/dumps/0044interval_overlap_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/0044interval_overlap_1.json-nft b/tests/shell/testcases/sets/dumps/0044interval_overlap_1.json-nft
new file mode 100644 (file)
index 0000000..8f82990
--- /dev/null
@@ -0,0 +1,527 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "inet_service",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          25,
+          30,
+          82,
+          119,
+          349,
+          745,
+          748,
+          1165,
+          1233,
+          1476,
+          1550,
+          1562,
+          1743,
+          1745,
+          1882,
+          2070,
+          2194,
+          2238,
+          2450,
+          2455,
+          2642,
+          2671,
+          2906,
+          3093,
+          3203,
+          3287,
+          3348,
+          3411,
+          3540,
+          3892,
+          3943,
+          4133,
+          4205,
+          4317,
+          4733,
+          5095,
+          5156,
+          5223,
+          5230,
+          5432,
+          5826,
+          5828,
+          6044,
+          6377,
+          6388,
+          6491,
+          6952,
+          6986,
+          7012,
+          7187,
+          7300,
+          7305,
+          7549,
+          7664,
+          8111,
+          8206,
+          8396,
+          8782,
+          8920,
+          8981,
+          9067,
+          9216,
+          9245,
+          9315,
+          9432,
+          9587,
+          9689,
+          9844,
+          9991,
+          10045,
+          10252,
+          10328,
+          10670,
+          10907,
+          11021,
+          11337,
+          11427,
+          11497,
+          11502,
+          11523,
+          11552,
+          11577,
+          11721,
+          11943,
+          12474,
+          12718,
+          12764,
+          12794,
+          12922,
+          13186,
+          13232,
+          13383,
+          13431,
+          13551,
+          13676,
+          13685,
+          13747,
+          13925,
+          13935,
+          14015,
+          14090,
+          14320,
+          14392,
+          14515,
+          14647,
+          14911,
+          15096,
+          15105,
+          15154,
+          15440,
+          15583,
+          15623,
+          15677,
+          15710,
+          15926,
+          15934,
+          15960,
+          16068,
+          16166,
+          16486,
+          16489,
+          16528,
+          16646,
+          16650,
+          16770,
+          16882,
+          17052,
+          17237,
+          17387,
+          17431,
+          17886,
+          17939,
+          17999,
+          18092,
+          18123,
+          18238,
+          18562,
+          18698,
+          19004,
+          19229,
+          19237,
+          19585,
+          19879,
+          19938,
+          19950,
+          19958,
+          20031,
+          20138,
+          20157,
+          20205,
+          20368,
+          20682,
+          20687,
+          20873,
+          20910,
+          20919,
+          21019,
+          21068,
+          21115,
+          21188,
+          21236,
+          21319,
+          21563,
+          21734,
+          21806,
+          21810,
+          21959,
+          21982,
+          22078,
+          22181,
+          22308,
+          22480,
+          22643,
+          22854,
+          22879,
+          22961,
+          23397,
+          23534,
+          23845,
+          23893,
+          24130,
+          24406,
+          24794,
+          24997,
+          25019,
+          25143,
+          25179,
+          25439,
+          25603,
+          25718,
+          25859,
+          25949,
+          26006,
+          26022,
+          26047,
+          26170,
+          26193,
+          26725,
+          26747,
+          26924,
+          27023,
+          27040,
+          27233,
+          27344,
+          27478,
+          27593,
+          27600,
+          27664,
+          27678,
+          27818,
+          27822,
+          28003,
+          28038,
+          28709,
+          28808,
+          29010,
+          29057,
+          29228,
+          29485,
+          30132,
+          30160,
+          30415,
+          30469,
+          30673,
+          30736,
+          30776,
+          30780,
+          31450,
+          31537,
+          31669,
+          31839,
+          31873,
+          32019,
+          32229,
+          32685,
+          32879,
+          33318,
+          33337,
+          33404,
+          33517,
+          33906,
+          34214,
+          34346,
+          34416,
+          34727,
+          34848,
+          35325,
+          35400,
+          35451,
+          35501,
+          35637,
+          35653,
+          35710,
+          35761,
+          35767,
+          36238,
+          36258,
+          36279,
+          36464,
+          36586,
+          36603,
+          36770,
+          36774,
+          36805,
+          36851,
+          37079,
+          37189,
+          37209,
+          37565,
+          37570,
+          37585,
+          37832,
+          37931,
+          37954,
+          38006,
+          38015,
+          38045,
+          38109,
+          38114,
+          38200,
+          38209,
+          38214,
+          38277,
+          38306,
+          38402,
+          38606,
+          38697,
+          38960,
+          39004,
+          39006,
+          39197,
+          39217,
+          39265,
+          39319,
+          39460,
+          39550,
+          39615,
+          39871,
+          39886,
+          40088,
+          40135,
+          40244,
+          40323,
+          40339,
+          40355,
+          40385,
+          40428,
+          40538,
+          40791,
+          40848,
+          40959,
+          41003,
+          41131,
+          41349,
+          41643,
+          41710,
+          41826,
+          41904,
+          42027,
+          42148,
+          42235,
+          42255,
+          42498,
+          42680,
+          42973,
+          43118,
+          43135,
+          43233,
+          43349,
+          43411,
+          43487,
+          43840,
+          43843,
+          43870,
+          44040,
+          44204,
+          44817,
+          44883,
+          44894,
+          44958,
+          45201,
+          45259,
+          45283,
+          45357,
+          45423,
+          45473,
+          45498,
+          45519,
+          45561,
+          45611,
+          45627,
+          45831,
+          46043,
+          46105,
+          46116,
+          46147,
+          46169,
+          46349,
+          47147,
+          47252,
+          47314,
+          47335,
+          47360,
+          47546,
+          47617,
+          47648,
+          47772,
+          47793,
+          47846,
+          47913,
+          47952,
+          48095,
+          48325,
+          48334,
+          48412,
+          48419,
+          48540,
+          48569,
+          48628,
+          48751,
+          48944,
+          48971,
+          49008,
+          49025,
+          49503,
+          49505,
+          49613,
+          49767,
+          49839,
+          49925,
+          50022,
+          50028,
+          50238,
+          51057,
+          51477,
+          51617,
+          51910,
+          52044,
+          52482,
+          52550,
+          52643,
+          52832,
+          53382,
+          53690,
+          53809,
+          53858,
+          54001,
+          54198,
+          54280,
+          54327,
+          54376,
+          54609,
+          54776,
+          54983,
+          54984,
+          55019,
+          55038,
+          55094,
+          55368,
+          55737,
+          55793,
+          55904,
+          55941,
+          55960,
+          55978,
+          56063,
+          56121,
+          56314,
+          56505,
+          56548,
+          56568,
+          56696,
+          56798,
+          56855,
+          57102,
+          57236,
+          57333,
+          57334,
+          57441,
+          57574,
+          57659,
+          57987,
+          58325,
+          58404,
+          58509,
+          58782,
+          58876,
+          59116,
+          59544,
+          59685,
+          59700,
+          59750,
+          59799,
+          59866,
+          59870,
+          59894,
+          59984,
+          60343,
+          60481,
+          60564,
+          60731,
+          61075,
+          61087,
+          61148,
+          61174,
+          61655,
+          61679,
+          61691,
+          61723,
+          61730,
+          61758,
+          61824,
+          62035,
+          62056,
+          62661,
+          62768,
+          62946,
+          63059,
+          63116,
+          63338,
+          63387,
+          63672,
+          63719,
+          63881,
+          63995,
+          64197,
+          64374,
+          64377,
+          64472,
+          64606,
+          64662,
+          64777,
+          64795,
+          64906,
+          65049,
+          65122,
+          65318
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0044interval_overlap_1.nft b/tests/shell/testcases/sets/dumps/0044interval_overlap_1.nft
new file mode 100644 (file)
index 0000000..5b249a3
--- /dev/null
@@ -0,0 +1,106 @@
+table ip t {
+       set s {
+               type inet_service
+               flags interval
+               elements = { 25, 30, 82, 119, 349,
+                            745, 748, 1165, 1233, 1476,
+                            1550, 1562, 1743, 1745, 1882,
+                            2070, 2194, 2238, 2450, 2455,
+                            2642, 2671, 2906, 3093, 3203,
+                            3287, 3348, 3411, 3540, 3892,
+                            3943, 4133, 4205, 4317, 4733,
+                            5095, 5156, 5223, 5230, 5432,
+                            5826, 5828, 6044, 6377, 6388,
+                            6491, 6952, 6986, 7012, 7187,
+                            7300, 7305, 7549, 7664, 8111,
+                            8206, 8396, 8782, 8920, 8981,
+                            9067, 9216, 9245, 9315, 9432,
+                            9587, 9689, 9844, 9991, 10045,
+                            10252, 10328, 10670, 10907, 11021,
+                            11337, 11427, 11497, 11502, 11523,
+                            11552, 11577, 11721, 11943, 12474,
+                            12718, 12764, 12794, 12922, 13186,
+                            13232, 13383, 13431, 13551, 13676,
+                            13685, 13747, 13925, 13935, 14015,
+                            14090, 14320, 14392, 14515, 14647,
+                            14911, 15096, 15105, 15154, 15440,
+                            15583, 15623, 15677, 15710, 15926,
+                            15934, 15960, 16068, 16166, 16486,
+                            16489, 16528, 16646, 16650, 16770,
+                            16882, 17052, 17237, 17387, 17431,
+                            17886, 17939, 17999, 18092, 18123,
+                            18238, 18562, 18698, 19004, 19229,
+                            19237, 19585, 19879, 19938, 19950,
+                            19958, 20031, 20138, 20157, 20205,
+                            20368, 20682, 20687, 20873, 20910,
+                            20919, 21019, 21068, 21115, 21188,
+                            21236, 21319, 21563, 21734, 21806,
+                            21810, 21959, 21982, 22078, 22181,
+                            22308, 22480, 22643, 22854, 22879,
+                            22961, 23397, 23534, 23845, 23893,
+                            24130, 24406, 24794, 24997, 25019,
+                            25143, 25179, 25439, 25603, 25718,
+                            25859, 25949, 26006, 26022, 26047,
+                            26170, 26193, 26725, 26747, 26924,
+                            27023, 27040, 27233, 27344, 27478,
+                            27593, 27600, 27664, 27678, 27818,
+                            27822, 28003, 28038, 28709, 28808,
+                            29010, 29057, 29228, 29485, 30132,
+                            30160, 30415, 30469, 30673, 30736,
+                            30776, 30780, 31450, 31537, 31669,
+                            31839, 31873, 32019, 32229, 32685,
+                            32879, 33318, 33337, 33404, 33517,
+                            33906, 34214, 34346, 34416, 34727,
+                            34848, 35325, 35400, 35451, 35501,
+                            35637, 35653, 35710, 35761, 35767,
+                            36238, 36258, 36279, 36464, 36586,
+                            36603, 36770, 36774, 36805, 36851,
+                            37079, 37189, 37209, 37565, 37570,
+                            37585, 37832, 37931, 37954, 38006,
+                            38015, 38045, 38109, 38114, 38200,
+                            38209, 38214, 38277, 38306, 38402,
+                            38606, 38697, 38960, 39004, 39006,
+                            39197, 39217, 39265, 39319, 39460,
+                            39550, 39615, 39871, 39886, 40088,
+                            40135, 40244, 40323, 40339, 40355,
+                            40385, 40428, 40538, 40791, 40848,
+                            40959, 41003, 41131, 41349, 41643,
+                            41710, 41826, 41904, 42027, 42148,
+                            42235, 42255, 42498, 42680, 42973,
+                            43118, 43135, 43233, 43349, 43411,
+                            43487, 43840, 43843, 43870, 44040,
+                            44204, 44817, 44883, 44894, 44958,
+                            45201, 45259, 45283, 45357, 45423,
+                            45473, 45498, 45519, 45561, 45611,
+                            45627, 45831, 46043, 46105, 46116,
+                            46147, 46169, 46349, 47147, 47252,
+                            47314, 47335, 47360, 47546, 47617,
+                            47648, 47772, 47793, 47846, 47913,
+                            47952, 48095, 48325, 48334, 48412,
+                            48419, 48540, 48569, 48628, 48751,
+                            48944, 48971, 49008, 49025, 49503,
+                            49505, 49613, 49767, 49839, 49925,
+                            50022, 50028, 50238, 51057, 51477,
+                            51617, 51910, 52044, 52482, 52550,
+                            52643, 52832, 53382, 53690, 53809,
+                            53858, 54001, 54198, 54280, 54327,
+                            54376, 54609, 54776, 54983, 54984,
+                            55019, 55038, 55094, 55368, 55737,
+                            55793, 55904, 55941, 55960, 55978,
+                            56063, 56121, 56314, 56505, 56548,
+                            56568, 56696, 56798, 56855, 57102,
+                            57236, 57333, 57334, 57441, 57574,
+                            57659, 57987, 58325, 58404, 58509,
+                            58782, 58876, 59116, 59544, 59685,
+                            59700, 59750, 59799, 59866, 59870,
+                            59894, 59984, 60343, 60481, 60564,
+                            60731, 61075, 61087, 61148, 61174,
+                            61655, 61679, 61691, 61723, 61730,
+                            61758, 61824, 62035, 62056, 62661,
+                            62768, 62946, 63059, 63116, 63338,
+                            63387, 63672, 63719, 63881, 63995,
+                            64197, 64374, 64377, 64472, 64606,
+                            64662, 64777, 64795, 64906, 65049,
+                            65122, 65318 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0045concat_ipv4_service.json-nft b/tests/shell/testcases/sets/dumps/0045concat_ipv4_service.json-nft
new file mode 100644 (file)
index 0000000..8473c33
--- /dev/null
@@ -0,0 +1,95 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "size": 65536,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ],
+        "elem": [
+          {
+            "concat": [
+              "192.168.7.1",
+              22
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 21
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "saddr"
+                        }
+                      },
+                      22
+                    ]
+                  },
+                  "timeout": 60
+                }
+              },
+              "set": "@s"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0046netmap_0.json-nft b/tests/shell/testcases/sets/dumps/0046netmap_0.json-nft
new file mode 100644 (file)
index 0000000..55f1a2a
--- /dev/null
@@ -0,0 +1,167 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "nat",
+        "hook": "postrouting",
+        "prio": 100,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "snat": {
+              "family": "ip",
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        {
+                          "prefix": {
+                            "addr": "10.141.11.0",
+                            "len": 24
+                          }
+                        },
+                        {
+                          "prefix": {
+                            "addr": "192.168.2.0",
+                            "len": 24
+                          }
+                        }
+                      ],
+                      [
+                        {
+                          "prefix": {
+                            "addr": "10.141.12.0",
+                            "len": 24
+                          }
+                        },
+                        {
+                          "prefix": {
+                            "addr": "192.168.3.0",
+                            "len": 24
+                          }
+                        }
+                      ],
+                      [
+                        {
+                          "prefix": {
+                            "addr": "10.141.13.0",
+                            "len": 24
+                          }
+                        },
+                        {
+                          "prefix": {
+                            "addr": "192.168.4.0",
+                            "len": 24
+                          }
+                        }
+                      ]
+                    ]
+                  }
+                }
+              },
+              "flags": "netmap",
+              "type_flags": "prefix"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "nat",
+        "hook": "postrouting",
+        "prio": 100,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "snat": {
+              "family": "ip6",
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip6",
+                      "field": "saddr"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        {
+                          "prefix": {
+                            "addr": "2001:db8:1111::",
+                            "len": 64
+                          }
+                        },
+                        {
+                          "prefix": {
+                            "addr": "2001:db8:2222::",
+                            "len": 64
+                          }
+                        }
+                      ]
+                    ]
+                  }
+                }
+              },
+              "flags": "netmap",
+              "type_flags": "prefix"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index 9fa9fc7456c5495c0e6520cfd67fb4c7f11efbbc..86dbb70880ff0a0c0fc2c9fa52d47c7cf6a46640 100644 (file)
@@ -2,7 +2,8 @@ table ip x {
        map y {
                type ipv4_addr : interval ipv4_addr
                flags interval
-               elements = { 10.141.10.0/24 : 192.168.2.2-192.168.2.4, 10.141.11.0/24 : 192.168.4.2/31,
+               elements = { 10.141.10.0/24 : 192.168.2.2-192.168.2.4,
+                            10.141.11.0/24 : 192.168.4.2/31,
                             10.141.12.0/24 : 192.168.5.10-192.168.5.20 }
        }
 
diff --git a/tests/shell/testcases/sets/dumps/0048set_counters_0.json-nft b/tests/shell/testcases/sets/dumps/0048set_counters_0.json-nft
new file mode 100644 (file)
index 0000000..4be4112
--- /dev/null
@@ -0,0 +1,102 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "z",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": {
+          "typeof": {
+            "payload": {
+              "protocol": "ip",
+              "field": "saddr"
+            }
+          }
+        },
+        "handle": 0,
+        "elem": [
+          {
+            "elem": {
+              "val": "192.168.10.35",
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          },
+          {
+            "elem": {
+              "val": "192.168.10.101",
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          },
+          {
+            "elem": {
+              "val": "192.168.10.135",
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          }
+        ],
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "z",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "@y"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index 2145f6b11b88fe9feb535e34c9a6aa6c55dedf2b..d6247868e9f06784caa51ff7e99f7d46fcd54e2b 100644 (file)
@@ -2,7 +2,8 @@ table ip x {
        set y {
                typeof ip saddr
                counter
-               elements = { 192.168.10.35 counter packets 0 bytes 0, 192.168.10.101 counter packets 0 bytes 0,
+               elements = { 192.168.10.35 counter packets 0 bytes 0,
+                            192.168.10.101 counter packets 0 bytes 0,
                             192.168.10.135 counter packets 0 bytes 0 }
        }
 
diff --git a/tests/shell/testcases/sets/dumps/0049set_define_0.json-nft b/tests/shell/testcases/sets/dumps/0049set_define_0.json-nft
new file mode 100644 (file)
index 0000000..98ccafd
--- /dev/null
@@ -0,0 +1,92 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "drop"
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "ip-block-4-test",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "auto-merge": true,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": {
+                "set": [
+                  22,
+                  80,
+                  443
+                ]
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "new"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0050set_define_1.json-nft b/tests/shell/testcases/sets/dumps/0050set_define_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0050set_define_1.nft b/tests/shell/testcases/sets/dumps/0050set_define_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/0051set_interval_counter_0.json-nft b/tests/shell/testcases/sets/dumps/0051set_interval_counter_0.json-nft
new file mode 100644 (file)
index 0000000..96cb397
--- /dev/null
@@ -0,0 +1,83 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "elem": {
+              "val": {
+                "prefix": {
+                  "addr": "192.168.2.0",
+                  "len": 24
+                }
+              },
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          }
+        ],
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "@s"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0052overlap_0.json-nft b/tests/shell/testcases/sets/dumps/0052overlap_0.json-nft
new file mode 100644 (file)
index 0000000..1ea8ede
--- /dev/null
@@ -0,0 +1,33 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "w_all",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "auto-merge": true,
+        "elem": [
+          "10.10.10.10",
+          "10.10.10.253"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0053echo_0.json-nft b/tests/shell/testcases/sets/dumps/0053echo_0.json-nft
new file mode 100644 (file)
index 0000000..12a5c4b
--- /dev/null
@@ -0,0 +1,101 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "drop"
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": {
+                "prefix": {
+                  "addr": "10.0.0.0",
+                  "len": 8
+                }
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "192.168.100.62"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 2001
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0054comments_set_0.json-nft b/tests/shell/testcases/sets/dumps/0054comments_set_0.json-nft
new file mode 100644 (file)
index 0000000..a729392
--- /dev/null
@@ -0,0 +1,41 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "comment": "test",
+        "flags": "interval"
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "m",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "comment": "another test",
+        "map": "ipv4_addr",
+        "flags": "interval"
+      }
+    }
+  ]
+}
index e37139f334466102cc2016e8c576131a6e3066c4..0232ad6f28e3b996b534bae7ea5b5d81cb10d158 100644 (file)
@@ -21,9 +21,7 @@
         "table": "test",
         "type": "tcp_flag",
         "handle": 0,
-        "flags": [
-          "constant"
-        ],
+        "flags": "constant",
         "elem": [
           {
             "|": [
diff --git a/tests/shell/testcases/sets/dumps/0056dynamic_limit_0.json-nft b/tests/shell/testcases/sets/dumps/0056dynamic_limit_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0056dynamic_limit_0.nft b/tests/shell/testcases/sets/dumps/0056dynamic_limit_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/0057set_create_fails_0.json-nft b/tests/shell/testcases/sets/dumps/0057set_create_fails_0.json-nft
new file mode 100644 (file)
index 0000000..79d7257
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "test",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "elem": [
+          "1.1.1.1"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0057set_create_fails_0.nft b/tests/shell/testcases/sets/dumps/0057set_create_fails_0.nft
new file mode 100644 (file)
index 0000000..de43d56
--- /dev/null
@@ -0,0 +1,7 @@
+table inet filter {
+       set test {
+               type ipv4_addr
+               size 65535
+               elements = { 1.1.1.1 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0058_setupdate_timeout_0.json-nft b/tests/shell/testcases/sets/dumps/0058_setupdate_timeout_0.json-nft
new file mode 100644 (file)
index 0000000..ac8d8be
--- /dev/null
@@ -0,0 +1,68 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "filter",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "ssh_meter",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ],
+        "timeout": 2592000
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "filter",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "timeout": 2592000
+                }
+              },
+              "set": "@ssh_meter"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0059set_update_multistmt_0.json-nft b/tests/shell/testcases/sets/dumps/0059set_update_multistmt_0.json-nft
new file mode 100644 (file)
index 0000000..16ecdb2
--- /dev/null
@@ -0,0 +1,79 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "z",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ],
+        "timeout": 3600
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "z",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "set": "@y",
+              "stmt": [
+                {
+                  "limit": {
+                    "rate": 1,
+                    "burst": 5,
+                    "per": "second"
+                  }
+                },
+                {
+                  "counter": null
+                }
+              ]
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0060set_multistmt_0.json-nft b/tests/shell/testcases/sets/dumps/0060set_multistmt_0.json-nft
new file mode 100644 (file)
index 0000000..1aede14
--- /dev/null
@@ -0,0 +1,105 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          {
+            "elem": {
+              "val": "1.1.1.1",
+              "limit": {
+                "rate": 1,
+                "burst": 5,
+                "per": "second"
+              }
+            }
+          },
+          {
+            "elem": {
+              "val": "4.4.4.4",
+              "limit": {
+                "rate": 1,
+                "burst": 5,
+                "per": "second"
+              }
+            }
+          },
+          {
+            "elem": {
+              "val": "5.5.5.5",
+              "limit": {
+                "rate": 1,
+                "burst": 5,
+                "per": "second"
+              }
+            }
+          }
+        ],
+        "stmt": [
+          {
+            "limit": {
+              "rate": 1,
+              "burst": 5,
+              "per": "second"
+            }
+          },
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "@y"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index df68fcdf89e6b621c73509ce10ca5213d562ec2a..8521e3f7c176eab77b88e9e2c22344b10fa220bf 100644 (file)
@@ -2,7 +2,8 @@ table ip x {
        set y {
                type ipv4_addr
                limit rate 1/second burst 5 packets counter
-               elements = { 1.1.1.1 limit rate 1/second burst 5 packets counter packets 0 bytes 0, 4.4.4.4 limit rate 1/second burst 5 packets counter packets 0 bytes 0,
+               elements = { 1.1.1.1 limit rate 1/second burst 5 packets counter packets 0 bytes 0,
+                            4.4.4.4 limit rate 1/second burst 5 packets counter packets 0 bytes 0,
                             5.5.5.5 limit rate 1/second burst 5 packets counter packets 0 bytes 0 }
        }
 
diff --git a/tests/shell/testcases/sets/dumps/0060set_multistmt_1.json-nft b/tests/shell/testcases/sets/dumps/0060set_multistmt_1.json-nft
new file mode 100644 (file)
index 0000000..99805e5
--- /dev/null
@@ -0,0 +1,103 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic",
+        "elem": [
+          {
+            "elem": {
+              "val": "1.1.1.1",
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          },
+          {
+            "elem": {
+              "val": "1.2.3.4",
+              "counter": {
+                "packets": 9,
+                "bytes": 756
+              }
+            }
+          },
+          {
+            "elem": {
+              "val": "2.2.2.2",
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          }
+        ],
+        "stmt": [
+          {
+            "counter": null
+          },
+          {
+            "quota": {
+              "val": 500,
+              "val_unit": "bytes"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "set": "@y"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index ac1bd26b3e5826e472d11470da58961b0df40c7e..befc2f75bd42d4192c734d9f49a3a0f14048c1fd 100644 (file)
@@ -4,7 +4,8 @@ table ip x {
                size 65535
                flags dynamic
                counter quota 500 bytes
-               elements = { 1.1.1.1 counter packets 0 bytes 0 quota 500 bytes, 1.2.3.4 counter packets 9 bytes 756 quota 500 bytes used 500 bytes,
+               elements = { 1.1.1.1 counter packets 0 bytes 0 quota 500 bytes,
+                            1.2.3.4 counter packets 9 bytes 756 quota 500 bytes used 500 bytes,
                             2.2.2.2 counter packets 0 bytes 0 quota 1000 bytes }
        }
 
diff --git a/tests/shell/testcases/sets/dumps/0061anonymous_automerge_0.json-nft b/tests/shell/testcases/sets/dumps/0061anonymous_automerge_0.json-nft
new file mode 100644 (file)
index 0000000..c559150
--- /dev/null
@@ -0,0 +1,57 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": {
+                "set": [
+                  {
+                    "range": [
+                      "1.1.1.1",
+                      "1.1.1.2"
+                    ]
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0062set_connlimit_0.json-nft b/tests/shell/testcases/sets/dumps/0062set_connlimit_0.json-nft
new file mode 100644 (file)
index 0000000..7a948b1
--- /dev/null
@@ -0,0 +1,48 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "est-connlimit",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "new-connlimit",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic",
+        "stmt": [
+          {
+            "ct count": {
+              "val": 20,
+              "inv": true
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0062set_connlimit_0.nft b/tests/shell/testcases/sets/dumps/0062set_connlimit_0.nft
new file mode 100644 (file)
index 0000000..13bbb95
--- /dev/null
@@ -0,0 +1,14 @@
+table ip x {
+       set est-connlimit {
+               type ipv4_addr
+               size 65535
+               flags dynamic
+       }
+
+       set new-connlimit {
+               type ipv4_addr
+               size 65535
+               flags dynamic
+               ct count over 20
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0063set_catchall_0.json-nft b/tests/shell/testcases/sets/dumps/0063set_catchall_0.json-nft
new file mode 100644 (file)
index 0000000..fcfe983
--- /dev/null
@@ -0,0 +1,92 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          {
+            "elem": {
+              "val": "1.1.1.1",
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          },
+          {
+            "elem": {
+              "val": "*",
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          }
+        ],
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "z",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "elem": {
+              "val": {
+                "prefix": {
+                  "addr": "1.1.1.0",
+                  "len": 24
+                }
+              },
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          },
+          {
+            "elem": {
+              "val": "*",
+              "counter": {
+                "packets": 0,
+                "bytes": 0
+              }
+            }
+          }
+        ],
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    }
+  ]
+}
index f0d42cc24e602f8ca92fced55ca34e520f6962c3..faa984bd6a1d6ee63e77ae8bd297b1497ffdbeb5 100644 (file)
@@ -2,13 +2,15 @@ table ip x {
        set y {
                type ipv4_addr
                counter
-               elements = { 1.1.1.1 counter packets 0 bytes 0, * counter packets 0 bytes 0 }
+               elements = { 1.1.1.1 counter packets 0 bytes 0,
+                            * counter packets 0 bytes 0 }
        }
 
        set z {
                type ipv4_addr
                flags interval
                counter
-               elements = { 1.1.1.0/24 counter packets 0 bytes 0, * counter packets 0 bytes 0 }
+               elements = { 1.1.1.0/24 counter packets 0 bytes 0,
+                            * counter packets 0 bytes 0 }
        }
 }
diff --git a/tests/shell/testcases/sets/dumps/0064map_catchall_0.json-nft b/tests/shell/testcases/sets/dumps/0064map_catchall_0.json-nft
new file mode 100644 (file)
index 0000000..b7496ac
--- /dev/null
@@ -0,0 +1,218 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "ipv4_addr",
+        "elem": [
+          [
+            "10.141.0.1",
+            "192.168.0.2"
+          ],
+          [
+            "*",
+            "192.168.0.4"
+          ]
+        ]
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "z",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "ipv4_addr",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "prefix": {
+                "addr": "10.141.0.0",
+                "len": 24
+              }
+            },
+            "192.168.0.2"
+          ],
+          [
+            "*",
+            "192.168.0.3"
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "snat": {
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "data": "@z"
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "snat": {
+              "addr": {
+                "map": {
+                  "key": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        {
+                          "prefix": {
+                            "addr": "10.141.0.0",
+                            "len": 24
+                          }
+                        },
+                        "192.168.0.2"
+                      ],
+                      [
+                        "*",
+                        "192.168.0.3"
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "snat": {
+              "addr": {
+                "map": {
+                  "key": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "saddr"
+                        }
+                      },
+                      {
+                        "payload": {
+                          "protocol": "ip",
+                          "field": "daddr"
+                        }
+                      }
+                    ]
+                  },
+                  "data": {
+                    "set": [
+                      [
+                        {
+                          "concat": [
+                            {
+                              "prefix": {
+                                "addr": "10.141.0.0",
+                                "len": 24
+                              }
+                            },
+                            {
+                              "prefix": {
+                                "addr": "10.0.0.0",
+                                "len": 8
+                              }
+                            }
+                          ]
+                        },
+                        "192.168.0.2"
+                      ],
+                      [
+                        {
+                          "concat": [
+                            {
+                              "prefix": {
+                                "addr": "192.168.9.0",
+                                "len": 24
+                              }
+                            },
+                            {
+                              "prefix": {
+                                "addr": "192.168.10.0",
+                                "len": 24
+                              }
+                            }
+                          ]
+                        },
+                        "192.168.0.4"
+                      ],
+                      [
+                        "*",
+                        "192.168.0.3"
+                      ]
+                    ]
+                  }
+                }
+              }
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index 890ed2aab080f127f1a9a4d9afa7b1cb4c005b18..a1bba842844ca6357b3f225202822d763ce44c36 100644 (file)
@@ -1,13 +1,15 @@
 table ip x {
        map y {
                type ipv4_addr : ipv4_addr
-               elements = { 10.141.0.1 : 192.168.0.2, * : 192.168.0.4 }
+               elements = { 10.141.0.1 : 192.168.0.2,
+                            * : 192.168.0.4 }
        }
 
        map z {
                type ipv4_addr : ipv4_addr
                flags interval
-               elements = { 10.141.0.0/24 : 192.168.0.2, * : 192.168.0.3 }
+               elements = { 10.141.0.0/24 : 192.168.0.2,
+                            * : 192.168.0.3 }
        }
 
        chain y {
diff --git a/tests/shell/testcases/sets/dumps/0065_icmp_postprocessing.json-nft b/tests/shell/testcases/sets/dumps/0065_icmp_postprocessing.json-nft
new file mode 100644 (file)
index 0000000..f470adf
--- /dev/null
@@ -0,0 +1,78 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "foo",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "foo",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "type"
+                }
+              },
+              "right": {
+                "set": [
+                  "echo-reply",
+                  "echo-request"
+                ]
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmp",
+                  "field": "id"
+                }
+              },
+              "right": 42
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0065_icmp_postprocessing.nft b/tests/shell/testcases/sets/dumps/0065_icmp_postprocessing.nft
new file mode 100644 (file)
index 0000000..461c7a7
--- /dev/null
@@ -0,0 +1,6 @@
+table ip x {
+       chain foo {
+               accept
+               icmp type { echo-reply, echo-request } icmp id 42
+       }
+}
index 0215691e28eec2f9ccc49ba542f0eeba36f4f155..9ac3774a7222c7cc18683e76381617f3605544f0 100644 (file)
@@ -1,10 +1,4 @@
 table ip nat {
-       map ipportmap {
-               type ipv4_addr : interval ipv4_addr . inet_service
-               flags interval
-               elements = { 192.168.1.2 : 10.141.10.1-10.141.10.3 . 8888-8999, 192.168.2.0/24 : 10.141.11.5-10.141.11.20 . 8888-8999 }
-       }
-
        map ipportmap2 {
                type ipv4_addr . ipv4_addr : interval ipv4_addr . inet_service
                flags interval
@@ -33,7 +27,6 @@ table ip nat {
 
        chain prerouting {
                type nat hook prerouting priority dstnat; policy accept;
-               ip protocol tcp dnat ip to ip saddr map @ipportmap
                ip protocol tcp dnat ip to ip saddr . ip daddr map @ipportmap2
                meta l4proto { tcp, udp } dnat ip to ip daddr . th dport map @fwdtoip_th
                dnat ip to iifname . ip saddr map @ipportmap4
diff --git a/tests/shell/testcases/sets/dumps/0067nat_interval_0.nft b/tests/shell/testcases/sets/dumps/0067nat_interval_0.nft
new file mode 100644 (file)
index 0000000..3e1584a
--- /dev/null
@@ -0,0 +1,13 @@
+table ip nat {
+       map ipportmap {
+               type ipv4_addr : interval ipv4_addr . inet_service
+               flags interval
+               elements = { 192.168.1.2 : 10.141.10.1-10.141.10.3 . 8888-8999,
+                            192.168.2.0/24 : 10.141.11.5-10.141.11.20 . 8888-8999 }
+       }
+
+       chain prerouting {
+               type nat hook prerouting priority dstnat; policy accept;
+               ip protocol tcp dnat ip to ip saddr map @ipportmap
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0068interval_stack_overflow_0.nodump b/tests/shell/testcases/sets/dumps/0068interval_stack_overflow_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/0069interval_merge_0.json-nft b/tests/shell/testcases/sets/dumps/0069interval_merge_0.json-nft
new file mode 100644 (file)
index 0000000..7868cb3
--- /dev/null
@@ -0,0 +1,49 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "auto-merge": true,
+        "elem": [
+          {
+            "range": [
+              "1.2.3.0",
+              "1.2.4.255"
+            ]
+          },
+          {
+            "range": [
+              "3.3.3.3",
+              "3.3.3.6"
+            ]
+          },
+          {
+            "range": [
+              "4.4.4.0",
+              "4.4.5.0"
+            ]
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0071unclosed_prefix_interval_0.json-nft b/tests/shell/testcases/sets/dumps/0071unclosed_prefix_interval_0.json-nft
new file mode 100644 (file)
index 0000000..588c2b1
--- /dev/null
@@ -0,0 +1,124 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "t",
+        "name": "c",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s1",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "10.0.0.0",
+              "len": 8
+            }
+          },
+          {
+            "prefix": {
+              "addr": "192.0.0.0",
+              "len": 2
+            }
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "s2",
+        "table": "t",
+        "type": "ipv6_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "fe80::",
+              "len": 10
+            }
+          },
+          {
+            "prefix": {
+              "addr": "ff00::",
+              "len": 8
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "@s1"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": "@s2"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0072destroy_0.json-nft b/tests/shell/testcases/sets/dumps/0072destroy_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0072destroy_0.nft b/tests/shell/testcases/sets/dumps/0072destroy_0.nft
new file mode 100644 (file)
index 0000000..5d4d2ca
--- /dev/null
@@ -0,0 +1,2 @@
+table ip x {
+}
diff --git a/tests/shell/testcases/sets/dumps/0073flat_interval_set.json-nft b/tests/shell/testcases/sets/dumps/0073flat_interval_set.json-nft
new file mode 100644 (file)
index 0000000..e4649a7
--- /dev/null
@@ -0,0 +1,50 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "counter": {
+        "family": "inet",
+        "name": "TEST",
+        "table": "filter",
+        "handle": 0,
+        "packets": 0,
+        "bytes": 0
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "testmap",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "counter",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "prefix": {
+                "addr": "192.168.0.0",
+                "len": 24
+              }
+            },
+            "TEST"
+          ]
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0073flat_interval_set.nft b/tests/shell/testcases/sets/dumps/0073flat_interval_set.nft
new file mode 100644 (file)
index 0000000..20f5374
--- /dev/null
@@ -0,0 +1,11 @@
+table inet filter {
+       counter TEST {
+               packets 0 bytes 0
+       }
+
+       map testmap {
+               type ipv4_addr : counter
+               flags interval
+               elements = { 192.168.0.0/24 : "TEST" }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/0074nested_interval_set.json-nft b/tests/shell/testcases/sets/dumps/0074nested_interval_set.json-nft
new file mode 100644 (file)
index 0000000..e4649a7
--- /dev/null
@@ -0,0 +1,50 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "counter": {
+        "family": "inet",
+        "name": "TEST",
+        "table": "filter",
+        "handle": 0,
+        "packets": 0,
+        "bytes": 0
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "testmap",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "counter",
+        "flags": "interval",
+        "elem": [
+          [
+            {
+              "prefix": {
+                "addr": "192.168.0.0",
+                "len": 24
+              }
+            },
+            "TEST"
+          ]
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/0074nested_interval_set.nft b/tests/shell/testcases/sets/dumps/0074nested_interval_set.nft
new file mode 100644 (file)
index 0000000..20f5374
--- /dev/null
@@ -0,0 +1,11 @@
+table inet filter {
+       counter TEST {
+               packets 0 bytes 0
+       }
+
+       map testmap {
+               type ipv4_addr : counter
+               flags interval
+               elements = { 192.168.0.0/24 : "TEST" }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/automerge_0.nodump b/tests/shell/testcases/sets/dumps/automerge_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/collapse_elem_0.json-nft b/tests/shell/testcases/sets/dumps/collapse_elem_0.json-nft
new file mode 100644 (file)
index 0000000..c8ff434
--- /dev/null
@@ -0,0 +1,53 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "a",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "x",
+        "table": "a",
+        "type": "inet_service",
+        "handle": 0,
+        "elem": [
+          1,
+          2,
+          3,
+          4,
+          5
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "a",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip6",
+        "name": "x",
+        "table": "a",
+        "type": "inet_service",
+        "handle": 0,
+        "elem": [
+          2
+        ]
+      }
+    }
+  ]
+}
index a3244fc616dee3f73fec2a86060794ad18d92464..775f0ab15d675bceda26f90574ecf605b4b54473 100644 (file)
@@ -1,7 +1,7 @@
 table ip a {
        set x {
                type inet_service
-               elements = { 1, 2 }
+               elements = { 1, 2, 3, 4, 5 }
        }
 }
 table ip6 a {
diff --git a/tests/shell/testcases/sets/dumps/concat_interval_0.json-nft b/tests/shell/testcases/sets/dumps/concat_interval_0.json-nft
new file mode 100644 (file)
index 0000000..3283f26
--- /dev/null
@@ -0,0 +1,64 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "inet_proto",
+          "inet_service"
+        ],
+        "handle": 0,
+        "flags": "interval",
+        "stmt": [
+          {
+            "counter": null
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s2",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "mark"
+        ],
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "concat": [
+              "10.10.10.10",
+              256
+            ]
+          },
+          {
+            "concat": [
+              "20.20.20.20",
+              512
+            ]
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/dynset_missing.json-nft b/tests/shell/testcases/sets/dumps/dynset_missing.json-nft
new file mode 100644 (file)
index 0000000..9de5b82
--- /dev/null
@@ -0,0 +1,81 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "output",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "dlist",
+        "table": "test",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "output",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 1234
+            }
+          },
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "set": "@dlist"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/elem_opts_compat_0.nodump b/tests/shell/testcases/sets/dumps/elem_opts_compat_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/errors_0.json-nft b/tests/shell/testcases/sets/dumps/errors_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/errors_0.nft b/tests/shell/testcases/sets/dumps/errors_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/exact_overlap_0.json-nft b/tests/shell/testcases/sets/dumps/exact_overlap_0.json-nft
new file mode 100644 (file)
index 0000000..7bba69d
--- /dev/null
@@ -0,0 +1,108 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "1.0.1.0",
+              "len": 24
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.0.2.0",
+              "len": 23
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.0.8.0",
+              "len": 21
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.0.32.0",
+              "len": 19
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.1.0.0",
+              "len": 24
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.1.2.0",
+              "len": 23
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.1.4.0",
+              "len": 22
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.1.8.0",
+              "len": 24
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.1.9.0",
+              "len": 24
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.1.10.0",
+              "len": 23
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.1.12.0",
+              "len": 22
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.1.16.0",
+              "len": 20
+            }
+          },
+          {
+            "prefix": {
+              "addr": "1.1.32.0",
+              "len": 19
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/exact_overlap_0.nft b/tests/shell/testcases/sets/dumps/exact_overlap_0.nft
new file mode 100644 (file)
index 0000000..c903e3f
--- /dev/null
@@ -0,0 +1,13 @@
+table ip t {
+       set s {
+               type ipv4_addr
+               flags interval
+               elements = { 1.0.1.0/24, 1.0.2.0/23,
+                            1.0.8.0/21, 1.0.32.0/19,
+                            1.1.0.0/24, 1.1.2.0/23,
+                            1.1.4.0/22, 1.1.8.0/24,
+                            1.1.9.0/24, 1.1.10.0/23,
+                            1.1.12.0/22, 1.1.16.0/20,
+                            1.1.32.0/19 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/inner_0.json-nft b/tests/shell/testcases/sets/dumps/inner_0.json-nft
new file mode 100644 (file)
index 0000000..581d534
--- /dev/null
@@ -0,0 +1,229 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "netdev",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "netdev",
+        "name": "x",
+        "table": "x",
+        "type": {
+          "typeof": {
+            "concat": [
+              {
+                "payload": {
+                  "tunnel": "vxlan",
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              {
+                "payload": {
+                  "tunnel": "vxlan",
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              }
+            ]
+          }
+        },
+        "handle": 0,
+        "elem": [
+          {
+            "concat": [
+              "3.3.3.3",
+              "4.4.4.4"
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "netdev",
+        "name": "y",
+        "table": "x",
+        "type": {
+          "typeof": {
+            "payload": {
+              "tunnel": "vxlan",
+              "protocol": "ip",
+              "field": "saddr"
+            }
+          }
+        },
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "rule": {
+        "family": "netdev",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 4789
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "tunnel": "vxlan",
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "tunnel": "vxlan",
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  }
+                ]
+              },
+              "right": {
+                "set": [
+                  {
+                    "concat": [
+                      "1.1.1.1",
+                      "2.2.2.2"
+                    ]
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "netdev",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 4789
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "tunnel": "vxlan",
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "tunnel": "vxlan",
+                      "protocol": "ip",
+                      "field": "daddr"
+                    }
+                  }
+                ]
+              },
+              "right": "@x"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "netdev",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 4789
+            }
+          },
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "payload": {
+                  "tunnel": "vxlan",
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "set": "@y"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/inner_0.nft b/tests/shell/testcases/sets/dumps/inner_0.nft
new file mode 100644 (file)
index 0000000..925ca77
--- /dev/null
@@ -0,0 +1,18 @@
+table netdev x {
+       set x {
+               typeof vxlan ip saddr . vxlan ip daddr
+               elements = { 3.3.3.3 . 4.4.4.4 }
+       }
+
+       set y {
+               typeof vxlan ip saddr
+               size 65535
+               flags dynamic
+       }
+
+       chain y {
+               udp dport 4789 vxlan ip saddr . vxlan ip daddr { 1.1.1.1 . 2.2.2.2 } counter packets 0 bytes 0
+               udp dport 4789 vxlan ip saddr . vxlan ip daddr @x counter packets 0 bytes 0
+               udp dport 4789 update @y { vxlan ip saddr }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/meter_0.json-nft b/tests/shell/testcases/sets/dumps/meter_0.json-nft
new file mode 100644 (file)
index 0000000..c318e4f
--- /dev/null
@@ -0,0 +1,203 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip6",
+        "name": "acct_out",
+        "table": "test",
+        "type": [
+          "iface_index",
+          "ipv6_addr"
+        ],
+        "handle": 0,
+        "size": 4096,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "ip6",
+        "name": "acct_out2",
+        "table": "test",
+        "type": [
+          "ipv6_addr",
+          "iface_index"
+        ],
+        "handle": 0,
+        "size": 12345,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "concat": [
+                      {
+                        "meta": {
+                          "key": "iif"
+                        }
+                      },
+                      {
+                        "payload": {
+                          "protocol": "ip6",
+                          "field": "saddr"
+                        }
+                      }
+                    ]
+                  },
+                  "timeout": 600
+                }
+              },
+              "set": "@acct_out",
+              "stmt": [
+                {
+                  "counter": null
+                }
+              ]
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "concat": [
+                      {
+                        "payload": {
+                          "protocol": "ip6",
+                          "field": "saddr"
+                        }
+                      },
+                      {
+                        "meta": {
+                          "key": "iif"
+                        }
+                      }
+                    ]
+                  },
+                  "timeout": 600
+                }
+              },
+              "set": "@acct_out2",
+              "stmt": [
+                {
+                  "counter": null
+                }
+              ]
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "test",
+        "name": "test",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "xyz",
+        "table": "test",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "size": 8192,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "test",
+        "chain": "test",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "elem": {
+                  "val": {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "timeout": 30
+                }
+              },
+              "set": "@xyz",
+              "stmt": [
+                {
+                  "counter": null
+                }
+              ]
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/meter_0.nft b/tests/shell/testcases/sets/dumps/meter_0.nft
new file mode 100644 (file)
index 0000000..3843f9a
--- /dev/null
@@ -0,0 +1,29 @@
+table ip6 test {
+       set acct_out {
+               type iface_index . ipv6_addr
+               size 4096
+               flags dynamic,timeout
+       }
+
+       set acct_out2 {
+               type ipv6_addr . iface_index
+               size 12345
+               flags dynamic,timeout
+       }
+
+       chain test {
+               update @acct_out { iif . ip6 saddr timeout 10m counter }
+               update @acct_out2 { ip6 saddr . iif timeout 10m counter }
+       }
+}
+table ip test {
+       set xyz {
+               type ipv4_addr
+               size 8192
+               flags dynamic,timeout
+       }
+
+       chain test {
+               update @xyz { ip saddr timeout 30s counter }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/meter_set_reuse.json-nft b/tests/shell/testcases/sets/dumps/meter_set_reuse.json-nft
new file mode 100644 (file)
index 0000000..9210c90
--- /dev/null
@@ -0,0 +1,103 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "input",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "http1",
+        "table": "filter",
+        "type": [
+          "inet_service",
+          "ipv4_addr"
+        ],
+        "handle": 0,
+        "size": 65535,
+        "flags": "dynamic"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 80
+            }
+          },
+          {
+            "set": {
+              "op": "add",
+              "elem": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "tcp",
+                      "field": "dport"
+                    }
+                  },
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  }
+                ]
+              },
+              "set": "@http1",
+              "stmt": [
+                {
+                  "limit": {
+                    "rate": 200,
+                    "burst": 5,
+                    "per": "second",
+                    "inv": true
+                  }
+                }
+              ]
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/meter_set_reuse.nft b/tests/shell/testcases/sets/dumps/meter_set_reuse.nft
new file mode 100644 (file)
index 0000000..f911aca
--- /dev/null
@@ -0,0 +1,11 @@
+table ip filter {
+       set http1 {
+               type inet_service . ipv4_addr
+               size 65535
+               flags dynamic
+       }
+
+       chain input {
+               tcp dport 80 add @http1 { tcp dport . ip saddr limit rate over 200/second burst 5 packets } counter packets 0 bytes 0 drop
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/range_with_same_start_end.json-nft b/tests/shell/testcases/sets/dumps/range_with_same_start_end.json-nft
new file mode 100644 (file)
index 0000000..e1daa8f
--- /dev/null
@@ -0,0 +1,33 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "X",
+        "table": "t",
+        "type": "inet_service",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          10,
+          30,
+          35
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/range_with_same_start_end.nft b/tests/shell/testcases/sets/dumps/range_with_same_start_end.nft
new file mode 100644 (file)
index 0000000..78979e9
--- /dev/null
@@ -0,0 +1,7 @@
+table ip t {
+       set X {
+               type inet_service
+               flags interval
+               elements = { 10, 30, 35 }
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/reset_command_0.nodump b/tests/shell/testcases/sets/dumps/reset_command_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/sets/dumps/set_element_timeout_updates.json-nft b/tests/shell/testcases/sets/dumps/set_element_timeout_updates.json-nft
new file mode 100644 (file)
index 0000000..acb2f1f
--- /dev/null
@@ -0,0 +1,48 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "base",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": {
+          "typeof": {
+            "payload": {
+              "protocol": "ip",
+              "field": "saddr"
+            }
+          }
+        },
+        "handle": 0,
+        "flags": "timeout",
+        "timeout": 60
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/set_element_timeout_updates.nft b/tests/shell/testcases/sets/dumps/set_element_timeout_updates.nft
new file mode 100644 (file)
index 0000000..1edd2ec
--- /dev/null
@@ -0,0 +1,10 @@
+table ip t {
+       set s {
+               typeof ip saddr
+               timeout 1m
+       }
+
+       chain base {
+               type filter hook input priority filter; policy accept;
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/set_eval_0.json-nft b/tests/shell/testcases/sets/dumps/set_eval_0.json-nft
new file mode 100644 (file)
index 0000000..6f4f4c6
--- /dev/null
@@ -0,0 +1,83 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "nat",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "nat",
+        "name": "prerouting",
+        "handle": 0,
+        "type": "nat",
+        "hook": "prerouting",
+        "prio": -100,
+        "policy": "accept"
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "set_with_interval",
+        "table": "nat",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "nat",
+        "chain": "prerouting",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "tcp",
+                  "udp"
+                ]
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "th",
+                  "field": "dport"
+                }
+              },
+              "right": 443
+            }
+          },
+          {
+            "dnat": {
+              "addr": "10.0.0.1"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/set_stmt.nft b/tests/shell/testcases/sets/dumps/set_stmt.nft
new file mode 100644 (file)
index 0000000..71ba799
--- /dev/null
@@ -0,0 +1,66 @@
+table ip x {
+       set y0 {
+               type ipv4_addr
+               counter
+               elements = { 2.2.2.0 counter packets 3 bytes 4,
+                            3.3.3.0 counter packets 1 bytes 2,
+                            5.5.5.0 counter packets 1 bytes 2,
+                            6.6.6.0 counter packets 3 bytes 4 }
+       }
+
+       set y1 {
+               type ipv4_addr
+               limit rate 1/second burst 5 packets
+               elements = { 2.2.2.1 limit rate 5/second burst 5 packets,
+                            3.3.3.1 limit rate 1/second burst 5 packets,
+                            5.5.5.1 limit rate 1/second burst 5 packets,
+                            6.6.6.1 limit rate 5/second burst 5 packets }
+       }
+
+       set y2 {
+               type ipv4_addr
+               ct count over 2
+               elements = { 2.2.2.2 ct count over 5,
+                            3.3.3.2 ct count over 2,
+                            5.5.5.2 ct count over 2,
+                            6.6.6.2 ct count over 5 }
+       }
+
+       set y3 {
+               type ipv4_addr
+               last
+               elements = { 2.2.2.3 last used never,
+                            3.3.3.3 last used never,
+                            5.5.5.3 last used never,
+                            6.6.6.3 last used never }
+       }
+
+       set y4 {
+               type ipv4_addr
+               quota over 1000 bytes
+               elements = { 2.2.2.4 quota over 30000 bytes used 1000 bytes,
+                            3.3.3.4 quota over 1000 bytes,
+                            5.5.5.4 quota over 1000 bytes,
+                            6.6.6.4 quota over 30000 bytes used 1000 bytes }
+       }
+
+       chain y0 {
+               ip daddr @y0
+       }
+
+       chain y1 {
+               ip daddr @y1
+       }
+
+       chain y2 {
+               ip daddr @y2
+       }
+
+       chain y3 {
+               ip daddr @y3
+       }
+
+       chain y4 {
+               ip daddr @y4
+       }
+}
diff --git a/tests/shell/testcases/sets/dumps/sets_with_ifnames.json-nft b/tests/shell/testcases/sets/dumps/sets_with_ifnames.json-nft
new file mode 100644 (file)
index 0000000..77ca508
--- /dev/null
@@ -0,0 +1,545 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "testifsets",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "testifsets",
+        "name": "v4icmp",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "testifsets",
+        "name": "v4icmpc",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "testifsets",
+        "name": "input",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "testifsets",
+        "name": "do_nothing",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "simple",
+        "table": "testifsets",
+        "type": "ifname",
+        "handle": 0,
+        "elem": [
+          "abcdef0",
+          "abcdef1",
+          "othername"
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "simple_wild",
+        "table": "testifsets",
+        "type": "ifname",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          "abcdef*",
+          "othername",
+          "ppp0"
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "concat",
+        "table": "testifsets",
+        "type": [
+          "ipv4_addr",
+          "ifname"
+        ],
+        "handle": 0,
+        "elem": [
+          {
+            "concat": [
+              "10.1.2.2",
+              "abcdef0"
+            ]
+          },
+          {
+            "concat": [
+              "10.1.2.2",
+              "abcdef1"
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "set": {
+        "family": "inet",
+        "name": "concat_wild",
+        "table": "testifsets",
+        "type": [
+          "ipv4_addr",
+          "ifname"
+        ],
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "concat": [
+              "10.1.2.2",
+              "abcdef*"
+            ]
+          },
+          {
+            "concat": [
+              "10.1.2.1",
+              "bar"
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "1.1.2.0",
+                  "len": 24
+                }
+              },
+              "abcdef0"
+            ]
+          },
+          {
+            "concat": [
+              {
+                "prefix": {
+                  "addr": "12.2.2.0",
+                  "len": 24
+                }
+              },
+              "abcdef*"
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "map": {
+        "family": "inet",
+        "name": "map_wild",
+        "table": "testifsets",
+        "type": "ifname",
+        "handle": 0,
+        "map": "verdict",
+        "flags": "interval",
+        "elem": [
+          [
+            "abcdef*",
+            {
+              "jump": {
+                "target": "do_nothing"
+              }
+            }
+          ],
+          [
+            "eth0",
+            {
+              "jump": {
+                "target": "do_nothing"
+              }
+            }
+          ]
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "v4icmp",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "@simple"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "v4icmp",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "@simple_wild"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "v4icmp",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": {
+                "set": [
+                  "eth0",
+                  "abcdef0"
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "v4icmp",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": {
+                "set": [
+                  "abcdef*",
+                  "eth0"
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "v4icmp",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "data": "@map_wild"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "v4icmpc",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "meta": {
+                      "key": "iifname"
+                    }
+                  }
+                ]
+              },
+              "right": "@concat"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "v4icmpc",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "meta": {
+                      "key": "iifname"
+                    }
+                  }
+                ]
+              },
+              "right": "@concat_wild"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "v4icmpc",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "meta": {
+                      "key": "iifname"
+                    }
+                  }
+                ]
+              },
+              "right": {
+                "set": [
+                  {
+                    "concat": [
+                      "10.1.2.2",
+                      "abcdef0"
+                    ]
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "v4icmpc",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  {
+                    "meta": {
+                      "key": "iifname"
+                    }
+                  }
+                ]
+              },
+              "right": {
+                "set": [
+                  {
+                    "concat": [
+                      "10.1.2.2",
+                      "abcdef*"
+                    ]
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "protocol"
+                }
+              },
+              "right": "icmp"
+            }
+          },
+          {
+            "jump": {
+              "target": "v4icmp"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "testifsets",
+        "chain": "input",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "protocol"
+                }
+              },
+              "right": "icmp"
+            }
+          },
+          {
+            "goto": {
+              "target": "v4icmpc"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/sets/dumps/type_set_symbol.json-nft b/tests/shell/testcases/sets/dumps/type_set_symbol.json-nft
new file mode 100644 (file)
index 0000000..e22213e
--- /dev/null
@@ -0,0 +1,114 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s1",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "ipv4_addr",
+          "inet_service"
+        ],
+        "handle": 0,
+        "size": 65535,
+        "flags": [
+          "timeout",
+          "dynamic"
+        ],
+        "timeout": 10800
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "set": {
+              "op": "update",
+              "elem": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "10.180.0.4",
+                  80
+                ]
+              },
+              "set": "@s1"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c2",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "concat": [
+                  {
+                    "payload": {
+                      "protocol": "ip",
+                      "field": "saddr"
+                    }
+                  },
+                  "1.2.3.4",
+                  80
+                ]
+              },
+              "right": "@s1"
+            }
+          },
+          {
+            "goto": {
+              "target": "c1"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
index 499ff167f51de3d4b773e651532709cf3961fe8e..4d6abaaa151b690276304bd4422f35480a000806 100644 (file)
@@ -6,7 +6,7 @@ table inet t {
        }
 
        chain y {
-               ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e }
-               ip daddr . @ih,32,32 @y
+               ip saddr . @nh,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e }
+               ip daddr . @nh,32,32 @y
        }
 }
index 6f5b83af6bb9203404c7cc9da9e2c94c2841ca09..34aaab601cda310d3620d8fc876f2fbcc520456d 100644 (file)
@@ -55,6 +55,22 @@ table inet t {
                elements = { 3567 . 1.2.3.4 }
        }
 
+       set s12 {
+               typeof iifname . ip saddr . meta ipsec
+               elements = { "eth0" . 10.1.1.2 . exists }
+       }
+
+       set s13 {
+               typeof tcp option mptcp subtype
+               elements = { mp-join, dss }
+       }
+
+       set s14 {
+               typeof tcp option mptcp subtype . ip daddr
+               elements = { remove-addr . 10.1.1.1,
+                            mp-join . 10.1.1.2 }
+       }
+
        chain c1 {
                osf name @s1 accept
        }
@@ -94,4 +110,16 @@ table inet t {
        chain c11 {
                vlan id . ip saddr @s11 accept
        }
+
+       chain c12 {
+               iifname . ip saddr . meta ipsec @s12 accept
+       }
+
+       chain c13 {
+               tcp option mptcp subtype @s13 accept
+       }
+
+       chain c14 {
+               tcp option mptcp subtype . ip saddr @s14 accept
+       }
 }
index dbaf7cdc2d7d770ee812df2ba1c4af9d97cb4f7d..348b58487d5c554e848edf95e9cb7f51f8f2f5ec 100644 (file)
@@ -10,3 +10,14 @@ table netdev t {
                ether type != 8021q update @s { ether daddr . 123 timeout 1m } counter packets 0 bytes 0 return
        }
 }
+table ip t {
+       set s {
+               typeof ipsec in reqid . iif
+               size 16
+               flags interval
+       }
+
+       chain c2 {
+               ipsec in reqid . "lo" @s
+       }
+}
index b57f9274bcd0d6efeef02575fe3fcff0b4370a19..ed6009166fb97df3ccd97adf400d95ac8d05443a 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-## requires EXPR
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
 
 set -e
 
index 3467cc07e646921671fb481bd35de41f682a3e41..7563773e626f3be085e1fdd1ffdb6794912b3adf 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
 # ordering of element options and expressions has changed, make sure parser
 # accepts both ways
 
diff --git a/tests/shell/testcases/sets/inner_0 b/tests/shell/testcases/sets/inner_0
new file mode 100755 (executable)
index 0000000..39d91bd
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_inner_matching)
+
+set -e
+
+RULESET="table netdev x {
+       set x {
+               typeof vxlan ip saddr . vxlan ip daddr
+               elements = {
+                       3.3.3.3 . 4.4.4.4,
+               }
+       }
+
+       set y {
+               typeof vxlan ip saddr
+               flags dynamic
+       }
+
+        chain y {
+               udp dport 4789 vxlan ip saddr . vxlan ip daddr { 1.1.1.1 . 2.2.2.2 } counter
+               udp dport 4789 vxlan ip saddr . vxlan ip daddr @x counter
+               udp dport 4789 update @y { vxlan ip saddr }
+        }
+}"
+
+$NFT -f - <<< $RULESET
diff --git a/tests/shell/testcases/sets/interval_size b/tests/shell/testcases/sets/interval_size
new file mode 100755 (executable)
index 0000000..55a6cd4
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_rbtree_size_limit)
+
+RULESET="table inet x {
+       set x {
+               typeof ip saddr
+               flags interval
+               auto-merge
+               size 1
+       }
+
+       set y {
+               typeof ip saddr
+               flags interval
+               size 1
+       }
+}"
+
+$NFT -f - <<< $RULESET
+
+$NFT add element inet x x '{ 0.0.0.0, 255.255.255.255 }' && exit 1
+$NFT add element inet x x '{ 0.0.0.0 }' || exit 1
+$NFT add element inet x x '{ 255.255.255.0/24 }' && exit 1
+$NFT delete element inet x x '{ 0.0.0.0 }' || exit 1
+$NFT add element inet x x '{ 255.255.255.0/24 }' || exit 1
+$NFT add element inet x x '{ 0.0.0.0 }' && exit 1
+$NFT add element inet x x '{ 0.0.0.0-255.255.255.0 }' || exit 1
+$NFT delete element inet x x '{ 1.1.1.1 }' && exit 1
+$NFT delete element inet x x '{ 0.0.0.0/0 }' || exit 1
+$NFT add element inet x x '{ 255.255.255.0/24 }' || exit 1
+$NFT add element inet x x '{ 0.0.0.0 }' && exit 1
+
+$NFT add element inet x y '{ 0.0.0.0, 255.255.255.255 }' && exit 1
+$NFT add element inet x y '{ 0.0.0.0 }' || exit 1
+$NFT add element inet x y '{ 255.255.255.0/24 }' && exit 1
+$NFT delete element inet x y '{ 0.0.0.0 }' || exit 1
+$NFT add element inet x y '{ 255.255.255.0/24 }' || exit 1
+$NFT add element inet x y '{ 0.0.0.0 }' && exit 1
+$NFT add element inet x y '{ 0.0.0.0-255.255.255.0 }' && exit 1
+$NFT delete element inet x y '{ 255.255.255.0/24 }' || exit 1
+$NFT add element inet x y '{ 0.0.0.0 }' || exit 1
+$NFT add element inet x y '{ 255.255.255.255 }' && exit 1
+exit 0
diff --git a/tests/shell/testcases/sets/interval_size_random b/tests/shell/testcases/sets/interval_size_random
new file mode 100755 (executable)
index 0000000..3320b51
--- /dev/null
@@ -0,0 +1,115 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_rbtree_size_limit)
+
+generate_ip() {
+       local first=($1)
+       echo -n "$first.$((RANDOM % 256)).$((RANDOM % 256)).$((RANDOM % 256))"
+}
+
+ip_to_int() {
+       local IFS='.'
+       local ip=($1)
+       printf '%d' "$((${ip[0]}<<24 | ${ip[1]}<<16 | ${ip[2]}<<8 | ${ip[3]}))"
+}
+
+compare_ips() {
+       local ip1=$(ip_to_int $1)
+       local ip2=$(ip_to_int $2)
+       if [ "$ip1" -lt "$ip2" ]; then
+               echo "$1"
+       elif [ "$ip1" -gt "$ip2" ]; then
+               echo "$2"
+       else
+               echo "$1"
+       fi
+}
+
+generate_range() {
+       start=$(generate_ip $1)
+       end=$(generate_ip $1)
+       result=$(compare_ips $start $end)
+       if [[ "$result" != "$start" ]]
+       then
+               temp=$start
+               start=$end
+               end=$temp
+       fi
+       echo -n "$start-$end"
+}
+
+generate_prefix() {
+       prefix=$(generate_ip $1 | cut -d. -f1-3)
+       echo -n "$prefix.0/24"
+}
+
+generate_intervals() {
+       echo "define x = {"
+       # not so random, first octet in IP address is $i, this cannot go over 255
+       iter=$((RANDOM % 255 + 1))
+
+       [ $(($RANDOM % 2)) -eq 0 ] && echo "0.0.0.0,"
+
+       for ((i=0; i<iter; i++)); do
+               case $((RANDOM % 3)) in
+               0) generate_ip $i;;
+               1) generate_range $i;;
+               2) generate_prefix $i;;
+               esac
+               echo ","
+       done
+
+       [ $(($RANDOM % 2)) -eq 0 ] && echo "255.255.255.255,"
+
+       echo "}"
+}
+
+run_test() {
+       local count=($1)
+       local elems=($2)
+       local ruleset=($3)
+       echo "table inet x {
+       set y {
+               include \"$elems\"
+               typeof ip saddr
+               flags interval
+               size $count
+               elements = { \$x }
+       }
+      }" > $ruleset
+}
+
+count_elems() {
+       local elems=($2)
+       count=$(wc -l $elems_file | cut -f1 -d' ')
+       # subtract enclosing define lines
+       count=$(($count-2))
+       echo $count
+}
+
+elems_file=$(mktemp /tmp/elems-XXXXX.nft)
+ruleset_file=$(mktemp /tmp/ruleset-XXXXX.nft)
+
+if [ ! -w "$elems_file" ] ; then
+       # cwd might be readonly, mark as skip.
+       echo "Failed to create tmp file" >&2
+       exit 77
+fi
+
+trap "rm -rf $elems_file $ruleset_file" EXIT
+
+generate_intervals > $elems_file
+count=$(count_elems $elems_file)
+
+run_test $count $elems_file $ruleset_file
+$NFT -f $ruleset_file || exit 1
+
+$NFT flush ruleset
+
+# subtract 1 to size, too small, it should fail
+count=$(($count-1))
+
+run_test $count $elems_file $ruleset_file
+$NFT -f $ruleset_file && exit 1
+
+exit 0
diff --git a/tests/shell/testcases/sets/meter_0 b/tests/shell/testcases/sets/meter_0
new file mode 100755 (executable)
index 0000000..82e6f20
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+set -e
+
+RULESET="table ip6 test {
+       chain test {
+               meter acct_out size 4096 { meta iif . ip6 saddr timeout 600s counter }
+               meter acct_out2 size 12345 { ip6 saddr . meta iif timeout 600s counter }
+       }
+}
+
+table ip test {
+       chain test {
+               meter xyz size 8192 { ip saddr timeout 30s counter}
+       }
+}"
+
+$NFT -f - <<< $RULESET
diff --git a/tests/shell/testcases/sets/meter_set_reuse b/tests/shell/testcases/sets/meter_set_reuse
new file mode 100755 (executable)
index 0000000..94eccc1
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -e
+
+addrule()
+{
+       $NFT add rule ip filter input tcp dport 80 meter http1 { tcp dport . ip saddr limit rate over 200/second } counter drop
+}
+
+$NFT add table filter
+$NFT add chain filter input
+addrule
+
+$NFT list meters
+
+# This used to remove the anon set, but not anymore
+$NFT flush chain filter input
+
+# This re-add should work.
+addrule
diff --git a/tests/shell/testcases/sets/range_with_same_start_end b/tests/shell/testcases/sets/range_with_same_start_end
new file mode 100755 (executable)
index 0000000..127f092
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -e
+
+$NFT -f - <<EOF
+table ip t {
+       set X {
+               type inet_service
+               flags interval
+               elements = { 10, 30-30, 30, 35 }
+       }
+}
+EOF
diff --git a/tests/shell/testcases/sets/reset_command_0 b/tests/shell/testcases/sets/reset_command_0
new file mode 100755 (executable)
index 0000000..c59cc56
--- /dev/null
@@ -0,0 +1,137 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_reset_set)
+
+set -e
+
+trap '[[ $? -eq 0 ]] || echo FAIL' EXIT
+
+RULESET="table t {
+       set s {
+               type ipv4_addr . inet_proto . inet_service
+               flags interval, timeout
+               counter
+               timeout 30m
+               elements = {
+                       1.0.0.1 . udp . 53 counter packets 5 bytes 30 expires 20m,
+                       2.0.0.2 . tcp . 22 counter packets 10 bytes 100 timeout 15m expires 10m
+               }
+       }
+
+       set s2 {
+               type ipv4_addr
+               flags interval, timeout
+               counter
+               timeout 30m
+               elements = {
+                       1.0.0.1 counter packets 5 bytes 30 expires 20m,
+                       1.0.1.1-1.0.1.10 counter packets 5 bytes 30 expires 20m,
+                       2.0.0.2 counter packets 10 bytes 100 timeout 15m expires 10m
+               }
+       }
+
+       map m {
+               type ipv4_addr : ipv4_addr
+               quota 50 bytes
+               elements = {
+                       1.2.3.4 quota 50 bytes used 10 bytes : 10.2.3.4,
+                       5.6.7.8 quota 100 bytes used 50 bytes : 50.6.7.8
+               }
+       }
+
+       map m1 {
+               type ipv4_addr : ipv4_addr
+               counter
+               timeout 30m
+               elements = {
+                       1.2.3.4 counter packets 5 bytes 30 expires 20m : 10.2.3.4,
+                       5.6.7.8 counter packets 10 bytes 100 timeout 15m expires 10m : 50.6.7.8
+               }
+       }
+
+       map m2 {
+               type ipv4_addr : ipv4_addr
+               flags interval, timeout
+               counter
+               timeout 30m
+               elements = {
+                       1.2.3.4-1.2.3.10 counter packets 5 bytes 30 expires 20m : 10.2.3.4,
+                       5.6.7.8-5.6.7.10 counter packets 10 bytes 100 timeout 15m expires 10m : 50.6.7.8
+               }
+       }
+}"
+
+echo -n "applying test ruleset: "
+$NFT -f - <<< "$RULESET"
+echo OK
+
+drop_seconds() {
+       sed 's/[0-9]\+m\?s//g'
+}
+expires_minutes() {
+       sed -n 's/.*expires \([0-9]*\)m.*/\1/p'
+}
+
+get_and_reset()
+{
+       local setname="$1"
+       local key="$2"
+
+       echo -n "get set elem matches reset set elem in set $setname: "
+
+       elem="element t $setname { $key }"
+       echo $NFT get $elem
+       $NFT get $elem
+       [[ $($NFT "get $elem ; reset $elem" | \
+               grep 'elements = ' | drop_seconds | uniq | wc -l) == 1 ]]
+       echo OK
+
+       echo -n "counters are reset, expiry left alone in set $setname: "
+       NEW=$($NFT "get $elem")
+       echo NEW $NEW
+       grep -q 'counter packets 0 bytes 0' <<< "$NEW"
+       [[ $(expires_minutes <<< "$NEW") -lt 20 ]]
+       echo OK
+}
+
+get_and_reset "s" "1.0.0.1 . udp . 53"
+get_and_reset "s2" "1.0.0.1"
+get_and_reset "s2" "1.0.1.1-1.0.1.10"
+get_and_reset "m1" "1.2.3.4"
+get_and_reset "m2" "1.2.3.4-1.2.3.10"
+
+echo -n "get map elem matches reset map elem: "
+elem='element t m { 1.2.3.4 }'
+[[ $($NFT "get $elem ; reset $elem" | \
+       grep 'elements = ' | uniq | wc -l) == 1 ]]
+echo OK
+
+echo -n "quota value is reset: "
+$NFT get element t m '{ 1.2.3.4 }' | grep -q 'quota 50 bytes : 10.2.3.4'
+echo OK
+
+echo -n "other elements remain the same: "
+OUT=$($NFT get element t s '{ 2.0.0.2 . tcp . 22 }')
+grep -q 'counter packets 10 bytes 100 timeout 15m' <<< "$OUT"
+VAL=$(expires_minutes <<< "$OUT")
+[[ $val -lt 10 ]]
+$NFT get element t m '{ 5.6.7.8 }' | grep -q 'quota 100 bytes used 50 bytes'
+echo OK
+
+echo -n "list set matches reset set: "
+EXP=$($NFT list set t s | drop_seconds)
+OUT=$($NFT reset set t s | drop_seconds)
+$DIFF -u <(echo "$EXP") <(echo "$OUT")
+echo OK
+
+echo -n "list map matches reset map: "
+EXP=$($NFT list map t m)
+OUT=$($NFT reset map t m)
+$DIFF -u <(echo "$EXP") <(echo "$OUT")
+echo OK
+
+echo -n "remaining elements are reset: "
+OUT=$($NFT list ruleset)
+grep -q '2.0.0.2 . tcp . 22 counter packets 0 bytes 0' <<< "$OUT"
+grep -q '5.6.7.8 quota 100 bytes : 50.6.7.8' <<< "$OUT"
+echo OK
diff --git a/tests/shell/testcases/sets/set_element_timeout_updates b/tests/shell/testcases/sets/set_element_timeout_updates
new file mode 100755 (executable)
index 0000000..4bf6c7c
--- /dev/null
@@ -0,0 +1,120 @@
+#!/bin/bash
+#
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_elem_timeout_update)
+#
+
+assert_fail()
+{
+       ret=$1
+
+       if [ $ret -eq 0 ];then
+               echo "subtest should have failed: $2"
+               exit 111
+       fi
+}
+
+assert_ok()
+{
+       ret=$1
+
+       if [ $ret -ne 0 ];then
+               echo "subtest should have passed: $2"
+               exit 111
+       fi
+}
+
+
+$NFT -f - <<EOF
+table t {
+       set s {
+               typeof ip saddr
+               timeout 1m
+               elements = { 10.0.0.1, 10.0.0.2, 10.0.0.3 }
+       }
+
+       chain base {
+               type filter hook input priority 0
+       }
+}
+EOF
+
+for i in 1 2 3;do
+       $NFT get element t s "{ 10.0.0.$i }"
+       assert_ok $? "get element $i"
+done
+
+# first, bogus updates to trigger abort path with updates.
+$NFT -f - <<EOF
+add element t s { 10.0.0.2 timeout 2m }
+create element t s { 10.0.0.1 }
+add element t s { 10.0.0.3 timeout 3m }
+EOF
+assert_fail $? "abort due to existing element"
+
+$NFT -f - <<EOF
+add chain t a
+add element t s { 10.0.0.1 timeout 1m }
+add element t s { 10.0.0.2 timeout 2m }
+add element t s { 10.0.0.3 timeout 3m }
+add chain t b
+add rule t a jump b
+add rule t b jump a
+add rule t base jump a
+EOF
+assert_fail $? "abort due to chainloop"
+
+$NFT -f - <<EOF
+add element t s { 10.0.0.1 expires 2m }
+EOF
+assert_fail $? "expire larger than timeout"
+
+$NFT -f - <<EOF
+add element t s { 10.0.0.1 timeout 1s }
+add element t s { 10.0.0.2 timeout 1s }
+add element t s { 10.0.0.3 timeout 1s }
+add element t s { 10.0.0.4 expires 2m }
+EOF
+assert_fail $? "abort because expire too large"
+
+# check timeout update had no effect
+sleep 1
+for i in 1 2 3;do
+       $NFT get element t s "{ 10.0.0.$i }"
+       assert_ok $? "get element $i after aborted update"
+done
+
+# adjust timeouts upwards.
+$NFT -f - <<EOF
+add element t s { 10.0.0.1 timeout 1m }
+add element t s { 10.0.0.2 timeout 2m }
+add element t s { 10.0.0.3 timeout 3m }
+EOF
+assert_ok $? "upwards adjust"
+
+for i in 1 2 3;do
+       $NFT get element t s "{ 10.0.0.$i }"
+       assert_ok $? "get element $i"
+done
+
+# insert 4th element with timeout larger than set default
+$NFT -f - <<EOF
+add element t s { 10.0.0.4 timeout 2m expires 2m }
+EOF
+$NFT get element t s "{ 10.0.0.4 }"
+assert_ok $? "get element 4"
+
+# adjust timeouts downwards
+$NFT -f - <<EOF
+add element t s { 10.0.0.1 timeout 1s }
+add element t s { 10.0.0.2 timeout 2s expires 1s }
+add element t s { 10.0.0.3 expires 1s }
+add element t s { 10.0.0.4 timeout 4m expires 1s }
+EOF
+assert_ok $?
+
+sleep 1
+
+for i in 1 2 3;do
+       $NFT get element t s "{ 10.0.0.$i }"
+       assert_fail $?
+done
diff --git a/tests/shell/testcases/sets/set_stmt b/tests/shell/testcases/sets/set_stmt
new file mode 100755 (executable)
index 0000000..ea50525
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_set_expr)
+
+test_set_stmt() {
+       local i=$1
+       local stmt1=$2
+       local stmt2=$3
+
+       RULESET="table x {
+       set y$i {
+               type ipv4_addr
+               $stmt1
+               elements = { 5.5.5.$i $stmt1,
+                            6.6.6.$i $stmt2 }
+       }
+       chain y$i {
+               ip daddr @y$i
+       }
+}"
+
+       $NFT -f - <<< $RULESET
+       # should work
+       if [ $? -ne 0 ]
+       then
+               exit 1
+       fi
+
+       # should work
+       $NFT add element x y$i { 2.2.2.$i $stmt2 }
+       if [ $? -ne 0 ]
+       then
+               exit 1
+       fi
+
+       # should work
+       $NFT add element x y$i { 3.3.3.$i }
+       if [ $? -ne 0 ]
+       then
+               exit 1
+       fi
+}
+
+test_set_stmt "0" "counter packets 1 bytes 2" "counter packets 3 bytes 4"
+test_set_stmt "1" "limit rate 1/second" "limit rate 5/second"
+test_set_stmt "2" "ct count over 2" "ct count over 5"
+test_set_stmt "3" "last" "last"
+test_set_stmt "4" "quota over 1000 bytes" "quota over 30000 bytes used 1000 bytes"
+
+exit 0
index 713778b8c9b7065e87fb68023a2879b2a28f69d1..c65499b76bc5fc81aefbf0aa954ede637b7f3e86 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 dumpfile=$(dirname $0)/dumps/$(basename $0).nft
 
 [ -z "$NFT" ] && exit 111
index 36396b5c2e1d862434861ff34ec998978af530f5..66042eb4085a99862211be3e530ae0b7716ea221 100755 (executable)
@@ -7,8 +7,8 @@ EXPECTED="table inet t {
        }
 
        chain y {
-               ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e }
-               ip daddr . @ih,32,32 @y
+               ip saddr . @nh,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e }
+               ip daddr . @nh,32,32 @y
        }
 }"
 
index 9f777a8c90bc597eac602d7aba74ece8010496d4..28e39b4d2cb3097c1c037cd88ed92893bec83cb0 100755 (executable)
@@ -4,12 +4,79 @@
 # s1 and s2 are identical, they just use different
 # ways for declaration.
 
-EXPECTED="table inet t {
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_ip_options)
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_bitshift)
+
+set -e
+
+die() {
+       printf '%s\n' "$*"
+       exit 1
+}
+
+INPUT_OSF_SET="
        set s1 {
                typeof osf name
                elements = { \"Linux\" }
        }
+"
+
+INPUT_FRAG_SET="
+       set s4 {
+               typeof frag frag-off
+               elements = { 1, 1024 }
+       }
+"
 
+INPUT_VERSION_SET="
+       set s8 {
+               typeof ip version
+               elements = { 4, 6 }
+       }
+"
+
+INPUT_OSF_CHAIN="
+       chain c1 {
+               osf name @s1 accept
+       }
+"
+
+INPUT_FRAG_CHAIN="
+       chain c4 {
+               frag frag-off @s4 accept
+       }
+"
+
+INPUT_SCTP_CHAIN="
+       chain c7 {
+               sctp chunk init num-inbound-streams @s7 accept
+       }
+"
+INPUT_VERSION_CHAIN="
+       chain c8 {
+               ip version @s8 accept
+       }
+"
+
+if [ "$NFT_TEST_HAVE_sctp_chunks" = n ] ; then
+       INPUT_SCTP_CHAIN=
+fi
+
+if [ "$NFT_TEST_HAVE_bitshift" = n ] ; then
+       INPUT_FRAG_CHAIN=
+       INPUT_VERSION_CHAIN=
+fi
+
+if [ "$NFT_TEST_HAVE_osf" = n ] ; then
+       if [ "$((RANDOM % 2))" -eq 1 ] ; then
+               # Regardless of $NFT_TEST_HAVE_osf, we can define the set.
+               # Randomly do so.
+               INPUT_OSF_SET=
+       fi
+       INPUT_OSF_CHAIN=
+fi
+
+INPUT="table inet t {$INPUT_OSF_SET
        set s2 {
                typeof vlan id
                elements = { 2, 3, 103 }
@@ -18,12 +85,7 @@ EXPECTED="table inet t {
        set s3 {
                typeof meta ibrpvid
                elements = { 2, 3, 103 }
-       }
-
-       set s4 {
-               typeof frag frag-off
-               elements = { 1, 1024 }
-       }
+       }$INPUT_FRAG_SET
 
        set s5 {
                typeof ip option ra value
@@ -38,12 +100,7 @@ EXPECTED="table inet t {
        set s7 {
                typeof sctp chunk init num-inbound-streams
                elements = { 1, 4 }
-       }
-
-       set s8 {
-               typeof ip version
-               elements = { 4, 6 }
-       }
+       }$INPUT_VERSION_SET
 
        set s9 {
                typeof ip hdrlength
@@ -59,19 +116,25 @@ EXPECTED="table inet t {
                typeof vlan id . ip saddr
                elements = { 3567 . 1.2.3.4 }
        }
+       set s12 {
+               typeof meta iifname . ip saddr . meta ipsec
+               elements = { \"eth0\" . 10.1.1.2 . 1 }
+       }
 
-       chain c1 {
-               osf name @s1 accept
+       set s13 {
+               typeof tcp option mptcp subtype
+               elements = { mp-join, dss }
        }
 
+       set s14 {
+               typeof tcp option mptcp subtype . ip daddr
+               elements = { remove-addr . 10.1.1.1, mp-join . 10.1.1.2 }
+       }
+$INPUT_OSF_CHAIN
        chain c2 {
                ether type vlan vlan id @s2 accept
        }
-
-       chain c4 {
-               frag frag-off @s4 accept
-       }
-
+$INPUT_FRAG_CHAIN
        chain c5 {
                ip option ra value @s5 accept
        }
@@ -79,28 +142,142 @@ EXPECTED="table inet t {
        chain c6 {
                tcp option maxseg size @s6 accept
        }
+$INPUT_SCTP_CHAIN
+$INPUT_VERSION_CHAIN
+       chain c9 {
+               ip hdrlength @s9 accept
+       }
 
-       chain c7 {
-               sctp chunk init num-inbound-streams @s7 accept
+       chain c10 {
+               meta iifname . ip saddr . ipsec in reqid @s10 accept
        }
 
-       chain c8 {
-               ip version @s8 accept
+       chain c11 {
+               ether type vlan vlan id . ip saddr @s11 accept
+       }
+
+       chain c12 {
+               meta iifname . ip saddr . meta ipsec @s12 accept
        }
 
+       chain c13 {
+               tcp option mptcp subtype @s13 accept
+       }
+
+       chain c14 {
+               tcp option mptcp subtype . ip saddr @s14 accept
+       }
+}"
+
+EXPECTED="table inet t {$INPUT_OSF_SET
+       set s2 {
+               typeof vlan id
+               elements = { 2, 3, 103 }
+       }
+
+       set s3 {
+               typeof meta ibrpvid
+               elements = { 2, 3, 103 }
+       }
+$INPUT_FRAG_SET
+       set s5 {
+               typeof ip option ra value
+               elements = { 1, 1024 }
+       }
+
+       set s6 {
+               typeof tcp option maxseg size
+               elements = { 1, 1024 }
+       }
+
+       set s7 {
+               typeof sctp chunk init num-inbound-streams
+               elements = { 1, 4 }
+       }
+$INPUT_VERSION_SET
+       set s9 {
+               typeof ip hdrlength
+               elements = { 0, 1, 2, 3, 4,
+                            15 }
+       }
+
+       set s10 {
+               typeof iifname . ip saddr . ipsec in reqid
+               elements = { \"eth0\" . 10.1.1.2 . 42 }
+       }
+
+       set s11 {
+               typeof vlan id . ip saddr
+               elements = { 3567 . 1.2.3.4 }
+       }
+
+       set s12 {
+               typeof iifname . ip saddr . meta ipsec
+               elements = { \"eth0\" . 10.1.1.2 . exists }
+       }
+
+       set s13 {
+               typeof tcp option mptcp subtype
+               elements = { mp-join, dss }
+       }
+
+       set s14 {
+               typeof tcp option mptcp subtype . ip daddr
+               elements = { remove-addr . 10.1.1.1,
+                            mp-join . 10.1.1.2 }
+       }
+$INPUT_OSF_CHAIN
+       chain c2 {
+               vlan id @s2 accept
+       }
+$INPUT_FRAG_CHAIN
+       chain c5 {
+               ip option ra value @s5 accept
+       }
+
+       chain c6 {
+               tcp option maxseg size @s6 accept
+       }
+$INPUT_SCTP_CHAIN$INPUT_VERSION_CHAIN
        chain c9 {
                ip hdrlength @s9 accept
        }
 
        chain c10 {
-               meta iifname . ip saddr . ipsec in reqid @s10 accept
+               iifname . ip saddr . ipsec in reqid @s10 accept
        }
 
        chain c11 {
-               ether type vlan vlan id . ip saddr @s11 accept
+               vlan id . ip saddr @s11 accept
+       }
+
+       chain c12 {
+               iifname . ip saddr . meta ipsec @s12 accept
+       }
+
+       chain c13 {
+               tcp option mptcp subtype @s13 accept
+       }
+
+       chain c14 {
+               tcp option mptcp subtype . ip saddr @s14 accept
        }
 }"
 
-set -e
-$NFT -f - <<< $EXPECTED
 
+$NFT -f - <<< "$INPUT" || die $'nft command failed to process input:\n'">$INPUT<"
+
+$DIFF -u <($NFT list ruleset) - <<<"$EXPECTED" || die $'diff failed between ruleset and expected data.\nExpected:\n'">$EXPECTED<"
+
+if [ "$NFT_TEST_HAVE_bitshift" = n ] ; then
+       echo "Partial test due to NFT_TEST_HAVE_bitshift=n. Skip"
+       exit 77
+fi
+if [ "$NFT_TEST_HAVE_osf" = n ] ; then
+       echo "Partial test due to NFT_TEST_HAVE_osf=n. Skip"
+       exit 77
+fi
+if [ "$NFT_TEST_HAVE_sctp_chunks" = n ] ; then
+       echo "Partial test due to NFT_TEST_HAVE_sctp_chunks=n. Skip"
+       exit 77
+fi
index 07820b7c4fdd80716baa3bb40ea156d1a9eb392a..34465f1da0bec3138d84ddd0bfd20ed12ecb17ef 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
 set -e
 dumpfile=$(dirname $0)/dumps/$(basename $0).nft
 
index e58c088c2e846e2e5d93a4b413e960c2fbab3b55..863bcde43aac7a40f240d93f122e6e9d87c63056 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 RULESET="add table x
-add chain x y
+add chain x y { type filter hook input priority 0; }
 add rule x y jump y"
 
 # kernel must return ELOOP
index 4c1ac41db3b471c925ee2b38b958bb7456088f1f..645319e271946990e9ccdf5ff4e7cae4761e8b56 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_position_id)
+
 RULESET="flush ruleset
 add table x
 add chain x y
index 684d27a17b5a399741ad8ffc0ee290e681214476..698716b2b156f3ccbb7c19ecb957b9a5dbd2c065 100755 (executable)
@@ -7,6 +7,15 @@ $NFT add table inet test
 $NFT add chain inet test c
 
 RULE_COUNT=3000
+
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+       # The socket limit /proc/sys/net/core/rmem_max may be unsuitable for
+       # the test.
+       #
+       # Run only a subset of the test and mark as skipped at the end.
+       RULE_COUNT=500
+fi
+
 RULESET=$(
 for ((i = 0; i < ${RULE_COUNT}; i++)); do
        echo "add rule inet test c accept comment rule$i"
@@ -28,7 +37,15 @@ done
        echo '{"add": {"rule": {"family": "inet", "table": "test", "chain": "c", "expr": [{"accept": null}], "comment": "rule'$((${RULE_COUNT} - 1))'"}}}'
 echo ']}'
 )
-test $($NFT -j -e -a -f - <<< "$RULESET" |sed 's/\({"add":\)/\n\1/g' |grep '"handle"' |wc -l) -eq ${RULE_COUNT} || exit 1
+
+if [ "$NFT_TEST_HAVE_json" != n ]; then
+       test $($NFT -j -e -a -f - <<< "$RULESET" |sed 's/\({"add":\)/\n\1/g' |grep '"handle"' |wc -l) -eq ${RULE_COUNT} || exit 1
+fi
+
+if [ "$NFT_TEST_HAVE_inet_nat" = n ]; then
+       echo "Test partially skipped due to missing inet nat support."
+       exit 77
+fi
 
 # Now an example from firewalld's testsuite
 #
@@ -38,4 +55,18 @@ RULESET='{"nftables": [{"metainfo": {"json_schema_version": 1}}, {"add": {"table
 {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PREROUTING", "type": "filter", "hook": "prerouting", "prio": -290}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PREROUTING_ZONES"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PREROUTING", "expr": [{"jump": {"target": "raw_PREROUTING_ZONES"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PREROUTING", "type": "filter", "hook": "prerouting", "prio": -140}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PREROUTING_ZONES"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PREROUTING", "expr": [{"jump": {"target": "mangle_PREROUTING_ZONES"}}]}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PREROUTING", "type": "nat", "hook": "prerouting", "prio": -90}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PREROUTING_ZONES"}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PREROUTING", "expr": [{"jump": {"target": "nat_PREROUTING_ZONES"}}]}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POSTROUTING", "type": "nat", "hook": "postrouting", "prio": 110}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POSTROUTING_ZONES"}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POSTROUTING", "expr": [{"jump": {"target": "nat_POSTROUTING_ZONES"}}]}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PREROUTING", "type": "nat", "hook": "prerouting", "prio": -90}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PREROUTING_ZONES"}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PREROUTING", "expr": [{"jump": {"target": "nat_PREROUTING_ZONES"}}]}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POSTROUTING", "type": "nat", "hook": "postrouting", "prio": 110}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POSTROUTING_ZONES"}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POSTROUTING", "expr": [{"jump": {"target": "nat_POSTROUTING_ZONES"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_INPUT", "type": "filter", "hook": "input", "prio": 10}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FORWARD", "type": "filter", "hook": "forward", "prio": 10}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_OUTPUT", "type": "filter", "hook": "output", "prio": 10}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_INPUT_ZONES"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_INPUT", "expr": [{"match": {"left": {"ct": {"key": "state"}}, "op": "in", "right": {"set": ["established", "related"]}}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_INPUT", "expr": [{"match": {"left": {"ct": {"key": "status"}}, "op": "in", "right": "dnat"}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_INPUT", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "lo"}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_INPUT", "expr": [{"jump": {"target": "filter_INPUT_ZONES"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_INPUT", "expr": [{"match": {"left": {"ct": {"key": "state"}}, "op": "in", "right": {"set": ["invalid"]}}}, {"drop": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_INPUT", "expr": [{"reject": {"type": "icmpx", "expr": "admin-prohibited"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FORWARD_IN_ZONES"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FORWARD_OUT_ZONES"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD", "expr": [{"match": {"left": {"ct": {"key": "state"}}, "op": "in", "right": {"set": ["established", "related"]}}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD", "expr": [{"match": {"left": {"ct": {"key": "status"}}, "op": "in", "right": "dnat"}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "lo"}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD", "expr": [{"jump": {"target": "filter_FORWARD_IN_ZONES"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD", "expr": [{"jump": {"target": "filter_FORWARD_OUT_ZONES"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD", "expr": [{"match": {"left": {"ct": {"key": "state"}}, "op": "in", "right": {"set": ["invalid"]}}}, {"drop": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD", "expr": [{"reject": {"type": "icmpx", "expr": "admin-prohibited"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_OUTPUT", "expr": [{"match": {"left": {"meta": {"key": "oifname"}}, "op": "==", "right": "lo"}}, {"accept": null}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PREROUTING", "expr": [{"match": {"left": {"meta": {"key": "nfproto"}}, "op": "==", "right": "ipv6"}}, {"match": {"left": {"fib": {"flags": ["saddr", "iif"], "result": "oif"}}, "op": "==", "right": false}}, {"drop": null}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PREROUTING", "expr": [{"match": {"left": {"payload": {"protocol": "icmpv6", "field": "type"}}, "op": "==", "right": {"set": ["nd-router-advert", "nd-neighbor-solicit"]}}}, {"accept": null}]}}},
 {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_OUTPUT", "index": 0, "expr": [{"match": {"left": {"payload": {"protocol": "ip6", "field": "daddr"}}, "op": "==", "right": {"set": [{"prefix": {"addr": "::0.0.0.0", "len": 96}}, {"prefix": {"addr": "::ffff:0.0.0.0", "len": 96}}, {"prefix": {"addr": "2002:0000::", "len": 24}}, {"prefix": {"addr": "2002:0a00::", "len": 24}}, {"prefix": {"addr": "2002:7f00::", "len": 24}}, {"prefix": {"addr": "2002:ac10::", "len": 28}}, {"prefix": {"addr": "2002:c0a8::", "len": 32}}, {"prefix": {"addr": "2002:a9fe::", "len": 32}}, {"prefix": {"addr": "2002:e000::", "len": 19}}]}}}, {"reject": {"type": "icmpv6", "expr": "addr-unreachable"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD", "index": 2, "expr": [{"match": {"left": {"payload": {"protocol": "ip6", "field": "daddr"}}, "op": "==", "right": {"set": [{"prefix": {"addr": "::0.0.0.0", "len": 96}}, {"prefix": {"addr": "::ffff:0.0.0.0", "len": 96}}, {"prefix": {"addr": "2002:0000::", "len": 24}}, {"prefix": {"addr": "2002:0a00::", "len": 24}}, {"prefix": {"addr": "2002:7f00::", "len": 24}}, {"prefix": {"addr": "2002:ac10::", "len": 28}}, {"prefix": {"addr": "2002:c0a8::", "len": 32}}, {"prefix": {"addr": "2002:a9fe::", "len": 32}}, {"prefix": {"addr": "2002:e000::", "len": 19}}]}}}, {"reject": {"type": "icmpv6", "expr": "addr-unreachable"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_public"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_public_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_public_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_public_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_public_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_public_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_public", "expr": [{"jump": {"target": "raw_PRE_public_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_public", "expr": [{"jump": {"target": "raw_PRE_public_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_public", "expr": [{"jump": {"target": "raw_PRE_public_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_public", "expr": [{"jump": {"target": "raw_PRE_public_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_public", "expr": [{"jump": {"target": "raw_PRE_public_post"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_public"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_public_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_public_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_public_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_public_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_public_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_public", "expr": [{"jump": {"target": "filter_IN_public_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_public", "expr": [{"jump": {"target": "filter_IN_public_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_public", "expr": [{"jump": {"target": "filter_IN_public_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_public", "expr": [{"jump": {"target": "filter_IN_public_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_public", "expr": [{"jump": {"target": "filter_IN_public_post"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_public_allow", "expr": [{"match": {"left": {"payload": {"protocol": "tcp", "field": "dport"}}, "op": "==", "right": 22}}, {"match": {"left": {"ct": {"key": "state"}}, "op": "in", "right": {"set": ["new", "untracked"]}}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_public_allow", "expr": [{"match": {"left": {"payload": {"protocol": "ip6", "field": "daddr"}}, "op": "==", "right": {"prefix": {"addr": "fe80::", "len": 64}}}}, {"match": {"left": {"payload": {"protocol": "udp", "field": "dport"}}, "op": "==", "right": 546}}, {"match": {"left": {"ct": {"key": "state"}}, "op": "in", "right": {"set": ["new", "untracked"]}}}, {"accept": null}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_public"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_public_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_public_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_public_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_public_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_public_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_public", "expr": [{"jump": {"target": "filter_FWDI_public_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_public", "expr": [{"jump": {"target": "filter_FWDI_public_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_public", "expr": [{"jump": {"target": "filter_FWDI_public_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_public", "expr": [{"jump": {"target": "filter_FWDI_public_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_public", "expr": [{"jump": {"target": "filter_FWDI_public_post"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_public", "index": 4, "expr": [{"match": {"left": {"meta": {"key": "l4proto"}}, "op": "==", "right": {"set": ["icmp", "icmpv6"]}}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_public", "index": 4, "expr": [{"match": {"left": {"meta": {"key": "l4proto"}}, "op": "==", "right": {"set": ["icmp", "icmpv6"]}}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PREROUTING_ZONES", "expr": [{"goto": {"target": "raw_PRE_public"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_public"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_public_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_public_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_public_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_public_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_public_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_public", "expr": [{"jump": {"target": "mangle_PRE_public_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_public", "expr": [{"jump": {"target": "mangle_PRE_public_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_public", "expr": [{"jump": {"target": "mangle_PRE_public_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_public", "expr": [{"jump": {"target": "mangle_PRE_public_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_public", "expr": [{"jump": {"target": "mangle_PRE_public_post"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PREROUTING_ZONES", "expr": [{"goto": {"target": "mangle_PRE_public"}}]}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_public"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_public_pre"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_public_log"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_public_deny"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_public_allow"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_public_post"}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_pre"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_log"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_deny"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_allow"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_post"}}]}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_public"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_public_pre"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_public_log"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_public_deny"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_public_allow"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_public_post"}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_pre"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_log"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_deny"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_allow"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_public", "expr": [{"jump": {"target": "nat_PRE_public_post"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PREROUTING_ZONES", "expr": [{"goto": {"target": "nat_PRE_public"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PREROUTING_ZONES", "expr": [{"goto": {"target": "nat_PRE_public"}}]}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_public"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_public_pre"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_public_log"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_public_deny"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_public_allow"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_public_post"}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_pre"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_log"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_deny"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_allow"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_post"}}]}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_public"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_public_pre"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_public_log"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_public_deny"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_public_allow"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_public_post"}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_pre"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_log"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_deny"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_allow"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_public", "expr": [{"jump": {"target": "nat_POST_public_post"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POSTROUTING_ZONES", "expr": [{"goto": {"target": "nat_POST_public"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POSTROUTING_ZONES", "expr": [{"goto": {"target": "nat_POST_public"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_INPUT_ZONES", "expr": [{"goto": {"target": "filter_IN_public"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD_IN_ZONES", "expr": [{"goto": {"target": "filter_FWDI_public"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_public"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_public_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_public_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_public_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_public_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_public_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_public", "expr": [{"jump": {"target": "filter_FWDO_public_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_public", "expr": [{"jump": {"target": "filter_FWDO_public_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_public", "expr": [{"jump": {"target": "filter_FWDO_public_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_public", "expr": [{"jump": {"target": "filter_FWDO_public_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_public", "expr": [{"jump": {"target": "filter_FWDO_public_post"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD_OUT_ZONES", "expr": [{"goto": {"target": "filter_FWDO_public"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_trusted"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_trusted_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_trusted_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_trusted_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_trusted_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_trusted_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_trusted", "expr": [{"jump": {"target": "raw_PRE_trusted_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_trusted", "expr": [{"jump": {"target": "raw_PRE_trusted_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_trusted", "expr": [{"jump": {"target": "raw_PRE_trusted_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_trusted", "expr": [{"jump": {"target": "raw_PRE_trusted_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_trusted", "expr": [{"jump": {"target": "raw_PRE_trusted_post"}}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PREROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy2"}}, {"goto": {"target": "raw_PRE_trusted"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_trusted"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_trusted_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_trusted_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_trusted_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_trusted_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_trusted_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_trusted", "expr": [{"jump": {"target": "mangle_PRE_trusted_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_trusted", "expr": [{"jump": {"target": "mangle_PRE_trusted_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_trusted", "expr": [{"jump": {"target": "mangle_PRE_trusted_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_trusted", "expr": [{"jump": {"target": "mangle_PRE_trusted_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_trusted", "expr": [{"jump": {"target": "mangle_PRE_trusted_post"}}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PREROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy2"}}, {"goto": {"target": "mangle_PRE_trusted"}}]}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_trusted"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_trusted_pre"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_trusted_log"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_trusted_deny"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_trusted_allow"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_trusted_post"}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_pre"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_log"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_deny"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_allow"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_post"}}]}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_trusted"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_trusted_pre"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_trusted_log"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_trusted_deny"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_trusted_allow"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_trusted_post"}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_pre"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_log"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_deny"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_allow"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_trusted", "expr": [{"jump": {"target": "nat_PRE_trusted_post"}}]}}}, {"insert": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PREROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy2"}}, {"goto": {"target": "nat_PRE_trusted"}}]}}}, {"insert": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PREROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy2"}}, {"goto": {"target": "nat_PRE_trusted"}}]}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_trusted"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_trusted_pre"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_trusted_log"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_trusted_deny"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_trusted_allow"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_trusted_post"}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_pre"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_log"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_deny"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_allow"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_post"}}]}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_trusted"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_trusted_pre"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_trusted_log"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_trusted_deny"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_trusted_allow"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_trusted_post"}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_pre"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_log"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_deny"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_allow"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_trusted", "expr": [{"jump": {"target": "nat_POST_trusted_post"}}]}}}, {"insert": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POSTROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "oifname"}}, "op": "==", "right": "perm_dummy2"}}, {"goto": {"target": "nat_POST_trusted"}}]}}}, {"insert": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POSTROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "oifname"}}, "op": "==", "right": "perm_dummy2"}}, {"goto": {"target": "nat_POST_trusted"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_trusted"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_trusted_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_trusted_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_trusted_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_trusted_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_trusted_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_trusted", "expr": [{"jump": {"target": "filter_IN_trusted_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_trusted", "expr": [{"jump": {"target": "filter_IN_trusted_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_trusted", "expr": [{"jump": {"target": "filter_IN_trusted_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_trusted", "expr": [{"jump": {"target": "filter_IN_trusted_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_trusted", "expr": [{"jump": {"target": "filter_IN_trusted_post"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_trusted", "expr": [{"accept": null}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_INPUT_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy2"}}, {"goto": {"target": "filter_IN_trusted"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_trusted"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_trusted_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_trusted_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_trusted_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_trusted_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_trusted_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_trusted", "expr": [{"jump": {"target": "filter_FWDI_trusted_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_trusted", "expr": [{"jump": {"target": "filter_FWDI_trusted_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_trusted", "expr": [{"jump": {"target": "filter_FWDI_trusted_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_trusted", "expr": [{"jump": {"target": "filter_FWDI_trusted_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_trusted", "expr": [{"jump": {"target": "filter_FWDI_trusted_post"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_trusted", "expr": [{"accept": null}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD_IN_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy2"}}, {"goto": {"target": "filter_FWDI_trusted"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_trusted"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_trusted_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_trusted_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_trusted_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_trusted_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_trusted_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_trusted", "expr": [{"jump": {"target": "filter_FWDO_trusted_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_trusted", "expr": [{"jump": {"target": "filter_FWDO_trusted_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_trusted", "expr": [{"jump": {"target": "filter_FWDO_trusted_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_trusted", "expr": [{"jump": {"target": "filter_FWDO_trusted_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_trusted", "expr": [{"jump": {"target": "filter_FWDO_trusted_post"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_trusted", "expr": [{"accept": null}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD_OUT_ZONES", "expr": [{"match": {"left": {"meta": {"key": "oifname"}}, "op": "==", "right": "perm_dummy2"}}, {"goto": {"target": "filter_FWDO_trusted"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_work"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_work_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_work_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_work_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_work_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "raw_PRE_work_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_work", "expr": [{"jump": {"target": "raw_PRE_work_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_work", "expr": [{"jump": {"target": "raw_PRE_work_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_work", "expr": [{"jump": {"target": "raw_PRE_work_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_work", "expr": [{"jump": {"target": "raw_PRE_work_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PRE_work", "expr": [{"jump": {"target": "raw_PRE_work_post"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_work"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_work_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_work_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_work_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_work_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_IN_work_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_work", "expr": [{"jump": {"target": "filter_IN_work_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_work", "expr": [{"jump": {"target": "filter_IN_work_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_work", "expr": [{"jump": {"target": "filter_IN_work_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_work", "expr": [{"jump": {"target": "filter_IN_work_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_work", "expr": [{"jump": {"target": "filter_IN_work_post"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_work_allow", "expr": [{"match": {"left": {"payload": {"protocol": "tcp", "field": "dport"}}, "op": "==", "right": 22}}, {"match": {"left": {"ct": {"key": "state"}}, "op": "in", "right": {"set": ["new", "untracked"]}}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_work_allow", "expr": [{"match": {"left": {"payload": {"protocol": "ip6", "field": "daddr"}}, "op": "==", "right": {"prefix": {"addr": "fe80::", "len": 64}}}}, {"match": {"left": {"payload": {"protocol": "udp", "field": "dport"}}, "op": "==", "right": 546}}, {"match": {"left": {"ct": {"key": "state"}}, "op": "in", "right": {"set": ["new", "untracked"]}}}, {"accept": null}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "raw_PREROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy"}}, {"goto": {"target": "raw_PRE_work"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_work"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_work_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_work_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_work_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_work_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "mangle_PRE_work_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_work", "expr": [{"jump": {"target": "mangle_PRE_work_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_work", "expr": [{"jump": {"target": "mangle_PRE_work_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_work", "expr": [{"jump": {"target": "mangle_PRE_work_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_work", "expr": [{"jump": {"target": "mangle_PRE_work_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PRE_work", "expr": [{"jump": {"target": "mangle_PRE_work_post"}}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "mangle_PREROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy"}}, {"goto": {"target": "mangle_PRE_work"}}]}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_work"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_work_pre"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_work_log"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_work_deny"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_work_allow"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_PRE_work_post"}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_pre"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_log"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_deny"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_allow"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_post"}}]}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_work"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_work_pre"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_work_log"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_work_deny"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_work_allow"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_PRE_work_post"}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_pre"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_log"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_deny"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_allow"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PRE_work", "expr": [{"jump": {"target": "nat_PRE_work_post"}}]}}}, {"insert": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_PREROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy"}}, {"goto": {"target": "nat_PRE_work"}}]}}}, {"insert": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_PREROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy"}}, {"goto": {"target": "nat_PRE_work"}}]}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_work"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_work_pre"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_work_log"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_work_deny"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_work_allow"}}}, {"add": {"chain": {"family": "ip", "table": "firewalld", "name": "nat_POST_work_post"}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_pre"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_log"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_deny"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_allow"}}]}}}, {"add": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_post"}}]}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_work"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_work_pre"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_work_log"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_work_deny"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_work_allow"}}}, {"add": {"chain": {"family": "ip6", "table": "firewalld", "name": "nat_POST_work_post"}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_pre"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_log"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_deny"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_allow"}}]}}}, {"add": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POST_work", "expr": [{"jump": {"target": "nat_POST_work_post"}}]}}}, {"insert": {"rule": {"family": "ip", "table": "firewalld", "chain": "nat_POSTROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "oifname"}}, "op": "==", "right": "perm_dummy"}}, {"goto": {"target": "nat_POST_work"}}]}}}, {"insert": {"rule": {"family": "ip6", "table": "firewalld", "chain": "nat_POSTROUTING_ZONES", "expr": [{"match": {"left": {"meta": {"key": "oifname"}}, "op": "==", "right": "perm_dummy"}}, {"goto": {"target": "nat_POST_work"}}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_INPUT_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy"}}, {"goto": {"target": "filter_IN_work"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_work"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_work_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_work_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_work_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_work_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDI_work_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_work", "expr": [{"jump": {"target": "filter_FWDI_work_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_work", "expr": [{"jump": {"target": "filter_FWDI_work_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_work", "expr": [{"jump": {"target": "filter_FWDI_work_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_work", "expr": [{"jump": {"target": "filter_FWDI_work_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_work", "expr": [{"jump": {"target": "filter_FWDI_work_post"}}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD_IN_ZONES", "expr": [{"match": {"left": {"meta": {"key": "iifname"}}, "op": "==", "right": "perm_dummy"}}, {"goto": {"target": "filter_FWDI_work"}}]}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_work"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_work_pre"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_work_log"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_work_deny"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_work_allow"}}}, {"add": {"chain": {"family": "inet", "table": "firewalld", "name": "filter_FWDO_work_post"}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_work", "expr": [{"jump": {"target": "filter_FWDO_work_pre"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_work", "expr": [{"jump": {"target": "filter_FWDO_work_log"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_work", "expr": [{"jump": {"target": "filter_FWDO_work_deny"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_work", "expr": [{"jump": {"target": "filter_FWDO_work_allow"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDO_work", "expr": [{"jump": {"target": "filter_FWDO_work_post"}}]}}}, {"insert": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FORWARD_OUT_ZONES", "expr": [{"match": {"left": {"meta": {"key": "oifname"}}, "op": "==", "right": "perm_dummy"}}, {"goto": {"target": "filter_FWDO_work"}}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_IN_work", "index": 4, "expr": [{"match": {"left": {"meta": {"key": "l4proto"}}, "op": "==", "right": {"set": ["icmp", "icmpv6"]}}}, {"accept": null}]}}}, {"add": {"rule": {"family": "inet", "table": "firewalld", "chain": "filter_FWDI_work", "index": 4, "expr": [{"match": {"left": {"meta": {"key": "l4proto"}}, "op": "==", "right": {"set": ["icmp", "icmpv6"]}}}, {"accept": null}]}}}]}'
 
-test -z "$($NFT -j -e -a -f - <<< "$RULESET" |sed 's/\({"add":\|{"insert":\)/\n\1/g' |grep '\({"add":\|{"insert":\)' | grep -v '"handle"')"
+if [ "$NFT_TEST_HAVE_json" != n ]; then
+       test -z "$($NFT -j -e -a -f - <<< "$RULESET" |sed 's/\({"add":\|{"insert":\)/\n\1/g' |grep '\({"add":\|{"insert":\)' | grep -v '"handle"')"
+fi
+
+if [ "$NFT_TEST_HAVE_json" = n ]; then
+       echo "Test partially skipped due to missing JSON support."
+       exit 77
+fi
+
+if [ "$RULE_COUNT" != 3000 ] ; then
+       echo "NFT_TEST_HAS_SOCKET_LIMITS indicates that the socket limit for"
+       echo "/proc/sys/net/core/rmem_max is too small for this test. Mark as SKIPPED"
+       echo "You may bump the limit and rerun with \`NFT_TEST_HAS_SOCKET_LIMITS=n\`."
+       exit 77
+fi
index 89e5f42fc9f4d5c48720f59088a2253e2ed23bff..cbf96892c00ec4d2a91da89e8acfa56bd44c87c2 100755 (executable)
@@ -2,6 +2,10 @@
 
 set -e
 
+# The ruleset is supposed to fail due to non-existing interfaces,
+# hence depends on non-name-based interface hooks.
+[ "$NFT_TEST_HAVE_ifname_based_hooks" = y ] && exit 77
+
 RULESET="table inet filter {
        flowtable ftable {
                hook ingress priority 0; devices = { eno1, eno0, x };
diff --git a/tests/shell/testcases/transactions/0051map_0 b/tests/shell/testcases/transactions/0051map_0
new file mode 100755 (executable)
index 0000000..9ea5cd4
--- /dev/null
@@ -0,0 +1,122 @@
+#!/bin/bash
+
+rnd=$(mktemp -u XXXXXXXX)
+ns1="nft1trans-$rnd"
+
+#
+# dependency tracking for implicit set
+#
+RULESET="table ip x {
+       chain w {}
+       chain m {}
+
+       chain y {
+               ip saddr vmap { 1.1.1.1 : jump w, 2.2.2.2 : accept, 3.3.3.3 : goto m }
+       }
+}"
+
+$NFT -c -f - <<< "$RULESET" >/dev/null || exit 0
+$NFT -f - <<< "$RULESET" >/dev/null || exit 0
+ip netns add $ns1
+ip netns exec $ns1 $NFT -f - <<< "$RULESET" >/dev/null || exit 0
+ip netns del $ns1
+
+RULESET="flush chain ip x y
+delete chain ip x w"
+
+$NFT -c -f - <<< "$RULESET" >/dev/null || exit 0
+$NFT -f - <<< "$RULESET" >/dev/null || exit 0
+
+#
+# dependency tracking for map in implicit chain
+#
+RULESET="table ip x {
+       chain w {}
+       chain m {}
+
+       chain y {
+               meta iifname \"eno1\" jump {
+                       ip saddr vmap { 1.1.1.1 : jump w, 3.3.3.3 : goto m }
+               }
+       }
+}"
+
+$NFT -c -f - <<< "$RULESET" >/dev/null || exit 0
+$NFT -f - <<< "$RULESET" >/dev/null || exit 0
+ip netns add $ns1
+ip netns exec $ns1 $NFT -f - <<< "$RULESET" >/dev/null || exit 0
+ip netns del $ns1
+
+RULESET="flush chain ip x y
+delete chain ip x w"
+
+$NFT -c -f - <<< "$RULESET" >/dev/null || exit 0
+$NFT -f - <<< "$RULESET" >/dev/null || exit 0
+
+#
+# dependency tracking for explicit map
+#
+RULESET="table ip x {
+       chain w {}
+       chain m {}
+
+       map y {
+               type ipv4_addr : verdict
+               elements = { 1.1.1.1 : jump w, 2.2.2.2 : accept, 3.3.3.3 : goto m }
+       }
+}"
+
+$NFT -c -f - <<< "$RULESET" >/dev/null || exit 0
+$NFT -f - <<< "$RULESET" >/dev/null || exit 0
+ip netns add $ns1
+ip netns exec $ns1 $NFT -f - <<< "$RULESET" >/dev/null || exit 0
+ip netns del $ns1
+
+RULESET="delete set ip x y
+delete chain ip x w"
+
+$NFT -c -f - <<< "$RULESET" >/dev/null || exit 0
+$NFT -f - <<< "$RULESET" >/dev/null || exit 0
+
+#
+# error path for implicit set
+#
+RULESET="table inet filter {
+       chain w {
+               jump z
+       }
+       chain z {
+               jump w
+       }
+
+       chain test {
+               ip protocol { tcp, udp } ip saddr vmap { 1.1.1.1 : jump z } counter flow add @nonexisting
+               ip6 nexthdr { tcp, udp } ct mark and 2 == 2 counter
+       }
+}"
+
+$NFT -c -f - <<< "$RULESET" >/dev/null || exit 0
+$NFT -f - <<< "$RULESET" >/dev/null || exit 0
+
+#
+# error path for implicit set
+#
+RULESET="table inet filter {
+       chain w {
+               jump z
+       }
+       chain z {
+               jump w
+       }
+
+       chain test {
+               ip protocol { tcp, udp } jump {
+                       ip saddr vmap { 1.1.1.1 : jump z }
+               }
+               ip6 nexthdr { tcp, udp } ct mark and 2 == 2 counter
+       }
+}"
+
+$NFT -c -f - <<< "$RULESET" >/dev/null || exit 0
+$NFT -f - <<< "$RULESET" >/dev/null || exit 0
+$NFT flush table inet filter || exit 0
diff --git a/tests/shell/testcases/transactions/30s-stress b/tests/shell/testcases/transactions/30s-stress
new file mode 100755 (executable)
index 0000000..e1e8b74
--- /dev/null
@@ -0,0 +1,709 @@
+#!/bin/bash
+
+# NFT_TEST_SKIP(NFT_TEST_SKIP_slow)
+
+runtime=30
+
+# allow stand-alone execution as well, e.g. '$0 3600'
+if [ x"$1" != "x" ] ;then
+       if [ -z "${NFT_TEST_HAVE_chain_binding+x}" ]; then
+               NFT_TEST_HAVE_chain_binding=y
+       fi
+       if [ -z "${NFT_TEST_HAVE_pipapo+x}" ]; then
+               NFT_TEST_HAVE_pipapo=y
+       fi
+       echo "running standalone with:"
+       echo "NFT_TEST_HAVE_chain_binding="$NFT_TEST_HAVE_chain_binding
+       echo "NFT_TEST_HAVE_pipapo="$NFT_TEST_HAVE_pipapo
+       if [ $1 -ge 0 ]; then
+               runtime="$1"
+       else
+               echo "Invalid runtime $1"
+               exit 1
+       fi
+fi
+
+if [ x = x"$NFT" ] ; then
+       NFT=nft
+fi
+
+if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then
+       # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for
+       # the test.
+       #
+       # Skip it. You may ensure that the limits are suitable and rerun
+       # with NFT_TEST_HAS_SOCKET_LIMITS=n.
+       exit 77
+fi
+
+if [ -z "${NFT_TEST_HAVE_chain_binding+x}" ] ; then
+       NFT_TEST_HAVE_chain_binding=n
+       mydir="$(dirname "$0")"
+       $NFT --check -f "$mydir/../../features/chain_binding.nft"
+       if [ $? -eq 0 ];then
+               NFT_TEST_HAVE_chain_binding=y
+       else
+               echo "Assuming anonymous chains are not supported"
+       fi
+fi
+
+if [ "$NFT_TEST_HAVE_pipapo" != y ] ;then
+       echo "Skipping pipapo set backend, kernel does not support it"
+fi
+
+testns=testns-$(mktemp -u "XXXXXXXX")
+tmp=""
+
+faultname="/proc/self/make-it-fail"
+tables="foo bar"
+
+failslab_defaults() {
+       test -w $faultname || return
+
+       # Disable fault injection unless process has 'make-it-fail' set
+       echo Y > /sys/kernel/debug/failslab/task-filter
+
+       # allow all slabs to fail (if process is tagged).
+       find /sys/kernel/slab/ -wholename '*/kmalloc-[0-9]*/failslab' -type f -exec sh -c 'echo 1 > {}' \;
+
+       # no limit on the number of failures, or clause works around old kernels that reject negative integer.
+       echo -1 > /sys/kernel/debug/failslab/times 2>/dev/null || printf '%#x -1' > /sys/kernel/debug/failslab/times
+
+       # Set to 2 for full dmesg traces for each injected error
+       echo 0 > /sys/kernel/debug/failslab/verbose
+}
+
+failslab_random()
+{
+       r=$((RANDOM%2))
+
+       if [ $r -eq 0 ]; then
+               echo Y > /sys/kernel/debug/failslab/ignore-gfp-wait
+       else
+               echo N > /sys/kernel/debug/failslab/ignore-gfp-wait
+       fi
+
+       r=$((RANDOM%5))
+       echo $r > /sys/kernel/debug/failslab/probability
+       r=$((RANDOM%100))
+       echo $r > /sys/kernel/debug/failslab/interval
+
+       # allow a small initial 'success budget'.
+       # failures only appear after this many allocated bytes.
+       r=$((RANDOM%16384))
+       echo $r > /sys/kernel/debug/$FAILTYPE/space
+}
+
+netns_del() {
+       ip netns pids "$testns" | xargs kill 2>/dev/null
+       ip netns del "$testns"
+}
+
+netns_add()
+{
+       ip netns add "$testns"
+       ip -netns "$testns" link set lo up
+}
+
+cleanup() {
+       [ "$tmp" = "" ] || rm -f "$tmp"
+       netns_del
+}
+
+nft_with_fault_inject()
+{
+       file="$1"
+
+       if [ -w "$faultname" ]; then
+               failslab_random
+
+               ip netns exec "$testns" bash -c "echo 1 > $faultname ; exec $NFT -f $file"
+       fi
+
+       ip netns exec "$testns" $NFT -f "$file"
+}
+
+trap cleanup EXIT
+tmp=$(mktemp)
+
+jump_or_goto()
+{
+       if [ $((RANDOM & 1)) -eq 0 ] ;then
+               echo -n "jump"
+       else
+               echo -n "goto"
+       fi
+}
+
+random_verdict()
+{
+       max="$1"
+
+       if [ $max -eq 0 ]; then
+               max=1
+       fi
+
+       rnd=$((RANDOM%max))
+
+       if [ $rnd -gt 0 ];then
+               jump_or_goto
+               printf " chain%03u" "$((rnd+1))"
+               return
+       fi
+
+       if [ $((RANDOM & 1)) -eq 0 ] ;then
+               echo "accept"
+       else
+               echo "drop"
+       fi
+}
+
+randsleep()
+{
+       local s=$((RANDOM%1))
+       local ms=$((RANDOM%1000))
+       sleep $s.$ms
+}
+
+randlist()
+{
+       while [ -r $tmp ]; do
+               randsleep
+               ip netns exec $testns $NFT list ruleset > /dev/null
+       done
+}
+
+randflush()
+{
+       while [ -r $tmp ]; do
+               randsleep
+               ip netns exec $testns $NFT flush ruleset > /dev/null
+       done
+}
+
+randdeltable()
+{
+       while [ -r $tmp ]; do
+               randsleep
+               for t in $tables; do
+                       r=$((RANDOM%10))
+
+                       if [ $r -eq 1 ] ;then
+                               ip netns exec $testns $NFT delete table inet $t
+                               randsleep
+                       fi
+               done
+       done
+}
+
+randdelset()
+{
+       while [ -r $tmp ]; do
+               randsleep
+               for t in $tables; do
+                       r=$((RANDOM%10))
+                       s=$((RANDOM%10))
+
+                       case $r in
+                       0)
+                               setname=set_$s
+                               ;;
+                       1)
+                               setname=sett${s}
+                               ;;
+                       2)
+                               setname=dmap_${s}
+                               ;;
+                       3)
+                               setname=dmapt${s}
+                               ;;
+                       4)
+                               setname=vmap_${s}
+                               ;;
+                       5)
+                               setname=vmapt${s}
+                               ;;
+                       *)
+                               continue
+                               ;;
+                       esac
+
+                       if [ $r -eq 1 ] ;then
+                               ip netns exec $testns $NFT delete set inet $t $setname
+                       fi
+               done
+       done
+}
+
+randdelchain()
+{
+       while [ -r $tmp ]; do
+               for t in $tables; do
+                       local c=$((RANDOM%100))
+                       randsleep
+                       chain=$(printf "chain%03u" "$c")
+
+                       local r=$((RANDOM%10))
+                       if [ $r -eq 1 ];then
+                               # chain can be invalid/unknown.
+                               ip netns exec $testns $NFT delete chain inet $t $chain
+                       fi
+               done
+       done
+}
+
+randdisable()
+{
+       while [ -r $tmp ]; do
+               for t in $tables; do
+                       randsleep
+                       local r=$((RANDOM%10))
+                       if [ $r -eq 1 ];then
+                               ip netns exec $testns $NFT add table inet $t '{flags dormant; }'
+                               randsleep
+                               ip netns exec $testns $NFT add table inet $t '{ }'
+                       fi
+               done
+       done
+}
+
+randdelns()
+{
+       while [ -r $tmp ]; do
+               randsleep
+               netns_del
+               netns_add
+               randsleep
+       done
+}
+
+available_flags()
+{
+       local -n available_flags=$1
+       selected_key=$2
+       if [ "$selected_key" == "single" ] ;then
+               available_flags+=("interval")
+       elif [ "$selected_key" == "concat" ] ;then
+               if [ "$NFT_TEST_HAVE_pipapo" = y ] ;then
+                       available_flags+=("interval")
+               fi
+       fi
+}
+
+random_timeout()
+{
+       local timeout=""
+       local expires
+       local r=$((RANDOM%3))
+
+       case "$r" in
+       0)
+               timeout=$((RANDOM%60000))
+               timeout="timeout ${timeout}ms"
+               ;;
+       1)
+               timeout=$((RANDOM%60000))
+               expires=$((timeout))
+               if [ $timeout -gt 0 ];then
+                       expires=$((RANDOM%expires))
+               else
+                       expires=0
+               fi
+
+               timeout="timeout ${timeout}ms expires ${expires}ms"
+               ;;
+       esac
+
+       echo -n "$timeout"
+}
+
+random_element_string=""
+# create a random element.  Could cause any of the following:
+# 1. Invalid set/map
+# 2. Element already exists in set/map w. create
+# 3. Element is new but wants to jump to unknown chain
+# 4. Element already exsists in set/map w. add, but verdict (map data) differs
+# 5. Element is created/added/deleted from 'flags constant' set.
+random_elem()
+{
+       tr=$((RANDOM%2))
+       t=0
+
+       for table in $tables; do
+               if [ $t -ne $tr ]; then
+                       t=$((t+1))
+                       continue
+               fi
+
+               kr=$((RANDOM%2))
+               k=0
+               cnt=0
+               for key in "single" "concat"; do
+                       if [ $k -ne $kr ] ;then
+                               cnt=$((cnt+2))
+                               k=$((k+1))
+                               continue
+                       fi
+
+                       fr=$((RANDOM%2))
+                       f=0
+
+                       FLAGS=("")
+                       available_flags FLAGS $key
+                       for flags in "${FLAGS[@]}" ; do
+                               cnt=$((cnt+1))
+                               if [ $f -ne fkr ] ;then
+                                       f=$((f+1))
+                                       continue
+                               fi
+
+                               want="${key}${flags}"
+
+                               e=$((RANDOM%256))
+                               case "$want" in
+                               "single") element="10.1.1.$e"
+                                       ;;
+                               "concat") element="10.1.2.$e . $((RANDOM%65536))"
+                                       ;;
+                               "singleinterval") element="10.1.$e.0-10.1.$e.$e"
+                                       ;;
+                               "concatinterval") element="10.1.$e.0-10.1.$e.$e . $((RANDOM%65536))"
+                                       ;;
+                               *)      echo "bogus key $want"
+                                       exit 111
+                                       ;;
+                               esac
+
+                               # This may result in invalid jump, but thats what we want.
+                               count=$(($RANDOM%100))
+
+                               r=$((RANDOM%7))
+                               case "$r" in
+                               0)
+                                       random_element_string="inet $table set_${cnt} { $element }"
+                                       ;;
+                               1)      random_element_string="inet $table sett${cnt} { $element $(random_timeout) }"
+                                       ;;
+                               2)      random_element_string="inet $table dmap_${cnt} { $element : $RANDOM }"
+                                       ;;
+                               3)      random_element_string="inet $table dmapt${cnt} { $element $(random_timeout) : $RANDOM }"
+                                       ;;
+                               4)      random_element_string="inet $table vmap_${cnt} { $element : `random_verdict $count` }"
+                                       ;;
+                               5)      random_element_string="inet $table vmapt${cnt} { $element $(random_timeout) : `random_verdict $count` }"
+                                       ;;
+                               6)      random_element_string="inet $table setc${cnt} { $element }"
+                                       ;;
+                               esac
+
+                               return
+                       done
+               done
+       done
+}
+
+randload()
+{
+       while [ -r $tmp ]; do
+               random_element_string=""
+               r=$((RANDOM%10))
+
+               what=""
+               case $r in
+               1)
+                       (echo "flush ruleset"; cat "$tmp"
+                        echo "insert rule inet foo INPUT meta nftrace set 1"
+                        echo "insert rule inet foo OUTPUT meta nftrace set 1"
+                       ) | nft_with_fault_inject "/dev/stdin"
+                       ;;
+               2)      what="add"
+                       ;;
+               3)      what="create"
+                       ;;
+               4)      what="delete"
+                       ;;
+               5)      what="destroy"
+                       ;;
+               6)      what="get"
+                       ;;
+               *)
+                       randsleep
+                       ;;
+               esac
+
+               if [ x"$what" = "x" ]; then
+                       nft_with_fault_inject "$tmp"
+               else
+                       # This can trigger abort path, for various reasons:
+                       # invalid set name
+                       # key mismatches set specification (concat vs. single value)
+                       # attempt to delete non-existent key
+                       # attempt to create dupliacte key
+                       # attempt to add duplicate key with non-matching value (data)
+                       # attempt to add new uniqeue key with a jump to an unknown chain
+                       random_elem
+                       ( cat "$tmp"; echo "$what element $random_element_string") | nft_with_fault_inject "/dev/stdin"
+               fi
+       done
+}
+
+randmonitor()
+{
+       while [ -r $tmp ]; do
+               randsleep
+               timeout=$((RANDOM%16))
+               timeout $((timeout+1)) $NFT monitor > /dev/null
+       done
+}
+
+floodping() {
+       cpunum=$(grep -c processor /proc/cpuinfo)
+       cpunum=$((cpunum+1))
+
+       while [ -r $tmp ]; do
+               spawn=$((RANDOM%$cpunum))
+
+               # spawn at most $cpunum processes. Or maybe none at all.
+               i=0
+               while [ $i -lt $spawn ]; do
+                       mask=$(printf 0x%x $((1<<$i)))
+                       timeout 3 ip netns exec "$testns" taskset $mask ping -4 -fq 127.0.0.1 > /dev/null &
+                       timeout 3 ip netns exec "$testns" taskset $mask ping -6 -fq ::1 > /dev/null &
+                       i=$((i+1))
+               done
+
+               wait
+               randsleep
+       done
+}
+
+stress_all()
+{
+       # if fault injection is enabled, first a quick test to trigger
+       # abort paths without any parallel deletes/flushes.
+       if [ -w $faultname ] ;then
+               for i in $(seq 1 10);do
+                       nft_with_fault_inject "$tmp"
+               done
+       fi
+
+       randlist &
+       randflush &
+       randdeltable &
+       randdisable &
+       randdelchain &
+       randdelset &
+       randdelns &
+       randload &
+       randmonitor &
+}
+
+gen_anon_chain_jump()
+{
+       echo -n "insert rule inet $@ "
+       jump_or_goto
+
+       if [ "$NFT_TEST_HAVE_chain_binding" = n ] ; then
+               echo " defaultchain"
+               return
+       fi
+
+       echo -n " { "
+       jump_or_goto
+       echo " defaultchain; counter; }"
+}
+
+gen_ruleset() {
+echo > "$tmp"
+for table in $tables; do
+       count=$((RANDOM % 100))
+       if [ $count -lt 1 ];then
+               count=1
+       fi
+
+       echo add table inet "$table" >> "$tmp"
+       echo flush table inet "$table" >> "$tmp"
+
+       echo "add chain inet $table INPUT { type filter hook input priority 0; }" >> "$tmp"
+       echo "add chain inet $table OUTPUT { type filter hook output priority 0; }" >> "$tmp"
+       for c in $(seq 1 $count); do
+               chain=$(printf "chain%03u" "$c")
+               echo "add chain inet $table $chain" >> "$tmp"
+       done
+
+       echo "add chain inet $table defaultchain" >> "$tmp"
+
+       for c in $(seq 1 $count); do
+               chain=$(printf "chain%03u" "$c")
+               for BASE in INPUT OUTPUT; do
+                       echo "add rule inet $table $BASE counter jump $chain" >> "$tmp"
+               done
+               if [ $((RANDOM%10)) -eq 1 ];then
+                       echo "add rule inet $table $chain counter jump defaultchain" >> "$tmp"
+               else
+                       echo "add rule inet $table $chain counter return" >> "$tmp"
+               fi
+       done
+
+       cnt=0
+
+       # add a few anonymous sets. rhashtable is convered by named sets below.
+       c=$((RANDOM%$count))
+       chain=$(printf "chain%03u" "$((c+1))")
+       echo "insert rule inet $table $chain tcp dport 22-26 ip saddr { 1.2.3.4, 5.6.7.8 } counter comment hash_fast" >> "$tmp"
+       echo "insert rule inet $table $chain ip6 saddr { ::1, dead::beef } counter" comment hash >> "$tmp"
+       echo "insert rule inet $table $chain ip saddr { 1.2.3.4 - 5.6.7.8, 127.0.0.1 } comment rbtree" >> "$tmp"
+       # bitmap 1byte, with anon chain jump
+       gen_anon_chain_jump "$table $chain ip protocol { 6, 17 }" >> "$tmp"
+
+       # bitmap 2byte
+       echo "insert rule inet $table $chain tcp dport != { 22, 23, 80 } goto defaultchain" >> "$tmp"
+       echo "insert rule inet $table $chain tcp dport { 1-1024, 8000-8080 } jump defaultchain comment rbtree" >> "$tmp"
+       if [ "$NFT_TEST_HAVE_pipapo" = y ] ;then
+               # pipapo (concat + set), with goto anonymous chain.
+               gen_anon_chain_jump "$table $chain ip saddr . tcp dport { 1.2.3.4 . 1-1024, 1.2.3.6 - 1.2.3.10 . 8000-8080, 1.2.3.4 . 8080, 1.2.3.6 - 1.2.3.10 . 22 }" >> "$tmp"
+       fi
+
+       # add a few anonymous sets. rhashtable is convered by named sets below.
+       c=$((RANDOM%$count))
+       chain=$(printf "chain%03u" "$((c+1))")
+       echo "insert rule inet $table $chain tcp dport 22-26 ip saddr { 1.2.3.4, 5.6.7.8 } counter comment hash_fast" >> "$tmp"
+       echo "insert rule inet $table $chain ip6 saddr { ::1, dead::beef } counter" comment hash >> "$tmp"
+       echo "insert rule inet $table $chain ip saddr { 1.2.3.4 - 5.6.7.8, 127.0.0.1 } comment rbtree" >> "$tmp"
+       # bitmap 1byte, with anon chain jump
+       gen_anon_chain_jump "$table $chain ip protocol { 6, 17 }" >> "$tmp"
+       # bitmap 2byte
+       echo "insert rule inet $table $chain tcp dport != { 22, 23, 80 } goto defaultchain" >> "$tmp"
+       echo "insert rule inet $table $chain tcp dport { 1-1024, 8000-8080 } jump defaultchain comment rbtree" >> "$tmp"
+       if [ "$NFT_TEST_HAVE_pipapo" = y ] ;then
+               # pipapo (concat + set), with goto anonymous chain.
+               gen_anon_chain_jump "$table $chain ip saddr . tcp dport { 1.2.3.4 . 1-1024, 1.2.3.6 - 1.2.3.10 . 8000-8080, 1.2.3.4 . 8080, 1.2.3.6 - 1.2.3.10 . 22 }" >> "$tmp"
+       fi
+
+       # add constant/immutable sets
+       size=$((RANDOM%5120000))
+       size=$((size+2))
+       echo "add set inet $table setc1 { typeof tcp dport; size $size; flags constant; elements = { 22, 44 } }" >> "$tmp"
+       echo "add set inet $table setc2 { typeof ip saddr; size $size; flags constant; elements = { 1.2.3.4, 5.6.7.8 } }" >> "$tmp"
+       echo "add set inet $table setc3 { typeof ip6 daddr; size $size; flags constant; elements = { ::1, dead::1 } }" >> "$tmp"
+       echo "add set inet $table setc4 { typeof tcp dport; size $size; flags interval,constant; elements = { 22-44, 55-66 } }" >> "$tmp"
+       echo "add set inet $table setc5 { typeof ip saddr; size $size; flags interval,constant; elements = { 1.2.3.4-5.6.7.8, 10.1.1.1 } }" >> "$tmp"
+       echo "add set inet $table setc6 { typeof ip6 daddr; size $size; flags interval,constant; elements = { ::1, dead::1-dead::3 } }" >> "$tmp"
+
+       # add named sets with various combinations (plain value, range, concatenated values, concatenated ranges, with timeouts, with data ...)
+       for key in "ip saddr" "ip saddr . tcp dport"; do
+               FLAGS=("")
+               if [ "$key" == "ip saddr" ] ;then
+                       FLAGS+=("flags interval;")
+               elif [ "$key" == "ip saddr . tcp dport" ] ;then
+                       if [ "$NFT_TEST_HAVE_pipapo" = y ] ;then
+                               FLAGS+=("flags interval;")
+                       fi
+               fi
+               for ((i = 0; i < ${#FLAGS[@]}; i++)) ; do
+                       timeout=$((RANDOM%10))
+                       timeout=$((timeout+1))
+                       timeout="timeout ${timeout}s"
+
+                       cnt=$((cnt+1))
+                       flags=${FLAGS[$i]}
+                       echo "add set inet $table set_${cnt}  { typeof ${key} ; ${flags} }" >> "$tmp"
+                       echo "add set inet $table sett${cnt} { typeof ${key} ; $timeout; ${flags} }" >> "$tmp"
+                       echo "add map inet $table dmap_${cnt} { typeof ${key} : meta mark ; ${flags} }" >> "$tmp"
+                       echo "add map inet $table dmapt${cnt} { typeof ${key} : meta mark ; $timeout ; ${flags} }" >> "$tmp"
+                       echo "add map inet $table vmap_${cnt} { typeof ${key} : verdict ; ${flags} }" >> "$tmp"
+                       echo "add map inet $table vmapt${cnt} { typeof ${key} : verdict; $timeout ; ${flags} }" >> "$tmp"
+               done
+       done
+
+       cnt=0
+       for key in "single" "concat"; do
+               FLAGS=("")
+               available_flags FLAGS $key
+
+               for ((i = 0; i < ${#FLAGS[@]}; i++)) ; do
+                       flags=${FLAGS[$i]}
+                       want="${key}${flags}"
+                       cnt=$((cnt+1))
+                       maxip=$((RANDOM%256))
+
+                       if [ $maxip -eq 0 ];then
+                               maxip=1
+                       fi
+
+                       for e in $(seq 1 $maxip);do
+                               case "$want" in
+                               "single") element="10.1.1.$e"
+                                       ;;
+                               "concat")
+                                       element="10.1.2.$e . $((RANDOM%65536))"
+                                       ;;
+                               "singleinterval")
+                                       element="10.1.$e.0-10.1.$e.$e"
+                                       ;;
+                               "concatinterval")
+                                       element="10.1.$e.0-10.1.$e.$e . $((RANDOM%65536))"
+                                       ;;
+                               *)
+                                       echo "bogus key $want"
+                                       exit 111
+                                       ;;
+                               esac
+
+                               echo "add element inet $table set_${cnt} { $element }" >> "$tmp"
+                               echo "add element inet $table sett${cnt} { $element $(random_timeout) }" >> "$tmp"
+                               echo "add element inet $table dmap_${cnt} { $element : $RANDOM }" >> "$tmp"
+                               echo "add element inet $table dmapt${cnt} { $element $(random_timeout) : $RANDOM }" >> "$tmp"
+                               echo "add element inet $table vmap_${cnt} { $element : `random_verdict $count` }" >> "$tmp"
+                               echo "add element inet $table vmapt${cnt} { $element $(random_timeout) : `random_verdict $count` }" >> "$tmp"
+                       done
+               done
+       done
+done
+}
+
+run_test()
+{
+       local time_now=$(date +%s)
+       local time_stop=$((time_now + $runtime))
+       local regen=30
+
+       while [ $time_now -lt $time_stop ]; do
+               if [ $regen -gt 0 ];then
+                       sleep 1
+                       time_now=$(date +%s)
+                       regen=$((regen-1))
+                       continue
+               fi
+
+               # This clobbers the previously generated ruleset, this is intentional.
+               gen_ruleset
+               regen=$((RANDOM%60))
+               regen=$((regen+2))
+               time_now=$(date +%s)
+       done
+}
+
+netns_add
+
+gen_ruleset
+ip netns exec "$testns" $NFT -f "$tmp" || exit 1
+
+failslab_defaults
+
+stress_all 2>/dev/null &
+
+randsleep
+
+floodping 2> /dev/null &
+
+run_test
+
+# this stops stress_all
+rm -f "$tmp"
+tmp=""
+sleep 4
+
+if [ "$NFT_TEST_HAVE_chain_binding" = n ] ; then
+       echo "Ran a modified version of the test due to NFT_TEST_HAVE_chain_binding=n"
+fi
diff --git a/tests/shell/testcases/transactions/anon_chain_loop b/tests/shell/testcases/transactions/anon_chain_loop
new file mode 100755 (executable)
index 0000000..3053d16
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# anon chains with c1 -> c2 recursive jump, expect failure
+$NFT -f - <<EOF
+table ip t {
+ chain c2 { type filter hook input priority 0; }
+ chain c1 { }
+}
+
+add t c1 ip saddr 127.0.0.1 jump { jump c2; }
+add t c2 ip saddr 127.0.0.1 jump { jump c1; }
+EOF
+
+if [ $? -eq 0 ] ; then
+        echo "E: able to load bad ruleset" >&2
+        exit 1
+fi
+
+exit 0
diff --git a/tests/shell/testcases/transactions/atomic_replace.sh b/tests/shell/testcases/transactions/atomic_replace.sh
new file mode 100755 (executable)
index 0000000..dce1786
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+set -e
+
+rnd=$(mktemp -u XXXXXXXX)
+ns="nft-atomic-$rnd"
+pid1=""
+pid2=""
+duration=8
+
+cleanup()
+{
+       kill "$pid1" "$pid2"
+       ip netns del "$ns"
+}
+
+trap cleanup EXIT
+
+ip netns add "$ns" || exit 111
+ip -net "$ns" link set lo up
+
+ip netns exec "$ns" ping 127.0.0.1 -q -c 1
+
+ip netns exec "$ns" $NFT -f - <<EOF
+table ip t {
+       set s {
+               type ipv4_addr
+               elements = { 127.0.0.1 }
+       }
+
+       chain input {
+               type filter hook input priority 0; policy accept;
+               ip protocol icmp counter
+       }
+
+       chain output {
+               type filter hook output priority 0; policy accept;
+               ip protocol icmp ip daddr @s drop
+       }
+}
+EOF
+
+ip netns exec "$ns" ping -f 127.0.0.1 &
+pid1=$!
+ip netns exec "$ns" ping -f 127.0.0.1 &
+pid2=$!
+
+time_now=$(date +%s)
+time_stop=$((time_now + duration))
+repl=0
+
+while [ $time_now -lt $time_stop ]; do
+ip netns exec "$ns" $NFT -f - <<EOF
+flush chain ip t output
+table ip t {
+       chain output {
+               type filter hook output priority 0; policy accept;
+               ip protocol icmp ip daddr @s drop
+       }
+}
+EOF
+       repl=$((repl+1))
+
+       # do at least 100 replaces and stop after $duration seconds.
+       if [ $((repl % 101)) -eq 100 ];then
+               time_now=$(date +%s)
+       fi
+done
+
+# must match, all icmp packets dropped in output.
+ip netns exec "$ns" $NFT list chain ip t input | grep "counter packets 0"
+
+echo "Completed $repl chain replacements"
diff --git a/tests/shell/testcases/transactions/bad_expression b/tests/shell/testcases/transactions/bad_expression
new file mode 100755 (executable)
index 0000000..794b625
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# table with invalid expression (masquerade called from filter table).
+# nft must return an error.  Also catch nfnetlink retry loops that
+# cause nft or kernel to spin.
+timeout 3 $NFT -f - <<EOF
+table ip t0 {
+       chain c { }
+       chain input {
+               type filter hook input priority 0;
+               jump c
+       }
+}
+
+table ip t1 {
+       chain a {
+               masquerade
+       }
+       chain input {
+               type filter hook input priority 1;
+               jump a
+       }
+}
+EOF
+
+rc=$?
+if [ $rc -eq 0 ]; then
+       echo "Ruleset should have failed" 1>&2
+       exit 111
+fi
+
+# 124 means 'command timed out', fail if this
+# happens.  Else, pass, failure is wanted here.
+if [ $rc -ne 124 ]; then
+       exit 0
+fi
+
+exit $rc
diff --git a/tests/shell/testcases/transactions/bad_rule_graphs b/tests/shell/testcases/transactions/bad_rule_graphs
new file mode 100755 (executable)
index 0000000..53047c3
--- /dev/null
@@ -0,0 +1,262 @@
+#!/bin/bash
+
+# test case to attempt to fool ruleset validation.
+# Initial ruleset added here is fine, then we try to make the
+# ruleset exceed the jump chain depth via jumps, gotos, verdict
+# map entries etc, either by having the map loop back to itself,
+# jumping back to an earlier chain and so on.
+#
+# Also check that can't hook up a user-defined chain with a
+# restricted expression (here: tproxy, only valid from prerouting
+# hook) to the input hook, even if reachable indirectly via vmap.
+
+bad_ruleset()
+{
+       ret=$1
+       shift
+
+       if [ $ret -eq 0 ];then
+               echo "Accepted bad ruleset with $@"
+               $NFT list ruleset
+               exit 1
+       fi
+}
+
+good_ruleset()
+{
+       ret=$1
+       shift
+
+       if [ $ret -ne 0 ];then
+               echo "Rejected good ruleset with $@"
+               exit 1
+       fi
+}
+
+# add a loop with a vmap statement, either goto or jump,
+# both with single rule and delta-transaction that also
+# contains valid information.
+check_loop()
+{
+       what=$1
+
+       $NFT "add element t m { 1.2.3.9 : $what c1 }"
+       bad_ruleset $? "bound map with $what to backjump should exceed jump stack"
+
+       $NFT "add element t m { 1.2.3.9 : $what c7 }"
+       bad_ruleset $? "bound map with $what to backjump should exceed jump stack"
+
+       $NFT "add element t m { 1.2.3.9 : $what c8 }"
+       bad_ruleset $? "bound map with $what to self should exceed jump stack"
+
+       # rule bound to c8, this should not work -- jump stack should be exceeded.
+       $NFT "add element t m { 1.2.3.9 : jump c9 }"
+       bad_ruleset $? "bound map with $what should exceed jump stack"
+
+       # rule bound to c8, this should be within jump stack limit
+       $NFT "add element t m { 1.2.3.9 : jump c10 }"
+       good_ruleset $? "bound map with $what should not have exceeded jump stack"
+
+$NFT -f - <<EOF
+flush chain t c16
+flush chain t c15
+table t {
+       chain c9 {
+               ip protocol 6 goto c14
+       }
+
+       # calls @m again, but @m now runs c10, which is linked to c14 already.
+       chain c14 {
+               ip protocol 6 return
+               ip daddr vmap @m
+       }
+}
+EOF
+       bad_ruleset $? "delta with bound map with $what loop and rule deletions"
+
+       # delete mapping again
+       $NFT "delete element t m { 1.2.3.9 }"
+       good_ruleset $? "cannot delete mapping"
+}
+
+check_bad_expr()
+{
+$NFT -f -<<EOF
+table t {
+       chain c1 {
+               jump c9
+       }
+}
+EOF
+bad_ruleset $? "tproxy expr exposed to input hook"
+
+$NFT -f -<<EOF
+flush map t m
+
+table t {
+       chain c1 {
+               ip saddr vmap @m
+       }
+}
+EOF
+good_ruleset $? "bound vmap to c1"
+
+$NFT -f -<<EOF
+table t {
+       map m {
+               type ipv4_addr : verdict
+               elements = { 1.2.3.4 : jump c9 }
+       }
+}
+EOF
+bad_ruleset $? "tproxy expr exposed to input hook by vmap"
+
+$NFT -f -<<EOF
+flush chain t c10
+flush chain t c11
+add rule t c8 jump c9
+
+table t {
+       map m {
+               type ipv4_addr : verdict
+               elements = { 1.2.3.4 : goto c2 }
+       }
+}
+EOF
+bad_ruleset $? "tproxy expr exposed to input hook by vmap"
+
+$NFT -f -<<EOF
+flush chain t c2
+flush chain t c3
+flush chain t c4
+flush chain t c5
+flush chain t c6
+flush chain t c7
+flush chain t c10
+flush chain t c11
+flush chain t c12
+flush chain t c13
+flush chain t c14
+flush chain t c15
+flush chain t c16
+delete chain t c16
+delete chain t c15
+delete chain t c14
+delete chain t c13
+delete chain t c12
+delete chain t c11
+delete chain t c7
+delete chain t c6
+delete chain t c5
+delete chain t c4
+delete chain t c3
+add rule t c8 jump c9
+EOF
+good_ruleset $? "connect chain c8 to chain c9"
+
+$NFT -f -<<EOF
+table t {
+       map m {
+               type ipv4_addr : verdict
+               elements = { 1.2.3.4 : goto c8 }
+       }
+}
+EOF
+bad_ruleset $? "tproxy expr exposed to input hook by vmap c1 -> vmap -> c8 -> c9"
+}
+
+# 16 jump levels are permitted.
+# First ruleset is fine, there is no jump
+# from c8 to c9.
+$NFT -f - <<EOF
+table t {
+       map m {
+               type ipv4_addr : verdict
+       }
+
+       chain c16 { }
+       chain c15 { jump c16; }
+       chain c14 { jump c15; }
+       chain c13 { jump c14; }
+       chain c12 { jump c13; }
+       chain c11 { jump c12; }
+       chain c10 { jump c11; }
+       chain c9 { jump c10; }
+       chain c8 { }
+       chain c7 { jump c8; }
+       chain c6 { jump c7; }
+       chain c5 { jump c6; }
+       chain c4 { jump c5; }
+       chain c3 { jump c4; }
+       chain c2 { jump c3; }
+       chain c1 { jump c2; }
+       chain c0 { type filter hook input priority 0;
+               jump c1
+       }
+}
+EOF
+
+ret=$?
+if [ $ret -ne 0 ];then
+       exit 1
+fi
+
+# ensure kernel catches the exceeded jumpstack use, despite no new chains
+# are added here and cycle is acyclic.
+$NFT -f - <<EOF
+# unrelated rule.
+add rule t c14 accept
+add rule t c15 accept
+
+# close jump gap; after this jumpstack limit is exceeded.
+add rule t c8 goto c9
+
+# unrelated rules.
+add rule t c14 accept
+add rule t c15 accept
+EOF
+
+bad_ruleset $? "chain jump stack exhausted without cycle"
+
+$NFT -f - <<EOF
+# unrelated rule.
+add rule t c12 accept
+add rule t c13 accept
+
+add element t m { 1.2.3.1 : accept }
+add element t m { 1.2.3.16 : goto c16 }
+add element t m { 1.2.3.15 : goto c15 }
+
+# after this jumpstack limit is exceeded,
+# IFF @m was bound to c8, but it is not.
+add element t m { 1.2.3.9 : jump c9 }
+
+# unrelated rules.
+add rule t c12 accept
+add rule t c13 accept
+
+add element t m { 1.2.3.16 : goto c16 }
+EOF
+good_ruleset $? "unbounded map"
+
+# bind vmap to c8.  This MUST fail, map jumps to c9.
+$NFT "add rule t c8 ip saddr vmap @m"
+bad_ruleset $? "jump c8->c9 via vmap expression"
+
+# delete the mapping again.
+$NFT "delete element t m { 1.2.3.9 }"
+$NFT "add rule t c8 ip saddr vmap @m"
+good_ruleset $? "bind empty map to c8"
+
+check_loop "jump"
+check_loop "goto"
+
+$NFT "flush chain t c8"
+good_ruleset $? "flush chain t c8"
+
+# should work, c9 not connected to c0 aka filter input.
+$NFT "add rule t c9 tcp dport 80 tproxy to :20000 meta mark set 1 accept"
+good_ruleset $? "add tproxy expression to c9"
+check_bad_expr
+
+exit $?
diff --git a/tests/shell/testcases/transactions/concat_range_abort b/tests/shell/testcases/transactions/concat_range_abort
new file mode 100755 (executable)
index 0000000..b2bbe37
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
+set -e
+
+$NFT -f /dev/stdin <<EOF
+table ip x {
+        map m {
+                typeof ip saddr . meta mark : verdict
+                flags interval
+                counter
+                elements = {
+                        127.0.0.1-127.0.0.4 . 0x123434-0xb00122 : jump foo,
+                }
+        }
+
+       chain foo {
+               accept
+       }
+}
+EOF
+
+$NFT -f /dev/stdin <<EOF
+add chain ip x bar
+add element ip x m { 1.2.3.4 . 42 : jump bar }
+delete set ip x m
+EOF
diff --git a/tests/shell/testcases/transactions/doubled-set b/tests/shell/testcases/transactions/doubled-set
new file mode 100755 (executable)
index 0000000..50b568e
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_pipapo)
+
+$NFT -f /dev/stdin <<EOF
+table t {
+       set s {
+               type ipv4_addr . ifname
+               flags interval
+               elements = { 1.2.3.4 . "foo" }
+       }
+
+       set s {
+               type ipv4_addr . ifname
+               flags interval
+               elements = { 1.2.3.4 . "foo" }
+
+       }
+}
+EOF
+
+# run-tests.sh will validate dumpfile.
diff --git a/tests/shell/testcases/transactions/dumps/0001table_0.json-nft b/tests/shell/testcases/transactions/dumps/0001table_0.json-nft
new file mode 100644 (file)
index 0000000..ea75b43
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0002table_0.json-nft b/tests/shell/testcases/transactions/dumps/0002table_0.json-nft
new file mode 100644 (file)
index 0000000..b1fefc3
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0,
+        "flags": "dormant"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "nat",
+        "hook": "prerouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0003table_0.json-nft b/tests/shell/testcases/transactions/dumps/0003table_0.json-nft
new file mode 100644 (file)
index 0000000..ea75b43
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0003table_0.nft b/tests/shell/testcases/transactions/dumps/0003table_0.nft
new file mode 100644 (file)
index 0000000..e4e5f9b
--- /dev/null
@@ -0,0 +1,4 @@
+table ip x {
+}
+table ip y {
+}
diff --git a/tests/shell/testcases/transactions/dumps/0010chain_0.json-nft b/tests/shell/testcases/transactions/dumps/0010chain_0.json-nft
new file mode 100644 (file)
index 0000000..8594767
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "w",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "w",
+        "name": "y",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0011chain_0.json-nft b/tests/shell/testcases/transactions/dumps/0011chain_0.json-nft
new file mode 100644 (file)
index 0000000..12cf0bb
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "drop"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0012chain_0.json-nft b/tests/shell/testcases/transactions/dumps/0012chain_0.json-nft
new file mode 100644 (file)
index 0000000..dc5eaa6
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "w",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "w",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0013chain_0.json-nft b/tests/shell/testcases/transactions/dumps/0013chain_0.json-nft
new file mode 100644 (file)
index 0000000..dc5eaa6
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "w",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "w",
+        "name": "y",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0014chain_1.json-nft b/tests/shell/testcases/transactions/dumps/0014chain_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0014chain_1.nft b/tests/shell/testcases/transactions/dumps/0014chain_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0015chain_0.json-nft b/tests/shell/testcases/transactions/dumps/0015chain_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0015chain_0.nft b/tests/shell/testcases/transactions/dumps/0015chain_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0020rule_0.json-nft b/tests/shell/testcases/transactions/dumps/0020rule_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0020rule_0.nft b/tests/shell/testcases/transactions/dumps/0020rule_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0021rule_0.json-nft b/tests/shell/testcases/transactions/dumps/0021rule_0.json-nft
new file mode 100644 (file)
index 0000000..4c5500c
--- /dev/null
@@ -0,0 +1,54 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "right": "2.2.2.2"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0022rule_1.json-nft b/tests/shell/testcases/transactions/dumps/0022rule_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0022rule_1.nft b/tests/shell/testcases/transactions/dumps/0022rule_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0023rule_1.json-nft b/tests/shell/testcases/transactions/dumps/0023rule_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0023rule_1.nft b/tests/shell/testcases/transactions/dumps/0023rule_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0024rule_0.json-nft b/tests/shell/testcases/transactions/dumps/0024rule_0.json-nft
new file mode 100644 (file)
index 0000000..1e37f7d
--- /dev/null
@@ -0,0 +1,82 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "comment": "rule1",
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "comment": "rule2",
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "comment": "rule3",
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "comment": "rule4",
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0025rule_0.json-nft b/tests/shell/testcases/transactions/dumps/0025rule_0.json-nft
new file mode 100644 (file)
index 0000000..623d976
--- /dev/null
@@ -0,0 +1,52 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "y",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "log": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "y",
+        "handle": 0,
+        "expr": [
+          {
+            "drop": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0030set_0.json-nft b/tests/shell/testcases/transactions/dumps/0030set_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0031set_0.json-nft b/tests/shell/testcases/transactions/dumps/0031set_0.json-nft
new file mode 100644 (file)
index 0000000..c1b7639
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0032set_0.json-nft b/tests/shell/testcases/transactions/dumps/0032set_0.json-nft
new file mode 100644 (file)
index 0000000..66bbf0e
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "w",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "w",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0033set_0.json-nft b/tests/shell/testcases/transactions/dumps/0033set_0.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0034set_0.json-nft b/tests/shell/testcases/transactions/dumps/0034set_0.json-nft
new file mode 100644 (file)
index 0000000..c1b7639
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0035set_0.json-nft b/tests/shell/testcases/transactions/dumps/0035set_0.json-nft
new file mode 100644 (file)
index 0000000..6b8f671
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "elem": [
+          "3.3.3.3"
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0036set_1.json-nft b/tests/shell/testcases/transactions/dumps/0036set_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0036set_1.nft b/tests/shell/testcases/transactions/dumps/0036set_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0037set_0.json-nft b/tests/shell/testcases/transactions/dumps/0037set_0.json-nft
new file mode 100644 (file)
index 0000000..f9fe4e6
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0038set_0.json-nft b/tests/shell/testcases/transactions/dumps/0038set_0.json-nft
new file mode 100644 (file)
index 0000000..5f97d09
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "192.168.4.0",
+              "len": 24
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0039set_0.json-nft b/tests/shell/testcases/transactions/dumps/0039set_0.json-nft
new file mode 100644 (file)
index 0000000..5f97d09
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "y",
+        "table": "x",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "prefix": {
+              "addr": "192.168.4.0",
+              "len": 24
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0040set_0.json-nft b/tests/shell/testcases/transactions/dumps/0040set_0.json-nft
new file mode 100644 (file)
index 0000000..1718a5b
--- /dev/null
@@ -0,0 +1,84 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "FORWARD",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "filter",
+        "name": "client_to_any",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "client_to_any",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "verdict"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "client_to_any"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "filter",
+        "chain": "client_to_any",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": "@client_to_any"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0041nat_restore_0.json-nft b/tests/shell/testcases/transactions/dumps/0041nat_restore_0.json-nft
new file mode 100644 (file)
index 0000000..32fce94
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "nat",
+        "hook": "postrouting",
+        "prio": 0,
+        "policy": "accept"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0041nat_restore_0.nft b/tests/shell/testcases/transactions/dumps/0041nat_restore_0.nft
new file mode 100644 (file)
index 0000000..b718001
--- /dev/null
@@ -0,0 +1,5 @@
+table ip t {
+       chain c {
+               type nat hook postrouting priority filter; policy accept;
+       }
+}
diff --git a/tests/shell/testcases/transactions/dumps/0042_stateful_expr_0.json-nft b/tests/shell/testcases/transactions/dumps/0042_stateful_expr_0.json-nft
new file mode 100644 (file)
index 0000000..ea3b5d3
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "m1",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "counter"
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0042_stateful_expr_0.nft b/tests/shell/testcases/transactions/dumps/0042_stateful_expr_0.nft
new file mode 100644 (file)
index 0000000..e5cc63f
--- /dev/null
@@ -0,0 +1,5 @@
+table ip filter {
+       map m1 {
+               type ipv4_addr : counter
+       }
+}
diff --git a/tests/shell/testcases/transactions/dumps/0043set_1.json-nft b/tests/shell/testcases/transactions/dumps/0043set_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0043set_1.nft b/tests/shell/testcases/transactions/dumps/0043set_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0044rule_0.json-nft b/tests/shell/testcases/transactions/dumps/0044rule_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0044rule_0.nft b/tests/shell/testcases/transactions/dumps/0044rule_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0045anon-unbind_0.json-nft b/tests/shell/testcases/transactions/dumps/0045anon-unbind_0.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0045anon-unbind_0.nft b/tests/shell/testcases/transactions/dumps/0045anon-unbind_0.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0046set_0.json-nft b/tests/shell/testcases/transactions/dumps/0046set_0.json-nft
new file mode 100644 (file)
index 0000000..f9b488e
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0046set_0.nft b/tests/shell/testcases/transactions/dumps/0046set_0.nft
new file mode 100644 (file)
index 0000000..eb39c44
--- /dev/null
@@ -0,0 +1,2 @@
+table ip filter {
+}
diff --git a/tests/shell/testcases/transactions/dumps/0047set_0.json-nft b/tests/shell/testcases/transactions/dumps/0047set_0.json-nft
new file mode 100644 (file)
index 0000000..fb6348f
--- /dev/null
@@ -0,0 +1,71 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "group_10060",
+        "table": "filter",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "classid",
+        "flags": "interval",
+        "elem": [
+          [
+            "10.1.26.2",
+            "1:bbf8"
+          ],
+          [
+            "10.1.26.3",
+            "1:c1ad"
+          ],
+          [
+            "10.1.26.4",
+            "1:b2d7"
+          ],
+          [
+            "10.1.26.5",
+            "1:f705"
+          ],
+          [
+            "10.1.26.6",
+            "1:b895"
+          ],
+          [
+            "10.1.26.7",
+            "1:ec4c"
+          ],
+          [
+            "10.1.26.8",
+            "1:de78"
+          ],
+          [
+            "10.1.26.9",
+            "1:b4f3"
+          ],
+          [
+            "10.1.26.10",
+            "1:dec6"
+          ],
+          [
+            "10.1.26.11",
+            "1:b4c0"
+          ]
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0047set_0.nft b/tests/shell/testcases/transactions/dumps/0047set_0.nft
new file mode 100644 (file)
index 0000000..d8e8e38
--- /dev/null
@@ -0,0 +1,16 @@
+table ip filter {
+       map group_10060 {
+               type ipv4_addr : classid
+               flags interval
+               elements = { 10.1.26.2 : 1:bbf8,
+                            10.1.26.3 : 1:c1ad,
+                            10.1.26.4 : 1:b2d7,
+                            10.1.26.5 : 1:f705,
+                            10.1.26.6 : 1:b895,
+                            10.1.26.7 : 1:ec4c,
+                            10.1.26.8 : 1:de78,
+                            10.1.26.9 : 1:b4f3,
+                            10.1.26.10 : 1:dec6,
+                            10.1.26.11 : 1:b4c0 }
+       }
+}
diff --git a/tests/shell/testcases/transactions/dumps/0048helpers_0.json-nft b/tests/shell/testcases/transactions/dumps/0048helpers_0.json-nft
new file mode 100644 (file)
index 0000000..f9b488e
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "filter",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0048helpers_0.nft b/tests/shell/testcases/transactions/dumps/0048helpers_0.nft
new file mode 100644 (file)
index 0000000..eb39c44
--- /dev/null
@@ -0,0 +1,2 @@
+table ip filter {
+}
diff --git a/tests/shell/testcases/transactions/dumps/0049huge_0.json-nft b/tests/shell/testcases/transactions/dumps/0049huge_0.json-nft
new file mode 100644 (file)
index 0000000..456ada9
--- /dev/null
@@ -0,0 +1,5121 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "inet",
+        "name": "firewalld",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PREROUTING",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -290,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PREROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PREROUTING",
+        "handle": 0,
+        "type": "filter",
+        "hook": "prerouting",
+        "prio": -140,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PREROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_INPUT",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FORWARD",
+        "handle": 0,
+        "type": "filter",
+        "hook": "forward",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_OUTPUT",
+        "handle": 0,
+        "type": "filter",
+        "hook": "output",
+        "prio": 10,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_INPUT_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FORWARD_IN_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FORWARD_OUT_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_public_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_public_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_public_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_public_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_public_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_trusted",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_trusted_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_trusted_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_trusted_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_trusted_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_trusted_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_trusted",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_trusted_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_trusted_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_trusted_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_trusted_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_trusted_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_trusted",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_trusted_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_trusted_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_trusted_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_trusted_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_trusted_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_trusted",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_trusted_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_trusted_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_trusted_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_trusted_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_trusted_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_trusted",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_trusted_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_trusted_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_trusted_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_trusted_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_trusted_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "raw_PRE_work_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_IN_work_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "mangle_PRE_work_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDI_work_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "inet",
+        "table": "firewalld",
+        "name": "filter_FWDO_work_post",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "icmpv6",
+                  "field": "type"
+                }
+              },
+              "right": {
+                "set": [
+                  "nd-router-advert",
+                  "nd-neighbor-solicit"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "nfproto"
+                }
+              },
+              "right": "ipv6"
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "fib": {
+                  "result": "oif",
+                  "flags": [
+                    "saddr",
+                    "iif"
+                  ]
+                }
+              },
+              "right": false
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PREROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy"
+            }
+          },
+          {
+            "goto": {
+              "target": "raw_PRE_work"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy2"
+            }
+          },
+          {
+            "goto": {
+              "target": "raw_PRE_trusted"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "raw_PRE_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PREROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy"
+            }
+          },
+          {
+            "goto": {
+              "target": "mangle_PRE_work"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy2"
+            }
+          },
+          {
+            "goto": {
+              "target": "mangle_PRE_trusted"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "mangle_PRE_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": {
+                "set": [
+                  "established",
+                  "related"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "status"
+                }
+              },
+              "right": "dnat"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_INPUT_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "invalid"
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "reject": {
+              "type": "icmpx",
+              "expr": "admin-prohibited"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": {
+                "set": [
+                  "established",
+                  "related"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "status"
+                }
+              },
+              "right": "dnat"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "set": [
+                  {
+                    "prefix": {
+                      "addr": "::",
+                      "len": 96
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "::ffff:0.0.0.0",
+                      "len": 96
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002::",
+                      "len": 24
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:a00::",
+                      "len": 24
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:7f00::",
+                      "len": 24
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:a9fe::",
+                      "len": 32
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:ac10::",
+                      "len": 28
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:c0a8::",
+                      "len": 32
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:e000::",
+                      "len": 19
+                    }
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "reject": {
+              "type": "icmpv6",
+              "expr": "addr-unreachable"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FORWARD_IN_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FORWARD_OUT_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "in",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": "invalid"
+            }
+          },
+          {
+            "drop": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD",
+        "handle": 0,
+        "expr": [
+          {
+            "reject": {
+              "type": "icmpx",
+              "expr": "admin-prohibited"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_OUTPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "lo"
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_OUTPUT",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "set": [
+                  {
+                    "prefix": {
+                      "addr": "::",
+                      "len": 96
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "::ffff:0.0.0.0",
+                      "len": 96
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002::",
+                      "len": 24
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:a00::",
+                      "len": 24
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:7f00::",
+                      "len": 24
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:a9fe::",
+                      "len": 32
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:ac10::",
+                      "len": 28
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:c0a8::",
+                      "len": 32
+                    }
+                  },
+                  {
+                    "prefix": {
+                      "addr": "2002:e000::",
+                      "len": 19
+                    }
+                  }
+                ]
+              }
+            }
+          },
+          {
+            "reject": {
+              "type": "icmpv6",
+              "expr": "addr-unreachable"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy"
+            }
+          },
+          {
+            "goto": {
+              "target": "filter_IN_work"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy2"
+            }
+          },
+          {
+            "goto": {
+              "target": "filter_IN_trusted"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_INPUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "filter_IN_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_IN_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy"
+            }
+          },
+          {
+            "goto": {
+              "target": "filter_FWDI_work"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_IN_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy2"
+            }
+          },
+          {
+            "goto": {
+              "target": "filter_FWDI_trusted"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_IN_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "filter_FWDI_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_OUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "perm_dummy"
+            }
+          },
+          {
+            "goto": {
+              "target": "filter_FWDO_work"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_OUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "perm_dummy2"
+            }
+          },
+          {
+            "goto": {
+              "target": "filter_FWDO_trusted"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FORWARD_OUT_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "filter_FWDO_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_public_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_public_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_public_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_public_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": {
+                "set": [
+                  "new",
+                  "untracked"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_public_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "prefix": {
+                  "addr": "fe80::",
+                  "len": 64
+                }
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 546
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": {
+                "set": [
+                  "new",
+                  "untracked"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_public_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_public_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_public",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_public_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_public_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_public_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_public_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_trusted_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_trusted_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_trusted_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_trusted_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_trusted_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_trusted_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_trusted_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_trusted_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_trusted_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_trusted_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_trusted_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_trusted_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_trusted_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_trusted_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_trusted_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_trusted_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_trusted_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_trusted_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_trusted_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_trusted_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_trusted_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_trusted_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_trusted_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_trusted_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_trusted_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_work_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "raw_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "raw_PRE_work_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_work_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_IN_work_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 22
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": {
+                "set": [
+                  "new",
+                  "untracked"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_IN_work_allow",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip6",
+                  "field": "daddr"
+                }
+              },
+              "right": {
+                "prefix": {
+                  "addr": "fe80::",
+                  "len": 64
+                }
+              }
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "udp",
+                  "field": "dport"
+                }
+              },
+              "right": 546
+            }
+          },
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "ct": {
+                  "key": "state"
+                }
+              },
+              "right": {
+                "set": [
+                  "new",
+                  "untracked"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_work_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "mangle_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "mangle_PRE_work_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_work_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDI_work_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDI_work",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "l4proto"
+                }
+              },
+              "right": {
+                "set": [
+                  "icmp",
+                  "ipv6-icmp"
+                ]
+              }
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_work_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "inet",
+        "table": "firewalld",
+        "chain": "filter_FWDO_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "filter_FWDO_work_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "firewalld",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PREROUTING",
+        "handle": 0,
+        "type": "nat",
+        "hook": "prerouting",
+        "prio": -90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PREROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING",
+        "handle": 0,
+        "type": "nat",
+        "hook": "postrouting",
+        "prio": 110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_public_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_public_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_trusted",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_PRE_work_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "firewalld",
+        "name": "nat_POST_work_post",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PREROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_PRE_work"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy2"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_PRE_trusted"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "nat_PRE_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POSTROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "perm_dummy"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_POST_work"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "perm_dummy2"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_POST_trusted"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "nat_POST_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "table": {
+        "family": "ip6",
+        "name": "firewalld",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PREROUTING",
+        "handle": 0,
+        "type": "nat",
+        "hook": "prerouting",
+        "prio": -90,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PREROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING",
+        "handle": 0,
+        "type": "nat",
+        "hook": "postrouting",
+        "prio": 110,
+        "policy": "accept"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POSTROUTING_ZONES",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_public_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_public_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_trusted_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_trusted",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_trusted_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_PRE_work_post",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work_pre",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work_log",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work_deny",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work_allow",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip6",
+        "table": "firewalld",
+        "name": "nat_POST_work_post",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PREROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_PRE_work"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "iifname"
+                }
+              },
+              "right": "perm_dummy2"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_PRE_trusted"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PREROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "nat_PRE_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POSTROUTING_ZONES"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "perm_dummy"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_POST_work"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "meta": {
+                  "key": "oifname"
+                }
+              },
+              "right": "perm_dummy2"
+            }
+          },
+          {
+            "goto": {
+              "target": "nat_POST_trusted"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POSTROUTING_ZONES",
+        "handle": 0,
+        "expr": [
+          {
+            "goto": {
+              "target": "nat_POST_public"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_public_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_public",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_public_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_trusted_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_trusted",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_trusted_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_PRE_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_PRE_work_post"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_pre"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_log"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_deny"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_allow"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip6",
+        "table": "firewalld",
+        "chain": "nat_POST_work",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "nat_POST_work_post"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0049huge_0.nft b/tests/shell/testcases/transactions/dumps/0049huge_0.nft
new file mode 100644 (file)
index 0000000..96f5a38
--- /dev/null
@@ -0,0 +1,749 @@
+table inet firewalld {
+       chain raw_PREROUTING {
+               type filter hook prerouting priority raw + 10; policy accept;
+               icmpv6 type { nd-router-advert, nd-neighbor-solicit } accept
+               meta nfproto ipv6 fib saddr . iif oif missing drop
+               jump raw_PREROUTING_ZONES
+       }
+
+       chain raw_PREROUTING_ZONES {
+               iifname "perm_dummy" goto raw_PRE_work
+               iifname "perm_dummy2" goto raw_PRE_trusted
+               goto raw_PRE_public
+       }
+
+       chain mangle_PREROUTING {
+               type filter hook prerouting priority mangle + 10; policy accept;
+               jump mangle_PREROUTING_ZONES
+       }
+
+       chain mangle_PREROUTING_ZONES {
+               iifname "perm_dummy" goto mangle_PRE_work
+               iifname "perm_dummy2" goto mangle_PRE_trusted
+               goto mangle_PRE_public
+       }
+
+       chain filter_INPUT {
+               type filter hook input priority filter + 10; policy accept;
+               ct state { established, related } accept
+               ct status dnat accept
+               iifname "lo" accept
+               jump filter_INPUT_ZONES
+               ct state invalid drop
+               reject with icmpx admin-prohibited
+       }
+
+       chain filter_FORWARD {
+               type filter hook forward priority filter + 10; policy accept;
+               ct state { established, related } accept
+               ct status dnat accept
+               iifname "lo" accept
+               ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } reject with icmpv6 addr-unreachable
+               jump filter_FORWARD_IN_ZONES
+               jump filter_FORWARD_OUT_ZONES
+               ct state invalid drop
+               reject with icmpx admin-prohibited
+       }
+
+       chain filter_OUTPUT {
+               type filter hook output priority filter + 10; policy accept;
+               oifname "lo" accept
+               ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } reject with icmpv6 addr-unreachable
+       }
+
+       chain filter_INPUT_ZONES {
+               iifname "perm_dummy" goto filter_IN_work
+               iifname "perm_dummy2" goto filter_IN_trusted
+               goto filter_IN_public
+       }
+
+       chain filter_FORWARD_IN_ZONES {
+               iifname "perm_dummy" goto filter_FWDI_work
+               iifname "perm_dummy2" goto filter_FWDI_trusted
+               goto filter_FWDI_public
+       }
+
+       chain filter_FORWARD_OUT_ZONES {
+               oifname "perm_dummy" goto filter_FWDO_work
+               oifname "perm_dummy2" goto filter_FWDO_trusted
+               goto filter_FWDO_public
+       }
+
+       chain raw_PRE_public {
+               jump raw_PRE_public_pre
+               jump raw_PRE_public_log
+               jump raw_PRE_public_deny
+               jump raw_PRE_public_allow
+               jump raw_PRE_public_post
+       }
+
+       chain raw_PRE_public_pre {
+       }
+
+       chain raw_PRE_public_log {
+       }
+
+       chain raw_PRE_public_deny {
+       }
+
+       chain raw_PRE_public_allow {
+       }
+
+       chain raw_PRE_public_post {
+       }
+
+       chain filter_IN_public {
+               jump filter_IN_public_pre
+               jump filter_IN_public_log
+               jump filter_IN_public_deny
+               jump filter_IN_public_allow
+               jump filter_IN_public_post
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_IN_public_pre {
+       }
+
+       chain filter_IN_public_log {
+       }
+
+       chain filter_IN_public_deny {
+       }
+
+       chain filter_IN_public_allow {
+               tcp dport 22 ct state { new, untracked } accept
+               ip6 daddr fe80::/64 udp dport 546 ct state { new, untracked } accept
+       }
+
+       chain filter_IN_public_post {
+       }
+
+       chain filter_FWDI_public {
+               jump filter_FWDI_public_pre
+               jump filter_FWDI_public_log
+               jump filter_FWDI_public_deny
+               jump filter_FWDI_public_allow
+               jump filter_FWDI_public_post
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_FWDI_public_pre {
+       }
+
+       chain filter_FWDI_public_log {
+       }
+
+       chain filter_FWDI_public_deny {
+       }
+
+       chain filter_FWDI_public_allow {
+       }
+
+       chain filter_FWDI_public_post {
+       }
+
+       chain mangle_PRE_public {
+               jump mangle_PRE_public_pre
+               jump mangle_PRE_public_log
+               jump mangle_PRE_public_deny
+               jump mangle_PRE_public_allow
+               jump mangle_PRE_public_post
+       }
+
+       chain mangle_PRE_public_pre {
+       }
+
+       chain mangle_PRE_public_log {
+       }
+
+       chain mangle_PRE_public_deny {
+       }
+
+       chain mangle_PRE_public_allow {
+       }
+
+       chain mangle_PRE_public_post {
+       }
+
+       chain filter_FWDO_public {
+               jump filter_FWDO_public_pre
+               jump filter_FWDO_public_log
+               jump filter_FWDO_public_deny
+               jump filter_FWDO_public_allow
+               jump filter_FWDO_public_post
+       }
+
+       chain filter_FWDO_public_pre {
+       }
+
+       chain filter_FWDO_public_log {
+       }
+
+       chain filter_FWDO_public_deny {
+       }
+
+       chain filter_FWDO_public_allow {
+       }
+
+       chain filter_FWDO_public_post {
+       }
+
+       chain raw_PRE_trusted {
+               jump raw_PRE_trusted_pre
+               jump raw_PRE_trusted_log
+               jump raw_PRE_trusted_deny
+               jump raw_PRE_trusted_allow
+               jump raw_PRE_trusted_post
+       }
+
+       chain raw_PRE_trusted_pre {
+       }
+
+       chain raw_PRE_trusted_log {
+       }
+
+       chain raw_PRE_trusted_deny {
+       }
+
+       chain raw_PRE_trusted_allow {
+       }
+
+       chain raw_PRE_trusted_post {
+       }
+
+       chain mangle_PRE_trusted {
+               jump mangle_PRE_trusted_pre
+               jump mangle_PRE_trusted_log
+               jump mangle_PRE_trusted_deny
+               jump mangle_PRE_trusted_allow
+               jump mangle_PRE_trusted_post
+       }
+
+       chain mangle_PRE_trusted_pre {
+       }
+
+       chain mangle_PRE_trusted_log {
+       }
+
+       chain mangle_PRE_trusted_deny {
+       }
+
+       chain mangle_PRE_trusted_allow {
+       }
+
+       chain mangle_PRE_trusted_post {
+       }
+
+       chain filter_IN_trusted {
+               jump filter_IN_trusted_pre
+               jump filter_IN_trusted_log
+               jump filter_IN_trusted_deny
+               jump filter_IN_trusted_allow
+               jump filter_IN_trusted_post
+               accept
+       }
+
+       chain filter_IN_trusted_pre {
+       }
+
+       chain filter_IN_trusted_log {
+       }
+
+       chain filter_IN_trusted_deny {
+       }
+
+       chain filter_IN_trusted_allow {
+       }
+
+       chain filter_IN_trusted_post {
+       }
+
+       chain filter_FWDI_trusted {
+               jump filter_FWDI_trusted_pre
+               jump filter_FWDI_trusted_log
+               jump filter_FWDI_trusted_deny
+               jump filter_FWDI_trusted_allow
+               jump filter_FWDI_trusted_post
+               accept
+       }
+
+       chain filter_FWDI_trusted_pre {
+       }
+
+       chain filter_FWDI_trusted_log {
+       }
+
+       chain filter_FWDI_trusted_deny {
+       }
+
+       chain filter_FWDI_trusted_allow {
+       }
+
+       chain filter_FWDI_trusted_post {
+       }
+
+       chain filter_FWDO_trusted {
+               jump filter_FWDO_trusted_pre
+               jump filter_FWDO_trusted_log
+               jump filter_FWDO_trusted_deny
+               jump filter_FWDO_trusted_allow
+               jump filter_FWDO_trusted_post
+               accept
+       }
+
+       chain filter_FWDO_trusted_pre {
+       }
+
+       chain filter_FWDO_trusted_log {
+       }
+
+       chain filter_FWDO_trusted_deny {
+       }
+
+       chain filter_FWDO_trusted_allow {
+       }
+
+       chain filter_FWDO_trusted_post {
+       }
+
+       chain raw_PRE_work {
+               jump raw_PRE_work_pre
+               jump raw_PRE_work_log
+               jump raw_PRE_work_deny
+               jump raw_PRE_work_allow
+               jump raw_PRE_work_post
+       }
+
+       chain raw_PRE_work_pre {
+       }
+
+       chain raw_PRE_work_log {
+       }
+
+       chain raw_PRE_work_deny {
+       }
+
+       chain raw_PRE_work_allow {
+       }
+
+       chain raw_PRE_work_post {
+       }
+
+       chain filter_IN_work {
+               jump filter_IN_work_pre
+               jump filter_IN_work_log
+               jump filter_IN_work_deny
+               jump filter_IN_work_allow
+               jump filter_IN_work_post
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_IN_work_pre {
+       }
+
+       chain filter_IN_work_log {
+       }
+
+       chain filter_IN_work_deny {
+       }
+
+       chain filter_IN_work_allow {
+               tcp dport 22 ct state { new, untracked } accept
+               ip6 daddr fe80::/64 udp dport 546 ct state { new, untracked } accept
+       }
+
+       chain filter_IN_work_post {
+       }
+
+       chain mangle_PRE_work {
+               jump mangle_PRE_work_pre
+               jump mangle_PRE_work_log
+               jump mangle_PRE_work_deny
+               jump mangle_PRE_work_allow
+               jump mangle_PRE_work_post
+       }
+
+       chain mangle_PRE_work_pre {
+       }
+
+       chain mangle_PRE_work_log {
+       }
+
+       chain mangle_PRE_work_deny {
+       }
+
+       chain mangle_PRE_work_allow {
+       }
+
+       chain mangle_PRE_work_post {
+       }
+
+       chain filter_FWDI_work {
+               jump filter_FWDI_work_pre
+               jump filter_FWDI_work_log
+               jump filter_FWDI_work_deny
+               jump filter_FWDI_work_allow
+               jump filter_FWDI_work_post
+               meta l4proto { icmp, ipv6-icmp } accept
+       }
+
+       chain filter_FWDI_work_pre {
+       }
+
+       chain filter_FWDI_work_log {
+       }
+
+       chain filter_FWDI_work_deny {
+       }
+
+       chain filter_FWDI_work_allow {
+       }
+
+       chain filter_FWDI_work_post {
+       }
+
+       chain filter_FWDO_work {
+               jump filter_FWDO_work_pre
+               jump filter_FWDO_work_log
+               jump filter_FWDO_work_deny
+               jump filter_FWDO_work_allow
+               jump filter_FWDO_work_post
+       }
+
+       chain filter_FWDO_work_pre {
+       }
+
+       chain filter_FWDO_work_log {
+       }
+
+       chain filter_FWDO_work_deny {
+       }
+
+       chain filter_FWDO_work_allow {
+       }
+
+       chain filter_FWDO_work_post {
+       }
+}
+table ip firewalld {
+       chain nat_PREROUTING {
+               type nat hook prerouting priority dstnat + 10; policy accept;
+               jump nat_PREROUTING_ZONES
+       }
+
+       chain nat_PREROUTING_ZONES {
+               iifname "perm_dummy" goto nat_PRE_work
+               iifname "perm_dummy2" goto nat_PRE_trusted
+               goto nat_PRE_public
+       }
+
+       chain nat_POSTROUTING {
+               type nat hook postrouting priority srcnat + 10; policy accept;
+               jump nat_POSTROUTING_ZONES
+       }
+
+       chain nat_POSTROUTING_ZONES {
+               oifname "perm_dummy" goto nat_POST_work
+               oifname "perm_dummy2" goto nat_POST_trusted
+               goto nat_POST_public
+       }
+
+       chain nat_PRE_public {
+               jump nat_PRE_public_pre
+               jump nat_PRE_public_log
+               jump nat_PRE_public_deny
+               jump nat_PRE_public_allow
+               jump nat_PRE_public_post
+       }
+
+       chain nat_PRE_public_pre {
+       }
+
+       chain nat_PRE_public_log {
+       }
+
+       chain nat_PRE_public_deny {
+       }
+
+       chain nat_PRE_public_allow {
+       }
+
+       chain nat_PRE_public_post {
+       }
+
+       chain nat_POST_public {
+               jump nat_POST_public_pre
+               jump nat_POST_public_log
+               jump nat_POST_public_deny
+               jump nat_POST_public_allow
+               jump nat_POST_public_post
+       }
+
+       chain nat_POST_public_pre {
+       }
+
+       chain nat_POST_public_log {
+       }
+
+       chain nat_POST_public_deny {
+       }
+
+       chain nat_POST_public_allow {
+       }
+
+       chain nat_POST_public_post {
+       }
+
+       chain nat_PRE_trusted {
+               jump nat_PRE_trusted_pre
+               jump nat_PRE_trusted_log
+               jump nat_PRE_trusted_deny
+               jump nat_PRE_trusted_allow
+               jump nat_PRE_trusted_post
+       }
+
+       chain nat_PRE_trusted_pre {
+       }
+
+       chain nat_PRE_trusted_log {
+       }
+
+       chain nat_PRE_trusted_deny {
+       }
+
+       chain nat_PRE_trusted_allow {
+       }
+
+       chain nat_PRE_trusted_post {
+       }
+
+       chain nat_POST_trusted {
+               jump nat_POST_trusted_pre
+               jump nat_POST_trusted_log
+               jump nat_POST_trusted_deny
+               jump nat_POST_trusted_allow
+               jump nat_POST_trusted_post
+       }
+
+       chain nat_POST_trusted_pre {
+       }
+
+       chain nat_POST_trusted_log {
+       }
+
+       chain nat_POST_trusted_deny {
+       }
+
+       chain nat_POST_trusted_allow {
+       }
+
+       chain nat_POST_trusted_post {
+       }
+
+       chain nat_PRE_work {
+               jump nat_PRE_work_pre
+               jump nat_PRE_work_log
+               jump nat_PRE_work_deny
+               jump nat_PRE_work_allow
+               jump nat_PRE_work_post
+       }
+
+       chain nat_PRE_work_pre {
+       }
+
+       chain nat_PRE_work_log {
+       }
+
+       chain nat_PRE_work_deny {
+       }
+
+       chain nat_PRE_work_allow {
+       }
+
+       chain nat_PRE_work_post {
+       }
+
+       chain nat_POST_work {
+               jump nat_POST_work_pre
+               jump nat_POST_work_log
+               jump nat_POST_work_deny
+               jump nat_POST_work_allow
+               jump nat_POST_work_post
+       }
+
+       chain nat_POST_work_pre {
+       }
+
+       chain nat_POST_work_log {
+       }
+
+       chain nat_POST_work_deny {
+       }
+
+       chain nat_POST_work_allow {
+       }
+
+       chain nat_POST_work_post {
+       }
+}
+table ip6 firewalld {
+       chain nat_PREROUTING {
+               type nat hook prerouting priority dstnat + 10; policy accept;
+               jump nat_PREROUTING_ZONES
+       }
+
+       chain nat_PREROUTING_ZONES {
+               iifname "perm_dummy" goto nat_PRE_work
+               iifname "perm_dummy2" goto nat_PRE_trusted
+               goto nat_PRE_public
+       }
+
+       chain nat_POSTROUTING {
+               type nat hook postrouting priority srcnat + 10; policy accept;
+               jump nat_POSTROUTING_ZONES
+       }
+
+       chain nat_POSTROUTING_ZONES {
+               oifname "perm_dummy" goto nat_POST_work
+               oifname "perm_dummy2" goto nat_POST_trusted
+               goto nat_POST_public
+       }
+
+       chain nat_PRE_public {
+               jump nat_PRE_public_pre
+               jump nat_PRE_public_log
+               jump nat_PRE_public_deny
+               jump nat_PRE_public_allow
+               jump nat_PRE_public_post
+       }
+
+       chain nat_PRE_public_pre {
+       }
+
+       chain nat_PRE_public_log {
+       }
+
+       chain nat_PRE_public_deny {
+       }
+
+       chain nat_PRE_public_allow {
+       }
+
+       chain nat_PRE_public_post {
+       }
+
+       chain nat_POST_public {
+               jump nat_POST_public_pre
+               jump nat_POST_public_log
+               jump nat_POST_public_deny
+               jump nat_POST_public_allow
+               jump nat_POST_public_post
+       }
+
+       chain nat_POST_public_pre {
+       }
+
+       chain nat_POST_public_log {
+       }
+
+       chain nat_POST_public_deny {
+       }
+
+       chain nat_POST_public_allow {
+       }
+
+       chain nat_POST_public_post {
+       }
+
+       chain nat_PRE_trusted {
+               jump nat_PRE_trusted_pre
+               jump nat_PRE_trusted_log
+               jump nat_PRE_trusted_deny
+               jump nat_PRE_trusted_allow
+               jump nat_PRE_trusted_post
+       }
+
+       chain nat_PRE_trusted_pre {
+       }
+
+       chain nat_PRE_trusted_log {
+       }
+
+       chain nat_PRE_trusted_deny {
+       }
+
+       chain nat_PRE_trusted_allow {
+       }
+
+       chain nat_PRE_trusted_post {
+       }
+
+       chain nat_POST_trusted {
+               jump nat_POST_trusted_pre
+               jump nat_POST_trusted_log
+               jump nat_POST_trusted_deny
+               jump nat_POST_trusted_allow
+               jump nat_POST_trusted_post
+       }
+
+       chain nat_POST_trusted_pre {
+       }
+
+       chain nat_POST_trusted_log {
+       }
+
+       chain nat_POST_trusted_deny {
+       }
+
+       chain nat_POST_trusted_allow {
+       }
+
+       chain nat_POST_trusted_post {
+       }
+
+       chain nat_PRE_work {
+               jump nat_PRE_work_pre
+               jump nat_PRE_work_log
+               jump nat_PRE_work_deny
+               jump nat_PRE_work_allow
+               jump nat_PRE_work_post
+       }
+
+       chain nat_PRE_work_pre {
+       }
+
+       chain nat_PRE_work_log {
+       }
+
+       chain nat_PRE_work_deny {
+       }
+
+       chain nat_PRE_work_allow {
+       }
+
+       chain nat_PRE_work_post {
+       }
+
+       chain nat_POST_work {
+               jump nat_POST_work_pre
+               jump nat_POST_work_log
+               jump nat_POST_work_deny
+               jump nat_POST_work_allow
+               jump nat_POST_work_post
+       }
+
+       chain nat_POST_work_pre {
+       }
+
+       chain nat_POST_work_log {
+       }
+
+       chain nat_POST_work_deny {
+       }
+
+       chain nat_POST_work_allow {
+       }
+
+       chain nat_POST_work_post {
+       }
+}
diff --git a/tests/shell/testcases/transactions/dumps/0050rule_1.json-nft b/tests/shell/testcases/transactions/dumps/0050rule_1.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/0050rule_1.nft b/tests/shell/testcases/transactions/dumps/0050rule_1.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/0051map_0.nodump b/tests/shell/testcases/transactions/dumps/0051map_0.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/30s-stress.json-nft b/tests/shell/testcases/transactions/dumps/30s-stress.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/30s-stress.nft b/tests/shell/testcases/transactions/dumps/30s-stress.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/anon_chain_loop.json-nft b/tests/shell/testcases/transactions/dumps/anon_chain_loop.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/anon_chain_loop.nft b/tests/shell/testcases/transactions/dumps/anon_chain_loop.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/atomic_replace.sh.nodump b/tests/shell/testcases/transactions/dumps/atomic_replace.sh.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/bad_expression.json-nft b/tests/shell/testcases/transactions/dumps/bad_expression.json-nft
new file mode 100644 (file)
index 0000000..546cc59
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/bad_expression.nft b/tests/shell/testcases/transactions/dumps/bad_expression.nft
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/dumps/bad_rule_graphs.json-nft b/tests/shell/testcases/transactions/dumps/bad_rule_graphs.json-nft
new file mode 100644 (file)
index 0000000..3078921
--- /dev/null
@@ -0,0 +1,201 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c10",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c9",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c8",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c2",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c1",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c0",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "map": {
+        "family": "ip",
+        "name": "m",
+        "table": "t",
+        "type": "ipv4_addr",
+        "handle": 0,
+        "map": "verdict"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c9",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c10"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c9",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "tcp",
+                  "field": "dport"
+                }
+              },
+              "right": 80
+            }
+          },
+          {
+            "tproxy": {
+              "port": 20000
+            }
+          },
+          {
+            "mangle": {
+              "key": {
+                "meta": {
+                  "key": "mark"
+                }
+              },
+              "value": 1
+            }
+          },
+          {
+            "accept": null
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c8",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c9"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c2"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c1",
+        "handle": 0,
+        "expr": [
+          {
+            "vmap": {
+              "key": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "saddr"
+                }
+              },
+              "data": "@m"
+            }
+          }
+        ]
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c0",
+        "handle": 0,
+        "expr": [
+          {
+            "jump": {
+              "target": "c1"
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/bad_rule_graphs.nft b/tests/shell/testcases/transactions/dumps/bad_rule_graphs.nft
new file mode 100644 (file)
index 0000000..3a59365
--- /dev/null
@@ -0,0 +1,30 @@
+table ip t {
+       map m {
+               type ipv4_addr : verdict
+       }
+
+       chain c10 {
+       }
+
+       chain c9 {
+               jump c10
+               tcp dport 80 tproxy to :20000 meta mark set 0x00000001 accept
+       }
+
+       chain c8 {
+               jump c9
+       }
+
+       chain c2 {
+       }
+
+       chain c1 {
+               jump c2
+               ip saddr vmap @m
+       }
+
+       chain c0 {
+               type filter hook input priority filter; policy accept;
+               jump c1
+       }
+}
diff --git a/tests/shell/testcases/transactions/dumps/concat_range_abort.json-nft b/tests/shell/testcases/transactions/dumps/concat_range_abort.json-nft
new file mode 100644 (file)
index 0000000..8db7189
--- /dev/null
@@ -0,0 +1,47 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "foo",
+        "handle": 0
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "x",
+        "name": "bar",
+        "handle": 0
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "x",
+        "chain": "foo",
+        "handle": 0,
+        "expr": [
+          {
+            "accept": null
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/concat_range_abort.nft b/tests/shell/testcases/transactions/dumps/concat_range_abort.nft
new file mode 100644 (file)
index 0000000..06adca7
--- /dev/null
@@ -0,0 +1,8 @@
+table ip x {
+       chain foo {
+               accept
+       }
+
+       chain bar {
+       }
+}
diff --git a/tests/shell/testcases/transactions/dumps/doubled-set.json-nft b/tests/shell/testcases/transactions/dumps/doubled-set.json-nft
new file mode 100644 (file)
index 0000000..1b9af21
--- /dev/null
@@ -0,0 +1,39 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0
+      }
+    },
+    {
+      "set": {
+        "family": "ip",
+        "name": "s",
+        "table": "t",
+        "type": [
+          "ipv4_addr",
+          "ifname"
+        ],
+        "handle": 0,
+        "flags": "interval",
+        "elem": [
+          {
+            "concat": [
+              "1.2.3.4",
+              "foo"
+            ]
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/doubled-set.nft b/tests/shell/testcases/transactions/dumps/doubled-set.nft
new file mode 100644 (file)
index 0000000..48a322e
--- /dev/null
@@ -0,0 +1,7 @@
+table ip t {
+       set s {
+               type ipv4_addr . ifname
+               flags interval
+               elements = { 1.2.3.4 . "foo" }
+       }
+}
diff --git a/tests/shell/testcases/transactions/dumps/handle_bad_family.json-nft b/tests/shell/testcases/transactions/dumps/handle_bad_family.json-nft
new file mode 100644 (file)
index 0000000..15ec0aa
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "x",
+        "handle": 0
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/handle_bad_family.nft b/tests/shell/testcases/transactions/dumps/handle_bad_family.nft
new file mode 100644 (file)
index 0000000..5d4d2ca
--- /dev/null
@@ -0,0 +1,2 @@
+table ip x {
+}
diff --git a/tests/shell/testcases/transactions/dumps/table_onoff.json-nft b/tests/shell/testcases/transactions/dumps/table_onoff.json-nft
new file mode 100644 (file)
index 0000000..a7583e8
--- /dev/null
@@ -0,0 +1,59 @@
+{
+  "nftables": [
+    {
+      "metainfo": {
+        "version": "VERSION",
+        "release_name": "RELEASE_NAME",
+        "json_schema_version": 1
+      }
+    },
+    {
+      "table": {
+        "family": "ip",
+        "name": "t",
+        "handle": 0,
+        "flags": "dormant"
+      }
+    },
+    {
+      "chain": {
+        "family": "ip",
+        "table": "t",
+        "name": "c",
+        "handle": 0,
+        "type": "filter",
+        "hook": "input",
+        "prio": 0,
+        "policy": "accept"
+      }
+    },
+    {
+      "rule": {
+        "family": "ip",
+        "table": "t",
+        "chain": "c",
+        "handle": 0,
+        "expr": [
+          {
+            "match": {
+              "op": "==",
+              "left": {
+                "payload": {
+                  "protocol": "ip",
+                  "field": "daddr"
+                }
+              },
+              "right": "127.0.0.42"
+            }
+          },
+          {
+            "counter": {
+              "packets": 0,
+              "bytes": 0
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
diff --git a/tests/shell/testcases/transactions/dumps/table_onoff.nft b/tests/shell/testcases/transactions/dumps/table_onoff.nft
new file mode 100644 (file)
index 0000000..038be1c
--- /dev/null
@@ -0,0 +1,8 @@
+table ip t {
+       flags dormant
+
+       chain c {
+               type filter hook input priority filter; policy accept;
+               ip daddr 127.0.0.42 counter packets 0 bytes 0
+       }
+}
diff --git a/tests/shell/testcases/transactions/dumps/validation_recursion.sh.nodump b/tests/shell/testcases/transactions/dumps/validation_recursion.sh.nodump
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/shell/testcases/transactions/handle_bad_family b/tests/shell/testcases/transactions/handle_bad_family
new file mode 100755 (executable)
index 0000000..5922418
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+NFT=nft
+
+HANDLE=$($NFT -a -e add table ip x | cut -d '#' -f 2 | awk '{ print $2 }' | head -1)
+
+# should fail
+$NFT delete table inet handle $HANDLE
+[ $? -ne 0 ] && exit 0
diff --git a/tests/shell/testcases/transactions/table_onoff b/tests/shell/testcases/transactions/table_onoff
new file mode 100755 (executable)
index 0000000..831d461
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+# attempt to re-awaken a table that is flagged dormant within
+# same transaction
+$NFT -f - <<EOF
+add table ip t
+add table ip t { flags dormant; }
+add chain ip t c { type filter hook input priority 0; }
+add table ip t
+delete table ip t
+EOF
+
+if [ $? -eq 0 ]; then
+       exit 1
+fi
+
+set -e
+
+ip link set lo up
+
+# add a dormant table, then wake it up in same
+# transaction.
+$NFT -f - <<EOF
+add table ip t { flags dormant; }
+add chain ip t c { type filter hook input priority 0; }
+add rule ip t c ip daddr 127.0.0.42 counter
+add table ip t
+EOF
+
+# check table is indeed active.
+ping -c 1 127.0.0.42
+$NFT list chain ip t c | grep "counter packets 1"
+$NFT delete table ip t
+
+# allow to flag table dormant.
+$NFT -f - <<EOF
+add table ip t
+add chain ip t c { type filter hook input priority 0; }
+add rule ip t c ip daddr 127.0.0.42 counter
+add table ip t { flags dormant; }
+EOF
+
+ping -c 1 127.0.0.42
+# expect run-tests.sh to complain if counter isn't 0.
diff --git a/tests/shell/testcases/transactions/validation_recursion.sh b/tests/shell/testcases/transactions/validation_recursion.sh
new file mode 100755 (executable)
index 0000000..bc3ebcc
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# regression check for kernel commit
+# cff3bd012a95 ("netfilter: nf_tables: prefer nft_chain_validate")
+
+chains=100
+
+# first create skeleton, linear list
+# of 1k jumps, c1 -> c2 .. -> c100.
+#
+# not caught, commit phase validation doesn't care about
+# non-base chains.
+(
+       echo add table ip t
+
+       for i in $(seq 1 $chains);do
+               echo add chain t c$i
+       done
+
+       for i in $(seq 1 $((chains-1)) );do
+               echo add rule t c$i jump c$((i+1))
+       done
+) | $NFT -f -
+
+# now link up c0 to c1.  This triggers register-store validation for
+# c1. Old algorithm is recursive and will blindly chase the entire
+# list of chains created above.  On older kernels, this will cause kernel
+# stack overflow/guard page crash.
+$NFT -f - <<EOF
+add chain t c0 { type filter hook input priority 0; }
+add rule t c0 jump c1
+EOF
+
+if [ $? -eq 0 ] ; then
+        echo "E: loaded bogus ruleset" >&2
+        exit 1
+fi
+
+$NFT delete table ip t