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 <[email protected]>
---
 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

Reply via email to