Add command to test control packet filter - add/delete control packet filter
Signed-off-by: Jingjing Wu <jingjing.wu at intel.com> --- app/test-pmd/cmdline.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 225f669..1354230 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -660,6 +660,12 @@ static void cmd_help_long_parsed(void *parsed_result, "get_flex_filter (port_id) index (idx)\n" " get info of a flex filter.\n\n" + + "ctrl_pkt_filter (port_id) (add|del)" + "mac_addr (mac_address) ethertype (ether_type)" + "(none|options) queue (queue_id)\n" + " Add/Del a control packet filter.\n\n" + ); } } @@ -7411,6 +7417,148 @@ cmdline_parse_inst_t cmd_get_flex_filter = { }, }; +/* *** Filters Control *** */ + +static inline int +parse_ctrl_pkt_filter_options(const char *q_arg, + uint16_t *flags) +{ +#define MAX_NUM_OPTIONS 3 + char s[256]; + char *str_fld[MAX_NUM_OPTIONS]; + int i; + int num_options = -1; + unsigned size; + + *flags = 0; + if (!strcmp(q_arg, "none")) + return 0; + + size = strnlen(q_arg, sizeof(s)); + snprintf(s, sizeof(s), "%.*s", size, q_arg); + num_options = rte_strsplit(s, sizeof(s), str_fld, MAX_NUM_OPTIONS, '-'); + /* multi-options are combined by - */ + if (num_options < 0 || num_options > MAX_NUM_OPTIONS) + return -1; + for (i = 0; i < num_options; i++) { + if (!strcmp(str_fld[i], "tx")) + *flags |= RTE_CONTROL_PACKET_FLAGS_TX; + if (!strcmp(str_fld[i], "mac_ignr")) + *flags |= RTE_CONTROL_PACKET_FLAGS_IGNORE_MAC; + if (!strcmp(str_fld[i], "drop")) + *flags |= RTE_CONTROL_PACKET_FLAGS_DROP; + } + return num_options; +} + +struct cmd_ctrl_pkt_filter_result { + cmdline_fixed_string_t filter; + uint8_t port_id; + cmdline_fixed_string_t ops; + cmdline_fixed_string_t mac_addr; + struct ether_addr mac_addr_value; + cmdline_fixed_string_t ethertype; + uint16_t ethertype_value; + cmdline_fixed_string_t options; + cmdline_fixed_string_t queue; + uint16_t queue_id; +}; + +cmdline_parse_token_string_t cmd_ctrl_pkt_filter_filter = + TOKEN_STRING_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + filter, "ctrl_pkt_filter"); +cmdline_parse_token_num_t cmd_ctrl_pkt_filter_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_ctrl_pkt_filter_ops = + TOKEN_STRING_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + ops, "add#del"); +cmdline_parse_token_string_t cmd_ctrl_pkt_filter_mac_addr = + TOKEN_STRING_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + mac_addr, "mac_addr"); +cmdline_parse_token_etheraddr_t cmd_ctrl_pkt_filter_mac_addr_value = + TOKEN_ETHERADDR_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + mac_addr_value); +cmdline_parse_token_string_t cmd_ctrl_pkt_filter_ethertype = + TOKEN_STRING_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + ethertype, "ethertype"); +cmdline_parse_token_num_t cmd_ctrl_pkt_filter_ethertype_value = + TOKEN_NUM_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + ethertype_value, UINT16); +cmdline_parse_token_string_t cmd_ctrl_pkt_filter_options = + TOKEN_STRING_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + options, NULL); +cmdline_parse_token_string_t cmd_ctrl_pkt_filter_queue = + TOKEN_STRING_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + queue, "queue"); +cmdline_parse_token_num_t cmd_ctrl_pkt_filter_queue_id = + TOKEN_NUM_INITIALIZER(struct cmd_ctrl_pkt_filter_result, + queue_id, UINT16); + +static void +cmd_ctrl_pkt_filter_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_ctrl_pkt_filter_result *res = parsed_result; + struct rte_ctrl_pkt_filter filter; + int ret = 0; + + ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_CTRL_PKT); + if (ret < 0) { + printf("control packet filter is not supported on port %u. \n", + res->port_id); + return; + } + + memset(&filter, 0, sizeof(filter)); + + (void)rte_memcpy(&filter.mac_addr, &res->mac_addr_value, + sizeof(struct ether_addr)); + filter.ether_type = res->ethertype_value; + + ret = parse_ctrl_pkt_filter_options(res->options, &filter.flags); + if (ret < 0) { + printf("options input is invalid. \n"); + return; + } + if (!(filter.flags & RTE_CONTROL_PACKET_FLAGS_DROP)) { + filter.flags |= RTE_CONTROL_PACKET_FLAGS_TO_QUEUE; + filter.queue = res->queue_id; + } + if (!strcmp(res->ops, "add")) + ret = rte_eth_dev_filter_ctrl(res->port_id, + RTE_ETH_FILTER_CTRL_PKT, + RTE_ETH_FILTER_OP_ADD, + &filter); + else + ret = rte_eth_dev_filter_ctrl(res->port_id, + RTE_ETH_FILTER_CTRL_PKT, + RTE_ETH_FILTER_OP_DELETE, + &filter); + if (ret < 0) + printf("control packet filter programming error: (%s)\n", strerror(-ret)); +} + +cmdline_parse_inst_t cmd_ctrl_pkt_filter = { + .f = cmd_ctrl_pkt_filter_parsed, + .data = NULL, + .help_str = "add or delete a control packet filter entry", + .tokens = { + (void *)&cmd_ctrl_pkt_filter_filter, + (void *)&cmd_ctrl_pkt_filter_port_id, + (void *)&cmd_ctrl_pkt_filter_ops, + (void *)&cmd_ctrl_pkt_filter_mac_addr, + (void *)&cmd_ctrl_pkt_filter_mac_addr_value, + (void *)&cmd_ctrl_pkt_filter_ethertype, + (void *)&cmd_ctrl_pkt_filter_ethertype_value, + (void *)&cmd_ctrl_pkt_filter_options, + (void *)&cmd_ctrl_pkt_filter_queue, + (void *)&cmd_ctrl_pkt_filter_queue_id, + NULL, + }, +}; + /* ******************************************************************************** */ /* list of instructions */ @@ -7537,6 +7685,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_add_flex_filter, (cmdline_parse_inst_t *)&cmd_remove_flex_filter, (cmdline_parse_inst_t *)&cmd_get_flex_filter, + (cmdline_parse_inst_t *)&cmd_ctrl_pkt_filter, NULL, }; -- 1.8.1.4