Hi Jie,
> -----Original Message----- > From: Jie Wang <jie1x.w...@intel.com> > Sent: Monday, October 18, 2021 12:34 PM > To: dev@dpdk.org > Subject: [PATCH v4 3/3] app/testpmd: support L2TPV2 and PPP protocol pattern > > Add support for test-pmd to parse protocol pattern L2TPv2 and PPP. > > Signed-off-by: Wenjun Wu <wenjun1...@intel.com> > Signed-off-by: Jie Wang <jie1x.w...@intel.com> > --- > app/test-pmd/cmdline_flow.c | 251 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 251 insertions(+) > > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index > a90822b660..c1046e3e28 100644 > --- a/app/test-pmd/cmdline_flow.c > +++ b/app/test-pmd/cmdline_flow.c > @@ -310,6 +310,23 @@ enum index { > ITEM_PORT_REPRESENTOR_PORT_ID, > ITEM_REPRESENTED_PORT, > ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID, > + ITEM_L2TPV2, > + ITEM_L2TPV2_COMMON, > + ITEM_L2TPV2_COMMON_TYPE, > + ITEM_L2TPV2_COMMON_TYPE_DATA_L, > + ITEM_L2TPV2_COMMON_TYPE_CTRL, > + ITEM_L2TPV2_MSG_DATA_L_LENGTH, > + ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID, > + ITEM_L2TPV2_MSG_DATA_L_SESSION_ID, > + ITEM_L2TPV2_MSG_CTRL_LENGTH, > + ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID, > + ITEM_L2TPV2_MSG_CTRL_SESSION_ID, > + ITEM_L2TPV2_MSG_CTRL_NS, > + ITEM_L2TPV2_MSG_CTRL_NR, > + ITEM_PPP, > + ITEM_PPP_ADDR, > + ITEM_PPP_CTRL, > + ITEM_PPP_PROTO_ID, > > /* Validate/create actions. */ > ACTIONS, > @@ -1018,6 +1035,8 @@ static const enum index next_item[] = { > ITEM_CONNTRACK, > ITEM_PORT_REPRESENTOR, > ITEM_REPRESENTED_PORT, > + ITEM_L2TPV2, > + ITEM_PPP, > END_SET, > ZERO, > }; > @@ -1398,6 +1417,31 @@ static const enum index item_represented_port[] = { > ZERO, > }; > > +static const enum index item_l2tpv2[] = { > + ITEM_L2TPV2_COMMON, > + ITEM_NEXT, > + ZERO, > +}; > + > +static const enum index item_l2tpv2_common[] = { > + ITEM_L2TPV2_COMMON_TYPE, > + ZERO, > +}; > + > +static const enum index item_l2tpv2_common_type[] = { > + ITEM_L2TPV2_COMMON_TYPE_DATA_L, > + ITEM_L2TPV2_COMMON_TYPE_CTRL, > + ZERO, > +}; > + > +static const enum index item_ppp[] = { > + ITEM_PPP_ADDR, > + ITEM_PPP_CTRL, > + ITEM_PPP_PROTO_ID, > + ITEM_NEXT, > + ZERO, > +}; > + > static const enum index next_action[] = { > ACTION_END, > ACTION_VOID, > @@ -1781,6 +1825,9 @@ static int parse_vc_conf(struct context *, const struct > token *, static int > parse_vc_item_ecpri_type(struct context *, const struct token *, > const char *, unsigned int, > void *, unsigned int); > +static int parse_vc_item_l2tpv2_type(struct context *, const struct token *, > + const char *, unsigned int, > + void *, unsigned int); > static int parse_vc_action_meter_color_type(struct context *, > const struct token *, > const char *, unsigned int, void *, @@ > -3682,6 +3729,153 @@ > static const struct token token_list[] = { > item_param), > .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)), > }, > + [ITEM_L2TPV2] = { > + .name = "l2tpv2", > + .help = "match l2tpv2 header", > + .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)), > + .next = NEXT(item_l2tpv2), > + .call = parse_vc, > + }, > + [ITEM_L2TPV2_COMMON] = { > + .name = "common", > + .help = "l2tpv2 common header", > + .next = NEXT(item_l2tpv2_common), > + }, > + [ITEM_L2TPV2_COMMON_TYPE] = { > + .name = "type", > + .help = "type of common header", > + .next = NEXT(item_l2tpv2_common_type), > + .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)), > + }, > + [ITEM_L2TPV2_COMMON_TYPE_DATA_L] = { > + .name = "data_l", > + .help = "Type #6: data message with length option", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_DATA_L_LENGTH, > + ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID, > + ITEM_L2TPV2_MSG_DATA_L_SESSION_ID, > + ITEM_NEXT)), > + .call = parse_vc_item_l2tpv2_type, > + }, > + [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = { > + .name = "length", > + .help = "message length", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_DATA_L_LENGTH, > + ITEM_L2TPV2_COMMON, ITEM_NEXT), > + NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, > + hdr.type6.length)), > + }, > + [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = { > + .name = "tunnel_id", > + .help = "tunnel identifier", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID, > + ITEM_L2TPV2_COMMON, ITEM_NEXT), > + NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, > + hdr.type6.tunnel_id)), > + }, > + [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = { > + .name = "session_id", > + .help = "session identifier", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_DATA_L_SESSION_ID, > + ITEM_L2TPV2_COMMON, ITEM_NEXT), > + NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, > + hdr.type6.session_id)), > + }, > + [ITEM_L2TPV2_COMMON_TYPE_CTRL] = { > + .name = "control", > + .help = "Type #3: conrtol message contains length, ns, nr > options", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_LENGTH, > + ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID, > + ITEM_L2TPV2_MSG_CTRL_SESSION_ID, > + ITEM_L2TPV2_MSG_CTRL_NS, > + ITEM_L2TPV2_MSG_CTRL_NR, > + ITEM_NEXT)), > + .call = parse_vc_item_l2tpv2_type, > + }, > + [ITEM_L2TPV2_MSG_CTRL_LENGTH] = { > + .name = "length", > + .help = "message length", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_LENGTH, > + ITEM_L2TPV2_COMMON, ITEM_NEXT), > + NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, > + hdr.type3.length)), > + }, > + [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = { > + .name = "tunnel_id", > + .help = "tunnel identifier", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID, > + ITEM_L2TPV2_COMMON, ITEM_NEXT), > + NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, > + hdr.type3.tunnel_id)), > + }, > + [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = { > + .name = "session_id", > + .help = "session identifier", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_SESSION_ID, > + ITEM_L2TPV2_COMMON, ITEM_NEXT), > + NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, > + hdr.type3.session_id)), > + }, > + [ITEM_L2TPV2_MSG_CTRL_NS] = { > + .name = "ns", > + .help = "sequence number for message", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_NS, > + ITEM_L2TPV2_COMMON, ITEM_NEXT), > + NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, > + hdr.type3.ns)), > + }, > + [ITEM_L2TPV2_MSG_CTRL_NR] = { > + .name = "nr", > + .help = "sequence number for next receive message", > + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_NS, > + ITEM_L2TPV2_COMMON, ITEM_NEXT), > + NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, > + hdr.type3.nr)), > + }, > + [ITEM_PPP] = { > + .name = "ppp", > + .help = "match ppp header", > + .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)), > + .next = NEXT(item_ppp), > + .call = parse_vc, > + }, > + [ITEM_PPP_ADDR] = { > + .name = "addr", > + .help = "ppp address", > + .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)), > + }, > + [ITEM_PPP_CTRL] = { > + .name = "ctrl", > + .help = "ppp control", > + .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)), > + }, > + [ITEM_PPP_PROTO_ID] = { > + .name = "proto_id", > + .help = "ppp protocol id", > + .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), > + item_param), > + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, > + hdr.proto_id)), > + }, > /* Validate/create actions. */ > [ACTIONS] = { > .name = "actions", > @@ -5569,6 +5763,57 @@ parse_vc_item_ecpri_type(struct context *ctx, const > struct token *token, > return len; > } > > +/** Parse L2TPV2 common header type field. */ static int > +parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct rte_flow_item_l2tpv2 *l2tpv2; > + struct rte_flow_item_l2tpv2 *l2tpv2_mask; > + struct rte_flow_item *item; > + uint32_t data_size; > + uint8_t msg_type = 0; > + struct buffer *out = buf; > + const struct arg *arg; > + > + (void)size; > + /* Token name must match. */ > + if (parse_default(ctx, token, str, len, NULL, 0) < 0) > + return -1; > + switch (ctx->curr) { > + case ITEM_L2TPV2_COMMON_TYPE_DATA_L: > + msg_type |= 0x4000; > + break; > + case ITEM_L2TPV2_COMMON_TYPE_CTRL: > + msg_type |= 0xC800; > + break; > + default: > + return -1; > + } > + if (!ctx->object) > + return len; > + arg = pop_args(ctx); > + if (!arg) > + return -1; > + l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data; > + l2tpv2->hdr.common.flags_version |= msg_type; > + data_size = ctx->objdata / 3; /* spec, last, mask */ > + l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data + > + (data_size * 2)); > + l2tpv2_mask->hdr.common.flags_version = 0xFFFF; > + if (arg->hton) { > + l2tpv2->hdr.common.flags_version = > + rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version); > + l2tpv2_mask->hdr.common.flags_version = > + rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version); > + } > + item = &out->args.vc.pattern[out->args.vc.pattern_n - 1]; > + item->spec = l2tpv2; > + item->mask = l2tpv2_mask; > + return len; > +} > + > /** Parse meter color action type. */ > static int > parse_vc_action_meter_color_type(struct context *ctx, const struct token > *token, @@ -8461,6 > +8706,12 @@ flow_item_default_mask(const struct rte_flow_item *item) > case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT: > mask = &rte_flow_item_ethdev_mask; > break; > + case RTE_FLOW_ITEM_TYPE_L2TPV2: > + mask = &rte_flow_item_l2tpv2_mask; > + break; > + case RTE_FLOW_ITEM_TYPE_PPP: > + mask = &rte_flow_item_ppp_mask; > + break; > default: > break; > } > -- > 2.25.1 I see that you are missing updating the cmd_set_raw_parsed function, without it raw encap/decap will not work for your new tunnel header. Best, Ori