Support testing the flow tables query rate.

Signed-off-by: Sunyang Wu <sunyang...@jaguarmicro.com>

---
:: [Latency | query] All Cores :: Port 0 :: Total query rate -> 951.138132 K 
Rules/Sec
:: [Latency | query] All Cores :: Port 0 :: The time for query 10000 rules is 
0.010514 seconds
:: [Throughput | query] All Cores :: Port 0 :: Total query rate -> 951.138132 K 
Rules/Sec
:: [Throughput | query] All Cores :: Port 0 :: The average time for query 10000 
rules is 0.010514 seconds
---
 app/test-flow-perf/main.c | 118 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
index 07ddfe0e46..56dbee5ef3 100644
--- a/app/test-flow-perf/main.c
+++ b/app/test-flow-perf/main.c
@@ -75,6 +75,7 @@ static uint16_t dst_ports[RTE_MAX_ETHPORTS];
 static volatile bool force_quit;
 static bool dump_iterations;
 static bool delete_flag;
+static bool query_flag;
 static bool dump_socket_mem_flag;
 static bool enable_fwd;
 static bool unique_data;
@@ -129,6 +130,7 @@ static struct lcore_info lcore_infos[RTE_MAX_LCORE];
 struct used_cpu_time {
        double insertion[MAX_PORTS][RTE_MAX_LCORE];
        double deletion[MAX_PORTS][RTE_MAX_LCORE];
+       double query[MAX_PORTS][RTE_MAX_LCORE];
 };
 
 struct __rte_cache_aligned multi_cores_pool {
@@ -488,6 +490,7 @@ usage(char *progname)
                " iteration\n");
        printf("  --deletion-rate: Enable deletion rate"
                " calculations\n");
+       printf("  --query-rate: Enable query rate calculations\n");
        printf("  --dump-socket-mem: To dump all socket memory\n");
        printf("  --enable-fwd: To enable packets forwarding"
                " after insertion\n");
@@ -656,6 +659,7 @@ args_parse(int argc, char **argv)
                { "rules-batch",                1, 0, 0 },
                { "dump-iterations",            0, 0, 0 },
                { "deletion-rate",              0, 0, 0 },
+               { "query-rate",                 0, 0, 0 },
                { "dump-socket-mem",            0, 0, 0 },
                { "enable-fwd",                 0, 0, 0 },
                { "unique-data",                0, 0, 0 },
@@ -883,6 +887,9 @@ args_parse(int argc, char **argv)
                        if (strcmp(lgopts[opt_idx].name,
                                        "deletion-rate") == 0)
                                delete_flag = true;
+                       if (strcmp(lgopts[opt_idx].name,
+                           "query-rate") == 0)
+                               query_flag = true;
                        if (strcmp(lgopts[opt_idx].name,
                                        "dump-socket-mem") == 0)
                                dump_socket_mem_flag = true;
@@ -1375,6 +1382,81 @@ destroy_flows(int port_id, uint8_t core_id, struct 
rte_flow **flows_list)
        mc_pool.flows_record.deletion[port_id][core_id] = cpu_time_used;
 }
 
+static inline void
+query_flows(int port_id, uint8_t core_id, struct rte_flow **flows_list)
+{
+       struct rte_flow_error error;
+       clock_t start_batch, end_batch;
+       double cpu_time_used = 0;
+       double query_rate;
+       double cpu_time_per_batch[MAX_BATCHES_COUNT] = { 0 };
+       double delta;
+       uint32_t i;
+       int rules_batch_idx;
+       int rules_count_per_core;
+       union {
+               struct rte_flow_query_count count;
+               struct rte_flow_action_rss rss_conf;
+               struct rte_flow_query_age age;
+       } query;
+       struct rte_flow_action count_action[] = {
+                {
+                         .type = RTE_FLOW_ACTION_TYPE_COUNT,
+                         .conf = NULL,
+                },
+                {
+                         .type = RTE_FLOW_ACTION_TYPE_END,
+                },
+       };
+
+       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)
+                rules_count_per_core++;
+
+       memset(&query, 0, sizeof(query));
+       start_batch = rte_get_timer_cycles();
+       for (i = 0; i < (uint32_t)rules_count_per_core; i++) {
+                if (flows_list[i] == 0)
+                         break;
+
+                memset(&error, 0x33, sizeof(error));
+                if (rte_flow_query(port_id, flows_list[i],
+                                     count_action, &query, &error)) {
+                         print_flow_error(error);
+                         rte_exit(EXIT_FAILURE, "Error in deleting flow\n");
+                }
+
+                /*
+                 * Save the query rate for rules batch.
+                 * Check if the query reached the rules
+                 * patch counter, then save the query rate
+                 * for this batch.
+                 */
+                if (!((i + 1) % rules_batch)) {
+                         end_batch = rte_get_timer_cycles();
+                         delta = (double)(end_batch - start_batch);
+                         rules_batch_idx = ((i + 1) / rules_batch) - 1;
+                         cpu_time_per_batch[rules_batch_idx] = delta / 
rte_get_timer_hz();
+                         cpu_time_used += cpu_time_per_batch[rules_batch_idx];
+                         start_batch = rte_get_timer_cycles();
+                }
+       }
+
+       /* Print query rates for all batches */
+       if (dump_iterations)
+                print_rules_batches(cpu_time_per_batch);
+
+       /* query rate for all rules */
+       query_rate = ((double)(rules_count_per_core / cpu_time_used) / 1000);
+       printf(":: Port %d :: Core %d :: Rules query rate -> %f K Rule/Sec\n",
+               port_id, core_id, query_rate);
+       printf(":: Port %d :: Core %d :: The time for query %d rules is %f 
seconds\n",
+               port_id, core_id, rules_count_per_core, cpu_time_used);
+
+       mc_pool.flows_record.query[port_id][core_id] = cpu_time_used;
+}
+
 static struct rte_flow **
 insert_flows(int port_id, uint8_t core_id, uint16_t dst_port_id)
 {
@@ -1532,6 +1614,8 @@ flows_handler(uint8_t core_id)
                        if (has_meter())
                                meters_handler(port_id, core_id, METER_DELETE);
                }
