net/sfc: rename array of SW stats descriptions
[dpdk.git] / app / test-flow-perf / main.c
index d10fa3f..9be8edc 100644 (file)
@@ -34,6 +34,7 @@
 #include <rte_mbuf.h>
 #include <rte_ethdev.h>
 #include <rte_flow.h>
+#include <rte_mtr.h>
 
 #include "config.h"
 #include "flow_gen.h"
@@ -60,6 +61,7 @@ static bool dump_iterations;
 static bool delete_flag;
 static bool dump_socket_mem_flag;
 static bool enable_fwd;
+static bool unique_data;
 
 static struct rte_mempool *mbuf_mp;
 static uint32_t nb_lcores;
@@ -72,6 +74,8 @@ static uint32_t nb_lcores;
 #define LCORE_MODE_PKT    1
 #define LCORE_MODE_STATS  2
 #define MAX_STREAMS      64
+#define METER_CREATE     1
+#define METER_DELETE     2
 
 struct stream {
        int tx_port;
@@ -101,8 +105,8 @@ struct used_cpu_time {
 struct multi_cores_pool {
        uint32_t cores_count;
        uint32_t rules_count;
-       struct used_cpu_time create_meter;
-       struct used_cpu_time create_flow;
+       struct used_cpu_time meters_record;
+       struct used_cpu_time flows_record;
        int64_t last_alloc[RTE_MAX_LCORE];
        int64_t current_alloc[RTE_MAX_LCORE];
 } __rte_cache_aligned;
@@ -128,6 +132,8 @@ usage(char *progname)
        printf("  --enable-fwd: To enable packets forwarding"
                " after insertion\n");
        printf("  --portmask=N: hexadecimal bitmask of ports used\n");
+       printf("  --unique-data: flag to set using unique data for all"
+               " actions that support data, such as header modify and encap actions\n");
 
        printf("To set flow attributes:\n");
        printf("  --ingress: set ingress attribute in flows\n");
@@ -200,6 +206,7 @@ usage(char *progname)
        printf("  --set-ipv6-dscp: add set ipv6 dscp action to flow actions\n"
                "ipv6 dscp value to be set is random each flow\n");
        printf("  --flag: add flag action to flow actions\n");
+       printf("  --meter: add meter action to flow actions\n");
        printf("  --raw-encap=<data>: add raw encap action to flow actions\n"
                "Data is the data needed to be encaped\n"
                "Example: raw-encap=ether,ipv4,udp,vxlan\n");
@@ -528,6 +535,14 @@ args_parse(int argc, char **argv)
                        .map = &flow_actions[0],
                        .map_idx = &actions_idx
                },
+               {
+                       .str = "meter",
+                       .mask = FLOW_ACTION_MASK(
+                               RTE_FLOW_ACTION_TYPE_METER
+                       ),
+                       .map = &flow_actions[0],
+                       .map_idx = &actions_idx
+               },
                {
                        .str = "vxlan-encap",
                        .mask = FLOW_ACTION_MASK(
@@ -555,6 +570,7 @@ args_parse(int argc, char **argv)
                { "deletion-rate",              0, 0, 0 },
                { "dump-socket-mem",            0, 0, 0 },
                { "enable-fwd",                 0, 0, 0 },
+               { "unique-data",                0, 0, 0 },
                { "portmask",                   1, 0, 0 },
                { "cores",                      1, 0, 0 },
                /* Attributes */
@@ -607,6 +623,7 @@ args_parse(int argc, char **argv)
                { "set-ipv4-dscp",              0, 0, 0 },
                { "set-ipv6-dscp",              0, 0, 0 },
                { "flag",                       0, 0, 0 },
+               { "meter",                      0, 0, 0 },
                { "raw-encap",                  1, 0, 0 },
                { "raw-decap",                  1, 0, 0 },
                { "vxlan-encap",                0, 0, 0 },
@@ -626,7 +643,7 @@ args_parse(int argc, char **argv)
                case 0:
                        if (strcmp(lgopts[opt_idx].name, "help") == 0) {
                                usage(argv[0]);
-                               rte_exit(EXIT_SUCCESS, "Displayed help\n");
+                               exit(EXIT_SUCCESS);
                        }
 
                        if (strcmp(lgopts[opt_idx].name, "group") == 0) {
@@ -634,7 +651,7 @@ args_parse(int argc, char **argv)
                                if (n >= 0)
                                        flow_group = n;
                                else
-                                       rte_exit(EXIT_SUCCESS,
+                                       rte_exit(EXIT_FAILURE,
                                                "flow group should be >= 0\n");
                                printf("group %d / ", flow_group);
                        }
@@ -654,7 +671,7 @@ args_parse(int argc, char **argv)
                                if (n > 0)
                                        hairpin_queues_num = n;
                                else
-                                       rte_exit(EXIT_SUCCESS,
+                                       rte_exit(EXIT_FAILURE,
                                                "Hairpin queues should be > 0\n");
 
                                flow_actions[actions_idx++] =
@@ -667,7 +684,7 @@ args_parse(int argc, char **argv)
                                if (n > 0)
                                        hairpin_queues_num = n;
                                else
-                                       rte_exit(EXIT_SUCCESS,
+                                       rte_exit(EXIT_FAILURE,
                                                "Hairpin queues should be > 0\n");
 
                                flow_actions[actions_idx++] =
@@ -691,11 +708,9 @@ args_parse(int argc, char **argv)
                                                        break;
                                                }
                                                /* Reached last item with no match */
-                                               if (i == (RTE_DIM(flow_options) - 1)) {
-                                                       fprintf(stderr, "Invalid encap item: %s\n", token);
-                                                       usage(argv[0]);
-                                                       rte_exit(EXIT_SUCCESS, "Invalid encap item\n");
-                                               }
+                                               if (i == (RTE_DIM(flow_options) - 1))
+                                                       rte_exit(EXIT_FAILURE,
+                                                               "Invalid encap item: %s\n", token);
                                        }
                                        token = strtok(NULL, ",");
                                }
@@ -713,15 +728,13 @@ args_parse(int argc, char **argv)
                                        for (i = 0; i < RTE_DIM(flow_options); i++) {
                                                if (strcmp(flow_options[i].str, token) == 0) {
                                                        printf("%s,", token);
-                                                       encap_data |= flow_options[i].mask;
+                                                       decap_data |= flow_options[i].mask;
                                                        break;
                                                }
                                                /* Reached last item with no match */
-                                               if (i == (RTE_DIM(flow_options) - 1)) {
-                                                       fprintf(stderr, "Invalid decap item: %s\n", token);
-                                                       usage(argv[0]);
-                                                       rte_exit(EXIT_SUCCESS, "Invalid decap item\n");
-                                               }
+                                               if (i == (RTE_DIM(flow_options) - 1))
+                                                       rte_exit(EXIT_FAILURE,
+                                                               "Invalid decap item %s\n", token);
                                        }
                                        token = strtok(NULL, ",");
                                }
@@ -734,9 +747,9 @@ args_parse(int argc, char **argv)
                                if (n >= DEFAULT_RULES_BATCH)
                                        rules_batch = n;
                                else {
-                                       printf("\n\nrules_batch should be >= %d\n",
+                                       rte_exit(EXIT_FAILURE,
+                                               "rules_batch should be >= %d\n",
                                                DEFAULT_RULES_BATCH);
-                                       rte_exit(EXIT_SUCCESS, " ");
                                }
                        }
                        if (strcmp(lgopts[opt_idx].name,
@@ -745,13 +758,17 @@ args_parse(int argc, char **argv)
                                if (n >= (int) rules_batch)
                                        rules_count = n;
                                else {
-                                       printf("\n\nrules_count should be >= %d\n",
+                                       rte_exit(EXIT_FAILURE,
+                                               "rules_count should be >= %d\n",
                                                rules_batch);
                                }
                        }
                        if (strcmp(lgopts[opt_idx].name,
                                        "dump-iterations") == 0)
                                dump_iterations = true;
+                       if (strcmp(lgopts[opt_idx].name,
+                                       "unique-data") == 0)
+                               unique_data = true;
                        if (strcmp(lgopts[opt_idx].name,
                                        "deletion-rate") == 0)
                                delete_flag = true;
@@ -773,23 +790,23 @@ args_parse(int argc, char **argv)
                        if (strcmp(lgopts[opt_idx].name, "cores") == 0) {
                                n = atoi(optarg);
                                if ((int) rte_lcore_count() <= n) {
-                                       printf("\nError: you need %d cores to run on multi-cores\n"
+                                       rte_exit(EXIT_FAILURE,
+                                               "Error: you need %d cores to run on multi-cores\n"
                                                "Existing cores are: %d\n", n, rte_lcore_count());
-                                       rte_exit(EXIT_FAILURE, " ");
                                }
                                if (n <= RTE_MAX_LCORE && n > 0)
                                        mc_pool.cores_count = n;
                                else {
-                                       printf("Error: cores count must be > 0 "
-                                               " and < %d\n", RTE_MAX_LCORE);
-                                       rte_exit(EXIT_FAILURE, " ");
+                                       rte_exit(EXIT_FAILURE,
+                                               "Error: cores count must be > 0 and < %d\n",
+                                               RTE_MAX_LCORE);
                                }
                        }
                        break;
                default:
-                       fprintf(stderr, "Invalid option: %s\n", argv[optind]);
                        usage(argv[0]);
-                       rte_exit(EXIT_SUCCESS, "Invalid option\n");
+                       rte_exit(EXIT_FAILURE, "Invalid option: %s\n",
+                                       argv[optind]);
                        break;
                }
        }
@@ -879,6 +896,178 @@ print_rules_batches(double *cpu_time_per_batch)
        }
 }
 
+
+static inline int
+has_meter(void)
+{
+       int i;
+
+       for (i = 0; i < MAX_ACTIONS_NUM; i++) {
+               if (flow_actions[i] == 0)
+                       break;
+               if (flow_actions[i]
+                               & FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_METER))
+                       return 1;
+       }
+       return 0;
+}
+
+static void
+create_meter_rule(int port_id, uint32_t counter)
+{
+       int ret;
+       struct rte_mtr_params params;
+       uint32_t default_prof_id = 100;
+       struct rte_mtr_error error;
+
+       memset(&params, 0, sizeof(struct rte_mtr_params));
+       params.meter_enable = 1;
+       params.stats_mask = 0xffff;
+       params.use_prev_mtr_color = 0;
+       params.dscp_table = NULL;
+
+       /*create meter*/
+       params.meter_profile_id = default_prof_id;
+       ret = rte_mtr_create(port_id, counter, &params, 1, &error);
+       if (ret != 0) {
+               printf("Port %u create meter idx(%d) error(%d) message: %s\n",
+                       port_id, counter, error.type,
+                       error.message ? error.message : "(no stated reason)");
+               rte_exit(EXIT_FAILURE, "Error in creating meter\n");
+       }
+}
+
+static void
+destroy_meter_rule(int port_id, uint32_t counter)
+{
+       struct rte_mtr_error error;
+
+       if (rte_mtr_destroy(port_id, counter, &error)) {
+               printf("Port %u destroy meter(%d) error(%d) message: %s\n",
+                       port_id, counter, error.type,
+                       error.message ? error.message : "(no stated reason)");
+               rte_exit(EXIT_FAILURE, "Error in deleting meter rule\n");
+       }
+}
+
+static void
+meters_handler(int port_id, uint8_t core_id, uint8_t ops)
+{
+       uint64_t start_batch;
+       double cpu_time_used, insertion_rate;
+       int rules_count_per_core, rules_batch_idx;
+       uint32_t counter, start_counter = 0, end_counter;
+       double cpu_time_per_batch[MAX_BATCHES_COUNT] = { 0 };
+
+       rules_count_per_core = rules_count / mc_pool.cores_count;
+
+       if (core_id)
+               start_counter = core_id * rules_count_per_core;
+       end_counter = (core_id + 1) * rules_count_per_core;
+
+       cpu_time_used = 0;
+       start_batch = rte_get_timer_cycles();
+       for (counter = start_counter; counter < end_counter; counter++) {
+               if (ops == METER_CREATE)
+                       create_meter_rule(port_id, counter);
+               else
+                       destroy_meter_rule(port_id, counter);
+               /*
+                * Save the insertion rate for rules batch.
+                * Check if the insertion reached the rules
+                * patch counter, then save the insertion rate
+                * for this batch.
+                */
+               if (!((counter + 1) % rules_batch)) {
+                       rules_batch_idx = ((counter + 1) / rules_batch) - 1;
+                       cpu_time_per_batch[rules_batch_idx] =
+                               ((double)(rte_get_timer_cycles() - start_batch))
+                               / rte_get_timer_hz();
+                       cpu_time_used += cpu_time_per_batch[rules_batch_idx];
+                       start_batch = rte_get_timer_cycles();
+               }
+       }
+
+       /* Print insertion rates for all batches */
+       if (dump_iterations)
+               print_rules_batches(cpu_time_per_batch);
+
+       insertion_rate =
+               ((double) (rules_count_per_core / cpu_time_used) / 1000);
+
+       /* Insertion rate for all rules in one core */
+       printf(":: Port %d :: Core %d Meter %s :: start @[%d] - end @[%d],"
+               " use:%.02fs, rate:%.02fk Rule/Sec\n",
+               port_id, core_id, ops == METER_CREATE ? "create" : "delete",
+               start_counter, end_counter - 1,
+               cpu_time_used, insertion_rate);
+
+       if (ops == METER_CREATE)
+               mc_pool.meters_record.insertion[port_id][core_id]
+                       = cpu_time_used;
+       else
+               mc_pool.meters_record.deletion[port_id][core_id]
+                       = cpu_time_used;
+}
+
+static void
+destroy_meter_profile(void)
+{
+       struct rte_mtr_error error;
+       uint16_t nr_ports;
+       int port_id;
+
+       nr_ports = rte_eth_dev_count_avail();
+       for (port_id = 0; port_id < nr_ports; port_id++) {
+               /* If port outside portmask */
+               if (!((ports_mask >> port_id) & 0x1))
+                       continue;
+
+               if (rte_mtr_meter_profile_delete
+                       (port_id, DEFAULT_METER_PROF_ID, &error)) {
+                       printf("Port %u del profile error(%d) message: %s\n",
+                               port_id, error.type,
+                               error.message ? error.message : "(no stated reason)");
+                       rte_exit(EXIT_FAILURE, "Error: Destroy meter profile Failed!\n");
+               }
+       }
+}
+
+static void
+create_meter_profile(void)
+{
+       uint16_t nr_ports;
+       int ret, port_id;
+       struct rte_mtr_meter_profile mp;
+       struct rte_mtr_error error;
+
+       /*
+        *currently , only create one meter file for one port
+        *1 meter profile -> N meter rules -> N rte flows
+        */
+       memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+       nr_ports = rte_eth_dev_count_avail();
+       for (port_id = 0; port_id < nr_ports; port_id++) {
+               /* If port outside portmask */
+               if (!((ports_mask >> port_id) & 0x1))
+                       continue;
+
+               mp.alg = RTE_MTR_SRTCM_RFC2697;
+               mp.srtcm_rfc2697.cir = METER_CIR;
+               mp.srtcm_rfc2697.cbs = METER_CIR / 8;
+               mp.srtcm_rfc2697.ebs = 0;
+
+               ret = rte_mtr_meter_profile_add
+                       (port_id, DEFAULT_METER_PROF_ID, &mp, &error);
+               if (ret != 0) {
+                       printf("Port %u create Profile error(%d) message: %s\n",
+                               port_id, error.type,
+                               error.message ? error.message : "(no stated reason)");
+                       rte_exit(EXIT_FAILURE, "Error: Creation meter profile Failed!\n");
+               }
+       }
+}
+
 static inline void
 destroy_flows(int port_id, uint8_t core_id, struct rte_flow **flows_list)
 {
@@ -893,8 +1082,11 @@ destroy_flows(int port_id, uint8_t core_id, struct rte_flow **flows_list)
        int rules_count_per_core;
 
        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++;
 
-       start_batch = rte_rdtsc();
+       start_batch = rte_get_timer_cycles();
        for (i = 0; i < (uint32_t) rules_count_per_core; i++) {
                if (flows_list[i] == 0)
                        break;
@@ -902,7 +1094,7 @@ destroy_flows(int port_id, uint8_t core_id, struct rte_flow **flows_list)
                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");
+                       rte_exit(EXIT_FAILURE, "Error in deleting flow\n");
                }
 
                /*
@@ -912,12 +1104,12 @@ destroy_flows(int port_id, uint8_t core_id, struct rte_flow **flows_list)
                 * for this batch.
                 */
                if (!((i + 1) % rules_batch)) {
-                       end_batch = rte_rdtsc();
+                       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_tsc_hz();
+                       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_rdtsc();
+                       start_batch = rte_get_timer_cycles();
                }
        }
 
