Add a simple tool that demonstrates adding a flower filter with two VLAN push actions. This example can be invoked as: # ./tools/samples/tc-filter-add p2 # tc -j -p filter show dev p2 ingress pref 2211 [ { "protocol": "802.1Q", "kind": "flower", "chain": 0 },{ "protocol": "802.1Q", "kind": "flower", "chain": 0, "options": { "handle": 1, "keys": { "num_of_vlans": 3, "vlan_id": 255, "vlan_prio": 5 }, "not_in_hw": true, "actions": [ { "order": 1, "kind": "vlan", "vlan_action": "push", "id": 255, "control_action": { "type": "pass" }, "index": 5, "ref": 1, "bind": 1 },{ "order": 2, "kind": "vlan", "vlan_action": "push", "id": 555, "control_action": { "type": "pass" }, "index": 6, "ref": 1, "bind": 1 } ] } } ] This shows the filter with two VLAN push actions, verifying that tc action attributes are handled correctly. Signed-off-by: Zahari Doychev --- tools/net/ynl/Makefile.deps | 1 + tools/net/ynl/samples/.gitignore | 1 + tools/net/ynl/samples/tc-filter-add.c | 92 +++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 tools/net/ynl/samples/tc-filter-add.c diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps index 865fd2e8519e..96c390af060e 100644 --- a/tools/net/ynl/Makefile.deps +++ b/tools/net/ynl/Makefile.deps @@ -47,4 +47,5 @@ CFLAGS_tc:= $(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \ $(call get_hdr_inc,_TC_MIRRED_H,tc_act/tc_mirred.h) \ $(call get_hdr_inc,_TC_SKBEDIT_H,tc_act/tc_skbedit.h) \ $(call get_hdr_inc,_TC_TUNNEL_KEY_H,tc_act/tc_tunnel_key.h) +CFLAGS_tc-filter-add:=$(CFLAGS_tc) CFLAGS_tcp_metrics:=$(call get_hdr_inc,_LINUX_TCP_METRICS_H,tcp_metrics.h) diff --git a/tools/net/ynl/samples/.gitignore b/tools/net/ynl/samples/.gitignore index 7f5fca7682d7..05087ee323ba 100644 --- a/tools/net/ynl/samples/.gitignore +++ b/tools/net/ynl/samples/.gitignore @@ -7,3 +7,4 @@ rt-addr rt-link rt-route tc +tc-filter-add diff --git a/tools/net/ynl/samples/tc-filter-add.c b/tools/net/ynl/samples/tc-filter-add.c new file mode 100644 index 000000000000..b9c6f30f2a30 --- /dev/null +++ b/tools/net/ynl/samples/tc-filter-add.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tc-user.h" + +int main(int argc, char **argv) +{ + struct tc_newtfilter_req *req; + struct tc_act_attrs *acts; + struct tc_vlan p = { + .v_action = TCA_VLAN_ACT_PUSH + }; + __u16 flags = NLM_F_EXCL | NLM_F_CREATE; + struct ynl_error yerr; + struct ynl_sock *ys; + int ifi; + + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + ifi = if_nametoindex(argv[1]); + if (!ifi) { + perror("if_nametoindex"); + return 1; + } + + ys = ynl_sock_create(&ynl_tc_family, &yerr); + if (!ys) { + fprintf(stderr, "YNL: %s\n", yerr.msg); + return 1; + } + + req = tc_newtfilter_req_alloc(); + if (!req) { + fprintf(stderr, "tc_newtfilter_req_alloc failed\n"); + goto err_destroy; + } + memset(req, 0, sizeof(*req)); + + acts = tc_act_attrs_alloc(2); + if (!acts) { + fprintf(stderr, "tc_act_attrs_alloc\n"); + goto err_act; + } + memset(acts, 0, sizeof(*acts)); + + req->_hdr.tcm_ifindex = ifi; + req->_hdr.tcm_parent = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS); + req->_hdr.tcm_info = TC_H_MAKE((2211 << 16), htons(0x8100)); + req->chain = 0; + + tc_newtfilter_req_set_nlflags(req, flags); + tc_newtfilter_req_set_kind(req, "flower"); + tc_newtfilter_req_set_options_flower_key_vlan_id(req, 255); + tc_newtfilter_req_set_options_flower_key_vlan_prio(req, 5); + tc_newtfilter_req_set_options_flower_key_num_of_vlans(req, 3); + + __tc_newtfilter_req_set_options_flower_act(req, acts, 2); + + tc_act_attrs_set_kind(&acts[0], "vlan"); + tc_act_attrs_set_options_vlan_parms(&acts[0], &p, sizeof(p)); + tc_act_attrs_set_options_vlan_push_vlan_id(&acts[0], 255); + tc_act_attrs_set_kind(&acts[1], "vlan"); + tc_act_attrs_set_options_vlan_parms(&acts[1], &p, sizeof(p)); + tc_act_attrs_set_options_vlan_push_vlan_id(&acts[1], 555); + + tc_newtfilter_req_set_options_flower_flags(req, 0); + tc_newtfilter_req_set_options_flower_key_eth_type(req, htons(0x8100)); + + if (tc_newtfilter(ys, req)) + fprintf(stderr, "YNL: %s\n", ys->err.msg); + + tc_newtfilter_req_free(req); + ynl_sock_destroy(ys); + return 0; + +err_act: + tc_newtfilter_req_free(req); +err_destroy: + ynl_sock_destroy(ys); + return 2; +} -- 2.51.0