diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index a418cf4a92..ef7211ac06 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -81,6 +81,8 @@ #include "testpmd.h" +static void cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue); + /* *** HELP *** */ struct cmd_help_result { cmdline_fixed_string_t help; @@ -224,6 +226,32 @@ static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, " port_dst_mask flexbytes 0|1 vlan_id 0|1\n" " vlan_prio 0|1 compare_dst 0|1\n" "\n"); + cmdline_printf(cl, + "Port Operations:\n" + "--------------\n" + "- port start|stop|close all|X\n" + " start/stop/close all ports or port X\n" + "- port config all|X speed 10|100|1000|10000|auto " + "duplex half|full|auto\n" + " set speed for all ports or port X\n" + "- port config all rxq|txq|rxd|txd value\n" + " set number for rxq/txq/rxd/txd\n" + "- port config all max-pkt-len value\n" + " set the max packet lenght\n" + "- port config all crc-strip|rx-cksum|hw-vlan|drop-en on|off\n" + " set crc-strip/rx-checksum/hardware-vlan/drop_en on or off" + "\n" + "- port config all rss ip|udp|none\n" + " set rss mode\n" + "- port config all burst value\n" + " set the number of packet per burst\n" + "- port config all txpt|txht|txwt|rxpt|rxht|rxwt value\n" + " set ring prefetch/host/writeback threshold for " + "tx/rx queue\n" + "- port config all txfreet|txrst|rxfreet value\n" + " set free threshold for rx/tx, or set tx rs bit " + "threshold\n" + "\n"); cmdline_printf(cl, "Misc:\n" "-----\n" @@ -245,6 +273,807 @@ cmdline_parse_inst_t cmd_help = { }, }; +/* *** start/stop/close all ports *** */ +struct cmd_operate_port_result { + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t name; + cmdline_fixed_string_t value; +}; + +static void cmd_operate_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_port_result *res = parsed_result; + + if (!strcmp(res->name, "start")) + start_port(RTE_PORT_ALL); + else if (!strcmp(res->name, "stop")) + stop_port(RTE_PORT_ALL); + else if (!strcmp(res->name, "close")) + close_port(RTE_PORT_ALL); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_port_all_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, keyword, + "port"); +cmdline_parse_token_string_t cmd_operate_port_all_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, name, + "start#stop#close"); +cmdline_parse_token_string_t cmd_operate_port_all_all = + TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, value, "all"); + +cmdline_parse_inst_t cmd_operate_port = { + .f = cmd_operate_port_parsed, + .data = NULL, + .help_str = "port start|stop|close all: start/stop/close all ports", + .tokens = { + (void *)&cmd_operate_port_all_cmd, + (void *)&cmd_operate_port_all_port, + (void *)&cmd_operate_port_all_all, + NULL, + }, +}; + +/* *** start/stop/close specific port *** */ +struct cmd_operate_specific_port_result { + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t name; + uint8_t value; +}; + +static void cmd_operate_specific_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_specific_port_result *res = parsed_result; + + if (!strcmp(res->name, "start")) + start_port(res->value); + else if (!strcmp(res->name, "stop")) + stop_port(res->value); + else if (!strcmp(res->name, "close")) + close_port(res->value); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_specific_port_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result, + keyword, "port"); +cmdline_parse_token_string_t cmd_operate_specific_port_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result, + name, "start#stop#close"); +cmdline_parse_token_num_t cmd_operate_specific_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_operate_specific_port_result, + value, UINT8); + +cmdline_parse_inst_t cmd_operate_specific_port = { + .f = cmd_operate_specific_port_parsed, + .data = NULL, + .help_str = "port start|stop|close X: start/stop/close port X", + .tokens = { + (void *)&cmd_operate_specific_port_cmd, + (void *)&cmd_operate_specific_port_port, + (void *)&cmd_operate_specific_port_id, + NULL, + }, +}; + +/* *** configure speed for all ports *** */ +struct cmd_config_speed_all { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t all; + cmdline_fixed_string_t item1; + cmdline_fixed_string_t item2; + cmdline_fixed_string_t value1; + cmdline_fixed_string_t value2; +}; + +static void +cmd_config_speed_all_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_config_speed_all *res = parsed_result; + uint16_t link_speed = ETH_LINK_SPEED_AUTONEG; + uint16_t link_duplex = 0; + portid_t pid; + + if (!all_ports_stopped()) { + printf("Please stop all ports first\n"); + return; + } + + if (!strcmp(res->value1, "10")) + link_speed = ETH_LINK_SPEED_10; + else if (!strcmp(res->value1, "100")) + link_speed = ETH_LINK_SPEED_100; + else if (!strcmp(res->value1, "1000")) + link_speed = ETH_LINK_SPEED_1000; + else if (!strcmp(res->value1, "10000")) + link_speed = ETH_LINK_SPEED_10000; + else if (!strcmp(res->value1, "auto")) + link_speed = ETH_LINK_SPEED_AUTONEG; + else { + printf("Unknown parameter\n"); + return; + } + + if (!strcmp(res->value2, "half")) + link_duplex = ETH_LINK_HALF_DUPLEX; + else if (!strcmp(res->value2, "full")) + link_duplex = ETH_LINK_FULL_DUPLEX; + else if (!strcmp(res->value2, "auto")) + link_duplex = ETH_LINK_AUTONEG_DUPLEX; + else { + printf("Unknown parameter\n"); + return; + } + + for (pid = 0; pid < nb_ports; pid++) { + ports[pid].dev_conf.link_speed = link_speed; + ports[pid].dev_conf.link_duplex = link_duplex; + } + + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); +} + +cmdline_parse_token_string_t cmd_config_speed_all_port = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, port, "port"); +cmdline_parse_token_string_t cmd_config_speed_all_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, keyword, + "config"); +cmdline_parse_token_string_t cmd_config_speed_all_all = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, all, "all"); +cmdline_parse_token_string_t cmd_config_speed_all_item1 = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item1, "speed"); +cmdline_parse_token_string_t cmd_config_speed_all_value1 = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1, + "10#100#1000#10000#auto"); +cmdline_parse_token_string_t cmd_config_speed_all_item2 = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2, "duplex"); +cmdline_parse_token_string_t cmd_config_speed_all_value2 = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value2, + "half#full#auto"); + +cmdline_parse_inst_t cmd_config_speed_all = { + .f = cmd_config_speed_all_parsed, + .data = NULL, + .help_str = "port config all speed 10|100|1000|10000|auto duplex " + "half|full|auto", + .tokens = { + (void *)&cmd_config_speed_all_port, + (void *)&cmd_config_speed_all_keyword, + (void *)&cmd_config_speed_all_all, + (void *)&cmd_config_speed_all_item1, + (void *)&cmd_config_speed_all_value1, + (void *)&cmd_config_speed_all_item2, + (void *)&cmd_config_speed_all_value2, + NULL, + }, +}; + +/* *** configure speed for specific port *** */ +struct cmd_config_speed_specific { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + uint8_t id; + cmdline_fixed_string_t item1; + cmdline_fixed_string_t item2; + cmdline_fixed_string_t value1; + cmdline_fixed_string_t value2; +}; + +static void +cmd_config_speed_specific_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_config_speed_specific *res = parsed_result; + uint16_t link_speed = ETH_LINK_SPEED_AUTONEG; + uint16_t link_duplex = 0; + + if (!all_ports_stopped()) { + printf("Please stop all ports first\n"); + return; + } + + if (res->id >= nb_ports) { + printf("Port id %d must be less than %d\n", res->id, nb_ports); + return; + } + + if (!strcmp(res->value1, "10")) + link_speed = ETH_LINK_SPEED_10; + else if (!strcmp(res->value1, "100")) + link_speed = ETH_LINK_SPEED_100; + else if (!strcmp(res->value1, "1000")) + link_speed = ETH_LINK_SPEED_1000; + else if (!strcmp(res->value1, "10000")) + link_speed = ETH_LINK_SPEED_10000; + else if (!strcmp(res->value1, "auto")) + link_speed = ETH_LINK_SPEED_AUTONEG; + else { + printf("Unknown parameter\n"); + return; + } + + if (!strcmp(res->value2, "half")) + link_duplex = ETH_LINK_HALF_DUPLEX; + else if (!strcmp(res->value2, "full")) + link_duplex = ETH_LINK_FULL_DUPLEX; + else if (!strcmp(res->value2, "auto")) + link_duplex = ETH_LINK_AUTONEG_DUPLEX; + else { + printf("Unknown parameter\n"); + return; + } + + ports[res->id].dev_conf.link_speed = link_speed; + ports[res->id].dev_conf.link_duplex = link_duplex; + + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); +} + + +cmdline_parse_token_string_t cmd_config_speed_specific_port = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, port, + "port"); +cmdline_parse_token_string_t cmd_config_speed_specific_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, keyword, + "config"); +cmdline_parse_token_num_t cmd_config_speed_specific_id = + TOKEN_NUM_INITIALIZER(struct cmd_config_speed_specific, id, UINT8); +cmdline_parse_token_string_t cmd_config_speed_specific_item1 = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item1, + "speed"); +cmdline_parse_token_string_t cmd_config_speed_specific_value1 = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1, + "10#100#1000#10000#auto"); +cmdline_parse_token_string_t cmd_config_speed_specific_item2 = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2, + "duplex"); +cmdline_parse_token_string_t cmd_config_speed_specific_value2 = + TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value2, + "half#full#auto"); + +cmdline_parse_inst_t cmd_config_speed_specific = { + .f = cmd_config_speed_specific_parsed, + .data = NULL, + .help_str = "port config X speed 10|100|1000|10000|auto duplex " + "half|full|auto", + .tokens = { + (void *)&cmd_config_speed_specific_port, + (void *)&cmd_config_speed_specific_keyword, + (void *)&cmd_config_speed_specific_id, + (void *)&cmd_config_speed_specific_item1, + (void *)&cmd_config_speed_specific_value1, + (void *)&cmd_config_speed_specific_item2, + (void *)&cmd_config_speed_specific_value2, + NULL, + }, +}; + +/* *** configure txq/rxq, txd/rxd *** */ +struct cmd_config_rx_tx { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t all; + cmdline_fixed_string_t name; + uint16_t value; +}; + +static void +cmd_config_rx_tx_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_config_rx_tx *res = parsed_result; + + if (!all_ports_stopped()) { + printf("Please stop all ports first\n"); + return; + } + + if (!strcmp(res->name, "rxq")) { + if (res->value <= 0) { + printf("rxq %d invalid - must be > 0\n", res->value); + return; + } + nb_rxq = res->value; + } + else if (!strcmp(res->name, "txq")) { + if (res->value <= 0) { + printf("txq %d invalid - must be > 0\n", res->value); + return; + } + nb_txq = res->value; + } + else if (!strcmp(res->name, "rxd")) { + if (res->value <= 0 || res->value > RTE_TEST_RX_DESC_MAX) { + printf("rxd %d invalid - must be > 0 && <= %d\n", + res->value, RTE_TEST_RX_DESC_MAX); + return; + } + nb_rxd = res->value; + } else if (!strcmp(res->name, "txd")) { + if (res->value <= 0 || res->value > RTE_TEST_TX_DESC_MAX) { + printf("txd %d invalid - must be > 0 && <= %d\n", + res->value, RTE_TEST_TX_DESC_MAX); + return; + } + nb_txd = res->value; + } else { + printf("Unknown parameter\n"); + return; + } + + init_port_config(); + + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); +} + +cmdline_parse_token_string_t cmd_config_rx_tx_port = + TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, port, "port"); +cmdline_parse_token_string_t cmd_config_rx_tx_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, keyword, "config"); +cmdline_parse_token_string_t cmd_config_rx_tx_all = + TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, all, "all"); +cmdline_parse_token_string_t cmd_config_rx_tx_name = + TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, name, + "rxq#txq#rxd#txd"); +cmdline_parse_token_num_t cmd_config_rx_tx_value = + TOKEN_NUM_INITIALIZER(struct cmd_config_rx_tx, value, UINT16); + +cmdline_parse_inst_t cmd_config_rx_tx = { + .f = cmd_config_rx_tx_parsed, + .data = NULL, + .help_str = "port config all rxq|txq|rxd|txd value", + .tokens = { + (void *)&cmd_config_rx_tx_port, + (void *)&cmd_config_rx_tx_keyword, + (void *)&cmd_config_rx_tx_all, + (void *)&cmd_config_rx_tx_name, + (void *)&cmd_config_rx_tx_value, + NULL, + }, +}; + +/* *** config max packet length *** */ +struct cmd_config_max_pkt_len_result { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t all; + cmdline_fixed_string_t name; + uint32_t value; +}; + +static void +cmd_config_max_pkt_len_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_config_max_pkt_len_result *res = parsed_result; + + if (!all_ports_stopped()) { + printf("Please stop all ports first\n"); + return; + } + + if (!strcmp(res->name, "max-pkt-len")) { + if (res->value < ETHER_MIN_LEN) { + printf("max-pkt-len can not be less than %d\n", + ETHER_MIN_LEN); + return; + } + if (res->value == rx_mode.max_rx_pkt_len) + return; + + rx_mode.max_rx_pkt_len = res->value; + if (res->value > ETHER_MAX_LEN) + rx_mode.jumbo_frame = 1; + else + rx_mode.jumbo_frame = 0; + } else { + printf("Unknown parameter\n"); + return; + } + + init_port_config(); + + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); +} + +cmdline_parse_token_string_t cmd_config_max_pkt_len_port = + TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, port, + "port"); +cmdline_parse_token_string_t cmd_config_max_pkt_len_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, keyword, + "config"); +cmdline_parse_token_string_t cmd_config_max_pkt_len_all = + TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, all, + "all"); +cmdline_parse_token_string_t cmd_config_max_pkt_len_name = + TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, name, + "max-pkt-len"); +cmdline_parse_token_num_t cmd_config_max_pkt_len_value = + TOKEN_NUM_INITIALIZER(struct cmd_config_max_pkt_len_result, value, + UINT32); + +cmdline_parse_inst_t cmd_config_max_pkt_len = { + .f = cmd_config_max_pkt_len_parsed, + .data = NULL, + .help_str = "port config all max-pkt-len value", + .tokens = { + (void *)&cmd_config_max_pkt_len_port, + (void *)&cmd_config_max_pkt_len_keyword, + (void *)&cmd_config_max_pkt_len_all, + (void *)&cmd_config_max_pkt_len_name, + (void *)&cmd_config_max_pkt_len_value, + NULL, + }, +}; + +/* *** configure rx mode *** */ +struct cmd_config_rx_mode_flag { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t all; + cmdline_fixed_string_t name; + cmdline_fixed_string_t value; +}; + +static void +cmd_config_rx_mode_flag_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_config_rx_mode_flag *res = parsed_result; + + if (!all_ports_stopped()) { + printf("Please stop all ports first\n"); + return; + } + + if (!strcmp(res->name, "crc-strip")) { + if (!strcmp(res->value, "on")) + rx_mode.hw_strip_crc = 1; + else if (!strcmp(res->value, "off")) + rx_mode.hw_strip_crc = 0; + else { + printf("Unknown parameter\n"); + return; + } + } else if (!strcmp(res->name, "rx-cksum")) { + if (!strcmp(res->value, "on")) + rx_mode.hw_ip_checksum = 1; + else if (!strcmp(res->value, "off")) + rx_mode.hw_ip_checksum = 0; + else { + printf("Unknown parameter\n"); + return; + } + } else if (!strcmp(res->name, "hw-vlan")) { + if (!strcmp(res->value, "on")) { + rx_mode.hw_vlan_filter = 1; + rx_mode.hw_vlan_strip = 1; + } + else if (!strcmp(res->value, "off")) { + rx_mode.hw_vlan_filter = 0; + rx_mode.hw_vlan_strip = 0; + } + else { + printf("Unknown parameter\n"); + return; + } + } else if (!strcmp(res->name, "drop-en")) { + if (!strcmp(res->value, "on")) + rx_drop_en = 1; + else if (!strcmp(res->value, "off")) + rx_drop_en = 0; + else { + printf("Unknown parameter\n"); + return; + } + } else { + printf("Unknown parameter\n"); + return; + } + + init_port_config(); + + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); +} + +cmdline_parse_token_string_t cmd_config_rx_mode_flag_port = + TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, port, "port"); +cmdline_parse_token_string_t cmd_config_rx_mode_flag_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, keyword, + "config"); +cmdline_parse_token_string_t cmd_config_rx_mode_flag_all = + TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, all, "all"); +cmdline_parse_token_string_t cmd_config_rx_mode_flag_name = + TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, name, + "crc-strip#rx-cksum#hw-vlan"); +cmdline_parse_token_string_t cmd_config_rx_mode_flag_value = + TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, value, + "on#off"); + +cmdline_parse_inst_t cmd_config_rx_mode_flag = { + .f = cmd_config_rx_mode_flag_parsed, + .data = NULL, + .help_str = "port config all crc-strip|rx-cksum|hw-vlan on|off", + .tokens = { + (void *)&cmd_config_rx_mode_flag_port, + (void *)&cmd_config_rx_mode_flag_keyword, + (void *)&cmd_config_rx_mode_flag_all, + (void *)&cmd_config_rx_mode_flag_name, + (void *)&cmd_config_rx_mode_flag_value, + NULL, + }, +}; + +/* *** configure rss *** */ +struct cmd_config_rss { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t all; + cmdline_fixed_string_t name; + cmdline_fixed_string_t value; +}; + +static void +cmd_config_rss_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_config_rss *res = parsed_result; + + if (!all_ports_stopped()) { + printf("Please stop all ports first\n"); + return; + } + + if (!strcmp(res->value, "ip")) + rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6; + else if (!strcmp(res->value, "udp")) + rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6 | ETH_RSS_IPV4_UDP; + else if (!strcmp(res->value, "none")) + rss_hf = 0; + else { + printf("Unknown parameter\n"); + return; + } + + init_port_config(); + + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); +} + +cmdline_parse_token_string_t cmd_config_rss_port = + TOKEN_STRING_INITIALIZER(struct cmd_config_rss, port, "port"); +cmdline_parse_token_string_t cmd_config_rss_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_config_rss, keyword, "config"); +cmdline_parse_token_string_t cmd_config_rss_all = + TOKEN_STRING_INITIALIZER(struct cmd_config_rss, all, "all"); +cmdline_parse_token_string_t cmd_config_rss_name = + TOKEN_STRING_INITIALIZER(struct cmd_config_rss, name, "rss"); +cmdline_parse_token_string_t cmd_config_rss_value = + TOKEN_STRING_INITIALIZER(struct cmd_config_rss, value, "ip#udp#none"); + +cmdline_parse_inst_t cmd_config_rss = { + .f = cmd_config_rss_parsed, + .data = NULL, + .help_str = "port config all rss ip|udp|none", + .tokens = { + (void *)&cmd_config_rss_port, + (void *)&cmd_config_rss_keyword, + (void *)&cmd_config_rss_all, + (void *)&cmd_config_rss_name, + (void *)&cmd_config_rss_value, + NULL, + }, +}; + +/* *** configure number of packets per burst *** */ +struct cmd_config_burst { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t all; + cmdline_fixed_string_t name; + uint16_t value; +}; + +static void +cmd_config_burst_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_config_burst *res = parsed_result; + + if (!all_ports_stopped()) { + printf("Please stop all ports first\n"); + return; + } + + if (!strcmp(res->name, "burst")) { + if (res->value < 1 || res->value > MAX_PKT_BURST) { + printf("burst must be >= 1 && <= %d\n", MAX_PKT_BURST); + return; + } + nb_pkt_per_burst = res->value; + } else { + printf("Unknown parameter\n"); + return; + } + + init_port_config(); + + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); +} + +cmdline_parse_token_string_t cmd_config_burst_port = + TOKEN_STRING_INITIALIZER(struct cmd_config_burst, port, "port"); +cmdline_parse_token_string_t cmd_config_burst_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_config_burst, keyword, "config"); +cmdline_parse_token_string_t cmd_config_burst_all = + TOKEN_STRING_INITIALIZER(struct cmd_config_burst, all, "all"); +cmdline_parse_token_string_t cmd_config_burst_name = + TOKEN_STRING_INITIALIZER(struct cmd_config_burst, name, "burst"); +cmdline_parse_token_num_t cmd_config_burst_value = + TOKEN_NUM_INITIALIZER(struct cmd_config_burst, value, UINT16); + +cmdline_parse_inst_t cmd_config_burst = { + .f = cmd_config_burst_parsed, + .data = NULL, + .help_str = "port config all burst value", + .tokens = { + (void *)&cmd_config_burst_port, + (void *)&cmd_config_burst_keyword, + (void *)&cmd_config_burst_all, + (void *)&cmd_config_burst_name, + (void *)&cmd_config_burst_value, + NULL, + }, +}; + +/* *** configure rx/tx queues *** */ +struct cmd_config_thresh { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t all; + cmdline_fixed_string_t name; + uint8_t value; +}; + +static void +cmd_config_thresh_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_config_thresh *res = parsed_result; + + if (!all_ports_stopped()) { + printf("Please stop all ports first\n"); + return; + } + + if (!strcmp(res->name, "txpt")) + tx_thresh.pthresh = res->value; + else if(!strcmp(res->name, "txht")) + tx_thresh.hthresh = res->value; + else if(!strcmp(res->name, "txwt")) + tx_thresh.wthresh = res->value; + else if(!strcmp(res->name, "rxpt")) + rx_thresh.pthresh = res->value; + else if(!strcmp(res->name, "rxht")) + rx_thresh.hthresh = res->value; + else if(!strcmp(res->name, "rxwt")) + rx_thresh.wthresh = res->value; + else { + printf("Unknown parameter\n"); + return; + } + + init_port_config(); + + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); +} + +cmdline_parse_token_string_t cmd_config_thresh_port = + TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, port, "port"); +cmdline_parse_token_string_t cmd_config_thresh_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, keyword, "config"); +cmdline_parse_token_string_t cmd_config_thresh_all = + TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, all, "all"); +cmdline_parse_token_string_t cmd_config_thresh_name = + TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, name, + "txpt#txht#txwt#rxpt#rxht#rxwt"); +cmdline_parse_token_num_t cmd_config_thresh_value = + TOKEN_NUM_INITIALIZER(struct cmd_config_thresh, value, UINT8); + +cmdline_parse_inst_t cmd_config_thresh = { + .f = cmd_config_thresh_parsed, + .data = NULL, + .help_str = "port config all txpt|txht|txwt|rxpt|rxht|rxwt value", + .tokens = { + (void *)&cmd_config_thresh_port, + (void *)&cmd_config_thresh_keyword, + (void *)&cmd_config_thresh_all, + (void *)&cmd_config_thresh_name, + (void *)&cmd_config_thresh_value, + NULL, + }, +}; + +/* *** configure free/rs threshold *** */ +struct cmd_config_threshold { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t all; + cmdline_fixed_string_t name; + uint16_t value; +}; + +static void +cmd_config_threshold_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_config_threshold *res = parsed_result; + + if (!all_ports_stopped()) { + printf("Please stop all ports first\n"); + return; + } + + if (!strcmp(res->name, "txfreet")) + tx_free_thresh = res->value; + else if (!strcmp(res->name, "txrst")) + tx_rs_thresh = res->value; + else if (!strcmp(res->name, "rxfreet")) + rx_free_thresh = res->value; + else { + printf("Unknown parameter\n"); + return; + } + + init_port_config(); + + cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); +} + +cmdline_parse_token_string_t cmd_config_threshold_port = + TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, port, "port"); +cmdline_parse_token_string_t cmd_config_threshold_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, keyword, + "config"); +cmdline_parse_token_string_t cmd_config_threshold_all = + TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, all, "all"); +cmdline_parse_token_string_t cmd_config_threshold_name = + TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, name, + "txfreet#txrst#rxfreet"); +cmdline_parse_token_num_t cmd_config_threshold_value = + TOKEN_NUM_INITIALIZER(struct cmd_config_threshold, value, UINT16); + +cmdline_parse_inst_t cmd_config_threshold = { + .f = cmd_config_threshold_parsed, + .data = NULL, + .help_str = "port config all txfreet|txrst|rxfreet value", + .tokens = { + (void *)&cmd_config_threshold_port, + (void *)&cmd_config_threshold_keyword, + (void *)&cmd_config_threshold_all, + (void *)&cmd_config_threshold_name, + (void *)&cmd_config_threshold_value, + NULL, + }, +}; + /* *** stop *** */ struct cmd_stop_result { cmdline_fixed_string_t stop; @@ -2455,6 +3284,17 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_stop, (cmdline_parse_inst_t *)&cmd_mac_addr, (cmdline_parse_inst_t *)&cmd_set_qmap, + (cmdline_parse_inst_t *)&cmd_operate_port, + (cmdline_parse_inst_t *)&cmd_operate_specific_port, + (cmdline_parse_inst_t *)&cmd_config_speed_all, + (cmdline_parse_inst_t *)&cmd_config_speed_specific, + (cmdline_parse_inst_t *)&cmd_config_rx_tx, + (cmdline_parse_inst_t *)&cmd_config_max_pkt_len, + (cmdline_parse_inst_t *)&cmd_config_rx_mode_flag, + (cmdline_parse_inst_t *)&cmd_config_rss, + (cmdline_parse_inst_t *)&cmd_config_burst, + (cmdline_parse_inst_t *)&cmd_config_thresh, + (cmdline_parse_inst_t *)&cmd_config_threshold, NULL, }; @@ -2471,3 +3311,27 @@ prompt(void) cmdline_interact(cl); cmdline_stdin_exit(cl); } + +static void +cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue) +{ + if (id < nb_ports) { + /* check if need_reconfig has been set to 1 */ + if (ports[id].need_reconfig == 0) + ports[id].need_reconfig = dev; + /* check if need_reconfig_queues has been set to 1 */ + if (ports[id].need_reconfig_queues == 0) + ports[id].need_reconfig_queues = queue; + } else { + portid_t pid; + + for (pid = 0; pid < nb_ports; pid++) { + /* check if need_reconfig has been set to 1 */ + if (ports[pid].need_reconfig == 0) + ports[pid].need_reconfig = dev; + /* check if need_reconfig_queues has been set to 1 */ + if (ports[pid].need_reconfig_queues == 0) + ports[pid].need_reconfig_queues = queue; + } + } +} diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 3b7b8f8472..b3664057aa 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -593,7 +593,8 @@ rxtx_config_display(void) nb_txq, nb_txd, tx_free_thresh); printf(" TX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n", tx_thresh.pthresh, tx_thresh.hthresh, tx_thresh.wthresh); - printf(" TX RS bit threshold=%d\n", tx_rs_thresh); + printf(" TX RS bit threshold=%d - TXQ flags=0x%"PRIx32"\n", + tx_rs_thresh, txq_flags); } /* diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index dfdd6739f6..df56e26d10 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -89,7 +89,7 @@ usage(char* progname) "--rss-ip | --rss-udp | " "--rxpt= | --rxht= | --rxwt= | --rxfreet= | " "--txpt= | --txht= | --txwt= | --txfreet= | " - "--txrst= ]\n", + "--txrst= | --txqflags= ]\n", progname); printf(" --interactive: run in interactive mode\n"); printf(" --help: display this message and quit\n"); @@ -158,6 +158,8 @@ usage(char* progname) " (0 <= N <= value of txd)\n"); printf(" --txrst=N set the transmit RS bit threshold of TX rings to N" " (0 <= N <= value of txd)\n"); + printf(" --txqflags=0xXXXXXXXX hexidecimal bitmask of TX queue flags" + " (0 <= N <= 0x7FFFFFFF)\n"); printf(" --tx-queue-stats-mapping (port,queue,mapping)[,(port,queue,mapping]:" " tx queues statistics counters mapping" " (0 <= mapping <= %d)\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); @@ -356,6 +358,7 @@ launch_args_parse(int argc, char** argv) { "txwt", 1, 0, 0 }, { "txfreet", 1, 0, 0 }, { "txrst", 1, 0, 0 }, + { "txqflags", 1, 0, 0 }, { "rxpt", 1, 0, 0 }, { "rxht", 1, 0, 0 }, { "rxwt", 1, 0, 0 }, @@ -541,6 +544,9 @@ launch_args_parse(int argc, char** argv) rx_mode.hw_vlan_extend = 0; } + if (!strcmp(lgopts[opt_idx].name, "enable-drop-en")) + rx_drop_en = 1; + if (!strcmp(lgopts[opt_idx].name, "disable-rss")) rss_hf = 0; if (!strcmp(lgopts[opt_idx].name, "port-topology")) { @@ -644,6 +650,15 @@ launch_args_parse(int argc, char** argv) else rte_exit(EXIT_FAILURE, "txrst must be >= 0\n"); } + if (!strcmp(lgopts[opt_idx].name, "txqflags")) { + char *end = NULL; + n = strtoul(optarg, &end, 16); + if (n >= 0) + txq_flags = (uint32_t)n; + else + rte_exit(EXIT_FAILURE, + "txqflags must be >= 0\n"); + } if (!strcmp(lgopts[opt_idx].name, "rxpt")) { n = atoi(optarg); if (n >= 0) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 2365a5d193..2e828e4582 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -204,6 +204,11 @@ struct rte_eth_thresh tx_thresh = { */ uint16_t rx_free_thresh = 0; /* Immediately free RX descriptors by default. */ +/* + * Configurable value of RX drop enable. + */ +uint8_t rx_drop_en = 0; /* Drop packets when no descriptors for queue. */ + /* * Configurable value of TX free threshold. */ @@ -214,6 +219,11 @@ uint16_t tx_free_thresh = 0; /* Use default values. */ */ uint16_t tx_rs_thresh = 0; /* Use default values. */ +/* + * Configurable value of TX queue flags. + */ +uint32_t txq_flags = 0; /* No flags set. */ + /* * Receive Side Scaling (RSS) configuration. */ @@ -260,6 +270,13 @@ uint16_t nb_rx_queue_stats_mappings = 0; /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); +static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask); + +/* + * Check if all the ports are started. + * If yes, return positive value. If not, return zero. + */ +static int all_ports_started(void); /* * Setup default configuration. @@ -394,35 +411,35 @@ mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf, testpmd_mbuf_ctor, &mb_ctor_arg, socket_id, 0); if (rte_mp == NULL) { - rte_exit(EXIT_FAILURE, "Creation of mbuf pool for socket %u failed\n", - socket_id); + rte_exit(EXIT_FAILURE, "Creation of mbuf pool for socket %u " + "failed\n", socket_id); } } static void init_config(void) { + portid_t pid; struct rte_port *port; struct rte_mempool *mbp; unsigned int nb_mbuf_per_pool; - streamid_t sm_id; lcoreid_t lc_id; - portid_t pt_id; /* Configuration of logical cores. */ fwd_lcores = rte_zmalloc("testpmd: fwd_lcores", sizeof(struct fwd_lcore *) * nb_lcores, CACHE_LINE_SIZE); if (fwd_lcores == NULL) { - rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_lcore *)) failed\n", - nb_lcores); + rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_lcore *)) " + "failed\n", nb_lcores); } for (lc_id = 0; lc_id < nb_lcores; lc_id++) { fwd_lcores[lc_id] = rte_zmalloc("testpmd: struct fwd_lcore", sizeof(struct fwd_lcore), CACHE_LINE_SIZE); if (fwd_lcores[lc_id] == NULL) { - rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_lcore) failed\n"); + rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_lcore) " + "failed\n"); } fwd_lcores[lc_id]->cpuid_idx = lc_id; } @@ -466,48 +483,86 @@ init_config(void) sizeof(struct rte_port) * nb_ports, CACHE_LINE_SIZE); if (ports == NULL) { - rte_exit(EXIT_FAILURE, "rte_zmalloc(%d struct rte_port) failed\n", - nb_ports); + rte_exit(EXIT_FAILURE, "rte_zmalloc(%d struct rte_port) " + "failed\n", nb_ports); } - port = ports; - for (pt_id = 0; pt_id < nb_ports; pt_id++, port++) { - rte_eth_dev_info_get(pt_id, &port->dev_info); + + for (pid = 0; pid < nb_ports; pid++) { + port = &ports[pid]; + rte_eth_dev_info_get(pid, &port->dev_info); + + /* set flag to initialize port/queue */ + port->need_reconfig = 1; + port->need_reconfig_queues = 1; + } + + init_port_config(); + + /* Configuration of packet forwarding streams. */ + if (init_fwd_streams() < 0) + rte_exit(EXIT_FAILURE, "FAIL from init_fwd_streams()\n"); +} + +int +init_fwd_streams(void) +{ + portid_t pid; + struct rte_port *port; + streamid_t sm_id, nb_fwd_streams_new; + + /* set socket id according to numa or not */ + for (pid = 0; pid < nb_ports; pid++) { + port = &ports[pid]; if (nb_rxq > port->dev_info.max_rx_queues) { - rte_exit(EXIT_FAILURE, "Port %d: max RX queues %d < nb_rxq %d\n", - (int) pt_id, - (int) port->dev_info.max_rx_queues, - (int) nb_rxq); + printf("Fail: nb_rxq(%d) is greater than " + "max_rx_queues(%d)\n", nb_rxq, + port->dev_info.max_rx_queues); + return -1; } if (nb_txq > port->dev_info.max_tx_queues) { - rte_exit(EXIT_FAILURE, "Port %d: max TX queues %d < nb_txq %d\n", - (int) pt_id, - (int) port->dev_info.max_tx_queues, - (int) nb_txq); + printf("Fail: nb_txq(%d) is greater than " + "max_tx_queues(%d)\n", nb_txq, + port->dev_info.max_tx_queues); + return -1; } - if (numa_support) - port->socket_id = (pt_id < (nb_ports >> 1)) ? 0 : 1; + port->socket_id = (pid < (nb_ports >> 1)) ? 0 : 1; else port->socket_id = 0; } - /* Configuration of packet forwarding streams. */ - nb_fwd_streams = (streamid_t) (nb_ports * nb_rxq); - fwd_streams = rte_zmalloc("testpmd: fwd_streams", - sizeof(struct fwd_stream *) * nb_fwd_streams, - CACHE_LINE_SIZE); - if (fwd_streams == NULL) { - rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_stream *)) failed\n", - nb_fwd_streams); + nb_fwd_streams_new = (streamid_t)(nb_ports * nb_rxq); + if (nb_fwd_streams_new == nb_fwd_streams) + return 0; + /* clear the old */ + if (fwd_streams != NULL) { + for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) { + if (fwd_streams[sm_id] == NULL) + continue; + rte_free(fwd_streams[sm_id]); + fwd_streams[sm_id] = NULL; + } + rte_free(fwd_streams); + fwd_streams = NULL; } + + /* init new */ + nb_fwd_streams = nb_fwd_streams_new; + fwd_streams = rte_zmalloc("testpmd: fwd_streams", + sizeof(struct fwd_stream *) * nb_fwd_streams, CACHE_LINE_SIZE); + if (fwd_streams == NULL) + rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_stream *)) " + "failed\n", nb_fwd_streams); + for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) { fwd_streams[sm_id] = rte_zmalloc("testpmd: struct fwd_stream", - sizeof(struct fwd_stream), - CACHE_LINE_SIZE); - if (fwd_streams[sm_id] == NULL) { - rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_stream) failed\n"); - } + sizeof(struct fwd_stream), CACHE_LINE_SIZE); + if (fwd_streams[sm_id] == NULL) + rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_stream)" + " failed\n"); } + + return 0; } #ifdef RTE_TEST_PMD_RECORD_BURST_STATS @@ -746,6 +801,10 @@ start_packet_forwarding(int with_tx_first) portid_t pt_id; streamid_t sm_id; + if (all_ports_started() == 0) { + printf("Not all ports were started\n"); + return; + } if (test_done == 0) { printf("Packet forwarding already started\n"); return; @@ -818,6 +877,10 @@ stop_packet_forwarding(void) #endif static const char *acc_stats_border = "+++++++++++++++"; + if (all_ports_started() == 0) { + printf("Not all ports were started\n"); + return; + } if (test_done) { printf("Packet forwarding not started\n"); return; @@ -931,6 +994,231 @@ stop_packet_forwarding(void) test_done = 1; } +static int +all_ports_started(void) +{ + portid_t pi; + struct rte_port *port; + + for (pi = 0; pi < nb_ports; pi++) { + port = &ports[pi]; + /* Check if there is a port which is not started */ + if (port->port_status != RTE_PORT_STARTED) + return 0; + } + + /* No port is not started */ + return 1; +} + +void +start_port(portid_t pid) +{ + int diag, need_check_link_status = 0; + portid_t pi; + queueid_t qi; + struct rte_port *port; + + if (test_done == 0) { + printf("Please stop forwarding first\n"); + return; + } + + if (init_fwd_streams() < 0) { + printf("Fail from init_fwd_streams()\n"); + return; + } + + if(dcb_config) + dcb_test = 1; + for (pi = 0; pi < nb_ports; pi++) { + if (pid < nb_ports && pid != pi) + continue; + + port = &ports[pi]; + if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED, + RTE_PORT_HANDLING) == 0) { + printf("Port %d is now not stopped\n", pi); + continue; + } + + if (port->need_reconfig > 0) { + port->need_reconfig = 0; + + printf("Configuring Port %d\n", pi); + /* configure port */ + diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq, + &(port->dev_conf)); + if (diag != 0) { + if (rte_atomic16_cmpset(&(port->port_status), + RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) + printf("Port %d can not be set back " + "to stopped\n", pi); + printf("Fail to configure port %d\n", pi); + /* try to reconfigure port next time */ + port->need_reconfig = 1; + return; + } + } + + if (port->need_reconfig_queues > 0) { + port->need_reconfig_queues = 0; + + /* setup tx queues */ + for (qi = 0; qi < nb_txq; qi++) { + diag = rte_eth_tx_queue_setup(pi, qi, nb_txd, + port->socket_id, &(port->tx_conf)); + if (diag == 0) + continue; + + /* Fail to setup tx queue, return */ + if (rte_atomic16_cmpset(&(port->port_status), + RTE_PORT_HANDLING, + RTE_PORT_STOPPED) == 0) + printf("Port %d can not be set back " + "to stopped\n", pi); + printf("Fail to configure port %d tx queues\n", pi); + /* try to reconfigure queues next time */ + port->need_reconfig_queues = 1; + return; + } + /* setup rx queues */ + for (qi = 0; qi < nb_rxq; qi++) { + diag = rte_eth_rx_queue_setup(pi, qi, nb_rxd, + port->socket_id, &(port->rx_conf), + mbuf_pool_find(port->socket_id)); + if (diag == 0) + continue; + + /* Fail to setup rx queue, return */ + if (rte_atomic16_cmpset(&(port->port_status), + RTE_PORT_HANDLING, + RTE_PORT_STOPPED) == 0) + printf("Port %d can not be set back " + "to stopped\n", pi); + printf("Fail to configure port %d rx queues\n", pi); + /* try to reconfigure queues next time */ + port->need_reconfig_queues = 1; + return; + } + } + + /* start port */ + if (rte_eth_dev_start(pi) < 0) { + printf("Fail to start port %d\n", pi); + + /* Fail to setup rx queue, return */ + if (rte_atomic16_cmpset(&(port->port_status), + RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) + printf("Port %d can not be set back to " + "stopped\n", pi); + continue; + } + + if (rte_atomic16_cmpset(&(port->port_status), + RTE_PORT_HANDLING, RTE_PORT_STARTED) == 0) + printf("Port %d can not be set into started\n", pi); + + /* at least one port started, need checking link status */ + need_check_link_status = 1; + } + + if (need_check_link_status) + check_all_ports_link_status(nb_ports, RTE_PORT_ALL); + else + printf("Please stop the ports first\n"); + + printf("Done\n"); +} + +void +stop_port(portid_t pid) +{ + portid_t pi; + struct rte_port *port; + int need_check_link_status = 0; + + if (test_done == 0) { + printf("Please stop forwarding first\n"); + return; + } + if (dcb_test) { + dcb_test = 0; + dcb_config = 0; + } + printf("Stopping ports...\n"); + + for (pi = 0; pi < nb_ports; pi++) { + if (pid < nb_ports && pid != pi) + continue; + + port = &ports[pi]; + if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STARTED, + RTE_PORT_HANDLING) == 0) + continue; + + rte_eth_dev_stop(pi); + + if (rte_atomic16_cmpset(&(port->port_status), + RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) + printf("Port %d can not be set into stopped\n", pi); + need_check_link_status = 1; + } + if (need_check_link_status) + check_all_ports_link_status(nb_ports, RTE_PORT_ALL); + + printf("Done\n"); +} + +void +close_port(portid_t pid) +{ + portid_t pi; + struct rte_port *port; + + if (test_done == 0) { + printf("Please stop forwarding first\n"); + return; + } + + printf("Closing ports...\n"); + + for (pi = 0; pi < nb_ports; pi++) { + if (pid < nb_ports && pid != pi) + continue; + + port = &ports[pi]; + if (rte_atomic16_cmpset(&(port->port_status), + RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 0) { + printf("Port %d is now not stopped\n", pi); + continue; + } + + rte_eth_dev_close(pi); + + if (rte_atomic16_cmpset(&(port->port_status), + RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0) + printf("Port %d can not be set into stopped\n", pi); + } + + printf("Done\n"); +} + +int +all_ports_stopped(void) +{ + portid_t pi; + struct rte_port *port; + + for (pi = 0; pi < nb_ports; pi++) { + port = &ports[pi]; + if (port->port_status != RTE_PORT_STOPPED) + return 0; + } + + return 1; +} + void pmd_test_exit(void) { @@ -953,11 +1241,57 @@ struct pmd_test_command { #define PMD_TEST_CMD_NB (sizeof(pmd_test_menu) / sizeof(pmd_test_menu[0])) +/* Check the link status of all ports in up to 9s, and print them finally */ static void -fatal_init_error(const char *func_name, uint8_t port_id, int diag) +check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { - rte_panic("%s(port_id=%d) failed - diag=%d\n", - func_name, port_id, diag); +#define CHECK_INTERVAL 100 /* 100ms */ +#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ + uint8_t portid, count, all_ports_up, print_flag = 0; + struct rte_eth_link link; + + printf("Checking link statuses...\n"); + fflush(stdout); + for (count = 0; count <= MAX_CHECK_TIME; count++) { + all_ports_up = 1; + for (portid = 0; portid < port_num; portid++) { + if ((port_mask & (1 << portid)) == 0) + continue; + memset(&link, 0, sizeof(link)); + rte_eth_link_get_nowait(portid, &link); + /* print link status if flag set */ + if (print_flag == 1) { + if (link.link_status) + printf("Port %d Link Up - speed %u " + "Mbps - %s\n", (uint8_t)portid, + (unsigned)link.link_speed, + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? + ("full-duplex") : ("half-duplex\n")); + else + printf("Port %d Link Down\n", + (uint8_t)portid); + continue; + } + /* clear all_ports_up flag if any link down */ + if (link.link_status == 0) { + all_ports_up = 0; + break; + } + } + /* after finally printing all link status, get out */ + if (print_flag == 1) + break; + + if (all_ports_up == 0) { + fflush(stdout); + rte_delay_ms(CHECK_INTERVAL); + } + + /* set the print_flag if all ports up or timeout */ + if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { + print_flag = 1; + } + } } static void @@ -1096,8 +1430,11 @@ main(int argc, char** argv) nb_rxq, nb_txq); init_config(); + start_port(RTE_PORT_ALL); - init_ports(); + /* set all ports to promiscuous mode by default */ + for (port_id = 0; port_id < nb_ports; port_id++) + rte_eth_promiscuous_enable(port_id); if (interactive == 1) prompt(); diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 937a1663e4..ea09584ba8 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -41,6 +41,16 @@ int main(int argc, char **argv); #endif +#define RTE_PORT_ALL (~(portid_t)0x0) + +#define RTE_TEST_RX_DESC_MAX 2048 +#define RTE_TEST_TX_DESC_MAX 2048 + +#define RTE_PORT_STOPPED (uint16_t)0 +#define RTE_PORT_STARTED (uint16_t)1 +#define RTE_PORT_CLOSED (uint16_t)2 +#define RTE_PORT_HANDLING (uint16_t)3 + /* * Default size of the mbuf data buffer to receive standard 1518-byte * Ethernet frames in a mono-segment memory buffer. @@ -133,6 +143,12 @@ struct rte_port { uint64_t rx_bad_l4_csum; /**< rx pkts with bad l4 checksum */ uint8_t tx_queue_stats_mapping_enabled; uint8_t rx_queue_stats_mapping_enabled; + volatile uint16_t port_status; /**< port started or not */ + uint8_t need_reconfig; /**< need reconfiguring port or not */ + uint8_t need_reconfig_queues; /**< need reconfiguring queues or not */ + uint8_t rss_flag; /**< enable rss or not */ + struct rte_eth_rxconf rx_conf; /**< rx configuration */ + struct rte_eth_txconf tx_conf; /**< tx configuration */ }; /** @@ -253,8 +269,10 @@ extern uint16_t nb_rxd; extern uint16_t nb_txd; extern uint16_t rx_free_thresh; +extern uint8_t rx_drop_en; extern uint16_t tx_free_thresh; extern uint16_t tx_rs_thresh; +extern uint32_t txq_flags; extern uint16_t mbuf_data_size; /**< Mbuf data space size. */ extern uint32_t param_total_num_mbufs; @@ -403,6 +421,11 @@ void set_nb_pkt_per_burst(uint16_t pkt_burst); void set_pkt_forwarding_mode(const char *fwd_mode); void start_packet_forwarding(int with_tx_first); void stop_packet_forwarding(void); +void init_port_config(void); +void start_port(portid_t pid); +void stop_port(portid_t pid); +void close_port(portid_t pid); +int all_ports_stopped(void); void pmd_test_exit(void); void fdir_add_signature_filter(portid_t port_id, uint8_t queue_id,