app/testpmd: support policy actions per color
authorHaifei Luo <haifeil@nvidia.com>
Tue, 20 Apr 2021 14:04:50 +0000 (17:04 +0300)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 21 Apr 2021 10:22:18 +0000 (12:22 +0200)
Add the create/del policy CLIs to support actions per color.
The CLIs are:
Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
y_actions (actions) r_actions (actions)
Delete:  del port meter policy (port_id) (policy_id)

Examples:
testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
r_actions drop / end
testpmd> del port meter policy 0 1

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
app/test-pmd/cmdline.c
app/test-pmd/cmdline_flow.c
app/test-pmd/cmdline_mtr.c
app/test-pmd/cmdline_mtr.h
app/test-pmd/config.c
app/test-pmd/testpmd.h
doc/guides/rel_notes/release_21_05.rst
doc/guides/testpmd_app_ug/testpmd_funcs.rst

index 21c2c1d..11f9c01 100644 (file)
@@ -705,9 +705,8 @@ static void cmd_help_long_parsed(void *parsed_result,
                        "del port meter profile (port_id) (profile_id)\n"
                        "    meter profile delete\n\n"
 
-                       "create port meter (port_id) (mtr_id) (profile_id) (meter_enable)\n"
-                       "(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
-                       "(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+                       "create port meter (port_id) (mtr_id) (profile_id) (policy_id) (meter_enable)\n"
+                       "(stats_mask) (shared) (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
                        "(dscp_tbl_entry63)]\n"
                        "    meter create\n\n"
 
@@ -720,6 +719,13 @@ static void cmd_help_long_parsed(void *parsed_result,
                        "del port meter (port_id) (mtr_id)\n"
                        "    meter delete\n\n"
 
+                       "add port meter policy (port_id) (policy_id) g_actions (actions)\n"
+                       "y_actions (actions) r_actions (actions)\n"
+                       "    meter policy add\n\n"
+
+                       "del port meter policy (port_id) (policy_id)\n"
+                       "    meter policy delete\n\n"
+
                        "set port meter profile (port_id) (mtr_id) (profile_id)\n"
                        "    meter update meter profile\n\n"
 
@@ -17425,6 +17431,7 @@ cmdline_parse_ctx_t main_ctx[] = {
        (cmdline_parse_inst_t *)&cmd_enable_port_meter,
        (cmdline_parse_inst_t *)&cmd_disable_port_meter,
        (cmdline_parse_inst_t *)&cmd_del_port_meter,
+       (cmdline_parse_inst_t *)&cmd_del_port_meter_policy,
        (cmdline_parse_inst_t *)&cmd_set_port_meter_profile,
        (cmdline_parse_inst_t *)&cmd_set_port_meter_dscp_table,
        (cmdline_parse_inst_t *)&cmd_set_port_meter_stats_mask,
index 3c4650b..5947341 100644 (file)
@@ -55,6 +55,10 @@ enum index {
        GROUP_ID,
        PRIORITY_LEVEL,
        INDIRECT_ACTION_ID,
+       POLICY_ID,
+
+       /* TOP-level command. */
+       ADD,
 
        /* Top-level command. */
        SET,
@@ -299,6 +303,9 @@ enum index {
        ITEM_INTEGRITY_LEVEL,
        ITEM_INTEGRITY_VALUE,
        ITEM_CONNTRACK,
+       ITEM_POL_PORT,
+       ITEM_POL_METER,
+       ITEM_POL_POLICY,
 
        /* Validate/create actions. */
        ACTIONS,
@@ -441,6 +448,9 @@ enum index {
        ACTION_CONNTRACK_UPDATE,
        ACTION_CONNTRACK_UPDATE_DIR,
        ACTION_CONNTRACK_UPDATE_CTX,
+       ACTION_POL_G,
+       ACTION_POL_Y,
+       ACTION_POL_R,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -826,6 +836,9 @@ struct buffer {
                struct {
                        int destroy;
                } aged; /**< Aged arguments. */
+               struct {
+                       uint32_t policy_id;
+               } policy;/**< Policy arguments. */
        } args; /**< Command arguments. */
 };
 
@@ -1848,6 +1861,9 @@ static int parse_ia_destroy(struct context *ctx, const struct token *token,
 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
                           const char *str, unsigned int len, void *buf,
                           unsigned int size);
+static int parse_mp(struct context *, const struct token *,
+                   const char *, unsigned int,
+                   void *, unsigned int);
 static int comp_none(struct context *, const struct token *,
                     unsigned int, char *, unsigned int);
 static int comp_boolean(struct context *, const struct token *,
@@ -1877,7 +1893,7 @@ static const struct token token_list[] = {
        [ZERO] = {
                .name = "ZERO",
                .help = "null entry, abused as the entry point",
-               .next = NEXT(NEXT_ENTRY(FLOW)),
+               .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
        },
        [END] = {
                .name = "",
@@ -1999,6 +2015,13 @@ static const struct token token_list[] = {
                .call = parse_int,
                .comp = comp_none,
        },
+       [POLICY_ID] = {
+               .name = "{policy_id}",
+               .type = "POLCIY_ID",
+               .help = "policy id",
+               .call = parse_int,
+               .comp = comp_none,
+       },
        /* Top-level command. */
        [FLOW] = {
                .name = "flow",
@@ -4669,6 +4692,54 @@ static const struct token token_list[] = {
                .help = "specify action to create indirect handle",
                .next = NEXT(next_action),
        },
+       [ACTION_POL_G] = {
+               .name = "g_actions",
+               .help = "submit a list of associated actions for green",
+               .next = NEXT(next_action),
+               .call = parse_mp,
+       },
+       [ACTION_POL_Y] = {
+               .name = "y_actions",
+               .help = "submit a list of associated actions for yellow",
+               .next = NEXT(next_action),
+       },
+       [ACTION_POL_R] = {
+               .name = "r_actions",
+               .help = "submit a list of associated actions for red",
+               .next = NEXT(next_action),
+       },
+
+       /* Top-level command. */
+       [ADD] = {
+               .name = "add",
+               .type = "port meter policy {port_id} {arg}",
+               .help = "add port meter policy",
+               .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
+               .call = parse_init,
+       },
+       /* Sub-level commands. */
+       [ITEM_POL_PORT] = {
+               .name = "port",
+               .help = "add port meter policy",
+               .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
+       },
+       [ITEM_POL_METER] = {
+               .name = "meter",
+               .help = "add port meter policy",
+               .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
+       },
+       [ITEM_POL_POLICY] = {
+               .name = "policy",
+               .help = "add port meter policy",
+               .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
+                               NEXT_ENTRY(ACTION_POL_Y),
+                               NEXT_ENTRY(ACTION_POL_G),
+                               NEXT_ENTRY(POLICY_ID),
+                               NEXT_ENTRY(PORT_ID)),
+               .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
+                               ARGS_ENTRY(struct buffer, port)),
+               .call = parse_mp,
+       },
 };
 
 /** Remove and return last entry from argument stack. */
@@ -4947,6 +5018,47 @@ parse_ia_destroy(struct context *ctx, const struct token *token,
        return len;
 }
 
+/** Parse tokens for meter policy action commands. */
+static int
+parse_mp(struct context *ctx, const struct token *token,
+       const char *str, unsigned int len,
+       void *buf, unsigned int size)
+{
+       struct buffer *out = buf;
+
+       /* Token name must match. */
+       if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+               return -1;
+       /* Nothing else to do if there is no buffer. */
+       if (!out)
+               return len;
+       if (!out->command) {
+               if (ctx->curr != ITEM_POL_POLICY)
+                       return -1;
+               if (sizeof(*out) > size)
+                       return -1;
+               out->command = ctx->curr;
+               ctx->objdata = 0;
+               ctx->object = out;
+               ctx->objmask = NULL;
+               out->args.vc.data = (uint8_t *)out + size;
+               return len;
+       }
+       switch (ctx->curr) {
+       case ACTION_POL_G:
+               out->args.vc.actions =
+                       (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+                                       sizeof(double));
+               out->command = ctx->curr;
+               ctx->objdata = 0;
+               ctx->object = out;
+               ctx->objmask = NULL;
+               return len;
+       default:
+               return -1;
+       }
+}
+
 /** Parse tokens for validate/create commands. */
 static int
 parse_vc(struct context *ctx, const struct token *token,
@@ -7876,6 +7988,10 @@ cmd_flow_parsed(const struct buffer *in)
        case TUNNEL_LIST:
                port_flow_tunnel_list(in->port);
                break;
+       case ACTION_POL_G:
+               port_meter_policy_add(in->port, in->args.policy.policy_id,
+                                       in->args.vc.actions);
+               break;
        default:
                break;
        }
index aa454af..eff2473 100644 (file)
@@ -37,6 +37,8 @@ print_err_msg(struct rte_mtr_error *error)
                [RTE_MTR_ERROR_TYPE_STATS] = "stats",
                [RTE_MTR_ERROR_TYPE_SHARED]
                        = "shared meter",
+               [RTE_MTR_ERROR_TYPE_METER_POLICY_ID] = "meter policy id",
+               [RTE_MTR_ERROR_TYPE_METER_POLICY] = "meter policy null",
        };
 
        const char *errstr;
@@ -56,6 +58,12 @@ print_err_msg(struct rte_mtr_error *error)
                error->type);
 }
 
+void
+print_mtr_err_msg(struct rte_mtr_error *error)
+{
+       print_err_msg(error);
+}
+
 static int
 parse_uint(uint64_t *value, const char *str)
 {
@@ -705,6 +713,7 @@ struct cmd_create_port_meter_result {
        uint16_t port_id;
        uint32_t mtr_id;
        uint32_t profile_id;
+       uint32_t policy_id;
        cmdline_fixed_string_t meter_enable;
        cmdline_fixed_string_t g_action;
        cmdline_fixed_string_t y_action;
@@ -732,6 +741,9 @@ cmdline_parse_token_num_t cmd_create_port_meter_mtr_id =
 cmdline_parse_token_num_t cmd_create_port_meter_profile_id =
        TOKEN_NUM_INITIALIZER(
                struct cmd_create_port_meter_result, profile_id, RTE_UINT32);
+cmdline_parse_token_num_t cmd_create_port_meter_policy_id =
+       TOKEN_NUM_INITIALIZER(
+               struct cmd_create_port_meter_result, policy_id, RTE_UINT32);
 cmdline_parse_token_string_t cmd_create_port_meter_meter_enable =
        TOKEN_STRING_INITIALIZER(struct cmd_create_port_meter_result,
                meter_enable, "yes#no");
@@ -775,7 +787,7 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
        /* Meter params */
        memset(&params, 0, sizeof(struct rte_mtr_params));
        params.meter_profile_id = res->profile_id;
-
+       params.meter_policy_id = res->policy_id;
        /* Parse meter input color string params */
        ret = parse_meter_color_str(c_str, &use_prev_meter_color, &dscp_table);
        if (ret) {
@@ -790,7 +802,6 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
                params.meter_enable = 1;
        else
                params.meter_enable = 0;
-
        params.stats_mask = res->statistics_mask;
 
        ret = rte_mtr_create(port_id, mtr_id, &params, shared, &error);
@@ -805,7 +816,6 @@ cmdline_parse_inst_t cmd_create_port_meter = {
        .f = cmd_create_port_meter_parsed,
        .data = NULL,
        .help_str = "create port meter <port_id> <mtr_id> <profile_id> <meter_enable>(yes|no) "
-               "<g_action>(R|Y|G|D) <y_action>(R|Y|G|D) <r_action>(R|Y|G|D) "
                "<stats_mask> <shared> <use_pre_meter_color> "
                "[<dscp_tbl_entry0> <dscp_tbl_entry1> ...<dscp_tbl_entry63>]",
        .tokens = {
@@ -815,10 +825,8 @@ cmdline_parse_inst_t cmd_create_port_meter = {
                (void *)&cmd_create_port_meter_port_id,
                (void *)&cmd_create_port_meter_mtr_id,
                (void *)&cmd_create_port_meter_profile_id,
+               (void *)&cmd_create_port_meter_policy_id,
                (void *)&cmd_create_port_meter_meter_enable,
-               (void *)&cmd_create_port_meter_g_action,
-               (void *)&cmd_create_port_meter_y_action,
-               (void *)&cmd_create_port_meter_r_action,
                (void *)&cmd_create_port_meter_statistics_mask,
                (void *)&cmd_create_port_meter_shared,
                (void *)&cmd_create_port_meter_input_color,
@@ -948,6 +956,71 @@ cmdline_parse_inst_t cmd_disable_port_meter = {
        },
 };
 
+/* *** Delete Port Meter Policy Object *** */
+struct cmd_del_port_meter_policy_result {
+       cmdline_fixed_string_t del;
+       cmdline_fixed_string_t port;
+       cmdline_fixed_string_t meter;
+       cmdline_fixed_string_t policy;
+       uint16_t port_id;
+       uint32_t policy_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_policy_del =
+       TOKEN_STRING_INITIALIZER(
+               struct cmd_del_port_meter_policy_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_policy_port =
+       TOKEN_STRING_INITIALIZER(
+               struct cmd_del_port_meter_policy_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_policy_meter =
+       TOKEN_STRING_INITIALIZER(
+               struct cmd_del_port_meter_policy_result, meter, "meter");
+cmdline_parse_token_string_t cmd_del_port_meter_policy_policy =
+       TOKEN_STRING_INITIALIZER(
+               struct cmd_del_port_meter_policy_result, policy, "policy");
+cmdline_parse_token_num_t cmd_del_port_meter_policy_port_id =
+       TOKEN_NUM_INITIALIZER(
+               struct cmd_del_port_meter_policy_result, port_id, RTE_UINT16);
+cmdline_parse_token_num_t cmd_del_port_meter_policy_policy_id =
+       TOKEN_NUM_INITIALIZER(
+               struct cmd_del_port_meter_policy_result, policy_id, RTE_UINT32);
+
+static void cmd_del_port_meter_policy_parsed(void *parsed_result,
+       __rte_unused struct cmdline *cl,
+       __rte_unused void *data)
+{
+       struct cmd_del_port_meter_policy_result *res = parsed_result;
+       struct rte_mtr_error error;
+       uint32_t policy_id = res->policy_id;
+       uint16_t port_id = res->port_id;
+       int ret;
+
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
+               return;
+
+       /* Delete Meter Policy*/
+       ret = rte_mtr_meter_policy_delete(port_id, policy_id, &error);
+       if (ret != 0) {
+               print_err_msg(&error);
+               return;
+       }
+}
+
+cmdline_parse_inst_t cmd_del_port_meter_policy = {
+       .f = cmd_del_port_meter_policy_parsed,
+       .data = NULL,
+       .help_str = "Delete port meter policy",
+       .tokens = {
+               (void *)&cmd_del_port_meter_policy_del,
+               (void *)&cmd_del_port_meter_policy_port,
+               (void *)&cmd_del_port_meter_policy_meter,
+               (void *)&cmd_del_port_meter_policy_policy,
+               (void *)&cmd_del_port_meter_policy_port_id,
+               (void *)&cmd_del_port_meter_policy_policy_id,
+               NULL,
+       },
+};
+
 /* *** Delete Port Meter Object *** */
 struct cmd_del_port_meter_result {
        cmdline_fixed_string_t del;
index 7e2713c..2415fc1 100644 (file)
@@ -4,6 +4,7 @@
 
 #ifndef _CMDLINE_MTR_H_
 #define _CMDLINE_MTR_H_
+#include <rte_mtr.h>
 
 /* Traffic Metering and Policing */
 extern cmdline_parse_inst_t cmd_show_port_meter_cap;
@@ -15,9 +16,11 @@ extern cmdline_parse_inst_t cmd_create_port_meter;
 extern cmdline_parse_inst_t cmd_enable_port_meter;
 extern cmdline_parse_inst_t cmd_disable_port_meter;
 extern cmdline_parse_inst_t cmd_del_port_meter;
+extern cmdline_parse_inst_t cmd_del_port_meter_policy;
 extern cmdline_parse_inst_t cmd_set_port_meter_profile;
 extern cmdline_parse_inst_t cmd_set_port_meter_dscp_table;
 extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
 extern cmdline_parse_inst_t cmd_show_port_meter_stats;
+void print_mtr_err_msg(struct rte_mtr_error *error);
 
 #endif /* _CMDLINE_MTR_H_ */
index ccb9bd3..5789f6d 100644 (file)
@@ -38,6 +38,7 @@
 #include <rte_string_fns.h>
 #include <rte_cycles.h>
 #include <rte_flow.h>
+#include <rte_mtr.h>
 #include <rte_errno.h>
 #ifdef RTE_NET_IXGBE
 #include <rte_pmd_ixgbe.h>
@@ -52,6 +53,7 @@
 #include <rte_hexdump.h>
 
 #include "testpmd.h"
+#include "cmdline_mtr.h"
 
 #define ETHDEV_FWVERS_LEN 32
 
@@ -1798,6 +1800,36 @@ port_flow_tunnel_offload_cmd_release(portid_t port_id,
        }
 }
 
+/** Add port meter policy */
+int
+port_meter_policy_add(portid_t port_id, uint32_t policy_id,
+                       const struct rte_flow_action *actions)
+{
+       struct rte_mtr_error error;
+       const struct rte_flow_action *act = actions;
+       const struct rte_flow_action *start;
+       struct rte_mtr_meter_policy_params policy;
+       uint32_t i = 0, act_n;
+       int ret;
+
+       for (i = 0; i < RTE_COLORS; i++) {
+               for (act_n = 0, start = act;
+                       act->type != RTE_FLOW_ACTION_TYPE_END; act++)
+                       act_n++;
+               if (act_n && act->type == RTE_FLOW_ACTION_TYPE_END)
+                       policy.actions[i] = start;
+               else
+                       policy.actions[i] = NULL;
+               act++;
+       }
+       ret = rte_mtr_meter_policy_add(port_id,
+                       policy_id,
+                       &policy, &error);
+       if (ret)
+               print_mtr_err_msg(&error);
+       return ret;
+}
+
 /** Validate flow rule. */
 int
 port_flow_validate(portid_t port_id,
index 9530ec5..6ca872d 100644 (file)
@@ -840,6 +840,8 @@ void port_flow_tunnel_list(portid_t port_id);
 void port_flow_tunnel_destroy(portid_t port_id, uint32_t tunnel_id);
 void port_flow_tunnel_create(portid_t port_id, const struct tunnel_ops *ops);
 int port_flow_isolate(portid_t port_id, int set);
+int port_meter_policy_add(portid_t port_id, uint32_t policy_id,
+               const struct rte_flow_action *actions);
 
 void rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id);
 void tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id);
index 1cb002b..11d3283 100644 (file)
@@ -235,6 +235,8 @@ New Features
     ``show port (port_id) rxq (queue_id) desc used count``
   * Added command to dump internal representation information of single flow.
     ``flow dump (port_id) rule (rule_id)``
+  * Added commands to create and delete meter policy.
+    ``add port meter policy (port_id) (policy_id) ...``
   * Added commands to construct conntrack context and relevant indirect
     action handle creation, update for conntrack action as well as conntrack
     item matching.
index ac2c0d6..dd362f9 100644 (file)
@@ -2765,13 +2765,37 @@ Delete meter profile from the ethernet device::
 
    testpmd> del port meter profile (port_id) (profile_id)
 
+create port policy
+~~~~~~~~~~~~~~~~~~
+
+Create new policy object for the ethernet device::
+
+   testpmd> add port meter policy (port_id) (policy_id) g_actions \
+   {action} y_actions {action} r_actions {action}
+
+where:
+
+* ``policy_id``: policy ID.
+* ``action``: action lists for green/yellow/red colors.
+
+delete port policy
+~~~~~~~~~~~~~~~~~~
+
+Delete policy object for the ethernet device::
+
+   testpmd> del port meter policy (port_id) (policy_id)
+
+where:
+
+* ``policy_id``: policy ID.
+
 create port meter
 ~~~~~~~~~~~~~~~~~
 
 Create new meter object for the ethernet device::
 
    testpmd> create port meter (port_id) (mtr_id) (profile_id) \
-   (meter_enable) (g_action) (y_action) (r_action) (stats_mask) (shared) \
+   (policy_id) (meter_enable) (stats_mask) (shared) \
    (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\
    (dscp_tbl_entry63)]
 
@@ -2779,11 +2803,9 @@ where:
 
 * ``mtr_id``: meter object ID.
 * ``profile_id``: ID for the meter profile.
+* ``policy_id``: ID for the policy.
 * ``meter_enable``: When this parameter has a non-zero value, the meter object
   gets enabled at the time of creation, otherwise remains disabled.
-* ``g_action``: Policer action for the packet with green color.
-* ``y_action``: Policer action for the packet with yellow color.
-* ``r_action``: Policer action for the packet with red color.
 * ``stats_mask``: Mask of statistics counter types to be enabled for the
   meter object.
 * ``shared``:  When this parameter has a non-zero value, the meter object is