* [PATCH] test-flow-perf: support measuring 2nd round rate
@ 2025-11-17 7:30 Bing Zhao
0 siblings, 0 replies; only message in thread
From: Bing Zhao @ 2025-11-17 7:30 UTC (permalink / raw)
To: viacheslavo, dev, rasland, wisamm
Cc: orika, dsosnowski, suanmingm, matan, thomas
In some driver, the flow table may start from a small size and
increase based on the rules number. The table resize may not reflact
the actual rules insertion rate due to the extra overhead.
Keeping 1 rule in the table and measuring the 2nd iteration would
be more accurate.
Signed-off-by: Bing Zhao <bingz@nvidia.com>
---
app/test-flow-perf/main.c | 103 ++++++++++++++++++++++++++++++--------
1 file changed, 83 insertions(+), 20 deletions(-)
diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
index a8876acf1f..06ebdc2d02 100644
--- a/app/test-flow-perf/main.c
+++ b/app/test-flow-perf/main.c
@@ -81,6 +81,7 @@ static bool enable_fwd;
static bool unique_data;
static bool policy_mtr;
static bool packet_mode;
+static bool no_rehash;
static uint8_t rx_queues_count;
static uint8_t tx_queues_count;
@@ -142,6 +143,9 @@ struct __rte_cache_aligned multi_cores_pool {
int64_t current_alloc[RTE_MAX_LCORE];
};
+/* In case the matcher is destroyed. */
+static struct rte_flow *placeholder_flows[RTE_MAX_ETHPORTS][RTE_MAX_LCORE];
+
static struct multi_cores_pool mc_pool = {
.cores_count = 1,
};
@@ -659,6 +663,7 @@ args_parse(int argc, char **argv)
{ "rules-count", 1, 0, 0 },
{ "rules-batch", 1, 0, 0 },
{ "dump-iterations", 0, 0, 0 },
+ { "second-run", 0, 0, 0 },
{ "deletion-rate", 0, 0, 0 },
{ "query-rate", 0, 0, 0 },
{ "dump-socket-mem", 0, 0, 0 },
@@ -864,6 +869,9 @@ args_parse(int argc, char **argv)
"rules-count") == 0) {
rules_count = atoi(optarg);
}
+ if (strcmp(lgopts[opt_idx].name, "second-run") == 0) {
+ no_rehash = true;
+ }
if (strcmp(lgopts[opt_idx].name, "random-priority") ==
0) {
end = NULL;
@@ -1333,21 +1341,27 @@ destroy_flows(int port_id, uint8_t core_id, struct rte_flow **flows_list)
double deletion_rate;
double cpu_time_per_batch[MAX_BATCHES_COUNT] = { 0 };
double delta;
- uint32_t i;
+ uint32_t i = 0;
int rules_batch_idx;
int rules_count_per_core;
+ memset(&error, 0x33, sizeof(error));
rules_count_per_core = rules_count / mc_pool.cores_count;
/* If group > 0 , should add 1 flow which created in group 0 */
- if (flow_group > 0 && core_id == 0)
+ if (flow_group > 0 && core_id == 0 && flows_list[i] != 0) {
+ if (rte_flow_destroy(port_id, flows_list[i], &error)) {
+ print_flow_error(error);
+ rte_exit(EXIT_FAILURE, "Error in deleting default jump flow\n");
+ }
+ i++;
rules_count_per_core++;
+ }
start_batch = rte_get_timer_cycles();
- for (i = 0; i < (uint32_t) rules_count_per_core; i++) {
+ for (; i < (uint32_t) rules_count_per_core; i++) {
if (flows_list[i] == 0)
break;
- memset(&error, 0x33, sizeof(error));
if (rte_flow_destroy(port_id, flows_list[i], &error)) {
print_flow_error(error);
rte_exit(EXIT_FAILURE, "Error in deleting flow\n");
@@ -1470,7 +1484,7 @@ insert_flows(int port_id, uint8_t core_id, uint16_t dst_port_id)
double cpu_time_per_batch[MAX_BATCHES_COUNT] = { 0 };
double delta;
uint32_t flow_index;
- uint32_t counter, start_counter = 0, end_counter;
+ uint32_t counter, start_counter = 0, end_counter, first_tick = 0;
uint64_t global_items[MAX_ITEMS_NUM] = { 0 };
uint64_t global_actions[MAX_ACTIONS_NUM] = { 0 };
int rules_batch_idx;
@@ -1525,15 +1539,8 @@ insert_flows(int port_id, uint8_t core_id, uint16_t dst_port_id)
core_id, rx_queues_count,
unique_data, max_priority, &error);
- if (!counter) {
- first_flow_latency = (double) (rte_get_timer_cycles() - start_batch);
- first_flow_latency /= rte_get_timer_hz();
- /* In millisecond */
- first_flow_latency *= 1000;
- printf(":: First Flow Latency :: Port %d :: First flow "
- "installed in %f milliseconds\n",
- port_id, first_flow_latency);
- }
+ if (!counter && !placeholder_flows[port_id][core_id])
+ first_tick = rte_get_timer_cycles();
if (force_quit)
counter = end_counter;
@@ -1561,6 +1568,29 @@ insert_flows(int port_id, uint8_t core_id, uint16_t dst_port_id)
}
}
+ if (first_tick) {
+ first_flow_latency = (double) (first_tick - start_batch);
+ first_flow_latency /= rte_get_timer_hz();
+ /* In millisecond */
+ first_flow_latency *= 1000;
+ printf(":: First Flow Latency :: Port %d :: First flow "
+ "installed in %f milliseconds\n",
+ port_id, first_flow_latency);
+ }
+
+ if (no_rehash && !placeholder_flows[port_id][core_id]) {
+ flow = generate_flow(port_id, flow_group, flow_attrs, flow_items,
+ flow_actions, JUMP_ACTION_TABLE, counter,
+ hairpin_queues_num, encap_data, decap_data,
+ dst_port_id, core_id, rx_queues_count,
+ unique_data, max_priority, &error);
+ if (!flow) {
+ print_flow_error(error);
+ rte_exit(EXIT_FAILURE, "Error in creating placeholder flow\n");
+ }
+ placeholder_flows[port_id][core_id] = flow;
+ }
+
/* Print insertion rates for all batches */
if (dump_iterations)
print_rules_batches(cpu_time_per_batch);
@@ -1579,6 +1609,21 @@ insert_flows(int port_id, uint8_t core_id, uint16_t dst_port_id)
return flows_list;
}
+static void
+cleanup_placeholder_flow(int port_id, uint8_t core_id)
+{
+ struct rte_flow_error error;
+
+ if (!placeholder_flows[port_id][core_id])
+ return;
+ memset(&error, 0x33, sizeof(error));
+ if (rte_flow_destroy(port_id, placeholder_flows[port_id][core_id], &error)) {
+ print_flow_error(error);
+ rte_exit(EXIT_FAILURE, "Error in deleting placeholder flow\n");
+ }
+ placeholder_flows[port_id][core_id] = NULL;
+}
+
static void
flows_handler(uint8_t core_id)
{
@@ -1613,17 +1658,36 @@ flows_handler(uint8_t core_id)
query_flows(port_id, core_id, flows_list);
/* Deletion part. */
+ if (delete_flag || no_rehash) {
+ destroy_flows(port_id, core_id, flows_list);
+ if (has_meter())
+ meters_handler(port_id, core_id, METER_DELETE);
+ rte_free(flows_list);
+ }
+
+ if (!no_rehash)
+ continue;
+
+ mc_pool.last_alloc[core_id] = (int64_t)dump_socket_mem(stdout);
+ if (has_meter())
+ meters_handler(port_id, core_id, METER_CREATE);
+ flows_list = insert_flows(port_id, core_id, dst_ports[port_idx++]);
+ if (flows_list == NULL)
+ rte_exit(EXIT_FAILURE, "Error: Insertion Failed!\n");
+ mc_pool.current_alloc[core_id] = (int64_t)dump_socket_mem(stdout);
+
if (delete_flag) {
destroy_flows(port_id, core_id, flows_list);
if (has_meter())
meters_handler(port_id, core_id, METER_DELETE);
+ rte_free(flows_list);
}
+ cleanup_placeholder_flow(port_id, core_id);
}
}
static void
-dump_used_cpu_time(const char *item,
- uint16_t port, struct used_cpu_time *used_time)
+dump_used_cpu_time(const char *item, uint16_t port, struct used_cpu_time *used_time)
{
uint32_t i;
/* Latency: total count of rte rules divided
@@ -1694,10 +1758,8 @@ dump_used_cpu_time(const char *item,
/ query_throughput_time) / 1000);
/* Latency stats */
- printf("\n%s\n:: [Latency | Insertion] All Cores :: Port %d :: ",
- item, port);
- printf("Total flows insertion rate -> %f K Rules/Sec\n",
- insertion_latency);
+ printf("\n%s\n:: [Latency | Insertion] All Cores :: Port %d :: ", item, port);
+ printf("Total flows insertion rate -> %f K Rules/Sec\n", insertion_latency);
printf(":: [Latency | Insertion] All Cores :: Port %d :: ", port);
printf("The time for creating %d rules is %f seconds\n",
mc_pool.rules_count, insertion_latency_time);
@@ -2296,6 +2358,7 @@ main(int argc, char **argv)
printf("Failed to stop device on port %u\n", port);
rte_eth_dev_close(port);
}
+ rte_eal_cleanup();
printf("\nBye ...\n");
return 0;
}
--
2.34.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-11-17 7:30 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-17 7:30 [PATCH] test-flow-perf: support measuring 2nd round rate Bing Zhao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).