diff --git a/0112-app-testpmd-support-packet-forwarding-for-specified-.patch b/0112-app-testpmd-support-packet-forwarding-for-specified-.patch new file mode 100644 index 0000000000000000000000000000000000000000..10ab12138871a734736a56ad5b7beab22f34f643 --- /dev/null +++ b/0112-app-testpmd-support-packet-forwarding-for-specified-.patch @@ -0,0 +1,531 @@ +From 4f0bae4fece6044aa160759feb5b2356a4139fbb Mon Sep 17 00:00:00 2001 +From: Dengdui Huang +Date: Thu, 19 Jun 2025 19:26:20 +0800 +Subject: [PATCH] app/testpmd: support packet forwarding for specified TCs + +Add command to set the TC number to packet forwarding +Usage: + set fwd-tc + +For example, packets forwarding only on TC0 and TC3, +use the following command: + set fwd-tc 1,0,0,1 + +Setting 0 means using the original DCB fwd +Usage: + set fwd-tc 0 + +Signed-off-by: Dengdui Huang +Signed-off-by: Donghua Huang +--- + app/test-pmd/cmdline.c | 169 +++++++++++++++++++++++++++++++++++++++++ + app/test-pmd/config.c | 151 +++++++++++++++++++++++++++++------- + app/test-pmd/testpmd.c | 77 ++++++++++--------- + app/test-pmd/testpmd.h | 4 + + 4 files changed, 341 insertions(+), 60 deletions(-) + +diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c +index 8ef116c..cb57016 100644 +--- a/app/test-pmd/cmdline.c ++++ b/app/test-pmd/cmdline.c +@@ -67,6 +67,9 @@ + #include "cmdline_tm.h" + #include "bpf_cmd.h" + ++unsigned int g_fwd_tc_map[RTE_ETH_DCB_NUM_TCS]; ++unsigned int g_fwd_tc_nb; ++ + static struct cmdline *testpmd_cl; + static cmdline_parse_ctx_t *main_ctx; + static TAILQ_HEAD(, testpmd_driver_commands) driver_commands_head = +@@ -361,6 +364,9 @@ static void cmd_help_long_parsed(void *parsed_result, + " Set the scheduling on timestamps" + " timings for the TXONLY mode\n\n" + ++ "set fwd-tc (tc0[,tc1]*)\n" ++ " Set the specified TC for packet forwarding.\n\n" ++ + "set corelist (x[,y]*)\n" + " Set the list of forwarding cores.\n\n" + +@@ -4170,6 +4176,168 @@ static cmdline_parse_inst_t cmd_set_txtimes = { + }, + }; + ++/* *** SET THE SPECIFIED TC FOR_PACKET FORWARDING *** */ ++struct cmd_set_fwd_tc_result { ++ cmdline_fixed_string_t set; ++ cmdline_fixed_string_t fwd_tc; ++ cmdline_fixed_string_t tcs; ++}; ++ ++/** ++ * Ensure that the DCB configuration is consistent across all forwarding ports. ++ */ ++static bool ++fwd_tc_check_dcb_info(void) ++{ ++ struct rte_eth_dcb_info dcb_info, compare_dcb_info; ++ unsigned int i, j, tc; ++ int ret; ++ ++ if (nb_fwd_ports == 1) ++ return true; ++ ++ ret = rte_eth_dev_get_dcb_info(fwd_ports_ids[0], &compare_dcb_info); ++ if (ret != 0) { ++ fprintf(stderr, "Get DCB info error, ret = %d\n", ret); ++ return false; ++ } ++ ++ for (i = 1; i < nb_fwd_ports; i++) { ++ ret = rte_eth_dev_get_dcb_info(fwd_ports_ids[i], &dcb_info); ++ if (ret != 0) { ++ fprintf(stderr, "Get DCB info error, ret = %d\n", ret); ++ return false; ++ } ++ ++ if (dcb_info.nb_tcs != compare_dcb_info.nb_tcs) { ++ fprintf(stderr, "Ports have different number of TCs\n"); ++ return false; ++ } ++ ++ for (j = 0; j < RTE_ETH_DCB_NUM_USER_PRIORITIES; j++) { ++ if (dcb_info.prio_tc[j] != compare_dcb_info.prio_tc[j]) { ++ fprintf(stderr, "Ports have different priority and TC mapping\n"); ++ return false; ++ } ++ } ++ ++ for (j = 0; j < RTE_ETH_MAX_VMDQ_POOL; j++) { ++ for (tc = 0; tc < RTE_ETH_DCB_NUM_TCS; tc++) { ++ if (dcb_info.tc_queue.tc_rxq[j][tc].base != ++ compare_dcb_info.tc_queue.tc_rxq[j][tc].base || ++ dcb_info.tc_queue.tc_rxq[j][tc].nb_queue != ++ compare_dcb_info.tc_queue.tc_rxq[j][tc].nb_queue) { ++ fprintf(stderr, ++ "Ports have different Rx queue and TC queue mapping\n"); ++ return false; ++ } ++ ++ if (dcb_info.tc_queue.tc_txq[j][tc].base != ++ compare_dcb_info.tc_queue.tc_txq[j][tc].base || ++ dcb_info.tc_queue.tc_txq[j][tc].nb_queue != ++ compare_dcb_info.tc_queue.tc_txq[j][tc].nb_queue) { ++ fprintf(stderr, ++ "Ports have different Tx queue and TC queue mapping\n"); ++ return false; ++ } ++ } ++ } ++ } ++ ++ return true; ++} ++ ++static void ++cmd_set_fwd_tc_parsed(void *parsed_result, ++ __rte_unused struct cmdline *cl, ++ __rte_unused void *data) ++{ ++ struct cmd_set_fwd_tc_result *res = parsed_result; ++ unsigned int fwd_tc_map[RTE_ETH_DCB_NUM_TCS]; ++ uint8_t tc_map_prio[RTE_ETH_DCB_NUM_TCS]; ++ struct rte_eth_dcb_info dcb_info; ++ unsigned int fwd_tc_nb; ++ unsigned int i; ++ int ret; ++ ++ if (test_done == 0) { ++ fprintf(stderr, "Please stop packet forwarding\n"); ++ return; ++ } ++ ++ if (!dcb_config) { ++ fprintf(stderr, "Not in DCB mode\n"); ++ return; ++ } ++ ++ fwd_tc_nb = parse_item_list(res->tcs, "TC list", RTE_ETH_DCB_NUM_TCS, ++ fwd_tc_map, 0); ++ if (fwd_tc_nb == 0) { ++ fprintf(stderr, "Bad arguments\n"); ++ return; ++ } ++ ++ for (i = 0; i < fwd_tc_nb; i++) { ++ if (fwd_tc_map[i] != 0) ++ break; ++ } ++ /* All 0s indicate that packet forwarding on the specified TC is disabled */ ++ if (i == fwd_tc_nb) { ++ g_fwd_tc_nb = 0; ++ memset(g_fwd_tc_map, 0, sizeof(g_fwd_tc_map)); ++ return; ++ } ++ ++ if (!fwd_tc_check_dcb_info()) ++ return; ++ ++ ret = rte_eth_dev_get_dcb_info(fwd_ports_ids[0], &dcb_info); ++ if (ret != 0) { ++ fprintf(stderr, "Get DCB info error, ret = %d\n", ret); ++ return; ++ } ++ ++ if (fwd_tc_nb > dcb_info.nb_tcs) { ++ fprintf(stderr, "TC number exceeds the number of port's TCs.\n"); ++ return; ++ } ++ ++ memset(tc_map_prio, 0, sizeof(tc_map_prio)); ++ for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) ++ tc_map_prio[dcb_info.prio_tc[i]] = 1; ++ for (i = 0; i < fwd_tc_nb; i++) { ++ if (fwd_tc_map[i] != 0 && tc_map_prio[i] == 0) { ++ fprintf(stderr, "The TC number does not map to any priority.\n"); ++ return; ++ } ++ } ++ ++ g_fwd_tc_nb = fwd_tc_nb; ++ memcpy(g_fwd_tc_map, fwd_tc_map, sizeof(g_fwd_tc_map)); ++} ++ ++static cmdline_parse_token_string_t cmd_set_fwd_tc_set = ++ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_tc_result, ++ set, "set"); ++static cmdline_parse_token_string_t cmd_set_fwd_tc_fwd_tc = ++ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_tc_result, ++ fwd_tc, "fwd-tc"); ++static cmdline_parse_token_string_t cmd_set_fwd_tc_tcs = ++ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_tc_result, ++ tcs, NULL); ++ ++static cmdline_parse_inst_t cmd_set_fwd_tc = { ++ .f = cmd_set_fwd_tc_parsed, ++ .data = NULL, ++ .help_str = "set fwd-tc : set the specified TC for packet forwarding", ++ .tokens = { ++ (void *)&cmd_set_fwd_tc_set, ++ (void *)&cmd_set_fwd_tc_fwd_tc, ++ (void *)&cmd_set_fwd_tc_tcs, ++ NULL, ++ }, ++}; ++ + /* *** ADD/REMOVE ALL VLAN IDENTIFIERS TO/FROM A PORT VLAN RX FILTER *** */ + struct cmd_rx_vlan_filter_all_result { + cmdline_fixed_string_t rx_vlan; +@@ -13152,6 +13320,7 @@ static cmdline_parse_ctx_t builtin_ctx[] = { + (cmdline_parse_inst_t *)&cmd_set_txpkts, + (cmdline_parse_inst_t *)&cmd_set_txsplit, + (cmdline_parse_inst_t *)&cmd_set_txtimes, ++ (cmdline_parse_inst_t *)&cmd_set_fwd_tc, + (cmdline_parse_inst_t *)&cmd_set_fwd_list, + (cmdline_parse_inst_t *)&cmd_set_fwd_mask, + (cmdline_parse_inst_t *)&cmd_set_fwd_mode, +diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c +index 2c4dedd..e20951b 100644 +--- a/app/test-pmd/config.c ++++ b/app/test-pmd/config.c +@@ -4844,6 +4844,125 @@ rss_fwd_config_setup(void) + } + } + ++static int ++dcb_fwd_reconfigure_ports(void) ++{ ++ struct rte_port *port; ++ portid_t pid; ++ int ret; ++ ++ /* ++ * The fwd_config_setup() is called when the port is RTE_PORT_STARTED ++ * or RTE_PORT_STOPPED. ++ * ++ * Re-configure ports to get updated mapping between tc and queue in ++ * case the queue number of the port is changed. Skip for started ports ++ * since modifying queue number and calling dev_configure need to stop ++ * ports first. ++ */ ++ for (pid = 0; pid < nb_fwd_ports; pid++) { ++ if (port_is_started(pid) == 1) ++ continue; ++ ++ port = &ports[pid]; ++ ret = rte_eth_dev_configure(pid, nb_rxq, nb_txq, ++ &port->dev_conf); ++ if (ret < 0) { ++ fprintf(stderr, ++ "Failed to re-configure port %d, ret = %d.\n", ++ pid, ret); ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * For the DCB forwarding test, can specify that only some TCs generate traffic. ++ */ ++static void ++spec_tx_fwd_config_setup(void) ++{ ++ struct rte_eth_dcb_info dcb_info, rxp_dcb_info, txp_dcb_info; ++ uint16_t nb_rx_queue, nb_tx_queue, stream_nb_on_tc; ++ uint16_t i, j, sm_id, total_streams = 0; ++ portid_t rxp, txp, port; ++ struct fwd_stream *fs; ++ queueid_t rxq, txq; ++ uint8_t tc; ++ int ret; ++ ++ if (dcb_fwd_reconfigure_ports() != 0) ++ return; ++ ++ for (port = 0; port < nb_fwd_ports; port++) { ++ ret = rte_eth_dev_get_dcb_info(fwd_ports_ids[port], &dcb_info); ++ if (ret != 0) { ++ fprintf(stderr, "Get DCB info error, ret = %d\n", ret); ++ return; ++ } ++ for (i = 0; i < RTE_ETH_MAX_VMDQ_POOL; i++) { ++ for (tc = 0; tc < g_fwd_tc_nb && tc < dcb_info.nb_tcs; tc++) { ++ if (g_fwd_tc_map[tc] == 0) ++ continue; ++ nb_rx_queue = dcb_info.tc_queue.tc_rxq[i][tc].nb_queue; ++ nb_tx_queue = dcb_info.tc_queue.tc_txq[i][tc].nb_queue; ++ stream_nb_on_tc = RTE_MIN(nb_rx_queue, nb_tx_queue); ++ total_streams += stream_nb_on_tc; ++ } ++ } ++ } ++ ++ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; ++ if (cur_fwd_config.nb_fwd_lcores > total_streams) ++ cur_fwd_config.nb_fwd_lcores = total_streams; ++ cur_fwd_config.nb_fwd_ports = nb_fwd_ports; ++ cur_fwd_config.nb_fwd_streams = (streamid_t) total_streams; ++ ++ /* reinitialize forwarding streams */ ++ (void)init_fwd_streams_by_nb(cur_fwd_config.nb_fwd_streams); ++ ++ setup_fwd_config_of_each_lcore(&cur_fwd_config); ++ ++ sm_id = 0; ++ for (rxp = 0; rxp < nb_fwd_ports; rxp++) { ++ ret = rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info); ++ if (ret != 0) { ++ fprintf(stderr, "Get DCB info error, ret = %d\n", ret); ++ return; ++ } ++ ++ txp = fwd_topology_tx_port_get(rxp); ++ ret = rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info); ++ if (ret != 0) { ++ fprintf(stderr, "Get DCB info error, ret = %d\n", ret); ++ return; ++ } ++ for (i = 0; i < RTE_ETH_MAX_VMDQ_POOL; i++) { ++ for (tc = 0; tc < dcb_info.nb_tcs; tc++) { ++ if (g_fwd_tc_map[tc] == 0) ++ continue; ++ nb_rx_queue = rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue; ++ nb_tx_queue = txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue; ++ rxq = rxp_dcb_info.tc_queue.tc_rxq[i][tc].base; ++ txq = txp_dcb_info.tc_queue.tc_txq[i][tc].base; ++ stream_nb_on_tc = RTE_MIN(nb_rx_queue, nb_tx_queue); ++ for (j = 0; j < stream_nb_on_tc; j++) { ++ fs = fwd_streams[sm_id]; ++ fs->tx_port = fwd_ports_ids[txp]; ++ fs->tx_queue = txq + j; ++ fs->rx_port = fwd_ports_ids[rxp]; ++ fs->rx_queue = rxq + j; ++ fs->peer_addr = fs->tx_port; ++ fs->retry_enabled = retry_enabled; ++ sm_id++; ++ } ++ } ++ } ++ } ++} ++ + static uint16_t + get_fwd_port_total_tc_num(void) + { +@@ -4879,34 +4998,10 @@ dcb_fwd_config_setup(void) + uint16_t nb_rx_queue, nb_tx_queue; + uint16_t i, j, k, sm_id = 0; + uint16_t total_tc_num; +- struct rte_port *port; + uint8_t tc = 0; +- portid_t pid; +- int ret; +- +- /* +- * The fwd_config_setup() is called when the port is RTE_PORT_STARTED +- * or RTE_PORT_STOPPED. +- * +- * Re-configure ports to get updated mapping between tc and queue in +- * case the queue number of the port is changed. Skip for started ports +- * since modifying queue number and calling dev_configure need to stop +- * ports first. +- */ +- for (pid = 0; pid < nb_fwd_ports; pid++) { +- if (port_is_started(pid) == 1) +- continue; + +- port = &ports[pid]; +- ret = rte_eth_dev_configure(pid, nb_rxq, nb_txq, +- &port->dev_conf); +- if (ret < 0) { +- fprintf(stderr, +- "Failed to re-configure port %d, ret = %d.\n", +- pid, ret); +- return; +- } +- } ++ if (dcb_fwd_reconfigure_ports() != 0) ++ return; + + cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; + cur_fwd_config.nb_fwd_ports = nb_fwd_ports; +@@ -5062,6 +5157,10 @@ fwd_config_setup(void) + "In DCB mode,the nb forwarding cores should be larger than 1.\n"); + return; + } ++ if (g_fwd_tc_nb) { ++ spec_tx_fwd_config_setup(); ++ return; ++ } + + dcb_fwd_config_setup(); + } else +diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c +index 9e4e99e..4f50fbc 100644 +--- a/app/test-pmd/testpmd.c ++++ b/app/test-pmd/testpmd.c +@@ -1829,12 +1829,53 @@ reconfig(portid_t new_port_id, unsigned socket_id) + init_port_config(); + } + ++int ++init_fwd_streams_by_nb(streamid_t streams_nb) ++{ ++ streamid_t sm_id; ++ /* 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 = streams_nb; ++ if (nb_fwd_streams) { ++ fwd_streams = rte_zmalloc("testpmd: fwd_streams", ++ sizeof(struct fwd_stream *) * nb_fwd_streams, ++ RTE_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), ++ RTE_CACHE_LINE_SIZE); ++ if (fwd_streams[sm_id] == NULL) ++ rte_exit(EXIT_FAILURE, "rte_zmalloc" ++ "(struct fwd_stream) failed\n"); ++ fwd_streams[sm_id]->disabled = false; ++ } ++ } ++ ++ return 0; ++} ++ + int + init_fwd_streams(void) + { + portid_t pid; + struct rte_port *port; +- streamid_t sm_id, nb_fwd_streams_new; ++ streamid_t nb_fwd_streams_new; + queueid_t q; + + /* set socket id according to numa or not */ +@@ -1883,40 +1924,8 @@ init_fwd_streams(void) + nb_fwd_streams_new = (streamid_t)(nb_ports * q); + 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; +- if (nb_fwd_streams) { +- fwd_streams = rte_zmalloc("testpmd: fwd_streams", +- sizeof(struct fwd_stream *) * nb_fwd_streams, +- RTE_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), +- RTE_CACHE_LINE_SIZE); +- if (fwd_streams[sm_id] == NULL) +- rte_exit(EXIT_FAILURE, "rte_zmalloc" +- "(struct fwd_stream) failed\n"); +- } +- } +- +- return 0; ++ return init_fwd_streams_by_nb(nb_fwd_streams_new); + } + + static void +diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h +index 9b10a9e..c6f1850 100644 +--- a/app/test-pmd/testpmd.h ++++ b/app/test-pmd/testpmd.h +@@ -676,6 +676,9 @@ extern struct rte_ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS]; + extern uint32_t burst_tx_delay_time; /**< Burst tx delay time(us) for mac-retry. */ + extern uint32_t burst_tx_retry_num; /**< Burst tx retry number for mac-retry. */ + ++extern unsigned int g_fwd_tc_map[RTE_ETH_DCB_NUM_TCS]; ++extern unsigned int g_fwd_tc_nb; ++ + #ifdef RTE_LIB_GRO + #define GRO_DEFAULT_ITEM_NUM_PER_FLOW 32 + #define GRO_DEFAULT_FLOW_NUM (RTE_GRO_MAX_BURST_ITEM_NUM / \ +@@ -937,6 +940,7 @@ void rxtx_config_display(void); + void fwd_config_setup(void); + void set_def_fwd_config(void); + void reconfig(portid_t new_port_id, unsigned socket_id); ++int init_fwd_streams_by_nb(streamid_t streams_nb); + int init_fwd_streams(void); + void update_fwd_ports(portid_t new_pid); + +-- +2.33.0 + diff --git a/0113-examples-l3fwd-power-support-specify-link-speed.patch b/0113-examples-l3fwd-power-support-specify-link-speed.patch new file mode 100644 index 0000000000000000000000000000000000000000..666f30b23ba8b890706a747a83ff06efdd026e29 --- /dev/null +++ b/0113-examples-l3fwd-power-support-specify-link-speed.patch @@ -0,0 +1,77 @@ +From 1406c515afcc5c49360e868fd62ee0d4b1be1bd9 Mon Sep 17 00:00:00 2001 +From: Dengdui Huang +Date: Mon, 4 Aug 2025 14:34:15 +0800 +Subject: [PATCH] examples/l3fwd-power: support specify link speed + +Currently, l3fwd-power starts in auto-negotiation mode, but it may fail +to link up when auto-negotiation is not supported. Therefore, it is +necessary to support starting with a specified speed for port. + +Additionally, this patch does not support changing the duplex mode. + So speeds like 10M, 100M are not configurable using this method. + +Signed-off-by: Dengdui Huang +Signed-off-by: Donghua Huang +--- + examples/l3fwd-power/main.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c +index 9c0dcd3..cb5e90c 100644 +--- a/examples/l3fwd-power/main.c ++++ b/examples/l3fwd-power/main.c +@@ -1503,6 +1503,7 @@ print_usage(const char *prgname) + " -U: set min/max frequency for uncore to maximum value\n" + " -i (frequency index): set min/max frequency for uncore to specified frequency index\n" + " --config (port,queue,lcore): rx queues configuration\n" ++ " --eth-link-speed: force link speed\n" + " --high-perf-cores CORELIST: list of high performance cores\n" + " --perf-config: similar as config, cores specified as indices" + " for bins containing high or regular performance cores\n" +@@ -1741,12 +1742,14 @@ parse_pmd_mgmt_config(const char *name) + #define CMD_LINE_OPT_PAUSE_DURATION "pause-duration" + #define CMD_LINE_OPT_SCALE_FREQ_MIN "scale-freq-min" + #define CMD_LINE_OPT_SCALE_FREQ_MAX "scale-freq-max" ++#define CMD_LINK_OPT_ETH_LINK_SPEED "eth-link-speed" + + /* Parse the argument given in the command line of the application */ + static int + parse_args(int argc, char **argv) + { + int opt, ret; ++ int speed_num; + char **argvopt; + int option_index; + char *prgname = argv[0]; +@@ -1765,6 +1768,7 @@ parse_args(int argc, char **argv) + {CMD_LINE_OPT_PAUSE_DURATION, 1, 0, 0}, + {CMD_LINE_OPT_SCALE_FREQ_MIN, 1, 0, 0}, + {CMD_LINE_OPT_SCALE_FREQ_MAX, 1, 0, 0}, ++ {CMD_LINK_OPT_ETH_LINK_SPEED, 1, 0, 0}, + {NULL, 0, 0, 0} + }; + +@@ -1935,6 +1939,20 @@ parse_args(int argc, char **argv) + scale_freq_max = parse_int(optarg); + } + ++ if (!strncmp(lgopts[option_index].name, ++ CMD_LINK_OPT_ETH_LINK_SPEED, ++ sizeof(CMD_LINK_OPT_ETH_LINK_SPEED))) { ++ speed_num = atoi(optarg); ++ if ((speed_num == RTE_ETH_SPEED_NUM_10M) || ++ (speed_num == RTE_ETH_SPEED_NUM_100M)) { ++ fprintf(stderr, "Unsupported fixed speed\n"); ++ print_usage(prgname); ++ return -1; ++ } ++ if (speed_num >= 0 && rte_eth_speed_bitflag(speed_num, 0) > 0) ++ port_conf.link_speeds = rte_eth_speed_bitflag(speed_num, 0); ++ } ++ + break; + + default: +-- +2.33.0 + diff --git a/0114-app-testpmd-fix-L4-protocol-retrieval-from-L3-header.patch b/0114-app-testpmd-fix-L4-protocol-retrieval-from-L3-header.patch new file mode 100644 index 0000000000000000000000000000000000000000..7aeff721de4e65702d022137f3e0069ca81e9c8c --- /dev/null +++ b/0114-app-testpmd-fix-L4-protocol-retrieval-from-L3-header.patch @@ -0,0 +1,97 @@ +From 112699748720de70221de04752a1cd04d9d261e8 Mon Sep 17 00:00:00 2001 +From: Dengdui Huang +Date: Wed, 27 Aug 2025 09:46:13 +0800 +Subject: [PATCH] app/testpmd: fix L4 protocol retrieval from L3 header + +Currently, when retrieving the L4 protocol from the L3 header, +the case of IPv6 with extension headers is not handled correctly. +This patch fixes it. + +Fixes: 76730c7b9b5a ("app/testpmd: use packet type parsing API") +Cc: stable@dpdk.org + +Signed-off-by: Dengdui Huang +Signed-off-by: Donghua Huang +--- + app/test-pmd/csumonly.c | 39 ++++++++++++++++----------------------- + 1 file changed, 16 insertions(+), 23 deletions(-) + +diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c +index 4891cb8..35726f5 100644 +--- a/app/test-pmd/csumonly.c ++++ b/app/test-pmd/csumonly.c +@@ -536,20 +536,8 @@ get_tunnel_ol_flags_by_ptype(uint32_t ptype) + } + } + +-static void +-parse_inner_l4_proto(void *outer_l3_hdr, +- struct testpmd_offload_info *info) +-{ +- struct rte_ipv4_hdr *ipv4_hdr = outer_l3_hdr; +- struct rte_ipv6_hdr *ipv6_hdr = outer_l3_hdr; +- if (info->ethertype == _htons(RTE_ETHER_TYPE_IPV4)) +- info->l4_proto = ipv4_hdr->next_proto_id; +- else +- info->l4_proto = ipv6_hdr->proto; +-} +- + static uint8_t +-parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype) ++parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype, bool parse_inner) + { + int frag = 0, ret; + +@@ -568,16 +556,19 @@ parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype) + if (unlikely(ip6h == NULL)) + return 0; + +- if ((ptype & RTE_PTYPE_INNER_L3_MASK) == +- RTE_PTYPE_INNER_L3_IPV6_EXT) { +- ret = rte_net_skip_ip6_ext(ip6h->proto, m, &off, &frag); +- if (ret < 0) +- return 0; +- return ret; +- } ++ if (!parse_inner && (ptype & RTE_PTYPE_L3_MASK) != RTE_PTYPE_L3_IPV6_EXT) ++ return ip6h->proto; ++ ++ if (parse_inner && (ptype & RTE_PTYPE_INNER_L3_MASK) != RTE_PTYPE_INNER_L3_IPV6_EXT) ++ return ip6h->proto; + +- return ip6h->proto; ++ off += sizeof(struct rte_ipv6_hdr); ++ ret = rte_net_skip_ip6_ext(ip6h->proto, m, &off, &frag); ++ if (ret < 0) ++ return 0; ++ return ret; + } ++ + return 0; + } + +@@ -704,7 +695,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) + info.l4_len = hdr_lens.l4_len; + info.ethertype = get_ethertype_by_ptype(eth_hdr, + ptype & RTE_PTYPE_L3_MASK); +- info.l4_proto = parse_l4_proto(m, info.l2_len, ptype); ++ info.l4_proto = parse_l4_proto(m, info.l2_len, ptype, false); + + l3_hdr = (char *)eth_hdr + info.l2_len; + /* check if it's a supported tunnel */ +@@ -722,9 +713,11 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) + } + /* update l3_hdr and outer_l3_hdr if a tunnel was parsed */ + if (info.is_tunnel) { ++ uint16_t l3_off = info.outer_l2_len + info.outer_l3_len + info.l2_len; ++ + outer_l3_hdr = l3_hdr; + l3_hdr = (char *)l3_hdr + info.outer_l3_len + info.l2_len; +- parse_inner_l4_proto(l3_hdr, &info); ++ info.l4_proto = parse_l4_proto(m, l3_off, ptype, true); + } + /* step 2: depending on user command line configuration, + * recompute checksum either in software or flag the +-- +2.33.0 + diff --git a/0115-net-hns3-print-invalid-mac-address-from-firmware.patch b/0115-net-hns3-print-invalid-mac-address-from-firmware.patch new file mode 100644 index 0000000000000000000000000000000000000000..122a05fb68d3ae11cb2007923204cd8f8c9691a4 --- /dev/null +++ b/0115-net-hns3-print-invalid-mac-address-from-firmware.patch @@ -0,0 +1,37 @@ +From fa6e29e12934449d2f214ad239a9e4cb710c417c Mon Sep 17 00:00:00 2001 +From: Xingui Yang +Date: Mon, 8 Sep 2025 18:49:16 +0800 +Subject: [PATCH] net/hns3: print invalid mac address from firmware + +The default mac address from the firmware is usually valid. Print the +default mac address when it's invalid to locate the problem. + +Signed-off-by: Xingui Yang +Signed-off-by: Donghua Huang +--- + drivers/net/hns3/hns3_common.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c +index dc70bf3..9088616 100644 +--- a/drivers/net/hns3/hns3_common.c ++++ b/drivers/net/hns3/hns3_common.c +@@ -723,12 +723,12 @@ hns3_init_mac_addrs(struct rte_eth_dev *dev) + eth_addr = (struct rte_ether_addr *)hw->mac.mac_addr; + if (!hns->is_vf) { + if (!rte_is_valid_assigned_ether_addr(eth_addr)) { ++ hns3_warn(hw, "MAC address " RTE_ETHER_ADDR_PRT_FMT " from firmware is invalid", ++ RTE_ETHER_ADDR_BYTES(eth_addr)); + rte_eth_random_addr(hw->mac.mac_addr); + hns3_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE, + (struct rte_ether_addr *)hw->mac.mac_addr); +- hns3_warn(hw, "default mac_addr from firmware is an invalid " +- "unicast address, using random MAC address %s", +- mac_str); ++ hns3_warn(hw, "using random MAC address %s", mac_str); + } + } else { + /* +-- +2.33.0 + diff --git a/dpdk.spec b/dpdk.spec index a70990791d12af45569c4cf2591f27c2bfad9de1..951652a644bce58327a8d1d892b68b0a02f6a4c8 100644 --- a/dpdk.spec +++ b/dpdk.spec @@ -11,7 +11,7 @@ Name: dpdk Version: 23.11 -Release: 36 +Release: 37 URL: http://dpdk.org Source: https://fast.dpdk.org/rel/dpdk-%{version}.tar.xz @@ -144,6 +144,10 @@ Patch6108: 0108-config-arm-adapt-RTE_MAX_NUMA_NODES-to-16.patch Patch6109: 0109-net-hns3-fix-inconsistent-lock.patch Patch6110: 0110-net-hns3-fix-overwrite-mbuf-in-vector-path.patch Patch6111: 0111-net-hns3-fix-unrelease-VLAN-resource-when-init-fail.patch +Patch6112: 0112-app-testpmd-support-packet-forwarding-for-specified-.patch +Patch6113: 0113-examples-l3fwd-power-support-specify-link-speed.patch +Patch6114: 0114-app-testpmd-fix-L4-protocol-retrieval-from-L3-header.patch +Patch6115: 0115-net-hns3-print-invalid-mac-address-from-firmware.patch BuildRequires: meson BuildRequires: python3-pyelftools @@ -348,6 +352,13 @@ fi /usr/sbin/depmod %changelog +* Wed Oct 29 2025 huangdonghua - 23.11-37 + Add TC Setting, Set Port Speed, Fix IPv6 Handling, Print MAC: + - app/testpmd: support packet forwarding for specified TCs + - examples/l3fwd-power: support specify link speed + - app/testpmd: fix L4 protocol retrieval from L3 header + - net/hns3: print invalid mac address from firmware + * Fri Sep 19 2025 huangdonghua - 23.11-36 Unify locks, fix Rx path and resource release: - net/hns3: fix inconsistent lock