@@ -932,7 +1124,7 @@ destroy_flows(int port_id, uint8_t core_id, struct rte_flow **flows_list)
        printf(":: Port %d :: Core %d :: The time for deleting %d rules is %f seconds\n",
                port_id, core_id, rules_count_per_core, cpu_time_used);
 
-       mc_pool.create_flow.deletion[port_id][core_id] = cpu_time_used;
+       mc_pool.flows_record.deletion[port_id][core_id] = cpu_time_used;
 }
 
 static struct rte_flow **
@@ -941,6 +1133,7 @@ insert_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 first_flow_latency;
        double cpu_time_used;
        double insertion_rate;
        double cpu_time_per_batch[MAX_BATCHES_COUNT] = { 0 };
@@ -965,7 +1158,7 @@ insert_flows(int port_id, uint8_t core_id)
        flows_list = rte_zmalloc("flows_list",
                (sizeof(struct rte_flow *) * rules_count_per_core) + 1, 0);
        if (flows_list == NULL)
-               rte_exit(EXIT_FAILURE, "No Memory available!");
+               rte_exit(EXIT_FAILURE, "No Memory available!\n");
 
        cpu_time_used = 0;
        flow_index = 0;
@@ -981,30 +1174,40 @@ insert_flows(int port_id, uint8_t core_id)
                 */
                flow = generate_flow(port_id, 0, flow_attrs,
                        global_items, global_actions,
-                       flow_group, 0, 0, 0, 0, core_id, &error);
+                       flow_group, 0, 0, 0, 0, core_id, unique_data, &error);
 
                if (flow == NULL) {
                        print_flow_error(error);
-                       rte_exit(EXIT_FAILURE, "error in creating flow");
+                       rte_exit(EXIT_FAILURE, "Error in creating flow\n");
                }
                flows_list[flow_index++] = flow;
        }
 
