xref: /dpdk/app/test-pmd/bpf_cmd.c (revision e977e4199a8d6bab72cf94e154adcad1fb964e5e)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4 
5 #include <stdio.h>
6 #include <rte_mbuf.h>
7 #include <rte_ethdev.h>
8 #include <rte_flow.h>
9 #include <rte_bpf_ethdev.h>
10 
11 #include <cmdline.h>
12 #include <cmdline_parse.h>
13 #include <cmdline_parse_num.h>
14 #include <cmdline_parse_string.h>
15 
16 #include "testpmd.h"
17 
18 static const struct rte_bpf_xsym bpf_xsym[] = {
19 	{
20 		.name = RTE_STR(stdout),
21 		.type = RTE_BPF_XTYPE_VAR,
22 		.var = &stdout,
23 	},
24 	{
25 		.name = RTE_STR(rte_pktmbuf_dump),
26 		.type = RTE_BPF_XTYPE_FUNC,
27 		.func = (void *)rte_pktmbuf_dump,
28 	},
29 };
30 
31 /* *** load BPF program *** */
32 struct cmd_bpf_ld_result {
33 	cmdline_fixed_string_t bpf;
34 	cmdline_fixed_string_t dir;
35 	uint8_t port;
36 	uint16_t queue;
37 	cmdline_fixed_string_t op;
38 	cmdline_fixed_string_t flags;
39 	cmdline_fixed_string_t prm;
40 };
41 
42 static void
43 bpf_parse_flags(const char *str, struct rte_bpf_arg *arg, uint32_t *flags)
44 {
45 	uint32_t i, v;
46 
47 	*flags = RTE_BPF_ETH_F_NONE;
48 	arg->type = RTE_BPF_ARG_PTR;
49 	arg->size = mbuf_data_size;
50 
51 	for (i = 0; str[i] != 0; i++) {
52 		v = toupper(str[i]);
53 		if (v == 'J')
54 			*flags |= RTE_BPF_ETH_F_JIT;
55 		else if (v == 'M') {
56 			arg->type = RTE_BPF_ARG_PTR_MBUF;
57 			arg->size = sizeof(struct rte_mbuf);
58 			arg->buf_size = mbuf_data_size;
59 		} else if (v == '-')
60 			continue;
61 		else
62 			printf("unknown flag: \'%c\'", v);
63 	}
64 }
65 
66 static void cmd_operate_bpf_ld_parsed(void *parsed_result,
67 				__attribute__((unused)) struct cmdline *cl,
68 				__attribute__((unused)) void *data)
69 {
70 	int32_t rc;
71 	uint32_t flags;
72 	struct cmd_bpf_ld_result *res;
73 	struct rte_bpf_prm prm;
74 	const char *fname, *sname;
75 
76 	res = parsed_result;
77 	memset(&prm, 0, sizeof(prm));
78 	prm.xsym = bpf_xsym;
79 	prm.nb_xsym = RTE_DIM(bpf_xsym);
80 
81 	bpf_parse_flags(res->flags, &prm.prog_arg, &flags);
82 	fname = res->prm;
83 	sname = ".text";
84 
85 	if (strcmp(res->dir, "rx") == 0) {
86 		rc = rte_bpf_eth_rx_elf_load(res->port, res->queue, &prm,
87 			fname, sname, flags);
88 		printf("%d:%s\n", rc, strerror(-rc));
89 	} else if (strcmp(res->dir, "tx") == 0) {
90 		rc = rte_bpf_eth_tx_elf_load(res->port, res->queue, &prm,
91 			fname, sname, flags);
92 		printf("%d:%s\n", rc, strerror(-rc));
93 	} else
94 		printf("invalid value: %s\n", res->dir);
95 }
96 
97 cmdline_parse_token_string_t cmd_load_bpf_start =
98 	TOKEN_STRING_INITIALIZER(struct cmd_bpf_ld_result,
99 			bpf, "bpf-load");
100 cmdline_parse_token_string_t cmd_load_bpf_dir =
101 	TOKEN_STRING_INITIALIZER(struct cmd_bpf_ld_result,
102 			dir, "rx#tx");
103 cmdline_parse_token_num_t cmd_load_bpf_port =
104 	TOKEN_NUM_INITIALIZER(struct cmd_bpf_ld_result, port, UINT8);
105 cmdline_parse_token_num_t cmd_load_bpf_queue =
106 	TOKEN_NUM_INITIALIZER(struct cmd_bpf_ld_result, queue, UINT16);
107 cmdline_parse_token_string_t cmd_load_bpf_flags =
108 	TOKEN_STRING_INITIALIZER(struct cmd_bpf_ld_result,
109 			flags, NULL);
110 cmdline_parse_token_string_t cmd_load_bpf_prm =
111 	TOKEN_STRING_INITIALIZER(struct cmd_bpf_ld_result,
112 			prm, NULL);
113 
114 cmdline_parse_inst_t cmd_operate_bpf_ld_parse = {
115 	.f = cmd_operate_bpf_ld_parsed,
116 	.data = NULL,
117 	.help_str = "bpf-load rx|tx <port> <queue> <J|M|B> <file_name>",
118 	.tokens = {
119 		(void *)&cmd_load_bpf_start,
120 		(void *)&cmd_load_bpf_dir,
121 		(void *)&cmd_load_bpf_port,
122 		(void *)&cmd_load_bpf_queue,
123 		(void *)&cmd_load_bpf_flags,
124 		(void *)&cmd_load_bpf_prm,
125 		NULL,
126 	},
127 };
128 
129 /* *** unload BPF program *** */
130 struct cmd_bpf_unld_result {
131 	cmdline_fixed_string_t bpf;
132 	cmdline_fixed_string_t dir;
133 	uint8_t port;
134 	uint16_t queue;
135 };
136 
137 static void cmd_operate_bpf_unld_parsed(void *parsed_result,
138 				__attribute__((unused)) struct cmdline *cl,
139 				__attribute__((unused)) void *data)
140 {
141 	struct cmd_bpf_unld_result *res;
142 
143 	res = parsed_result;
144 
145 	if (strcmp(res->dir, "rx") == 0)
146 		rte_bpf_eth_rx_unload(res->port, res->queue);
147 	else if (strcmp(res->dir, "tx") == 0)
148 		rte_bpf_eth_tx_unload(res->port, res->queue);
149 	else
150 		printf("invalid value: %s\n", res->dir);
151 }
152 
153 cmdline_parse_token_string_t cmd_unload_bpf_start =
154 	TOKEN_STRING_INITIALIZER(struct cmd_bpf_unld_result,
155 			bpf, "bpf-unload");
156 cmdline_parse_token_string_t cmd_unload_bpf_dir =
157 	TOKEN_STRING_INITIALIZER(struct cmd_bpf_unld_result,
158 			dir, "rx#tx");
159 cmdline_parse_token_num_t cmd_unload_bpf_port =
160 	TOKEN_NUM_INITIALIZER(struct cmd_bpf_unld_result, port, UINT8);
161 cmdline_parse_token_num_t cmd_unload_bpf_queue =
162 	TOKEN_NUM_INITIALIZER(struct cmd_bpf_unld_result, queue, UINT16);
163 
164 cmdline_parse_inst_t cmd_operate_bpf_unld_parse = {
165 	.f = cmd_operate_bpf_unld_parsed,
166 	.data = NULL,
167 	.help_str = "bpf-unload rx|tx <port> <queue>",
168 	.tokens = {
169 		(void *)&cmd_unload_bpf_start,
170 		(void *)&cmd_unload_bpf_dir,
171 		(void *)&cmd_unload_bpf_port,
172 		(void *)&cmd_unload_bpf_queue,
173 		NULL,
174 	},
175 };
176