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 A2E6EA0547; Thu, 28 Oct 2021 13:10:35 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 09EE44111A; Thu, 28 Oct 2021 13:10:34 +0200 (CEST) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by mails.dpdk.org (Postfix) with ESMTP id 0A09C41100 for ; Thu, 28 Oct 2021 13:10:31 +0200 (CEST) X-IronPort-AV: E=McAfee;i="6200,9189,10150"; a="293840852" X-IronPort-AV: E=Sophos;i="5.87,189,1631602800"; d="scan'208";a="293840852" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Oct 2021 04:10:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.87,189,1631602800"; d="scan'208";a="665368357" Received: from fmsmsx601.amr.corp.intel.com ([10.18.126.81]) by orsmga005.jf.intel.com with ESMTP; 28 Oct 2021 04:10:31 -0700 Received: from shsmsx601.ccr.corp.intel.com (10.109.6.141) by fmsmsx601.amr.corp.intel.com (10.18.126.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2242.12; Thu, 28 Oct 2021 04:10:30 -0700 Received: from shsmsx601.ccr.corp.intel.com (10.109.6.141) by SHSMSX601.ccr.corp.intel.com (10.109.6.141) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2242.12; Thu, 28 Oct 2021 19:10:28 +0800 Received: from shsmsx601.ccr.corp.intel.com ([10.109.6.141]) by SHSMSX601.ccr.corp.intel.com ([10.109.6.141]) with mapi id 15.01.2242.012; Thu, 28 Oct 2021 19:10:28 +0800 From: "Zhang, Qi Z" To: "Guo, Junfeng" , "Wu, Jingjing" , "Xing, Beilei" CC: "dev@dpdk.org" , "Yigit, Ferruh" , "Xu, Ting" Thread-Topic: [PATCH v7 4/4] net/ice: enable protocol agnostic flow offloading in FDIR Thread-Index: AQHXy9w5YMJ5lBKV7kyC+jt47SYx6qvoPx6A Date: Thu, 28 Oct 2021 11:10:28 +0000 Message-ID: References: <20211028083416.1490834-5-junfeng.guo@intel.com> <20211028091346.1674650-1-junfeng.guo@intel.com> <20211028091346.1674650-5-junfeng.guo@intel.com> In-Reply-To: <20211028091346.1674650-5-junfeng.guo@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-reaction: no-action dlp-version: 11.6.200.16 dlp-product: dlpe-windows x-originating-ip: [10.239.127.36] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH v7 4/4] net/ice: enable protocol agnostic flow offloading in FDIR 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" > -----Original Message----- > From: Guo, Junfeng > Sent: Thursday, October 28, 2021 5:14 PM > To: Zhang, Qi Z ; Wu, Jingjing ; > Xing, Beilei > Cc: dev@dpdk.org; Yigit, Ferruh ; Xu, Ting > ; Guo, Junfeng > Subject: [PATCH v7 4/4] net/ice: enable protocol agnostic flow offloading= in > FDIR >=20 > Protocol agnostic flow offloading in Flow Director is enabled by this pat= ch > based on the Parser Library, using existing rte_flow raw API. >=20 > Note that the raw flow requires: > 1. byte string of raw target packet bits. > 2. byte string of mask of target packet. >=20 > Here is an example: > FDIR matching ipv4 dst addr with 1.2.3.4 and redirect to queue 3: >=20 > flow create 0 ingress pattern raw \ > pattern spec \ > 0000000000000000000000000800450000140000400040100000000000000 > 1020304 \ pattern mask \ > 000000000000000000000000000000000000000000000000000000000000ff > ffffff \ / end actions queue index 3 / mark id 3 / end >=20 > Note that mask of some key bits (e.g., 0x0800 to indicate ipv4 proto) is > optional in our cases. To avoid redundancy, we just omit the mask of 0x08= 00 > (with 0xFFFF) in the mask byte string example. The prefix '0x' for the sp= ec and > mask byte (hex) strings are also omitted here. >=20 > Signed-off-by: Junfeng Guo > --- > doc/guides/rel_notes/release_21_11.rst | 1 + > drivers/net/ice/ice_ethdev.h | 17 ++ > drivers/net/ice/ice_fdir_filter.c | 260 +++++++++++++++++++++++++ > drivers/net/ice/ice_generic_flow.c | 7 + > drivers/net/ice/ice_generic_flow.h | 3 + > 5 files changed, 288 insertions(+) >=20 > diff --git a/doc/guides/rel_notes/release_21_11.rst > b/doc/guides/rel_notes/release_21_11.rst > index 9c13ceed1c..cc449a4340 100644 > --- a/doc/guides/rel_notes/release_21_11.rst > +++ b/doc/guides/rel_notes/release_21_11.rst > @@ -167,6 +167,7 @@ New Features >=20 > * **Updated Intel ice driver.** >=20 > + * Added protocol agnostic flow offloading support in Flow Director. > * Added 1PPS out support by a devargs. > * Added IPv4 and L4 (TCP/UDP/SCTP) checksum hash support in RSS flow. > * Added DEV_RX_OFFLOAD_TIMESTAMP support. > diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h = index > 599e0028f7..441242ee89 100644 > --- a/drivers/net/ice/ice_ethdev.h > +++ b/drivers/net/ice/ice_ethdev.h > @@ -318,6 +318,11 @@ struct ice_fdir_filter_conf { > uint64_t input_set_o; /* used for non-tunnel or tunnel outer fields */ > uint64_t input_set_i; /* only for tunnel inner fields */ > uint32_t mark_flag; > + > + struct ice_parser_profile *prof; > + const u8 *pkt_buf; > + bool parser_ena; > + u8 pkt_len; > }; >=20 > #define ICE_MAX_FDIR_FILTER_NUM (1024 * 16) > @@ -487,6 +492,17 @@ struct ice_devargs { > uint8_t pps_out_ena; > }; >=20 > +/** > + * Structure to store fdir fv entry. > + */ > +struct ice_fdir_prof_info { > + struct LIST_ENTRY_TYPE l_entry; > + > + struct ice_parser_profile prof; > + u16 ptg; > + u64 fdir_actived_cnt; > +}; > + > /** > * Structure to store private data for each PF/VF instance. > */ > @@ -509,6 +525,7 @@ struct ice_adapter { > struct rte_timecounter rx_tstamp_tc; > struct rte_timecounter tx_tstamp_tc; > bool ptp_ena; > + struct LIST_HEAD_TYPE fdir_prof_list; > #ifdef RTE_ARCH_X86 > bool rx_use_avx2; > bool rx_use_avx512; > diff --git a/drivers/net/ice/ice_fdir_filter.c b/drivers/net/ice/ice_fdir= _filter.c > index bd627e3aa8..bcf105d1bd 100644 > --- a/drivers/net/ice/ice_fdir_filter.c > +++ b/drivers/net/ice/ice_fdir_filter.c > @@ -107,6 +107,7 @@ > ICE_INSET_NAT_T_ESP_SPI) >=20 > static struct ice_pattern_match_item ice_fdir_pattern_list[] =3D { > + {pattern_raw, ICE_INSET_NONE, > ICE_INSET_NONE, ICE_INSET_NONE}, > {pattern_ethertype, ICE_FDIR_INSET_ETH, > ICE_INSET_NONE, ICE_INSET_NONE}, > {pattern_eth_ipv4, ICE_FDIR_INSET_ETH_IPV4, > ICE_INSET_NONE, ICE_INSET_NONE}, > {pattern_eth_ipv4_udp, ICE_FDIR_INSET_ETH_IPV4_UDP, > ICE_INSET_NONE, ICE_INSET_NONE}, > @@ -1158,6 +1159,8 @@ ice_fdir_init(struct ice_adapter *ad) > if (ret) > return ret; >=20 > + INIT_LIST_HEAD(&ad->fdir_prof_list); > + > parser =3D &ice_fdir_parser; >=20 > return ice_register_parser(parser, ad); @@ -1188,6 +1191,24 @@ > ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type) > return 0; > } >=20 > +static int > +ice_fdir_add_del_raw(struct ice_pf *pf, > + struct ice_fdir_filter_conf *filter, > + bool add) > +{ > + struct ice_hw *hw =3D ICE_PF_TO_HW(pf); > + > + unsigned char *pkt =3D (unsigned char *)pf->fdir.prg_pkt; > + rte_memcpy(pkt, filter->pkt_buf, filter->pkt_len); > + > + struct ice_fltr_desc desc; > + memset(&desc, 0, sizeof(desc)); > + filter->input.comp_report =3D ICE_FXD_FLTR_QW0_COMP_REPORT_SW; > + ice_fdir_get_prgm_desc(hw, &filter->input, &desc, add); > + > + return ice_fdir_programming(pf, &desc); } > + > static int > ice_fdir_add_del_filter(struct ice_pf *pf, > struct ice_fdir_filter_conf *filter, @@ -1303,6 +1324,100 @@ > ice_fdir_create_filter(struct ice_adapter *ad, > struct ice_fdir_fltr_pattern key; > bool is_tun; > int ret; > + int i; > + > + if (filter->parser_ena) { > + struct ice_hw *hw =3D ICE_PF_TO_HW(pf); > + > + int id =3D ice_find_first_bit(filter->prof->ptypes, UINT16_MAX); > + u16 ctrl_vsi =3D pf->fdir.fdir_vsi->idx; > + u16 main_vsi =3D pf->main_vsi->idx; > + bool fv_found =3D false; > + u16 vsi_num; > + > + struct ice_fdir_prof_info *pi; > + LIST_FOR_EACH_ENTRY(pi, &ad->fdir_prof_list, > + ice_fdir_prof_info, l_entry) { > + if (pi->ptg !=3D hw->blk[ICE_BLK_FD].xlt1.t[id]) > + continue; > + if (!pi->fdir_actived_cnt) { > + vsi_num =3D ice_get_hw_vsi_num(hw, ctrl_vsi); > + ret =3D ice_rem_prof_id_flow(hw, ICE_BLK_FD, > + vsi_num, id); Looks like you delay the "profile remove" until next call ice_fdir_add_del_= filter,=20 Why not just do this at the exact moment that "fdir_actived_cnt =3D 0"? > + if (ret) > + return -rte_errno; > + > + vsi_num =3D ice_get_hw_vsi_num(hw, main_vsi); > + ret =3D ice_rem_prof_id_flow(hw, ICE_BLK_FD, > + vsi_num, id); > + if (ret) > + return -rte_errno; > + > + LIST_DEL(&pi->l_entry); > + continue; > + } > + for (i =3D 0; i < ICE_MAX_FV_WORDS; i++) > + if (pi->prof.fv[i].proto_id !=3D > + filter->prof->fv[i].proto_id || > + pi->prof.fv[i].offset !=3D > + filter->prof->fv[i].offset) > + break; > + if (i =3D=3D ICE_MAX_FV_WORDS) { > + fv_found =3D true; > + pi->fdir_actived_cnt++; > + break; > + } > + } > + > + if (!fv_found) { > + ret =3D ice_flow_set_hw_prof(hw, main_vsi, ctrl_vsi, > + filter->prof, ICE_BLK_FD); > + if (ret) > + return -rte_errno; > + } > + > + ret =3D ice_fdir_add_del_raw(pf, filter, true); > + if (ret) > + return -rte_errno; > + > + if (!fv_found) { > + pi =3D (struct ice_fdir_prof_info *) > + ice_malloc(hw, sizeof(*pi)); > + if (!pi) > + return ICE_ERR_NO_MEMORY; > + > + memset(&pi->prof, 0, sizeof(pi->prof)); > + > + for (i =3D 0; i < filter->prof->fv_num; i++) { > + pi->prof.fv[i].proto_id =3D > + filter->prof->fv[i].proto_id; > + pi->prof.fv[i].offset =3D > + filter->prof->fv[i].offset; > + pi->prof.fv[i].spec =3D filter->prof->fv[i].spec; > + pi->prof.fv[i].msk =3D filter->prof->fv[i].msk; > + } > + pi->ptg =3D hw->blk[ICE_BLK_FD].xlt1.t[id]; > + pi->fdir_actived_cnt =3D 1; > + > + LIST_ADD(&pi->l_entry, &ad->fdir_prof_list); > + } > + > + if (filter->mark_flag =3D=3D 1) > + ice_fdir_rx_parsing_enable(ad, 1); > + > + entry =3D rte_zmalloc("fdir_entry", sizeof(*entry), 0); > + if (!entry) > + return -rte_errno; > + > + rte_memcpy(entry, filter, sizeof(*filter)); > + > + filter->prof =3D NULL; > + filter->pkt_buf =3D NULL; > + > + flow->rule =3D entry; > + > + return 0; > + } >=20 > ice_fdir_extract_fltr_key(&key, filter); > node =3D ice_fdir_entry_lookup(fdir_info, &key); @@ -1397,6 +1512,44 > @@ ice_fdir_destroy_filter(struct ice_adapter *ad, >=20 > filter =3D (struct ice_fdir_filter_conf *)flow->rule; >=20 > + if (filter->parser_ena) { > + struct ice_hw *hw =3D ICE_PF_TO_HW(pf); > + > + ret =3D ice_fdir_add_del_raw(pf, filter, false); > + if (ret) > + return -rte_errno; > + > + int id =3D ice_find_first_bit(filter->prof->ptypes, UINT16_MAX); > + int i; > + struct ice_fdir_prof_info *pi; > + LIST_FOR_EACH_ENTRY(pi, &ad->fdir_prof_list, > + ice_fdir_prof_info, l_entry) { > + if (pi->ptg !=3D hw->blk[ICE_BLK_FD].xlt1.t[id]) > + continue; > + for (i =3D 0; i < ICE_MAX_FV_WORDS; i++) > + if (pi->prof.fv[i].proto_id !=3D > + filter->prof->fv[i].proto_id || > + pi->prof.fv[i].offset !=3D > + filter->prof->fv[i].offset) > + break; > + if (i =3D=3D ICE_MAX_FV_WORDS) { > + pi->fdir_actived_cnt--; Here you can remove the profile. > + break; > + } > + } can all above part be moved into ice_fdir_add_del_filter, this make the add= /delete implementation symmetric . > + > + if (filter->mark_flag =3D=3D 1) > + ice_fdir_rx_parsing_enable(ad, 0); > + > + flow->rule =3D NULL; > + filter->prof =3D NULL; > + filter->pkt_buf =3D NULL; > + > + rte_free(filter); > + > + return 0; > + } > + > is_tun =3D ice_fdir_is_tunnel_profile(filter->tunnel_type); >=20 > if (filter->counter) { > @@ -1675,6 +1828,7 @@ ice_fdir_parse_pattern(__rte_unused struct > ice_adapter *ad, > enum rte_flow_item_type l3 =3D RTE_FLOW_ITEM_TYPE_END; > enum rte_flow_item_type l4 =3D RTE_FLOW_ITEM_TYPE_END; > enum ice_fdir_tunnel_type tunnel_type =3D > ICE_FDIR_TUNNEL_TYPE_NONE; > + const struct rte_flow_item_raw *raw_spec, *raw_mask; > const struct rte_flow_item_eth *eth_spec, *eth_mask; > const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_last, *ipv4_mask; > const struct rte_flow_item_ipv6 *ipv6_spec, *ipv6_mask; @@ -1702,6 > +1856,9 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad, > struct ice_fdir_extra *p_ext_data; > struct ice_fdir_v4 *p_v4 =3D NULL; > struct ice_fdir_v6 *p_v6 =3D NULL; > + struct ice_parser_result rslt; > + struct ice_parser *psr; > + uint8_t item_num =3D 0; >=20 > for (item =3D pattern; item->type !=3D RTE_FLOW_ITEM_TYPE_END; item++) = { > if (item->type =3D=3D RTE_FLOW_ITEM_TYPE_VXLAN) @@ -1713,6 > +1870,7 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad, > item->type =3D=3D RTE_FLOW_ITEM_TYPE_GTP_PSC) { > is_outer =3D false; > } > + item_num++; > } >=20 > /* This loop parse flow pattern and distinguish Non-tunnel and tunnel > @@ -1733,6 +1891,101 @@ ice_fdir_parse_pattern(__rte_unused struct > ice_adapter *ad, > &input_set_i : &input_set_o; >=20 > switch (item_type) { > + case RTE_FLOW_ITEM_TYPE_RAW: > + raw_spec =3D item->spec; > + raw_mask =3D item->mask; > + > + if (item_num !=3D 1) > + break; > + > + /* convert raw spec & mask from byte string to int */ > + unsigned char *tmp_spec =3D > + (uint8_t *)(uintptr_t)raw_spec->pattern; > + unsigned char *tmp_mask =3D > + (uint8_t *)(uintptr_t)raw_mask->pattern; > + uint16_t udp_port =3D 0; > + uint16_t tmp_val =3D 0; > + uint8_t pkt_len =3D 0; > + uint8_t tmp =3D 0; > + int i, j; > + > + pkt_len =3D strlen((char *)(uintptr_t)raw_spec->pattern); > + if (strlen((char *)(uintptr_t)raw_mask->pattern) !=3D > + pkt_len) > + return -rte_errno; > + > + for (i =3D 0, j =3D 0; i < pkt_len; i +=3D 2, j++) { > + tmp =3D tmp_spec[i]; > + if (tmp >=3D 'a' && tmp <=3D 'f') > + tmp_val =3D tmp - 'a' + 10; > + if (tmp >=3D 'A' && tmp <=3D 'F') > + tmp_val =3D tmp - 'A' + 10; > + if (tmp >=3D '0' && tmp <=3D '9') > + tmp_val =3D tmp - '0'; > + > + tmp_val *=3D 16; > + tmp =3D tmp_spec[i + 1]; > + if (tmp >=3D 'a' && tmp <=3D 'f') > + tmp_spec[j] =3D tmp_val + tmp - 'a' + 10; > + if (tmp >=3D 'A' && tmp <=3D 'F') > + tmp_spec[j] =3D tmp_val + tmp - 'A' + 10; > + if (tmp >=3D '0' && tmp <=3D '9') > + tmp_spec[j] =3D tmp_val + tmp - '0'; > + > + tmp =3D tmp_mask[i]; > + if (tmp >=3D 'a' && tmp <=3D 'f') > + tmp_val =3D tmp - 'a' + 10; > + if (tmp >=3D 'A' && tmp <=3D 'F') > + tmp_val =3D tmp - 'A' + 10; > + if (tmp >=3D '0' && tmp <=3D '9') > + tmp_val =3D tmp - '0'; > + > + tmp_val *=3D 16; > + tmp =3D tmp_mask[i + 1]; > + if (tmp >=3D 'a' && tmp <=3D 'f') > + tmp_mask[j] =3D tmp_val + tmp - 'a' + 10; > + if (tmp >=3D 'A' && tmp <=3D 'F') > + tmp_mask[j] =3D tmp_val + tmp - 'A' + 10; > + if (tmp >=3D '0' && tmp <=3D '9') > + tmp_mask[j] =3D tmp_val + tmp - '0'; > + } > + > + pkt_len /=3D 2; > + > + if (ice_parser_create(&ad->hw, &psr)) > + return -rte_errno; > + if (ice_get_open_tunnel_port(&ad->hw, TNL_VXLAN, > + &udp_port)) > + ice_parser_vxlan_tunnel_set(psr, udp_port, > + true); > + if (ice_parser_run(psr, tmp_spec, pkt_len, &rslt)) > + return -rte_errno; > + ice_parser_destroy(psr); > + > + if (!tmp_mask) > + return -rte_errno; > + > + filter->prof =3D (struct ice_parser_profile *) > + ice_malloc(&ad->hw, sizeof(*filter->prof)); > + if (!filter->prof) > + return -ENOMEM; > + > + if (ice_parser_profile_init(&rslt, tmp_spec, tmp_mask, > + pkt_len, ICE_BLK_FD, true, filter->prof)) > + return -rte_errno; > + > + u8 *pkt_buf =3D (u8 *)ice_malloc(&ad->hw, pkt_len + 1); > + if (!pkt_buf) > + return -ENOMEM; > + rte_memcpy(pkt_buf, tmp_spec, pkt_len); > + filter->pkt_buf =3D pkt_buf; > + > + filter->pkt_len =3D pkt_len; > + > + filter->parser_ena =3D true; > + > + break; > + > case RTE_FLOW_ITEM_TYPE_ETH: > flow_type =3D ICE_FLTR_PTYPE_NON_IP_L2; > eth_spec =3D item->spec; > @@ -2198,6 +2451,7 @@ ice_fdir_parse(struct ice_adapter *ad, > struct ice_fdir_filter_conf *filter =3D &pf->fdir.conf; > struct ice_pattern_match_item *item =3D NULL; > uint64_t input_set; > + bool raw =3D false; > int ret; >=20 > memset(filter, 0, sizeof(*filter)); > @@ -2213,7 +2467,13 @@ ice_fdir_parse(struct ice_adapter *ad, > ret =3D ice_fdir_parse_pattern(ad, pattern, error, filter); > if (ret) > goto error; > + > + if (item->pattern_list[0] =3D=3D RTE_FLOW_ITEM_TYPE_RAW) > + raw =3D true; > + > input_set =3D filter->input_set_o | filter->input_set_i; > + input_set =3D raw ? ~input_set : input_set; > + > if (!input_set || filter->input_set_o & > ~(item->input_set_mask_o | ICE_INSET_ETHERTYPE) || > filter->input_set_i & ~item->input_set_mask_i) { diff --git > a/drivers/net/ice/ice_generic_flow.c b/drivers/net/ice/ice_generic_flow.c > index 02f854666a..d3391c86c0 100644 > --- a/drivers/net/ice/ice_generic_flow.c > +++ b/drivers/net/ice/ice_generic_flow.c > @@ -65,6 +65,12 @@ enum rte_flow_item_type pattern_empty[] =3D { > RTE_FLOW_ITEM_TYPE_END, > }; >=20 > +/* raw */ > +enum rte_flow_item_type pattern_raw[] =3D { > + RTE_FLOW_ITEM_TYPE_RAW, > + RTE_FLOW_ITEM_TYPE_END, > +}; > + > /* L2 */ > enum rte_flow_item_type pattern_ethertype[] =3D { > RTE_FLOW_ITEM_TYPE_ETH, > @@ -2081,6 +2087,7 @@ struct ice_ptype_match { }; >=20 > static struct ice_ptype_match ice_ptype_map[] =3D { > + {pattern_raw, ICE_PTYPE_IPV4_PAY}, > {pattern_eth_ipv4, ICE_PTYPE_IPV4_PAY}, > {pattern_eth_ipv4_udp, ICE_PTYPE_IPV4_UDP_PAY}, > {pattern_eth_ipv4_tcp, ICE_PTYPE_IPV4_TCP_PAY}, > diff --git a/drivers/net/ice/ice_generic_flow.h > b/drivers/net/ice/ice_generic_flow.h > index 8845a3e156..1b030c0466 100644 > --- a/drivers/net/ice/ice_generic_flow.h > +++ b/drivers/net/ice/ice_generic_flow.h > @@ -124,6 +124,9 @@ > /* empty pattern */ > extern enum rte_flow_item_type pattern_empty[]; >=20 > +/* raw pattern */ > +extern enum rte_flow_item_type pattern_raw[]; > + > /* L2 */ > extern enum rte_flow_item_type pattern_ethertype[]; extern enum > rte_flow_item_type pattern_ethertype_vlan[]; > -- > 2.25.1