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