[v3,3/3] app/testpmd: support L2TPV2 and PPP protocol pattern
Checks
Commit Message
Add support for test-pmd to parse protocol pattern L2TPv2 and PPP.
Signed-off-by: Wenjun Wu <wenjun1.wu@intel.com>
Signed-off-by: Jie Wang <jie1x.wang@intel.com>
---
app/test-pmd/cmdline.c | 244 ++++++++++++++++++++++
app/test-pmd/cmdline_flow.c | 396 ++++++++++++++++++++++++++++++++++++
app/test-pmd/testpmd.h | 22 ++
3 files changed, 662 insertions(+)
Comments
Hi Jie,
Sorry if I wan't clear on my last review.
You don't need to implement encap/decap for those protocols just make sure they are working
with the set encap and set decap along with the raw action.
You can look at cmd_set_raw_parsed and use other tunnels as reference (for example gtp).
> -----Original Message-----
> From: Jie Wang <jie1x.wang@intel.com>
> Sent: Friday, October 15, 2021 12:58 PM
> To: dev@dpdk.org
> Subject: [PATCH v3 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.wu@intel.com>
> Signed-off-by: Jie Wang <jie1x.wang@intel.com>
> ---
> app/test-pmd/cmdline.c | 244 ++++++++++++++++++++++
> app/test-pmd/cmdline_flow.c | 396 ++++++++++++++++++++++++++++++++++++
> app/test-pmd/testpmd.h | 22 ++
> 3 files changed, 662 insertions(+)
>
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 36d50fd3c7..bba761ad4b 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -13300,6 +13300,247 @@ cmdline_parse_inst_t cmd_set_nvgre_with_vlan = {
> },
> };
>
> +/** Set L2TPV2 encapsulation details */ struct cmd_set_l2tpv2_result {
> + cmdline_fixed_string_t set;
> + cmdline_fixed_string_t l2tpv2;
> + cmdline_fixed_string_t pos_token;
> + cmdline_fixed_string_t ip_version;
> + uint32_t vlan_present:1;
> + uint16_t flags_version;
> + uint16_t session_id;
> + uint16_t udp_src;
> + uint16_t udp_dst;
> + cmdline_ipaddr_t ip_src;
> + cmdline_ipaddr_t ip_dst;
> + uint16_t tci;
> + uint8_t tos;
> + uint8_t ttl;
> + struct rte_ether_addr eth_src;
> + struct rte_ether_addr eth_dst;
> +};
> +
> +cmdline_parse_token_string_t cmd_set_l2tpv2_set =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, set, "set");
> +cmdline_parse_token_string_t cmd_set_l2tpv2_l2tpv2 =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, l2tpv2,
> +"l2tpv2"); cmdline_parse_token_string_t cmd_set_l2tpv2_l2tpv2_tos_ttl =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, l2tpv2,
> + "l2tpv2-tos-ttl");
> +cmdline_parse_token_string_t cmd_set_l2tpv2_l2tpv2_with_vlan =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, l2tpv2,
> + "l2tpv2-with-vlan");
> +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_version =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "ip-version");
> +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_version_value =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, ip_version,
> + "ipv4#ipv6");
> +cmdline_parse_token_string_t cmd_set_l2tpv2_flags_version =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "flags_version");
> +cmdline_parse_token_num_t cmd_set_l2tpv2_flags_version_value =
> + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, flags_version,
> + RTE_UINT16);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_session_id =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "session_id");
> +cmdline_parse_token_num_t cmd_set_l2tpv2_session_id_value =
> + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, session_id,
> + RTE_UINT16);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_udp_src =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "udp-src");
> +cmdline_parse_token_num_t cmd_set_l2tpv2_udp_src_value =
> + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, udp_src,
> + RTE_UINT16);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_udp_dst =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "udp-dst");
> +cmdline_parse_token_num_t cmd_set_l2tpv2_udp_dst_value =
> + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, udp_dst,
> + RTE_UINT16);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_tos =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "ip-tos");
> +cmdline_parse_token_num_t cmd_set_l2tpv2_ip_tos_value =
> + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, tos, RTE_UINT8);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_ttl =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "ip-ttl");
> +cmdline_parse_token_num_t cmd_set_l2tpv2_ip_ttl_value =
> + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, ttl, RTE_UINT8);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_src =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "ip-src");
> +cmdline_parse_token_ipaddr_t cmd_set_l2tpv2_ip_src_value =
> + TOKEN_IPADDR_INITIALIZER(struct cmd_set_l2tpv2_result, ip_src);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_dst =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "ip-dst");
> +cmdline_parse_token_ipaddr_t cmd_set_l2tpv2_ip_dst_value =
> + TOKEN_IPADDR_INITIALIZER(struct cmd_set_l2tpv2_result, ip_dst);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_vlan =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "vlan-tci");
> +cmdline_parse_token_num_t cmd_set_l2tpv2_vlan_value =
> + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, tci, RTE_UINT16);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_eth_src =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "eth-src");
> +cmdline_parse_token_etheraddr_t cmd_set_l2tpv2_eth_src_value =
> + TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_l2tpv2_result, eth_src);
> +cmdline_parse_token_string_t cmd_set_l2tpv2_eth_dst =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
> + "eth-dst");
> +cmdline_parse_token_etheraddr_t cmd_set_l2tpv2_eth_dst_value =
> + TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_l2tpv2_result, eth_dst);
> +
> +static void cmd_set_l2tpv2_parsed(void *parsed_result,
> + __rte_unused struct cmdline *cl,
> + __rte_unused void *data)
> +{
> + struct cmd_set_l2tpv2_result *res = parsed_result;
> +
> + l2tpv2_encap_conf.select_tos_ttl = 0;
> + if (strcmp(res->l2tpv2, "l2tpv2") == 0)
> + l2tpv2_encap_conf.select_vlan = 0;
> + else if (strcmp(res->l2tpv2, "l2tpv2-with-vlan") == 0)
> + l2tpv2_encap_conf.select_vlan = 1;
> + else if (strcmp(res->l2tpv2, "l2tpv2-tos-ttl") == 0) {
> + l2tpv2_encap_conf.select_vlan = 0;
> + l2tpv2_encap_conf.select_tos_ttl = 1;
> + }
> + if (strcmp(res->ip_version, "ipv4") == 0)
> + l2tpv2_encap_conf.select_ipv4 = 1;
> + else if (strcmp(res->ip_version, "ipv6") == 0)
> + l2tpv2_encap_conf.select_ipv4 = 0;
> + else
> + return;
> +
> + l2tpv2_encap_conf.flags_version = res->flags_version;
> + l2tpv2_encap_conf.session_id = res->session_id;
> + l2tpv2_encap_conf.udp_src = res->udp_src;
> + l2tpv2_encap_conf.udp_dst = res->udp_dst;
> + l2tpv2_encap_conf.ip_tos = res->tos;
> + l2tpv2_encap_conf.ip_ttl = res->ttl;
> + if (l2tpv2_encap_conf.select_ipv4) {
> + IPV4_ADDR_TO_UINT(res->ip_src, l2tpv2_encap_conf.ipv4_src);
> + IPV4_ADDR_TO_UINT(res->ip_dst, l2tpv2_encap_conf.ipv4_dst);
> + } else {
> + IPV6_ADDR_TO_ARRAY(res->ip_src, l2tpv2_encap_conf.ipv6_src);
> + IPV6_ADDR_TO_ARRAY(res->ip_dst, l2tpv2_encap_conf.ipv6_dst);
> + }
> + if (l2tpv2_encap_conf.select_vlan)
> + l2tpv2_encap_conf.vlan_tci = rte_cpu_to_be_16(res->tci);
> + rte_memcpy(l2tpv2_encap_conf.eth_src, res->eth_src.addr_bytes,
> + RTE_ETHER_ADDR_LEN);
> + rte_memcpy(l2tpv2_encap_conf.eth_dst, res->eth_dst.addr_bytes,
> + RTE_ETHER_ADDR_LEN);
> +}
> +
> +cmdline_parse_inst_t cmd_set_l2tpv2 = {
> + .f = cmd_set_l2tpv2_parsed,
> + .data = NULL,
> + .help_str = "set l2tpv2 ip-version ipv4|ipv6 flags_version"
> + " <flags_version> session_id <session_id> udp-src <udp-src>"
> + " udp-dst <udp-dst> ip-src <ip-src> ip-dst <ip-dst> eth-src"
> + " <eth-src> eth-dst <eth-dst>",
> + .tokens = {
> + (void *)&cmd_set_l2tpv2_set,
> + (void *)&cmd_set_l2tpv2_l2tpv2,
> + (void *)&cmd_set_l2tpv2_ip_version,
> + (void *)&cmd_set_l2tpv2_ip_version_value,
> + (void *)&cmd_set_l2tpv2_flags_version,
> + (void *)&cmd_set_l2tpv2_flags_version_value,
> + (void *)&cmd_set_l2tpv2_session_id,
> + (void *)&cmd_set_l2tpv2_session_id_value,
> + (void *)&cmd_set_l2tpv2_udp_src,
> + (void *)&cmd_set_l2tpv2_udp_src_value,
> + (void *)&cmd_set_l2tpv2_udp_dst,
> + (void *)&cmd_set_l2tpv2_udp_dst_value,
> + (void *)&cmd_set_l2tpv2_ip_src,
> + (void *)&cmd_set_l2tpv2_ip_src_value,
> + (void *)&cmd_set_l2tpv2_ip_dst,
> + (void *)&cmd_set_l2tpv2_ip_dst_value,
> + (void *)&cmd_set_l2tpv2_eth_src,
> + (void *)&cmd_set_l2tpv2_eth_src_value,
> + (void *)&cmd_set_l2tpv2_eth_dst,
> + (void *)&cmd_set_l2tpv2_eth_dst_value,
> + NULL,
> + },
> +};
> +
> +cmdline_parse_inst_t cmd_set_l2tpv2_tos_ttl = {
> + .f = cmd_set_l2tpv2_parsed,
> + .data = NULL,
> + .help_str = "set l2tpv2-tos-ttl ip-version ipv4|ipv6 flags_version"
> + " <flags_version> session_id <session_id> udp-src <udp-src>"
> + " udp-dst <udp-dst> ip-tos <ip-tos> ip-ttl <ip-ttl> ip-src"
> + " <ip-src> ip-dst <ip-dst> eth-src <eth-src> eth-dst <eth-dst>",
> + .tokens = {
> + (void *)&cmd_set_l2tpv2_set,
> + (void *)&cmd_set_l2tpv2_l2tpv2_tos_ttl,
> + (void *)&cmd_set_l2tpv2_ip_version,
> + (void *)&cmd_set_l2tpv2_ip_version_value,
> + (void *)&cmd_set_l2tpv2_flags_version,
> + (void *)&cmd_set_l2tpv2_flags_version_value,
> + (void *)&cmd_set_l2tpv2_session_id,
> + (void *)&cmd_set_l2tpv2_session_id_value,
> + (void *)&cmd_set_l2tpv2_udp_src,
> + (void *)&cmd_set_l2tpv2_udp_src_value,
> + (void *)&cmd_set_l2tpv2_udp_dst,
> + (void *)&cmd_set_l2tpv2_udp_dst_value,
> + (void *)&cmd_set_l2tpv2_ip_tos,
> + (void *)&cmd_set_l2tpv2_ip_tos_value,
> + (void *)&cmd_set_l2tpv2_ip_ttl,
> + (void *)&cmd_set_l2tpv2_ip_ttl_value,
> + (void *)&cmd_set_l2tpv2_ip_src,
> + (void *)&cmd_set_l2tpv2_ip_src_value,
> + (void *)&cmd_set_l2tpv2_ip_dst,
> + (void *)&cmd_set_l2tpv2_ip_dst_value,
> + (void *)&cmd_set_l2tpv2_eth_src,
> + (void *)&cmd_set_l2tpv2_eth_src_value,
> + (void *)&cmd_set_l2tpv2_eth_dst,
> + (void *)&cmd_set_l2tpv2_eth_dst_value,
> + NULL,
> + },
> +};
> +
> +cmdline_parse_inst_t cmd_set_l2tpv2_with_vlan = {
> + .f = cmd_set_l2tpv2_parsed,
> + .data = NULL,
> + .help_str = "set l2tpv2-with-vlan ip-version ipv4|ipv6 flags_version"
> + " <flags_version> session_id <session_id> udp-src <udp-src>"
> + " udp-dst <udp-dst> ip-src <ip-src> ip-dst <ip-dst> vlan-tci"
> + " <vlan-tci> eth-src <eth-src> eth-dst <eth-dst>",
> + .tokens = {
> + (void *)&cmd_set_l2tpv2_set,
> + (void *)&cmd_set_l2tpv2_l2tpv2_with_vlan,
> + (void *)&cmd_set_l2tpv2_ip_version,
> + (void *)&cmd_set_l2tpv2_ip_version_value,
> + (void *)&cmd_set_l2tpv2_flags_version,
> + (void *)&cmd_set_l2tpv2_flags_version_value,
> + (void *)&cmd_set_l2tpv2_session_id,
> + (void *)&cmd_set_l2tpv2_session_id_value,
> + (void *)&cmd_set_l2tpv2_udp_src,
> + (void *)&cmd_set_l2tpv2_udp_src_value,
> + (void *)&cmd_set_l2tpv2_udp_dst,
> + (void *)&cmd_set_l2tpv2_udp_dst_value,
> + (void *)&cmd_set_l2tpv2_ip_src,
> + (void *)&cmd_set_l2tpv2_ip_src_value,
> + (void *)&cmd_set_l2tpv2_ip_dst,
> + (void *)&cmd_set_l2tpv2_ip_dst_value,
> + (void *)&cmd_set_l2tpv2_vlan,
> + (void *)&cmd_set_l2tpv2_vlan_value,
> + (void *)&cmd_set_l2tpv2_eth_src,
> + (void *)&cmd_set_l2tpv2_eth_src_value,
> + (void *)&cmd_set_l2tpv2_eth_dst,
> + (void *)&cmd_set_l2tpv2_eth_dst_value,
> + NULL,
> + },
> +};
> +
> /** Set L2 encapsulation details */
> struct cmd_set_l2_encap_result {
> cmdline_fixed_string_t set;
> @@ -17774,6 +18015,9 @@ cmdline_parse_ctx_t main_ctx[] = {
> (cmdline_parse_inst_t *)&cmd_set_vxlan_with_vlan,
> (cmdline_parse_inst_t *)&cmd_set_nvgre,
> (cmdline_parse_inst_t *)&cmd_set_nvgre_with_vlan,
> + (cmdline_parse_inst_t *)&cmd_set_l2tpv2,
> + (cmdline_parse_inst_t *)&cmd_set_l2tpv2_tos_ttl,
> + (cmdline_parse_inst_t *)&cmd_set_l2tpv2_with_vlan,
> (cmdline_parse_inst_t *)&cmd_set_l2_encap,
> (cmdline_parse_inst_t *)&cmd_set_l2_encap_with_vlan,
> (cmdline_parse_inst_t *)&cmd_set_l2_decap, diff --git a/app/test-pmd/cmdline_flow.c
> b/app/test-pmd/cmdline_flow.c index 0b5856c7d5..4f73d4f39d 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -306,6 +306,23 @@ enum index {
> ITEM_POL_PORT,
> ITEM_POL_METER,
> ITEM_POL_POLICY,
> + 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,
> @@ -376,6 +393,8 @@ enum index {
> ACTION_VXLAN_DECAP,
> ACTION_NVGRE_ENCAP,
> ACTION_NVGRE_DECAP,
> + ACTION_L2TPV2_ENCAP,
> + ACTION_L2TPV2_DECAP,
> ACTION_L2_ENCAP,
> ACTION_L2_DECAP,
> ACTION_MPLSOGRE_ENCAP,
> @@ -581,6 +600,44 @@ struct action_nvgre_encap_data {
> struct rte_flow_item_nvgre item_nvgre; };
>
> +struct l2tpv2_encap_conf l2tpv2_encap_conf = {
> + .select_ipv4 = 1,
> + .select_vlan = 0,
> + .select_tos_ttl = 0,
> + .flags_version = 0,
> + .session_id = 0,
> + .udp_src = 0,
> + .udp_dst = 1701,
> + .ipv4_src = RTE_IPV4(127, 0, 0, 1),
> + .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
> + .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
> + "\x00\x00\x00\x00\x00\x00\x00\x01",
> + .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
> + "\x00\x00\x00\x00\x00\x00\x11\x11",
> + .vlan_tci = 0,
> + .ip_tos = 0,
> + .ip_ttl = 255,
> + .eth_src = "\x00\x00\x00\x00\x00\x00",
> + .eth_dst = "\xff\xff\xff\xff\xff\xff", };
> +
> +/** Maximum number of items in struct rte_flow_action_l2tpv2_encap. */
> +#define ACTION_L2TPV2_ENCAP_ITEMS_NUM 6
> +
> +/** Storage for struct rte_flow_action_l2tpv2_encap including external
> +data. */ struct action_l2tpv2_encap_data {
> + struct rte_flow_action_l2tpv2_encap conf;
> + struct rte_flow_item items[ACTION_L2TPV2_ENCAP_ITEMS_NUM];
> + struct rte_flow_item_eth item_eth;
> + struct rte_flow_item_vlan item_vlan;
> + union {
> + struct rte_flow_item_ipv4 item_ipv4;
> + struct rte_flow_item_ipv6 item_ipv6;
> + };
> + struct rte_flow_item_udp item_udp;
> + struct rte_flow_item_l2tpv2 item_l2tpv2; };
> +
> struct l2_encap_conf l2_encap_conf;
>
See my comment at the top.
> struct l2_decap_conf l2_decap_conf;
> @@ -614,6 +671,7 @@ struct rte_flow_action_port_id
> sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
> struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
> struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
> struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
> +struct action_l2tpv2_encap_data
> +sample_l2tpv2_encap[RAW_SAMPLE_CONFS_MAX_NUM];
> struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
> struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
>
> @@ -999,6 +1057,8 @@ static const enum index next_item[] = {
> ITEM_GENEVE_OPT,
> ITEM_INTEGRITY,
> ITEM_CONNTRACK,
> + ITEM_L2TPV2,
> + ITEM_PPP,
> END_SET,
> ZERO,
> };
> @@ -1367,6 +1427,31 @@ static const enum index item_integrity_lv[] = {
> 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,
> @@ -1400,6 +1485,8 @@ static const enum index next_action[] = {
> ACTION_VXLAN_DECAP,
> ACTION_NVGRE_ENCAP,
> ACTION_NVGRE_DECAP,
> + ACTION_L2TPV2_ENCAP,
> + ACTION_L2TPV2_DECAP,
> ACTION_L2_ENCAP,
> ACTION_L2_DECAP,
> ACTION_MPLSOGRE_ENCAP,
> @@ -1687,6 +1774,7 @@ static const enum index next_action_sample[] = {
> ACTION_RAW_ENCAP,
> ACTION_VXLAN_ENCAP,
> ACTION_NVGRE_ENCAP,
> + ACTION_L2TPV2_ENCAP,
> ACTION_NEXT,
> ZERO,
> };
> @@ -1757,6 +1845,9 @@ static int parse_vc_action_vxlan_encap(struct context *, const struct token
> *, static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
> const char *, unsigned int, void *,
> unsigned int);
> +static int parse_vc_action_l2tpv2_encap(struct context *, const struct token *,
> + const char *, unsigned int, void *,
> + unsigned int);
> static int parse_vc_action_l2_encap(struct context *, const struct token *,
> const char *, unsigned int, void *,
> unsigned int);
> @@ -3606,6 +3697,136 @@ static const struct token token_list[] = {
> item_param),
> .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
> },
> + [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_MSG_DATA_L_LENGTH] = {
> + .name = "length",
> + .help = "message length",
> + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED),
> + item_param),
> + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
> + hdr.type7.tunnel_id)),
> + },
> + [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
> + .name = "tunnel_id",
> + .help = "tunnel identifier",
> + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED),
> + item_param),
> + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
> + hdr.type7.tunnel_id)),
> + },
> + [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
> + .name = "session_id",
> + .help = "session identifier",
> + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED),
> + item_param),
> + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
> + hdr.type7.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_MSG_CTRL_LENGTH] = {
> + .name = "length",
> + .help = "message length",
> + .next = NEXT(item_l2tpv2, 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(item_l2tpv2, 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(item_l2tpv2, 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(item_l2tpv2, 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(item_l2tpv2, 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, 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, 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, proto_id)),
> + },
> /* Validate/create actions. */
> [ACTIONS] = {
> .name = "actions",
> @@ -4125,6 +4346,24 @@ static const struct token token_list[] = {
> .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
> .call = parse_vc,
> },
> + [ACTION_L2TPV2_ENCAP] = {
> + .name = "l2tpv2_encap",
> + .help = "L2TPV2 encapsulation, uses configuration set by \"set"
> + " l2tpv2\"",
> + .priv = PRIV_ACTION(L2TPV2_ENCAP,
> + sizeof(struct action_l2tpv2_encap_data)),
> + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
> + .call = parse_vc_action_l2tpv2_encap,
> + },
> + [ACTION_L2TPV2_DECAP] = {
> + .name = "l2tpv2_decap",
> + .help = "Performs a decapsulation action by stripping all"
> + " headers of the L2TPV2 tunnel network overlay from the"
> + " matched flow.",
> + .priv = PRIV_ACTION(L2TPV2_DECAP, 0),
> + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
> + .call = parse_vc,
> + },
> [ACTION_L2_ENCAP] = {
> .name = "l2_encap",
> .help = "l2 encap, uses configuration set by"
> @@ -5907,6 +6146,152 @@ parse_vc_action_nvgre_encap(struct context *ctx, const struct token
> *token,
> return ret;
> }
>
> +/** Setup L2TPV2 encap configuration. */ static int
> +parse_setup_l2tpv2_encap_data(struct action_l2tpv2_encap_data
> +*action_l2tpv2_encap_data) {
> + /* Set up default configuration. */
> + *action_l2tpv2_encap_data = (struct action_l2tpv2_encap_data){
> + .conf = (struct rte_flow_action_l2tpv2_encap){
> + .definition = action_l2tpv2_encap_data->items,
> + },
> + .items = {
> + {
> + .type = RTE_FLOW_ITEM_TYPE_ETH,
> + .spec = &action_l2tpv2_encap_data->item_eth,
> + .mask = &rte_flow_item_eth_mask,
> + },
> + {
> + .type = RTE_FLOW_ITEM_TYPE_VLAN,
> + .spec = &action_l2tpv2_encap_data->item_vlan,
> + .mask = &rte_flow_item_vlan_mask,
> + },
> + {
> + .type = RTE_FLOW_ITEM_TYPE_IPV4,
> + .spec = &action_l2tpv2_encap_data->item_ipv4,
> + .mask = &rte_flow_item_ipv4_mask,
> + },
> + {
> + .type = RTE_FLOW_ITEM_TYPE_UDP,
> + .spec = &action_l2tpv2_encap_data->item_udp,
> + .mask = &rte_flow_item_udp_mask,
> + },
> + {
> + .type = RTE_FLOW_ITEM_TYPE_L2TPV2,
> + .spec = &action_l2tpv2_encap_data->item_l2tpv2,
> + .mask = &rte_flow_item_l2tpv2_mask,
> + },
> + {
> + .type = RTE_FLOW_ITEM_TYPE_END,
> + },
> + },
> + .item_eth.type = 0,
> + .item_vlan = {
> + .tci = l2tpv2_encap_conf.vlan_tci,
> + .inner_type = 0,
> + },
> + .item_ipv4.hdr = {
> + .src_addr = l2tpv2_encap_conf.ipv4_src,
> + .dst_addr = l2tpv2_encap_conf.ipv4_dst,
> + },
> + .item_udp.hdr = {
> + .src_port = l2tpv2_encap_conf.udp_src,
> + .dst_port = l2tpv2_encap_conf.udp_dst,
> + },
> + };
> + memcpy(action_l2tpv2_encap_data->item_eth.dst.addr_bytes,
> + l2tpv2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
> + memcpy(action_l2tpv2_encap_data->item_eth.src.addr_bytes,
> + l2tpv2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
> + if (!l2tpv2_encap_conf.select_ipv4) {
> + memcpy(&action_l2tpv2_encap_data->item_ipv6.hdr.src_addr,
> + &l2tpv2_encap_conf.ipv6_src,
> + sizeof(l2tpv2_encap_conf.ipv6_src));
> + memcpy(&action_l2tpv2_encap_data->item_ipv6.hdr.dst_addr,
> + &l2tpv2_encap_conf.ipv6_dst,
> + sizeof(l2tpv2_encap_conf.ipv6_dst));
> + action_l2tpv2_encap_data->items[2] = (struct rte_flow_item){
> + .type = RTE_FLOW_ITEM_TYPE_IPV6,
> + .spec = &action_l2tpv2_encap_data->item_ipv6,
> + .mask = &rte_flow_item_ipv6_mask,
> + };
> + }
> + if (!l2tpv2_encap_conf.select_vlan)
> + action_l2tpv2_encap_data->items[1].type =
> + RTE_FLOW_ITEM_TYPE_VOID;
> + if (l2tpv2_encap_conf.select_tos_ttl) {
> + if (l2tpv2_encap_conf.select_ipv4) {
> + static struct rte_flow_item_ipv4 ipv4_mask_tos;
> +
> + memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
> + sizeof(ipv4_mask_tos));
> + ipv4_mask_tos.hdr.type_of_service = 0xff;
> + ipv4_mask_tos.hdr.time_to_live = 0xff;
> + action_l2tpv2_encap_data->item_ipv4.hdr.type_of_service =
> + l2tpv2_encap_conf.ip_tos;
> + action_l2tpv2_encap_data->item_ipv4.hdr.time_to_live =
> + l2tpv2_encap_conf.ip_ttl;
> + action_l2tpv2_encap_data->items[2].mask =
> + &ipv4_mask_tos;
> + } else {
> + static struct rte_flow_item_ipv6 ipv6_mask_tos;
> +
> + memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
> + sizeof(ipv6_mask_tos));
> + ipv6_mask_tos.hdr.vtc_flow |=
> + RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
> + ipv6_mask_tos.hdr.hop_limits = 0xff;
> + action_l2tpv2_encap_data->item_ipv6.hdr.vtc_flow |=
> + rte_cpu_to_be_32
> + ((uint32_t)l2tpv2_encap_conf.ip_tos <<
> + RTE_IPV6_HDR_TC_SHIFT);
> + action_l2tpv2_encap_data->item_ipv6.hdr.hop_limits =
> + l2tpv2_encap_conf.ip_ttl;
> + action_l2tpv2_encap_data->items[2].mask =
> + &ipv6_mask_tos;
> + }
> + }
> +
> + if (0xc800 == (l2tpv2_encap_conf.flags_version & 0xcb00)) {
> + action_l2tpv2_encap_data->item_l2tpv2.hdr.type3.session_id =
> + l2tpv2_encap_conf.session_id;
> + } else if (0x4000 == (l2tpv2_encap_conf.flags_version & 0xcb00)) {
> + action_l2tpv2_encap_data->item_l2tpv2.hdr.type6.session_id =
> + l2tpv2_encap_conf.session_id;
> + }
> +
> + return 0;
> +}
> +
> +/** Parse l2tpv2 encap action. */
> +static int
> +parse_vc_action_l2tpv2_encap(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_l2tpv2_encap_data *action_l2tpv2_encap_data;
> + 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;
> + action_l2tpv2_encap_data = ctx->object;
> + parse_setup_l2tpv2_encap_data(action_l2tpv2_encap_data);
> + action->conf = &action_l2tpv2_encap_data->conf;
> + return ret;
> +}
> +
> /** Parse l2 encap action. */
> static int
> parse_vc_action_l2_encap(struct context *ctx, const struct token *token, @@ -8333,6 +8718,12 @@
> flow_item_default_mask(const struct rte_flow_item *item)
> case RTE_FLOW_ITEM_TYPE_PFCP:
> mask = &rte_flow_item_pfcp_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;
> }
> @@ -8432,6 +8823,11 @@ cmd_set_raw_parsed_sample(const struct buffer *in)
> parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
> action->conf = &sample_nvgre_encap[idx];
> break;
> + case RTE_FLOW_ACTION_TYPE_L2TPV2_ENCAP:
> + size = sizeof(struct rte_flow_action_l2tpv2_encap);
> + parse_setup_l2tpv2_encap_data(&sample_l2tpv2_encap[idx]);
> + action->conf = &sample_l2tpv2_encap[idx];
> + break;
> default:
> fprintf(stderr, "Error - Not supported action\n");
> return;
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index e9d9db06ce..c744799b46
> 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -567,6 +567,28 @@ struct nvgre_encap_conf {
>
> extern struct nvgre_encap_conf nvgre_encap_conf;
>
> +/* L2TPV2 encap/decap parameters. */
> +struct l2tpv2_encap_conf {
> + uint32_t select_ipv4:1;
> + uint32_t select_vlan:1;
> + uint32_t select_tos_ttl:1;
> + rte_be16_t flags_version;
> + rte_be16_t session_id;
> + rte_be16_t udp_src;
> + rte_be16_t udp_dst;
> + rte_be32_t ipv4_src;
> + rte_be32_t ipv4_dst;
> + uint8_t ipv6_src[16];
> + uint8_t ipv6_dst[16];
> + rte_be16_t vlan_tci;
> + uint8_t ip_tos;
> + uint8_t ip_ttl;
> + uint8_t eth_src[RTE_ETHER_ADDR_LEN];
> + uint8_t eth_dst[RTE_ETHER_ADDR_LEN];
> +};
> +
> +extern struct l2tpv2_encap_conf l2tpv2_encap_conf;
> +
> /* L2 encap parameters. */
> struct l2_encap_conf {
> uint32_t select_ipv4:1;
> --
> 2.25.1
Best,
Ori
@@ -13300,6 +13300,247 @@ cmdline_parse_inst_t cmd_set_nvgre_with_vlan = {
},
};
+/** Set L2TPV2 encapsulation details */
+struct cmd_set_l2tpv2_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t l2tpv2;
+ cmdline_fixed_string_t pos_token;
+ cmdline_fixed_string_t ip_version;
+ uint32_t vlan_present:1;
+ uint16_t flags_version;
+ uint16_t session_id;
+ uint16_t udp_src;
+ uint16_t udp_dst;
+ cmdline_ipaddr_t ip_src;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t tci;
+ uint8_t tos;
+ uint8_t ttl;
+ struct rte_ether_addr eth_src;
+ struct rte_ether_addr eth_dst;
+};
+
+cmdline_parse_token_string_t cmd_set_l2tpv2_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, set, "set");
+cmdline_parse_token_string_t cmd_set_l2tpv2_l2tpv2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, l2tpv2, "l2tpv2");
+cmdline_parse_token_string_t cmd_set_l2tpv2_l2tpv2_tos_ttl =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, l2tpv2,
+ "l2tpv2-tos-ttl");
+cmdline_parse_token_string_t cmd_set_l2tpv2_l2tpv2_with_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, l2tpv2,
+ "l2tpv2-with-vlan");
+cmdline_parse_token_string_t cmd_set_l2tpv2_ip_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "ip-version");
+cmdline_parse_token_string_t cmd_set_l2tpv2_ip_version_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, ip_version,
+ "ipv4#ipv6");
+cmdline_parse_token_string_t cmd_set_l2tpv2_flags_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "flags_version");
+cmdline_parse_token_num_t cmd_set_l2tpv2_flags_version_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, flags_version,
+ RTE_UINT16);
+cmdline_parse_token_string_t cmd_set_l2tpv2_session_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "session_id");
+cmdline_parse_token_num_t cmd_set_l2tpv2_session_id_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, session_id,
+ RTE_UINT16);
+cmdline_parse_token_string_t cmd_set_l2tpv2_udp_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "udp-src");
+cmdline_parse_token_num_t cmd_set_l2tpv2_udp_src_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, udp_src,
+ RTE_UINT16);
+cmdline_parse_token_string_t cmd_set_l2tpv2_udp_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "udp-dst");
+cmdline_parse_token_num_t cmd_set_l2tpv2_udp_dst_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, udp_dst,
+ RTE_UINT16);
+cmdline_parse_token_string_t cmd_set_l2tpv2_ip_tos =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "ip-tos");
+cmdline_parse_token_num_t cmd_set_l2tpv2_ip_tos_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, tos, RTE_UINT8);
+cmdline_parse_token_string_t cmd_set_l2tpv2_ip_ttl =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "ip-ttl");
+cmdline_parse_token_num_t cmd_set_l2tpv2_ip_ttl_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, ttl, RTE_UINT8);
+cmdline_parse_token_string_t cmd_set_l2tpv2_ip_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "ip-src");
+cmdline_parse_token_ipaddr_t cmd_set_l2tpv2_ip_src_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_l2tpv2_result, ip_src);
+cmdline_parse_token_string_t cmd_set_l2tpv2_ip_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "ip-dst");
+cmdline_parse_token_ipaddr_t cmd_set_l2tpv2_ip_dst_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_l2tpv2_result, ip_dst);
+cmdline_parse_token_string_t cmd_set_l2tpv2_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "vlan-tci");
+cmdline_parse_token_num_t cmd_set_l2tpv2_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, tci, RTE_UINT16);
+cmdline_parse_token_string_t cmd_set_l2tpv2_eth_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "eth-src");
+cmdline_parse_token_etheraddr_t cmd_set_l2tpv2_eth_src_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_l2tpv2_result, eth_src);
+cmdline_parse_token_string_t cmd_set_l2tpv2_eth_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token,
+ "eth-dst");
+cmdline_parse_token_etheraddr_t cmd_set_l2tpv2_eth_dst_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_l2tpv2_result, eth_dst);
+
+static void cmd_set_l2tpv2_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_l2tpv2_result *res = parsed_result;
+
+ l2tpv2_encap_conf.select_tos_ttl = 0;
+ if (strcmp(res->l2tpv2, "l2tpv2") == 0)
+ l2tpv2_encap_conf.select_vlan = 0;
+ else if (strcmp(res->l2tpv2, "l2tpv2-with-vlan") == 0)
+ l2tpv2_encap_conf.select_vlan = 1;
+ else if (strcmp(res->l2tpv2, "l2tpv2-tos-ttl") == 0) {
+ l2tpv2_encap_conf.select_vlan = 0;
+ l2tpv2_encap_conf.select_tos_ttl = 1;
+ }
+ if (strcmp(res->ip_version, "ipv4") == 0)
+ l2tpv2_encap_conf.select_ipv4 = 1;
+ else if (strcmp(res->ip_version, "ipv6") == 0)
+ l2tpv2_encap_conf.select_ipv4 = 0;
+ else
+ return;
+
+ l2tpv2_encap_conf.flags_version = res->flags_version;
+ l2tpv2_encap_conf.session_id = res->session_id;
+ l2tpv2_encap_conf.udp_src = res->udp_src;
+ l2tpv2_encap_conf.udp_dst = res->udp_dst;
+ l2tpv2_encap_conf.ip_tos = res->tos;
+ l2tpv2_encap_conf.ip_ttl = res->ttl;
+ if (l2tpv2_encap_conf.select_ipv4) {
+ IPV4_ADDR_TO_UINT(res->ip_src, l2tpv2_encap_conf.ipv4_src);
+ IPV4_ADDR_TO_UINT(res->ip_dst, l2tpv2_encap_conf.ipv4_dst);
+ } else {
+ IPV6_ADDR_TO_ARRAY(res->ip_src, l2tpv2_encap_conf.ipv6_src);
+ IPV6_ADDR_TO_ARRAY(res->ip_dst, l2tpv2_encap_conf.ipv6_dst);
+ }
+ if (l2tpv2_encap_conf.select_vlan)
+ l2tpv2_encap_conf.vlan_tci = rte_cpu_to_be_16(res->tci);
+ rte_memcpy(l2tpv2_encap_conf.eth_src, res->eth_src.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+ rte_memcpy(l2tpv2_encap_conf.eth_dst, res->eth_dst.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+}
+
+cmdline_parse_inst_t cmd_set_l2tpv2 = {
+ .f = cmd_set_l2tpv2_parsed,
+ .data = NULL,
+ .help_str = "set l2tpv2 ip-version ipv4|ipv6 flags_version"
+ " <flags_version> session_id <session_id> udp-src <udp-src>"
+ " udp-dst <udp-dst> ip-src <ip-src> ip-dst <ip-dst> eth-src"
+ " <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_l2tpv2_set,
+ (void *)&cmd_set_l2tpv2_l2tpv2,
+ (void *)&cmd_set_l2tpv2_ip_version,
+ (void *)&cmd_set_l2tpv2_ip_version_value,
+ (void *)&cmd_set_l2tpv2_flags_version,
+ (void *)&cmd_set_l2tpv2_flags_version_value,
+ (void *)&cmd_set_l2tpv2_session_id,
+ (void *)&cmd_set_l2tpv2_session_id_value,
+ (void *)&cmd_set_l2tpv2_udp_src,
+ (void *)&cmd_set_l2tpv2_udp_src_value,
+ (void *)&cmd_set_l2tpv2_udp_dst,
+ (void *)&cmd_set_l2tpv2_udp_dst_value,
+ (void *)&cmd_set_l2tpv2_ip_src,
+ (void *)&cmd_set_l2tpv2_ip_src_value,
+ (void *)&cmd_set_l2tpv2_ip_dst,
+ (void *)&cmd_set_l2tpv2_ip_dst_value,
+ (void *)&cmd_set_l2tpv2_eth_src,
+ (void *)&cmd_set_l2tpv2_eth_src_value,
+ (void *)&cmd_set_l2tpv2_eth_dst,
+ (void *)&cmd_set_l2tpv2_eth_dst_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_l2tpv2_tos_ttl = {
+ .f = cmd_set_l2tpv2_parsed,
+ .data = NULL,
+ .help_str = "set l2tpv2-tos-ttl ip-version ipv4|ipv6 flags_version"
+ " <flags_version> session_id <session_id> udp-src <udp-src>"
+ " udp-dst <udp-dst> ip-tos <ip-tos> ip-ttl <ip-ttl> ip-src"
+ " <ip-src> ip-dst <ip-dst> eth-src <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_l2tpv2_set,
+ (void *)&cmd_set_l2tpv2_l2tpv2_tos_ttl,
+ (void *)&cmd_set_l2tpv2_ip_version,
+ (void *)&cmd_set_l2tpv2_ip_version_value,
+ (void *)&cmd_set_l2tpv2_flags_version,
+ (void *)&cmd_set_l2tpv2_flags_version_value,
+ (void *)&cmd_set_l2tpv2_session_id,
+ (void *)&cmd_set_l2tpv2_session_id_value,
+ (void *)&cmd_set_l2tpv2_udp_src,
+ (void *)&cmd_set_l2tpv2_udp_src_value,
+ (void *)&cmd_set_l2tpv2_udp_dst,
+ (void *)&cmd_set_l2tpv2_udp_dst_value,
+ (void *)&cmd_set_l2tpv2_ip_tos,
+ (void *)&cmd_set_l2tpv2_ip_tos_value,
+ (void *)&cmd_set_l2tpv2_ip_ttl,
+ (void *)&cmd_set_l2tpv2_ip_ttl_value,
+ (void *)&cmd_set_l2tpv2_ip_src,
+ (void *)&cmd_set_l2tpv2_ip_src_value,
+ (void *)&cmd_set_l2tpv2_ip_dst,
+ (void *)&cmd_set_l2tpv2_ip_dst_value,
+ (void *)&cmd_set_l2tpv2_eth_src,
+ (void *)&cmd_set_l2tpv2_eth_src_value,
+ (void *)&cmd_set_l2tpv2_eth_dst,
+ (void *)&cmd_set_l2tpv2_eth_dst_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_l2tpv2_with_vlan = {
+ .f = cmd_set_l2tpv2_parsed,
+ .data = NULL,
+ .help_str = "set l2tpv2-with-vlan ip-version ipv4|ipv6 flags_version"
+ " <flags_version> session_id <session_id> udp-src <udp-src>"
+ " udp-dst <udp-dst> ip-src <ip-src> ip-dst <ip-dst> vlan-tci"
+ " <vlan-tci> eth-src <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_l2tpv2_set,
+ (void *)&cmd_set_l2tpv2_l2tpv2_with_vlan,
+ (void *)&cmd_set_l2tpv2_ip_version,
+ (void *)&cmd_set_l2tpv2_ip_version_value,
+ (void *)&cmd_set_l2tpv2_flags_version,
+ (void *)&cmd_set_l2tpv2_flags_version_value,
+ (void *)&cmd_set_l2tpv2_session_id,
+ (void *)&cmd_set_l2tpv2_session_id_value,
+ (void *)&cmd_set_l2tpv2_udp_src,
+ (void *)&cmd_set_l2tpv2_udp_src_value,
+ (void *)&cmd_set_l2tpv2_udp_dst,
+ (void *)&cmd_set_l2tpv2_udp_dst_value,
+ (void *)&cmd_set_l2tpv2_ip_src,
+ (void *)&cmd_set_l2tpv2_ip_src_value,
+ (void *)&cmd_set_l2tpv2_ip_dst,
+ (void *)&cmd_set_l2tpv2_ip_dst_value,
+ (void *)&cmd_set_l2tpv2_vlan,
+ (void *)&cmd_set_l2tpv2_vlan_value,
+ (void *)&cmd_set_l2tpv2_eth_src,
+ (void *)&cmd_set_l2tpv2_eth_src_value,
+ (void *)&cmd_set_l2tpv2_eth_dst,
+ (void *)&cmd_set_l2tpv2_eth_dst_value,
+ NULL,
+ },
+};
+
/** Set L2 encapsulation details */
struct cmd_set_l2_encap_result {
cmdline_fixed_string_t set;
@@ -17774,6 +18015,9 @@ cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *)&cmd_set_vxlan_with_vlan,
(cmdline_parse_inst_t *)&cmd_set_nvgre,
(cmdline_parse_inst_t *)&cmd_set_nvgre_with_vlan,
+ (cmdline_parse_inst_t *)&cmd_set_l2tpv2,
+ (cmdline_parse_inst_t *)&cmd_set_l2tpv2_tos_ttl,
+ (cmdline_parse_inst_t *)&cmd_set_l2tpv2_with_vlan,
(cmdline_parse_inst_t *)&cmd_set_l2_encap,
(cmdline_parse_inst_t *)&cmd_set_l2_encap_with_vlan,
(cmdline_parse_inst_t *)&cmd_set_l2_decap,
@@ -306,6 +306,23 @@ enum index {
ITEM_POL_PORT,
ITEM_POL_METER,
ITEM_POL_POLICY,
+ 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,
@@ -376,6 +393,8 @@ enum index {
ACTION_VXLAN_DECAP,
ACTION_NVGRE_ENCAP,
ACTION_NVGRE_DECAP,
+ ACTION_L2TPV2_ENCAP,
+ ACTION_L2TPV2_DECAP,
ACTION_L2_ENCAP,
ACTION_L2_DECAP,
ACTION_MPLSOGRE_ENCAP,
@@ -581,6 +600,44 @@ struct action_nvgre_encap_data {
struct rte_flow_item_nvgre item_nvgre;
};
+struct l2tpv2_encap_conf l2tpv2_encap_conf = {
+ .select_ipv4 = 1,
+ .select_vlan = 0,
+ .select_tos_ttl = 0,
+ .flags_version = 0,
+ .session_id = 0,
+ .udp_src = 0,
+ .udp_dst = 1701,
+ .ipv4_src = RTE_IPV4(127, 0, 0, 1),
+ .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
+ .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x01",
+ .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x11\x11",
+ .vlan_tci = 0,
+ .ip_tos = 0,
+ .ip_ttl = 255,
+ .eth_src = "\x00\x00\x00\x00\x00\x00",
+ .eth_dst = "\xff\xff\xff\xff\xff\xff",
+};
+
+/** Maximum number of items in struct rte_flow_action_l2tpv2_encap. */
+#define ACTION_L2TPV2_ENCAP_ITEMS_NUM 6
+
+/** Storage for struct rte_flow_action_l2tpv2_encap including external data. */
+struct action_l2tpv2_encap_data {
+ struct rte_flow_action_l2tpv2_encap conf;
+ struct rte_flow_item items[ACTION_L2TPV2_ENCAP_ITEMS_NUM];
+ struct rte_flow_item_eth item_eth;
+ struct rte_flow_item_vlan item_vlan;
+ union {
+ struct rte_flow_item_ipv4 item_ipv4;
+ struct rte_flow_item_ipv6 item_ipv6;
+ };
+ struct rte_flow_item_udp item_udp;
+ struct rte_flow_item_l2tpv2 item_l2tpv2;
+};
+
struct l2_encap_conf l2_encap_conf;
struct l2_decap_conf l2_decap_conf;
@@ -614,6 +671,7 @@ struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
+struct action_l2tpv2_encap_data sample_l2tpv2_encap[RAW_SAMPLE_CONFS_MAX_NUM];
struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
@@ -999,6 +1057,8 @@ static const enum index next_item[] = {
ITEM_GENEVE_OPT,
ITEM_INTEGRITY,
ITEM_CONNTRACK,
+ ITEM_L2TPV2,
+ ITEM_PPP,
END_SET,
ZERO,
};
@@ -1367,6 +1427,31 @@ static const enum index item_integrity_lv[] = {
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,
@@ -1400,6 +1485,8 @@ static const enum index next_action[] = {
ACTION_VXLAN_DECAP,
ACTION_NVGRE_ENCAP,
ACTION_NVGRE_DECAP,
+ ACTION_L2TPV2_ENCAP,
+ ACTION_L2TPV2_DECAP,
ACTION_L2_ENCAP,
ACTION_L2_DECAP,
ACTION_MPLSOGRE_ENCAP,
@@ -1687,6 +1774,7 @@ static const enum index next_action_sample[] = {
ACTION_RAW_ENCAP,
ACTION_VXLAN_ENCAP,
ACTION_NVGRE_ENCAP,
+ ACTION_L2TPV2_ENCAP,
ACTION_NEXT,
ZERO,
};
@@ -1757,6 +1845,9 @@ static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
const char *, unsigned int, void *,
unsigned int);
+static int parse_vc_action_l2tpv2_encap(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
static int parse_vc_action_l2_encap(struct context *, const struct token *,
const char *, unsigned int, void *,
unsigned int);
@@ -3606,6 +3697,136 @@ static const struct token token_list[] = {
item_param),
.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
},
+ [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_MSG_DATA_L_LENGTH] = {
+ .name = "length",
+ .help = "message length",
+ .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type7.tunnel_id)),
+ },
+ [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
+ .name = "tunnel_id",
+ .help = "tunnel identifier",
+ .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type7.tunnel_id)),
+ },
+ [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
+ .name = "session_id",
+ .help = "session identifier",
+ .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type7.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_MSG_CTRL_LENGTH] = {
+ .name = "length",
+ .help = "message length",
+ .next = NEXT(item_l2tpv2, 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(item_l2tpv2, 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(item_l2tpv2, 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(item_l2tpv2, 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(item_l2tpv2, 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, 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, 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, proto_id)),
+ },
/* Validate/create actions. */
[ACTIONS] = {
.name = "actions",
@@ -4125,6 +4346,24 @@ static const struct token token_list[] = {
.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
.call = parse_vc,
},
+ [ACTION_L2TPV2_ENCAP] = {
+ .name = "l2tpv2_encap",
+ .help = "L2TPV2 encapsulation, uses configuration set by \"set"
+ " l2tpv2\"",
+ .priv = PRIV_ACTION(L2TPV2_ENCAP,
+ sizeof(struct action_l2tpv2_encap_data)),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_l2tpv2_encap,
+ },
+ [ACTION_L2TPV2_DECAP] = {
+ .name = "l2tpv2_decap",
+ .help = "Performs a decapsulation action by stripping all"
+ " headers of the L2TPV2 tunnel network overlay from the"
+ " matched flow.",
+ .priv = PRIV_ACTION(L2TPV2_DECAP, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
[ACTION_L2_ENCAP] = {
.name = "l2_encap",
.help = "l2 encap, uses configuration set by"
@@ -5907,6 +6146,152 @@ parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
return ret;
}
+/** Setup L2TPV2 encap configuration. */
+static int
+parse_setup_l2tpv2_encap_data(struct action_l2tpv2_encap_data *action_l2tpv2_encap_data)
+{
+ /* Set up default configuration. */
+ *action_l2tpv2_encap_data = (struct action_l2tpv2_encap_data){
+ .conf = (struct rte_flow_action_l2tpv2_encap){
+ .definition = action_l2tpv2_encap_data->items,
+ },
+ .items = {
+ {
+ .type = RTE_FLOW_ITEM_TYPE_ETH,
+ .spec = &action_l2tpv2_encap_data->item_eth,
+ .mask = &rte_flow_item_eth_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_VLAN,
+ .spec = &action_l2tpv2_encap_data->item_vlan,
+ .mask = &rte_flow_item_vlan_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_IPV4,
+ .spec = &action_l2tpv2_encap_data->item_ipv4,
+ .mask = &rte_flow_item_ipv4_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_UDP,
+ .spec = &action_l2tpv2_encap_data->item_udp,
+ .mask = &rte_flow_item_udp_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_L2TPV2,
+ .spec = &action_l2tpv2_encap_data->item_l2tpv2,
+ .mask = &rte_flow_item_l2tpv2_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_END,
+ },
+ },
+ .item_eth.type = 0,
+ .item_vlan = {
+ .tci = l2tpv2_encap_conf.vlan_tci,
+ .inner_type = 0,
+ },
+ .item_ipv4.hdr = {
+ .src_addr = l2tpv2_encap_conf.ipv4_src,
+ .dst_addr = l2tpv2_encap_conf.ipv4_dst,
+ },
+ .item_udp.hdr = {
+ .src_port = l2tpv2_encap_conf.udp_src,
+ .dst_port = l2tpv2_encap_conf.udp_dst,
+ },
+ };
+ memcpy(action_l2tpv2_encap_data->item_eth.dst.addr_bytes,
+ l2tpv2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
+ memcpy(action_l2tpv2_encap_data->item_eth.src.addr_bytes,
+ l2tpv2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
+ if (!l2tpv2_encap_conf.select_ipv4) {
+ memcpy(&action_l2tpv2_encap_data->item_ipv6.hdr.src_addr,
+ &l2tpv2_encap_conf.ipv6_src,
+ sizeof(l2tpv2_encap_conf.ipv6_src));
+ memcpy(&action_l2tpv2_encap_data->item_ipv6.hdr.dst_addr,
+ &l2tpv2_encap_conf.ipv6_dst,
+ sizeof(l2tpv2_encap_conf.ipv6_dst));
+ action_l2tpv2_encap_data->items[2] = (struct rte_flow_item){
+ .type = RTE_FLOW_ITEM_TYPE_IPV6,
+ .spec = &action_l2tpv2_encap_data->item_ipv6,
+ .mask = &rte_flow_item_ipv6_mask,
+ };
+ }
+ if (!l2tpv2_encap_conf.select_vlan)
+ action_l2tpv2_encap_data->items[1].type =
+ RTE_FLOW_ITEM_TYPE_VOID;
+ if (l2tpv2_encap_conf.select_tos_ttl) {
+ if (l2tpv2_encap_conf.select_ipv4) {
+ static struct rte_flow_item_ipv4 ipv4_mask_tos;
+
+ memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
+ sizeof(ipv4_mask_tos));
+ ipv4_mask_tos.hdr.type_of_service = 0xff;
+ ipv4_mask_tos.hdr.time_to_live = 0xff;
+ action_l2tpv2_encap_data->item_ipv4.hdr.type_of_service =
+ l2tpv2_encap_conf.ip_tos;
+ action_l2tpv2_encap_data->item_ipv4.hdr.time_to_live =
+ l2tpv2_encap_conf.ip_ttl;
+ action_l2tpv2_encap_data->items[2].mask =
+ &ipv4_mask_tos;
+ } else {
+ static struct rte_flow_item_ipv6 ipv6_mask_tos;
+
+ memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
+ sizeof(ipv6_mask_tos));
+ ipv6_mask_tos.hdr.vtc_flow |=
+ RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
+ ipv6_mask_tos.hdr.hop_limits = 0xff;
+ action_l2tpv2_encap_data->item_ipv6.hdr.vtc_flow |=
+ rte_cpu_to_be_32
+ ((uint32_t)l2tpv2_encap_conf.ip_tos <<
+ RTE_IPV6_HDR_TC_SHIFT);
+ action_l2tpv2_encap_data->item_ipv6.hdr.hop_limits =
+ l2tpv2_encap_conf.ip_ttl;
+ action_l2tpv2_encap_data->items[2].mask =
+ &ipv6_mask_tos;
+ }
+ }
+
+ if (0xc800 == (l2tpv2_encap_conf.flags_version & 0xcb00)) {
+ action_l2tpv2_encap_data->item_l2tpv2.hdr.type3.session_id =
+ l2tpv2_encap_conf.session_id;
+ } else if (0x4000 == (l2tpv2_encap_conf.flags_version & 0xcb00)) {
+ action_l2tpv2_encap_data->item_l2tpv2.hdr.type6.session_id =
+ l2tpv2_encap_conf.session_id;
+ }
+
+ return 0;
+}
+
+/** Parse l2tpv2 encap action. */
+static int
+parse_vc_action_l2tpv2_encap(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_l2tpv2_encap_data *action_l2tpv2_encap_data;
+ 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;
+ action_l2tpv2_encap_data = ctx->object;
+ parse_setup_l2tpv2_encap_data(action_l2tpv2_encap_data);
+ action->conf = &action_l2tpv2_encap_data->conf;
+ return ret;
+}
+
/** Parse l2 encap action. */
static int
parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
@@ -8333,6 +8718,12 @@ flow_item_default_mask(const struct rte_flow_item *item)
case RTE_FLOW_ITEM_TYPE_PFCP:
mask = &rte_flow_item_pfcp_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;
}
@@ -8432,6 +8823,11 @@ cmd_set_raw_parsed_sample(const struct buffer *in)
parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
action->conf = &sample_nvgre_encap[idx];
break;
+ case RTE_FLOW_ACTION_TYPE_L2TPV2_ENCAP:
+ size = sizeof(struct rte_flow_action_l2tpv2_encap);
+ parse_setup_l2tpv2_encap_data(&sample_l2tpv2_encap[idx]);
+ action->conf = &sample_l2tpv2_encap[idx];
+ break;
default:
fprintf(stderr, "Error - Not supported action\n");
return;
@@ -567,6 +567,28 @@ struct nvgre_encap_conf {
extern struct nvgre_encap_conf nvgre_encap_conf;
+/* L2TPV2 encap/decap parameters. */
+struct l2tpv2_encap_conf {
+ uint32_t select_ipv4:1;
+ uint32_t select_vlan:1;
+ uint32_t select_tos_ttl:1;
+ rte_be16_t flags_version;
+ rte_be16_t session_id;
+ rte_be16_t udp_src;
+ rte_be16_t udp_dst;
+ rte_be32_t ipv4_src;
+ rte_be32_t ipv4_dst;
+ uint8_t ipv6_src[16];
+ uint8_t ipv6_dst[16];
+ rte_be16_t vlan_tci;
+ uint8_t ip_tos;
+ uint8_t ip_ttl;
+ uint8_t eth_src[RTE_ETHER_ADDR_LEN];
+ uint8_t eth_dst[RTE_ETHER_ADDR_LEN];
+};
+
+extern struct l2tpv2_encap_conf l2tpv2_encap_conf;
+
/* L2 encap parameters. */
struct l2_encap_conf {
uint32_t select_ipv4:1;