From a47aa8b97afe46da6032910d88109948b4c49b21 Mon Sep 17 00:00:00 2001 From: Intel Date: Thu, 20 Dec 2012 00:00:00 +0100 Subject: [PATCH] app/testpmd: add vlan offload support Signed-off-by: Intel --- app/test-pmd/cmdline.c | 167 ++++++++++++++++++++++++++++++++++++-- app/test-pmd/config.c | 120 ++++++++++++++++++++++++++- app/test-pmd/parameters.c | 7 +- app/test-pmd/testpmd.c | 2 + app/test-pmd/testpmd.h | 8 +- 5 files changed, 292 insertions(+), 12 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 6142c15b98..2c82098b1c 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -135,13 +135,16 @@ static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, "- set corelist|portlist x[,y]*\n" " Set the list of forwarding cores / forwarding " "ports\n" + "- vlan set strip|filter|qinq on/off port_id\n" + " Set the VLAN strip, filter, QinQ(extended) on a port" "- rx_vlan add/rm vlan_id|all port_id\n" - " Add/remove vlan_id, or all identifiers, to/from " - "the set of VLAN Identifiers\n filtered by port_id\n" + " Set the VLAN filter table, add/remove vlan_id, or all " + "identifiers, to/from the set of VLAN Identifiers\n" + "filtered by port_id\n" + "- rx_vlan set tpid value port_id\n" + " Set Outer VLAN TPID for Packet Filtering on a port \n" "- tx_vlan set vlan_id port_id\n" - " Enable hardware insertion of a VLAN header with " - "the Tag Identifier vlan_id\n in packets sent on" - "port_id\n" + " Set hardware insertion of VLAN ID in packets sent on a port\n" "- tx_vlan reset port_id\n" " Disable hardware insertion of a VLAN header in " "packets sent on port_id\n" @@ -564,6 +567,153 @@ cmdline_parse_inst_t cmd_rx_vlan_filter_all = { }, }; +/* *** VLAN OFFLOAD SET ON A PORT *** */ +struct cmd_vlan_offload_result { + cmdline_fixed_string_t vlan; + cmdline_fixed_string_t set; + cmdline_fixed_string_t what; + cmdline_fixed_string_t on; + cmdline_fixed_string_t port_id; +}; + +static void +cmd_vlan_offload_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + int on; + struct cmd_vlan_offload_result *res = parsed_result; + char *str; + int i, len = 0; + portid_t port_id = 0; + unsigned int tmp; + + str = res->port_id; + len = strnlen(str, STR_TOKEN_SIZE); + i = 0; + /* Get port_id first */ + while(i < len){ + if(str[i] == ',') + break; + + i++; + } + str[i]='\0'; + tmp = strtoul(str, NULL, 0); + /* If port_id greater that what portid_t can represent, return */ + if(tmp > 255) + return; + port_id = (portid_t)tmp; + + if (!strcmp(res->on, "on")) + on = 1; + else + on = 0; + + if (!strcmp(res->what, "strip")) + rx_vlan_strip_set(port_id, on); + else if(!strcmp(res->what, "stripq")){ + uint16_t queue_id = 0; + + /* No queue_id, return */ + if(i + 1 >= len) + return; + tmp = strtoul(str + i + 1, NULL, 0); + /* If queue_id greater that what 16-bits can represent, return */ + if(tmp > 0xffff) + return; + + queue_id = (uint16_t)tmp; + rx_vlan_strip_set_on_queue(port_id, queue_id, on); + } + else if (!strcmp(res->what, "filter")) + rx_vlan_filter_set(port_id, on); + else + vlan_extend_set(port_id, on); + + return; +} + +cmdline_parse_token_string_t cmd_vlan_offload_vlan = + TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, + vlan, "vlan"); +cmdline_parse_token_string_t cmd_vlan_offload_set = + TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, + set, "set"); +cmdline_parse_token_string_t cmd_vlan_offload_what = + TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, + what, "strip#filter#qinq#stripq"); +cmdline_parse_token_string_t cmd_vlan_offload_on = + TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, + on, "on#off"); +cmdline_parse_token_string_t cmd_vlan_offload_portid = + TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, + port_id, NULL); + +cmdline_parse_inst_t cmd_vlan_offload = { + .f = cmd_vlan_offload_parsed, + .data = NULL, + .help_str = "set strip|filter|qinq|stripq on|off port_id[,queue_id], filter/strip for rx side" + " qinq(extended) for both rx/tx sides ", + .tokens = { + (void *)&cmd_vlan_offload_vlan, + (void *)&cmd_vlan_offload_set, + (void *)&cmd_vlan_offload_what, + (void *)&cmd_vlan_offload_on, + (void *)&cmd_vlan_offload_portid, + NULL, + }, +}; + +/* *** VLAN TPID SET ON A PORT *** */ +struct cmd_vlan_tpid_result { + cmdline_fixed_string_t vlan; + cmdline_fixed_string_t set; + cmdline_fixed_string_t what; + uint16_t tp_id; + uint8_t port_id; +}; + +static void +cmd_vlan_tpid_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_vlan_tpid_result *res = parsed_result; + vlan_tpid_set(res->port_id, res->tp_id); + return; +} + +cmdline_parse_token_string_t cmd_vlan_tpid_vlan = + TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result, + vlan, "vlan"); +cmdline_parse_token_string_t cmd_vlan_tpid_set = + TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result, + set, "set"); +cmdline_parse_token_string_t cmd_vlan_tpid_what = + TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result, + what, "tpid"); +cmdline_parse_token_num_t cmd_vlan_tpid_tpid = + TOKEN_NUM_INITIALIZER(struct cmd_vlan_tpid_result, + tp_id, UINT16); +cmdline_parse_token_num_t cmd_vlan_tpid_portid = + TOKEN_NUM_INITIALIZER(struct cmd_vlan_tpid_result, + port_id, UINT8); + +cmdline_parse_inst_t cmd_vlan_tpid = { + .f = cmd_vlan_tpid_parsed, + .data = NULL, + .help_str = "set tpid tp_id port_id, set the Outer VLAN Ether type", + .tokens = { + (void *)&cmd_vlan_tpid_vlan, + (void *)&cmd_vlan_tpid_set, + (void *)&cmd_vlan_tpid_what, + (void *)&cmd_vlan_tpid_tpid, + (void *)&cmd_vlan_tpid_portid, + NULL, + }, +}; + /* *** ADD/REMOVE A VLAN IDENTIFIER TO/FROM A PORT VLAN RX FILTER *** */ struct cmd_rx_vlan_filter_result { cmdline_fixed_string_t rx_vlan; @@ -580,9 +730,9 @@ cmd_rx_vlan_filter_parsed(void *parsed_result, struct cmd_rx_vlan_filter_result *res = parsed_result; if (!strcmp(res->what, "add")) - rx_vlan_filter_set(res->port_id, res->vlan_id, 1); + rx_vft_set(res->port_id, res->vlan_id, 1); else - rx_vlan_filter_set(res->port_id, res->vlan_id, 0); + rx_vft_set(res->port_id, res->vlan_id, 0); } cmdline_parse_token_string_t cmd_rx_vlan_filter_rx_vlan = @@ -626,7 +776,6 @@ cmd_tx_vlan_set_parsed(void *parsed_result, __attribute__((unused)) void *data) { struct cmd_tx_vlan_set_result *res = parsed_result; - tx_vlan_set(res->port_id, res->vlan_id); } @@ -2204,6 +2353,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_promisc_mode_all, (cmdline_parse_inst_t *)&cmd_set_allmulti_mode_one, (cmdline_parse_inst_t *)&cmd_set_allmulti_mode_all, + (cmdline_parse_inst_t *)&cmd_vlan_offload, + (cmdline_parse_inst_t *)&cmd_vlan_tpid, (cmdline_parse_inst_t *)&cmd_rx_vlan_filter_all, (cmdline_parse_inst_t *)&cmd_rx_vlan_filter, (cmdline_parse_inst_t *)&cmd_tx_vlan_set, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index bbf837d536..3b7b8f8472 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -206,6 +206,7 @@ port_infos_display(portid_t port_id) { struct rte_port *port; struct rte_eth_link link; + int vlan_offload; static const char *info_border = "*********************"; if (port_id >= nb_ports) { @@ -227,6 +228,25 @@ port_infos_display(portid_t port_id) rte_eth_allmulticast_get(port_id) ? "enabled" : "disabled"); printf("Maximum number of MAC addresses: %u\n", (unsigned int)(port->dev_info.max_mac_addrs)); + + vlan_offload = rte_eth_dev_get_vlan_offload(port_id); + if (vlan_offload >= 0){ + printf("VLAN offload: \n"); + if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD) + printf(" strip on \n"); + else + printf(" strip off \n"); + + if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD) + printf(" filter on \n"); + else + printf(" filter off \n"); + + if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) + printf(" qinq(extend) on \n"); + else + printf(" qinq(extend) off \n"); + } } static int @@ -1012,7 +1032,87 @@ set_verbose_level(uint16_t vb_level) } void -rx_vlan_filter_set(portid_t port_id, uint16_t vlan_id, int on) +vlan_extend_set(portid_t port_id, int on) +{ + int diag; + int vlan_offload; + + if (port_id_is_invalid(port_id)) + return; + + vlan_offload = rte_eth_dev_get_vlan_offload(port_id); + + if (on) + vlan_offload |= ETH_VLAN_EXTEND_OFFLOAD; + else + vlan_offload &= ~ETH_VLAN_EXTEND_OFFLOAD; + + diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); + if (diag < 0) + printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed " + "diag=%d\n", port_id, on, diag); +} + +void +rx_vlan_strip_set(portid_t port_id, int on) +{ + int diag; + int vlan_offload; + + if (port_id_is_invalid(port_id)) + return; + + vlan_offload = rte_eth_dev_get_vlan_offload(port_id); + + if (on) + vlan_offload |= ETH_VLAN_STRIP_OFFLOAD; + else + vlan_offload &= ~ETH_VLAN_STRIP_OFFLOAD; + + diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); + if (diag < 0) + printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed " + "diag=%d\n", port_id, on, diag); +} + +void +rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on) +{ + int diag; + + if (port_id_is_invalid(port_id)) + return; + + diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on); + if (diag < 0) + printf("rx_vlan_strip_set_on_queue(port_pi=%d, queue_id=%d, on=%d) failed " + "diag=%d\n", port_id, queue_id, on, diag); +} + +void +rx_vlan_filter_set(portid_t port_id, int on) +{ + int diag; + int vlan_offload; + + if (port_id_is_invalid(port_id)) + return; + + vlan_offload = rte_eth_dev_get_vlan_offload(port_id); + + if (on) + vlan_offload |= ETH_VLAN_FILTER_OFFLOAD; + else + vlan_offload &= ~ETH_VLAN_FILTER_OFFLOAD; + + diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); + if (diag < 0) + printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed " + "diag=%d\n", port_id, on, diag); +} + +void +rx_vft_set(portid_t port_id, uint16_t vlan_id, int on) { int diag; @@ -1036,7 +1136,23 @@ rx_vlan_all_filter_set(portid_t port_id, int on) if (port_id_is_invalid(port_id)) return; for (vlan_id = 0; vlan_id < 4096; vlan_id++) - rx_vlan_filter_set(port_id, vlan_id, on); + rx_vft_set(port_id, vlan_id, on); +} + +void +vlan_tpid_set(portid_t port_id, uint16_t tp_id) +{ + int diag; + if (port_id_is_invalid(port_id)) + return; + + diag = rte_eth_dev_set_vlan_ether_type(port_id, tp_id); + if (diag == 0) + return; + + printf("tx_vlan_tpid_set(port_pi=%d, tpid=%d) failed " + "diag=%d\n", + port_id, tp_id, diag); } void diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 526202a3f4..a478ce6a81 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -522,8 +522,13 @@ launch_args_parse(int argc, char** argv) rx_mode.hw_strip_crc = 1; if (!strcmp(lgopts[opt_idx].name, "enable-rx-cksum")) rx_mode.hw_ip_checksum = 1; - if (!strcmp(lgopts[opt_idx].name, "disable-hw-vlan")) + + if (!strcmp(lgopts[opt_idx].name, "disable-hw-vlan")) { rx_mode.hw_vlan_filter = 0; + rx_mode.hw_vlan_strip = 0; + rx_mode.hw_vlan_extend = 0; + } + if (!strcmp(lgopts[opt_idx].name, "disable-rss")) rss_hf = 0; if (!strcmp(lgopts[opt_idx].name, "port-topology")) { diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 44614fb3ca..919b395caa 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -231,6 +231,8 @@ struct rte_eth_rxmode rx_mode = { .header_split = 0, /**< Header Split disabled. */ .hw_ip_checksum = 0, /**< IP checksum offload disabled. */ .hw_vlan_filter = 1, /**< VLAN filtering enabled. */ + .hw_vlan_strip = 1, /**< VLAN strip enabled. */ + .hw_vlan_extend = 0, /**< Extended VLAN disabled. */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled. */ .hw_strip_crc = 0, /**< CRC stripping by hardware disabled. */ }; diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 6a5a6d44be..abb31f5e44 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -380,8 +380,14 @@ void set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt); void set_fwd_ports_mask(uint64_t portmask); void set_fwd_ports_number(uint16_t nb_pt); -void rx_vlan_filter_set(portid_t port_id, uint16_t vlan_id, int on); +void rx_vlan_strip_set(portid_t port_id, int on); +void rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on); + +void rx_vlan_filter_set(portid_t port_id, int on); void rx_vlan_all_filter_set(portid_t port_id, int on); +void rx_vft_set(portid_t port_id, uint16_t vlan_id, int on); +void vlan_extend_set(portid_t port_id, int on); +void vlan_tpid_set(portid_t port_id, uint16_t tp_id); void tx_vlan_set(portid_t port_id, uint16_t vlan_id); void tx_vlan_reset(portid_t port_id); -- 2.20.1