From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id F2306A0C4B; Fri, 15 Oct 2021 11:59:09 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0E0E3411FF; Fri, 15 Oct 2021 11:59:03 +0200 (CEST) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by mails.dpdk.org (Postfix) with ESMTP id 6321D40692 for ; Fri, 15 Oct 2021 11:59:01 +0200 (CEST) X-IronPort-AV: E=McAfee;i="6200,9189,10137"; a="227840739" X-IronPort-AV: E=Sophos;i="5.85,375,1624345200"; d="scan'208";a="227840739" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Oct 2021 02:59:00 -0700 X-IronPort-AV: E=Sophos;i="5.85,375,1624345200"; d="scan'208";a="492394850" Received: from dpdk.cd.intel.com ([10.240.178.133]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Oct 2021 02:58:56 -0700 From: Jie Wang To: dev@dpdk.org Cc: orika@nvidia.com, ferruh.yigit@intel.com, thomas@monjalon.net, andrew.rybchenko@oktetlabs.ru, xiaoyun.li@intel.com, stevex.yang@intel.com, jingjing.wu@intel.com, beilei.xing@intel.com, wenjun1.wu@intel.com, Jie Wang Date: Fri, 15 Oct 2021 17:58:23 +0800 Message-Id: <20211015095823.701188-4-jie1x.wang@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211015095823.701188-1-jie1x.wang@intel.com> References: <20211012102508.275790-1-jie1x.wang@intel.com> <20211015095823.701188-1-jie1x.wang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [PATCH v3 3/3] app/testpmd: support L2TPV2 and PPP protocol pattern X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add support for test-pmd to parse protocol pattern L2TPv2 and PPP. Signed-off-by: Wenjun Wu Signed-off-by: Jie Wang --- 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" + " session_id udp-src " + " udp-dst ip-src ip-dst eth-src" + " 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" + " session_id udp-src " + " udp-dst ip-tos ip-ttl ip-src" + " ip-dst eth-src 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" + " session_id udp-src " + " udp-dst ip-src ip-dst vlan-tci" + " eth-src 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; 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