+               if (query_flag)
+                       query_flows(port_id, core_id, flows_list);
        }
 }
 
@@ -1552,8 +1636,11 @@ dump_used_cpu_time(const char *item,
        double insertion_throughput_time;
        double deletion_latency_time;
        double deletion_throughput_time;
+       double query_latency_time;
+       double query_throughput_time;
        double insertion_latency, insertion_throughput;
        double deletion_latency, deletion_throughput;
+       double query_latency, query_throughput;
 
        /* Save first insertion/deletion rates from first thread.
         * Start comparing with all threads, if any thread used
@@ -1569,30 +1656,40 @@ dump_used_cpu_time(const char *item,
 
        insertion_latency_time = used_time->insertion[port][0];
        deletion_latency_time = used_time->deletion[port][0];
+       query_latency_time = used_time->query[port][0];
        insertion_throughput_time = used_time->insertion[port][0];
        deletion_throughput_time = used_time->deletion[port][0];
+       query_throughput_time = used_time->query[port][0];
 
        i = mc_pool.cores_count;
        while (i-- > 1) {
                insertion_throughput_time += used_time->insertion[port][i];
                deletion_throughput_time += used_time->deletion[port][i];
+               query_throughput_time += used_time->query[port][i];
                if (insertion_latency_time < used_time->insertion[port][i])
                        insertion_latency_time = used_time->insertion[port][i];
                if (deletion_latency_time < used_time->deletion[port][i])
                        deletion_latency_time = used_time->deletion[port][i];
+               if (query_throughput_time < used_time->query[port][i])
+                       query_throughput_time = used_time->query[port][i];
        }
 
        insertion_latency = ((double) (mc_pool.rules_count
                                / insertion_latency_time) / 1000);
        deletion_latency = ((double) (mc_pool.rules_count
                                / deletion_latency_time) / 1000);
+       query_latency = ((double)(mc_pool.rules_count
+                               / query_latency_time) / 1000);
 
        insertion_throughput_time /= mc_pool.cores_count;
        deletion_throughput_time /= mc_pool.cores_count;
+       query_throughput_time /= mc_pool.cores_count;
        insertion_throughput = ((double) (mc_pool.rules_count
                                / insertion_throughput_time) / 1000);
        deletion_throughput = ((double) (mc_pool.rules_count
                                / deletion_throughput_time) / 1000);
+       query_throughput = ((double)(mc_pool.rules_count
+                               / query_throughput_time) / 1000);
 
        /* Latency stats */
        printf("\n%s\n:: [Latency | Insertion] All Cores :: Port %d :: ",
@@ -1630,6 +1727,26 @@ dump_used_cpu_time(const char *item,
                printf("The average time for deleting %d rules is %f seconds\n",
                        mc_pool.rules_count, deletion_throughput_time);
        }
+
+       if (query_flag) {
+               /* Latency stats */
+               printf(":: [Latency | query] All Cores :: Port %d :: Total "
+                       "query rate -> %f K Rules/Sec\n",
+                       port, query_latency);
+               printf(":: [Latency | query] All Cores :: Port %d :: ",
+                       port);
+               printf("The time for querying %d rules is %f seconds\n",
+                       mc_pool.rules_count, query_latency_time);
+
+               /* Throughput stats */
+               printf(":: [Throughput | query] All Cores :: Port %d :: Total "
+                       "query rate -> %f K Rules/Sec\n",
+                       port, query_throughput);
+               printf(":: [Throughput | query] All Cores :: Port %d :: ",
+                       port);
+               printf("The average time for querying %d rules is %f seconds\n",
+                       mc_pool.rules_count, query_throughput_time);
+       }
 }
 
 static void
@@ -2120,6 +2237,7 @@ main(int argc, char **argv)
        rules_count = DEFAULT_RULES_COUNT;
        rules_batch = DEFAULT_RULES_BATCH;
        delete_flag = false;
+       query_flag = false;
        dump_socket_mem_flag = false;
        flow_group = DEFAULT_GROUP;
        unique_data = false;
-- 
2.19.0.rc0.windows.1

Reply via email to