-       start_batch = rte_rdtsc();
+       start_batch = rte_get_timer_cycles();
        for (counter = start_counter; counter < end_counter; counter++) {
                flow = generate_flow(port_id, flow_group,
                        flow_attrs, flow_items, flow_actions,
                        JUMP_ACTION_TABLE, counter,
                        hairpin_queues_num,
                        encap_data, decap_data,
-                       core_id, &error);
+                       core_id, unique_data, &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 (force_quit)
                        counter = end_counter;
 
                if (!flow) {
                        print_flow_error(error);
-                       rte_exit(EXIT_FAILURE, "error in creating flow");
+                       rte_exit(EXIT_FAILURE, "Error in creating flow\n");
                }
 
                flows_list[flow_index++] = flow;
@@ -1016,12 +1219,12 @@ insert_flows(int port_id, uint8_t core_id)
                 * for this batch.
                 */
                if (!((counter + 1) % rules_batch)) {
-                       end_batch = rte_rdtsc();
+                       end_batch = rte_get_timer_cycles();
                        delta = (double) (end_batch - start_batch);
                        rules_batch_idx = ((counter + 1) / rules_batch) - 1;
-                       cpu_time_per_batch[rules_batch_idx] = delta / rte_get_tsc_hz();
+                       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_rdtsc();
+                       start_batch = rte_get_timer_cycles();
                }
        }
 
