Add command lines to generate IPv6 routing extension push and
remove patterns and follow the raw_encap/decap style.

Add the new actions to the action template parsing.

Generating the action patterns
    1. IPv6 routing extension push
    set ipv6_ext_push 1 ipv6_ext type is 43 /
    ipv6_routing_ext ext_type is 4
    ext_next_hdr is 17 ext_seg_left is 2 / end_set
    2. IPv6 routing extension remove
    set ipv6_ext_remove 1 ipv6_ext type is 43 / end_set

Specifying the action in the template
    1. actions_template_id 1 template ipv6_ext_push index 1
    2. actions_template_id 1 template ipv6_ext_remove index 1

Signed-off-by: Rongwei Liu <rongw...@nvidia.com>
---
 app/test-pmd/cmdline_flow.c | 443 +++++++++++++++++++++++++++++++++++-
 1 file changed, 442 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 88e6594c12..45555ea1bd 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -78,6 +78,9 @@ enum index {
        SET_RAW_INDEX,
        SET_SAMPLE_ACTIONS,
        SET_SAMPLE_INDEX,
+       SET_IPV6_EXT_REMOVE,
+       SET_IPV6_EXT_PUSH,
+       SET_IPV6_EXT_INDEX,
 
        /* Top-level command. */
        FLOW,
@@ -536,6 +539,8 @@ enum index {
        ITEM_IB_BTH_PKEY,
        ITEM_IB_BTH_DST_QPN,
        ITEM_IB_BTH_PSN,
+       ITEM_IPV6_PUSH_REMOVE_EXT,
+       ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
 
        /* Validate/create actions. */
        ACTIONS,
@@ -721,6 +726,12 @@ enum index {
        ACTION_SET_TCP_TP_DST,
        ACTION_SET_TCP_TP_DST_TP_DST,
        ACTION_IPSEC,
+       ACTION_IPV6_EXT_REMOVE,
+       ACTION_IPV6_EXT_REMOVE_INDEX,
+       ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
+       ACTION_IPV6_EXT_PUSH,
+       ACTION_IPV6_EXT_PUSH_INDEX,
+       ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -787,6 +798,42 @@ struct action_raw_decap_data {
        uint16_t idx;
 };
 
+/** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
+#define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
+#define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
+
+/** Storage for struct rte_flow_action_ipv6_ext_push. */
+struct ipv6_ext_push_conf {
+       uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
+       size_t size;
+       uint8_t type;
+};
+
+struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
+
+/** Storage for struct rte_flow_action_ipv6_ext_push including external data. 
*/
+struct action_ipv6_ext_push_data {
+       struct rte_flow_action_ipv6_ext_push conf;
+       uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
+       uint8_t type;
+       uint16_t idx;
+};
+
+/** Storage for struct rte_flow_action_ipv6_ext_remove. */
+struct ipv6_ext_remove_conf {
+       struct rte_flow_action_ipv6_ext_remove conf;
+       uint8_t type;
+};
+
+struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
+
+/** Storage for struct rte_flow_action_ipv6_ext_remove including external 
data. */
+struct action_ipv6_ext_remove_data {
+       struct rte_flow_action_ipv6_ext_remove conf;
+       uint8_t type;
+       uint16_t idx;
+};
+
 struct vxlan_encap_conf vxlan_encap_conf = {
        .select_ipv4 = 1,
        .select_vlan = 0,
@@ -2118,6 +2165,8 @@ static const enum index next_action[] = {
        ACTION_SET_TCP_TP_SRC,
        ACTION_SET_TCP_TP_DST,
        ACTION_IPSEC,
+       ACTION_IPV6_EXT_REMOVE,
+       ACTION_IPV6_EXT_PUSH,
        ZERO,
 };
 
@@ -2326,6 +2375,18 @@ static const enum index action_raw_decap[] = {
        ZERO,
 };
 
+static const enum index action_ipv6_ext_remove[] = {
+       ACTION_IPV6_EXT_REMOVE_INDEX,
+       ACTION_NEXT,
+       ZERO,
+};
+
+static const enum index action_ipv6_ext_push[] = {
+       ACTION_IPV6_EXT_PUSH_INDEX,
+       ACTION_NEXT,
+       ZERO,
+};
+
 static const enum index action_set_tag[] = {
        ACTION_SET_TAG_DATA,
        ACTION_SET_TAG_INDEX,
@@ -2390,6 +2451,22 @@ static const enum index next_action_sample[] = {
        ZERO,
 };
 
+static const enum index item_ipv6_push_ext[] = {
+       ITEM_IPV6_PUSH_REMOVE_EXT,
+       ZERO,
+};
+
+static const enum index item_ipv6_push_ext_type[] = {
+       ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
+       ZERO,
+};
+
+static const enum index item_ipv6_push_ext_header[] = {
+       ITEM_IPV6_ROUTING_EXT,
+       ITEM_NEXT,
+       ZERO,
+};
+
 static const enum index action_modify_field_dst[] = {
        ACTION_MODIFY_FIELD_DST_LEVEL,
        ACTION_MODIFY_FIELD_DST_SUB_LEVEL,
@@ -2497,6 +2574,9 @@ static int parse_set_raw_encap_decap(struct context *, 
const struct token *,
 static int parse_set_sample_action(struct context *, const struct token *,
                                   const char *, unsigned int,
                                   void *, unsigned int);
+static int parse_set_ipv6_ext_action(struct context *, const struct token *,
+                                    const char *, unsigned int,
+                                    void *, unsigned int);
 static int parse_set_init(struct context *, const struct token *,
                          const char *, unsigned int,
                          void *, unsigned int);
@@ -2574,6 +2654,22 @@ static int parse_vc_action_raw_encap_index(struct 
context *,
 static int parse_vc_action_raw_decap_index(struct context *,
                                           const struct token *, const char *,
                                           unsigned int, void *, unsigned int);
+static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct 
token *token,
+                                          const char *str, unsigned int len, 
void *buf,
+                                          unsigned int size);
+static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
+                                                const struct token *token,
+                                                const char *str, unsigned int 
len,
+                                                void *buf,
+                                                unsigned int size);
+static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct 
token *token,
+                                        const char *str, unsigned int len, 
void *buf,
+                                        unsigned int size);
+static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
+                                              const struct token *token,
+                                              const char *str, unsigned int 
len,
+                                              void *buf,
+                                              unsigned int size);
 static int parse_vc_action_set_meta(struct context *ctx,
                                    const struct token *token, const char *str,
                                    unsigned int len, void *buf,
@@ -2789,6 +2885,8 @@ static int comp_set_raw_index(struct context *, const 
struct token *,
                              unsigned int, char *, unsigned int);
 static int comp_set_sample_index(struct context *, const struct token *,
                              unsigned int, char *, unsigned int);
+static int comp_set_ipv6_ext_index(struct context *ctx, const struct token 
*token,
+                                  unsigned int ent, char *buf, unsigned int 
size);
 static int comp_set_modify_field_op(struct context *, const struct token *,
                              unsigned int, char *, unsigned int);
 static int comp_set_modify_field_id(struct context *, const struct token *,
@@ -6765,6 +6863,48 @@ static const struct token token_list[] = {
                .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
                .call = parse_vc,
        },
+       [ACTION_IPV6_EXT_REMOVE] = {
+               .name = "ipv6_ext_remove",
+               .help = "IPv6 extension type, defined by set ipv6_ext_remove",
+               .priv = PRIV_ACTION(IPV6_EXT_REMOVE,
+                       sizeof(struct action_ipv6_ext_remove_data)),
+               .next = NEXT(action_ipv6_ext_remove),
+               .call = parse_vc_action_ipv6_ext_remove,
+       },
+       [ACTION_IPV6_EXT_REMOVE_INDEX] = {
+               .name = "index",
+               .help = "the index of ipv6_ext_remove",
+               .next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
+       },
+       [ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
+               .name = "{index}",
+               .type = "UNSIGNED",
+               .help = "unsigned integer value",
+               .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+               .call = parse_vc_action_ipv6_ext_remove_index,
+               .comp = comp_set_ipv6_ext_index,
+       },
+       [ACTION_IPV6_EXT_PUSH] = {
+               .name = "ipv6_ext_push",
+               .help = "IPv6 extension data, defined by set ipv6_ext_push",
+               .priv = PRIV_ACTION(IPV6_EXT_PUSH,
+                       sizeof(struct action_ipv6_ext_push_data)),
+               .next = NEXT(action_ipv6_ext_push),
+               .call = parse_vc_action_ipv6_ext_push,
+       },
+       [ACTION_IPV6_EXT_PUSH_INDEX] = {
+               .name = "index",
+               .help = "the index of ipv6_ext_push",
+               .next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
+       },
+       [ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
+               .name = "{index}",
+               .type = "UNSIGNED",
+               .help = "unsigned integer value",
+               .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+               .call = parse_vc_action_ipv6_ext_push_index,
+               .comp = comp_set_ipv6_ext_index,
+       },
        /* Top level command. */
        [SET] = {
                .name = "set",
@@ -6774,7 +6914,9 @@ static const struct token token_list[] = {
                .next = NEXT(NEXT_ENTRY
                             (SET_RAW_ENCAP,
                              SET_RAW_DECAP,
-                             SET_SAMPLE_ACTIONS)),
+                             SET_SAMPLE_ACTIONS,
+                             SET_IPV6_EXT_REMOVE,
+                             SET_IPV6_EXT_PUSH)),
                .call = parse_set_init,
        },
        /* Sub-level commands. */
@@ -6822,6 +6964,49 @@ static const struct token token_list[] = {
                                 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
                .call = parse_set_sample_action,
        },
+       [SET_IPV6_EXT_PUSH] = {
+               .name = "ipv6_ext_push",
+               .help = "set IPv6 extension header",
+               .next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
+               .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
+                               (offsetof(struct buffer, port),
+                                sizeof(((struct buffer *)0)->port),
+                                0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
+               .call = parse_set_ipv6_ext_action,
+       },
+       [SET_IPV6_EXT_REMOVE] = {
+               .name = "ipv6_ext_remove",
+               .help = "set IPv6 extension header",
+               .next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
+               .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
+                               (offsetof(struct buffer, port),
+                                sizeof(((struct buffer *)0)->port),
+                                0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
+               .call = parse_set_ipv6_ext_action,
+       },
+       [SET_IPV6_EXT_INDEX] = {
+               .name = "{index}",
+               .type = "UNSIGNED",
+               .help = "index of ipv6 extension push/remove actions",
+               .next = NEXT(item_ipv6_push_ext),
+               .call = parse_port,
+       },
+       [ITEM_IPV6_PUSH_REMOVE_EXT] = {
+               .name = "ipv6_ext",
+               .help = "set IPv6 extension header",
+               .priv = PRIV_ITEM(IPV6_EXT,
+                                 sizeof(struct rte_flow_item_ipv6_ext)),
+               .next = NEXT(item_ipv6_push_ext_type),
+               .call = parse_vc,
+       },
+       [ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
+               .name = "type",
+               .help = "set IPv6 extension type",
+               .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
+                                            next_hdr)),
+               .next = NEXT(item_ipv6_push_ext_header, 
NEXT_ENTRY(COMMON_UNSIGNED),
+                            item_param),
+       },
        [ACTION_SET_TAG] = {
                .name = "set_tag",
                .help = "set tag",
@@ -9401,6 +9586,140 @@ parse_vc_action_raw_decap(struct context *ctx, const 
struct token *token,
        return ret;
 }
 
+static int
+parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
+                               const char *str, unsigned int len, void *buf,
+                               unsigned int size)
+{
+       struct buffer *out = buf;
+       struct rte_flow_action *action;
+       struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
+       int ret;
+
+       ret = parse_vc(ctx, token, str, len, buf, size);
+       if (ret < 0)
+               return ret;
+       /* Nothing else to do if there is no buffer. */
+       if (!out)
+               return ret;
+       if (!out->args.vc.actions_n)
+               return -1;
+       action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+       /* Point to selected object. */
+       ctx->object = out->args.vc.data;
+       ctx->objmask = NULL;
+       /* Copy the headers to the buffer. */
+       ipv6_ext_remove_data = ctx->object;
+       ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
+       action->conf = &ipv6_ext_remove_data->conf;
+       return ret;
+}
+
+static int
+parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token 
*token,
+                                     const char *str, unsigned int len, void 
*buf,
+                                     unsigned int size)
+{
+       struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
+       struct rte_flow_action *action;
+       const struct arg *arg;
+       struct buffer *out = buf;
+       int ret;
+       uint16_t idx;
+
+       RTE_SET_USED(token);
+       RTE_SET_USED(buf);
+       RTE_SET_USED(size);
+       arg = ARGS_ENTRY_ARB_BOUNDED
+               (offsetof(struct action_ipv6_ext_remove_data, idx),
+                sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
+                0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
+       if (push_args(ctx, arg))
+               return -1;
+       ret = parse_int(ctx, token, str, len, NULL, 0);
+       if (ret < 0) {
+               pop_args(ctx);
+               return -1;
+       }
+       if (!ctx->object)
+               return len;
+       action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+       action_ipv6_ext_remove_data = ctx->object;
+       idx = action_ipv6_ext_remove_data->idx;
+       action_ipv6_ext_remove_data->conf.type = 
ipv6_ext_remove_confs[idx].type;
+       action->conf = &action_ipv6_ext_remove_data->conf;
+       return len;
+}
+
+static int
+parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
+                             const char *str, unsigned int len, void *buf,
+                             unsigned int size)
+{
+       struct buffer *out = buf;
+       struct rte_flow_action *action;
+       struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
+       int ret;
+
+       ret = parse_vc(ctx, token, str, len, buf, size);
+       if (ret < 0)
+               return ret;
+       /* Nothing else to do if there is no buffer. */
+       if (!out)
+               return ret;
+       if (!out->args.vc.actions_n)
+               return -1;
+       action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+       /* Point to selected object. */
+       ctx->object = out->args.vc.data;
+       ctx->objmask = NULL;
+       /* Copy the headers to the buffer. */
+       ipv6_ext_push_data = ctx->object;
+       ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
+       ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
+       ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
+       action->conf = &ipv6_ext_push_data->conf;
+       return ret;
+}
+
+static int
+parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token 
*token,
+                                   const char *str, unsigned int len, void 
*buf,
+                                   unsigned int size)
+{
+       struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
+       struct rte_flow_action *action;
+       const struct arg *arg;
+       struct buffer *out = buf;
+       int ret;
+       uint16_t idx;
+
+       RTE_SET_USED(token);
+       RTE_SET_USED(buf);
+       RTE_SET_USED(size);
+       arg = ARGS_ENTRY_ARB_BOUNDED
+               (offsetof(struct action_ipv6_ext_push_data, idx),
+                sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
+                0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
+       if (push_args(ctx, arg))
+               return -1;
+       ret = parse_int(ctx, token, str, len, NULL, 0);
+       if (ret < 0) {
+               pop_args(ctx);
+               return -1;
+       }
+       if (!ctx->object)
+               return len;
+       action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+       action_ipv6_ext_push_data = ctx->object;
+       idx = action_ipv6_ext_push_data->idx;
+       action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
+       action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
+       action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
+       action->conf = &action_ipv6_ext_push_data->conf;
+       return len;
+}
+
 static int
 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
                         const char *str, unsigned int len, void *buf,
@@ -11366,6 +11685,35 @@ parse_set_sample_action(struct context *ctx, const 
struct token *token,
        return len;
 }
 
+/** Parse set command, initialize output buffer for subsequent tokens. */
+static int
+parse_set_ipv6_ext_action(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;
+       /* Make sure buffer is large enough. */
+       if (size < sizeof(*out))
+               return -1;
+       ctx->objdata = 0;
+       ctx->objmask = NULL;
+       ctx->object = out;
+       if (!out->command)
+               return -1;
+       out->command = ctx->curr;
+       /* For ipv6_ext_push/remove we need is pattern */
+       out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+                                                      sizeof(double));
+       return len;
+}
+
 /**
  * Parse set raw_encap/raw_decap command,
  * initialize output buffer for subsequent tokens.
@@ -11793,6 +12141,24 @@ comp_set_raw_index(struct context *ctx, const struct 
token *token,
        return nb;
 }
 
+/** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. 
*/
+static int
+comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
+                       unsigned int ent, char *buf, unsigned int size)
+{
+       uint16_t idx = 0;
+       uint16_t nb = 0;
+
+       RTE_SET_USED(ctx);
+       RTE_SET_USED(token);
+       for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
+               if (buf && idx == ent)
+                       return snprintf(buf, size, "%u", idx);
+               ++nb;
+       }
+       return nb;
+}
+
 /** Complete index number for set raw_encap/raw_decap commands. */
 static int
 comp_set_sample_index(struct context *ctx, const struct token *token,
@@ -12697,6 +13063,78 @@ flow_item_default_mask(const struct rte_flow_item 
*item)
        return mask;
 }
 
+/** Dispatch parsed buffer to function calls. */
+static void
+cmd_set_ipv6_ext_parsed(const struct buffer *in)
+{
+       uint32_t n = in->args.vc.pattern_n;
+       int i = 0;
+       struct rte_flow_item *item = NULL;
+       size_t size = 0;
+       uint8_t *data = NULL;
+       uint8_t *type = NULL;
+       size_t *total_size = NULL;
+       uint16_t idx = in->port; /* We borrow port field as index */
+       struct rte_flow_item_ipv6_routing_ext *ext;
+       const struct rte_flow_item_ipv6_ext *ipv6_ext;
+
+       RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
+                  in->command == SET_IPV6_EXT_REMOVE);
+
+       if (in->command == SET_IPV6_EXT_REMOVE) {
+               if (n != 1 || in->args.vc.pattern->type !=
+                   RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
+                       fprintf(stderr, "Error - Not supported item\n");
+                       return;
+               }
+               type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
+               item = in->args.vc.pattern;
+               ipv6_ext = item->spec;
+               *type = ipv6_ext->next_hdr;
+               return;
+       }
+
+       total_size = &ipv6_ext_push_confs[idx].size;
+       data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
+       type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
+
+       *total_size = 0;
+       memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
+       for (i = n - 1 ; i >= 0; --i) {
+               item = in->args.vc.pattern + i;
+               switch (item->type) {
+               case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
+                       ipv6_ext = item->spec;
+                       *type = ipv6_ext->next_hdr;
+                       break;
+               case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
+                       ext = (struct rte_flow_item_ipv6_routing_ext 
*)(uintptr_t)item->spec;
+                       if (!ext->hdr.hdr_len) {
+                               size = sizeof(struct rte_ipv6_routing_ext) +
+                               (ext->hdr.segments_left << 4);
+                               ext->hdr.hdr_len = ext->hdr.segments_left << 1;
+                               /* Indicate no TLV once SRH. */
+                               if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
+                                       ext->hdr.last_entry = 
ext->hdr.segments_left - 1;
+                       } else {
+                               size = sizeof(struct rte_ipv6_routing_ext) +
+                               (ext->hdr.hdr_len << 3);
+                       }
+                       *total_size += size;
+                       memcpy(data, ext, size);
+                       break;
+               default:
+                       fprintf(stderr, "Error - Not supported item\n");
+                       goto error;
+               }
+       }
+       RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
+       return;
+error:
+       *total_size = 0;
+       memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
+}
+
 /** Dispatch parsed buffer to function calls. */
 static void
 cmd_set_raw_parsed_sample(const struct buffer *in)
@@ -12830,6 +13268,9 @@ cmd_set_raw_parsed(const struct buffer *in)
 
        if (in->command == SET_SAMPLE_ACTIONS)
                return cmd_set_raw_parsed_sample(in);
+       else if (in->command == SET_IPV6_EXT_PUSH ||
+                in->command == SET_IPV6_EXT_REMOVE)
+               return cmd_set_ipv6_ext_parsed(in);
        RTE_ASSERT(in->command == SET_RAW_ENCAP ||
                   in->command == SET_RAW_DECAP);
        if (in->command == SET_RAW_ENCAP) {
-- 
2.27.0

Reply via email to