@@ -1039,7 +1242,7 @@ insert_flows(int port_id, uint8_t core_id)
        printf(":: Port %d :: Core %d :: The time for creating %d in rules %f seconds\n",
                port_id, core_id, rules_count_per_core, cpu_time_used);
 
-       mc_pool.create_flow.insertion[port_id][core_id] = cpu_time_used;
+       mc_pool.flows_record.insertion[port_id][core_id] = cpu_time_used;
        return flows_list;
 }
 
@@ -1064,14 +1267,19 @@ flows_handler(uint8_t core_id)
 
                /* Insertion part. */
                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);
                if (flows_list == NULL)
                        rte_exit(EXIT_FAILURE, "Error: Insertion Failed!\n");
                mc_pool.current_alloc[core_id] = (int64_t)dump_socket_mem(stdout);
 
                /* Deletion part. */
-               if (delete_flag)
+               if (delete_flag) {
                        destroy_flows(port_id, core_id, flows_list);
+                       if (has_meter())
+                               meters_handler(port_id, core_id, METER_DELETE);
+               }
        }
 }
 
@@ -1230,9 +1438,14 @@ run_rte_flow_handler_cores(void *data __rte_unused)
        rte_eal_mp_wait_lcore();
 
        RTE_ETH_FOREACH_DEV(port) {
-
+               /* If port outside portmask */
+               if (!((ports_mask >> port) & 0x1))
+                       continue;
+               if (has_meter())
+                       dump_used_cpu_time("Meters:",
+                               port, &mc_pool.meters_record);
                dump_used_cpu_time("Flows:",
-                       port, &mc_pool.create_flow);
+                       port, &mc_pool.flows_record);
                dump_used_mem(port);
        }
 
@@ -1315,7 +1528,7 @@ packet_per_second_stats(void)
        old = rte_zmalloc("old",
                sizeof(struct lcore_info) * RTE_MAX_LCORE, 0);
        if (old == NULL)
-               rte_exit(EXIT_FAILURE, "No Memory available!");
+               rte_exit(EXIT_FAILURE, "No Memory available!\n");
 
        memcpy(old, lcore_infos,
                sizeof(struct lcore_info) * RTE_MAX_LCORE);
@@ -1661,6 +1874,7 @@ main(int argc, char **argv)
        delete_flag = false;
        dump_socket_mem_flag = false;
        flow_group = DEFAULT_GROUP;
+       unique_data = false;
 
        signal(SIGINT, signal_handler);
        signal(SIGTERM, signal_handler);
@@ -1676,15 +1890,18 @@ main(int argc, char **argv)
        if (nb_lcores <= 1)
                rte_exit(EXIT_FAILURE, "This app needs at least two cores\n");
 
-
        printf(":: Flows Count per port: %d\n\n", rules_count);
 
+       if (has_meter())
+               create_meter_profile();
        rte_eal_mp_remote_launch(run_rte_flow_handler_cores, NULL, CALL_MAIN);
 
        if (enable_fwd) {
                init_lcore_info();
                rte_eal_mp_remote_launch(start_forwarding, NULL, CALL_MAIN);
        }
+       if (has_meter() && delete_flag)
+               destroy_meter_profile();
 
        RTE_ETH_FOREACH_DEV(port) {
                rte_flow_flush(port, &error);