* [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels @ 2018-02-27 12:45 Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 01/14] net/sfc/base: support filters for encapsulated packets Andrew Rybchenko ` (14 more replies) 0 siblings, 15 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev Update base driver and the PMD itself to support flow API patterns for tunnels: VXLAN, NVGRE and Geneve. Applicable to SFN8xxx NICs with full-feature firmware variant running. Andrew Rybchenko (1): doc: add net/sfc flow API support for tunnels Roman Zhukov (12): net/sfc/base: support filters for encapsulated packets net/sfc/base: support VNI/VSID and inner frame local MAC net/sfc/base: distinguish filters for encapsulated packets net/sfc: add VXLAN in flow API filters support net/sfc: add NVGRE in flow API filters support net/sfc: add GENEVE in flow API filters support net/sfc: add inner frame ETH in flow API filters support net/sfc: add infrastructure to make many filters from flow net/sfc: multiply of specs with an unknown EtherType net/sfc: multiply of specs w/o inner frame destination MAC net/sfc: multiply of specs with an unknown destination MAC net/sfc: avoid creation of ineffective flow rules Vijay Srivastava (1): net/sfc/base: support VXLAN filter creation doc/guides/nics/sfc_efx.rst | 28 +- doc/guides/rel_notes/release_18_05.rst | 6 + drivers/net/sfc/base/ef10_filter.c | 100 +++- drivers/net/sfc/base/efx.h | 20 + drivers/net/sfc/base/efx_filter.c | 39 +- drivers/net/sfc/sfc_flow.c | 1001 ++++++++++++++++++++++++++++++-- drivers/net/sfc/sfc_flow.h | 19 +- 7 files changed, 1161 insertions(+), 52 deletions(-) -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 01/14] net/sfc/base: support filters for encapsulated packets 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-03-06 15:13 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 02/14] net/sfc/base: support VNI/VSID and inner frame local MAC Andrew Rybchenko ` (13 subsequent siblings) 14 siblings, 1 reply; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> This adds filters for encapsulated packets to the list returned by ef10_filter_supported_filters(). Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- drivers/net/sfc/base/ef10_filter.c | 65 ++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/drivers/net/sfc/base/ef10_filter.c b/drivers/net/sfc/base/ef10_filter.c index 27b5998..f643cdb 100644 --- a/drivers/net/sfc/base/ef10_filter.c +++ b/drivers/net/sfc/base/ef10_filter.c @@ -890,6 +890,7 @@ efx_mcdi_get_parser_disp_info( __in efx_nic_t *enp, __out_ecount(buffer_length) uint32_t *buffer, __in size_t buffer_length, + __in boolean_t encap, __out size_t *list_lengthp) { efx_mcdi_req_t req; @@ -906,7 +907,8 @@ efx_mcdi_get_parser_disp_info( req.emr_out_buf = payload; req.emr_out_length = MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX; - MCDI_IN_SET_DWORD(req, GET_PARSER_DISP_INFO_OUT_OP, + MCDI_IN_SET_DWORD(req, GET_PARSER_DISP_INFO_OUT_OP, encap ? + MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_ENCAP_RX_MATCHES : MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_RX_MATCHES); efx_mcdi_execute(enp, &req); @@ -966,28 +968,66 @@ ef10_filter_supported_filters( __in size_t buffer_length, __out size_t *list_lengthp) { - + efx_nic_cfg_t *encp = &(enp->en_nic_cfg); size_t mcdi_list_length; + size_t mcdi_encap_list_length; size_t list_length; uint32_t i; + uint32_t next_buf_idx; + size_t next_buf_length; efx_rc_t rc; + boolean_t no_space = B_FALSE; efx_filter_match_flags_t all_filter_flags = (EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_REM_MAC | EFX_FILTER_MATCH_REM_PORT | EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_INNER_VID | EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_IP_PROTO | + EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST | + EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST | EFX_FILTER_MATCH_UNKNOWN_MCAST_DST | EFX_FILTER_MATCH_UNKNOWN_UCAST_DST); - rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, - &mcdi_list_length); + /* + * Two calls to MC_CMD_GET_PARSER_DISP_INFO are needed: one to get the + * list of supported filters for ordinary packets, and then another to + * get the list of supported filters for encapsulated packets. + */ + rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, B_FALSE, + &mcdi_list_length); if (rc != 0) { - if (rc == ENOSPC) { - /* Pass through mcdi_list_length for the list length */ - *list_lengthp = mcdi_list_length; + if (rc == ENOSPC) + no_space = B_TRUE; + else + goto fail1; + } + + if (no_space) { + next_buf_idx = 0; + next_buf_length = 0; + } else { + EFSYS_ASSERT(mcdi_list_length < buffer_length); + next_buf_idx = mcdi_list_length; + next_buf_length = buffer_length - mcdi_list_length; + } + + if (encp->enc_tunnel_encapsulations_supported != 0) { + rc = efx_mcdi_get_parser_disp_info(enp, &buffer[next_buf_idx], + next_buf_length, B_TRUE, &mcdi_encap_list_length); + if (rc != 0) { + if (rc == ENOSPC) + no_space = B_TRUE; + else + goto fail2; } - goto fail1; + } else { + mcdi_encap_list_length = 0; + } + + if (no_space) { + *list_lengthp = mcdi_list_length + mcdi_encap_list_length; + rc = ENOSPC; + goto fail3; } /* @@ -1000,9 +1040,10 @@ ef10_filter_supported_filters( * of the matches is preserved as they are ordered from highest to * lowest priority. */ - EFSYS_ASSERT(mcdi_list_length <= buffer_length); + EFSYS_ASSERT(mcdi_list_length + mcdi_encap_list_length <= + buffer_length); list_length = 0; - for (i = 0; i < mcdi_list_length; i++) { + for (i = 0; i < mcdi_list_length + mcdi_encap_list_length; i++) { if ((buffer[i] & ~all_filter_flags) == 0) { buffer[list_length] = buffer[i]; list_length++; @@ -1013,6 +1054,10 @@ ef10_filter_supported_filters( return (0); +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [dpdk-dev] [PATCH 01/14] net/sfc/base: support filters for encapsulated packets 2018-02-27 12:45 ` [dpdk-dev] [PATCH 01/14] net/sfc/base: support filters for encapsulated packets Andrew Rybchenko @ 2018-03-06 15:13 ` Andrew Rybchenko 0 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:13 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov On 02/27/2018 03:45 PM, Andrew Rybchenko wrote: > From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> > > This adds filters for encapsulated packets to the list > returned by ef10_filter_supported_filters(). > > Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> > Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> > Reviewed-by: Andy Moreton <amoreton@solarflare.com> > --- > drivers/net/sfc/base/ef10_filter.c | 65 ++++++++++++++++++++++++++++++++------ > 1 file changed, 55 insertions(+), 10 deletions(-) <...> > - rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, > - &mcdi_list_length); > + /* > + * Two calls to MC_CMD_GET_PARSER_DISP_INFO are needed: one to get the > + * list of supported filters for ordinary packets, and then another to > + * get the list of supported filters for encapsulated packets. > + */ > + rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, B_FALSE, > + &mcdi_list_length); > if (rc != 0) { > - if (rc == ENOSPC) { > - /* Pass through mcdi_list_length for the list length */ > - *list_lengthp = mcdi_list_length; > + if (rc == ENOSPC) > + no_space = B_TRUE; > + else > + goto fail1; > + } > + > + if (no_space) { > + next_buf_idx = 0; > + next_buf_length = 0; > + } else { > + EFSYS_ASSERT(mcdi_list_length < buffer_length); In fact <= must be here since above call may return 0 if return array fits exactly in provided buffer. I'll send v2. > + next_buf_idx = mcdi_list_length; > + next_buf_length = buffer_length - mcdi_list_length; > + } <snip> ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 02/14] net/sfc/base: support VNI/VSID and inner frame local MAC 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 01/14] net/sfc/base: support filters for encapsulated packets Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 03/14] net/sfc/base: support VXLAN filter creation Andrew Rybchenko ` (12 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> This supports VNI/VSID and inner frame local MAC fields to match in VXLAN, GENEVE, or NVGRE packets. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- drivers/net/sfc/base/ef10_filter.c | 18 ++++++++++++++++++ drivers/net/sfc/base/efx.h | 8 ++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/net/sfc/base/ef10_filter.c b/drivers/net/sfc/base/ef10_filter.c index f643cdb..8026b1a 100644 --- a/drivers/net/sfc/base/ef10_filter.c +++ b/drivers/net/sfc/base/ef10_filter.c @@ -118,6 +118,10 @@ ef10_filter_init( MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_OUTER_VLAN)); EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IP_PROTO == MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IP_PROTO)); + EFX_STATIC_ASSERT(EFX_FILTER_MATCH_VNI_OR_VSID == + MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_VNI_OR_VSID)); + EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_LOC_MAC == + MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_DST_MAC)); EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST == MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_MCAST_DST)); EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST == @@ -290,6 +294,12 @@ efx_mcdi_filter_op_add( rc = EINVAL; goto fail2; } + + memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_VNI_OR_VSID), + spec->efs_vni_or_vsid, EFX_VNI_OR_VSID_LEN); + + memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_IFRM_DST_MAC), + spec->efs_ifrm_loc_mac, EFX_MAC_ADDR_LEN); } efx_mcdi_execute(enp, &req); @@ -413,6 +423,12 @@ ef10_filter_equal( return (B_FALSE); if (left->efs_encap_type != right->efs_encap_type) return (B_FALSE); + if (memcmp(left->efs_vni_or_vsid, right->efs_vni_or_vsid, + EFX_VNI_OR_VSID_LEN)) + return (B_FALSE); + if (memcmp(left->efs_ifrm_loc_mac, right->efs_ifrm_loc_mac, + EFX_MAC_ADDR_LEN)) + return (B_FALSE); return (B_TRUE); @@ -983,6 +999,8 @@ ef10_filter_supported_filters( EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_INNER_VID | EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_IP_PROTO | + EFX_FILTER_MATCH_VNI_OR_VSID | + EFX_FILTER_MATCH_IFRM_LOC_MAC | EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST | EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST | EFX_FILTER_MATCH_UNKNOWN_MCAST_DST | diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h index fe996e7..ac589f9 100644 --- a/drivers/net/sfc/base/efx.h +++ b/drivers/net/sfc/base/efx.h @@ -413,6 +413,8 @@ typedef enum efx_link_mode_e { #define EFX_MAC_ADDR_LEN 6 +#define EFX_VNI_OR_VSID_LEN 3 + #define EFX_MAC_ADDR_IS_MULTICAST(_address) (((uint8_t *)_address)[0] & 0x01) #define EFX_MAC_MULTICAST_LIST_MAX 256 @@ -2313,6 +2315,10 @@ typedef uint8_t efx_filter_flags_t; #define EFX_FILTER_MATCH_OUTER_VID 0x00000100 /* Match by IP transport protocol */ #define EFX_FILTER_MATCH_IP_PROTO 0x00000200 +/* Match by VNI or VSID */ +#define EFX_FILTER_MATCH_VNI_OR_VSID 0x00000800 +/* For encapsulated packets, match by inner frame local MAC address */ +#define EFX_FILTER_MATCH_IFRM_LOC_MAC 0x00010000 /* For encapsulated packets, match all multicast inner frames */ #define EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST 0x01000000 /* For encapsulated packets, match all unicast inner frames */ @@ -2359,6 +2365,8 @@ typedef struct efx_filter_spec_s { uint16_t efs_rem_port; efx_oword_t efs_rem_host; efx_oword_t efs_loc_host; + uint8_t efs_vni_or_vsid[EFX_VNI_OR_VSID_LEN]; + uint8_t efs_ifrm_loc_mac[EFX_MAC_ADDR_LEN]; } efx_filter_spec_t; -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 03/14] net/sfc/base: support VXLAN filter creation 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 01/14] net/sfc/base: support filters for encapsulated packets Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 02/14] net/sfc/base: support VNI/VSID and inner frame local MAC Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 04/14] net/sfc/base: distinguish filters for encapsulated packets Andrew Rybchenko ` (11 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Vijay Srivastava From: Vijay Srivastava <vijays@solarflare.com> Signed-off-by: Vijay Srivastava <vijays@solarflare.com> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> --- drivers/net/sfc/base/efx.h | 7 +++++++ drivers/net/sfc/base/efx_filter.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h index ac589f9..c0e4218 100644 --- a/drivers/net/sfc/base/efx.h +++ b/drivers/net/sfc/base/efx.h @@ -2462,6 +2462,13 @@ efx_filter_spec_set_encap_type( __in efx_tunnel_protocol_t encap_type, __in efx_filter_inner_frame_match_t inner_frame_match); +extern __checkReturn efx_rc_t +efx_filter_spec_set_vxlan_full( + __inout efx_filter_spec_t *spec, + __in const uint8_t *vxlan_id, + __in const uint8_t *inner_addr, + __in const uint8_t *outer_addr); + #if EFSYS_OPT_RX_SCALE extern __checkReturn efx_rc_t efx_filter_spec_set_rss_context( diff --git a/drivers/net/sfc/base/efx_filter.c b/drivers/net/sfc/base/efx_filter.c index b92541a..4bce050 100644 --- a/drivers/net/sfc/base/efx_filter.c +++ b/drivers/net/sfc/base/efx_filter.c @@ -462,6 +462,42 @@ efx_filter_spec_set_encap_type( return (rc); } +/* + * Specify inner and outer Ethernet address and VXLAN ID in filter + * specification. + */ + __checkReturn efx_rc_t +efx_filter_spec_set_vxlan_full( + __inout efx_filter_spec_t *spec, + __in const uint8_t *vxlan_id, + __in const uint8_t *inner_addr, + __in const uint8_t *outer_addr) +{ + EFSYS_ASSERT3P(spec, !=, NULL); + EFSYS_ASSERT3P(vxlan_id, !=, NULL); + EFSYS_ASSERT3P(inner_addr, !=, NULL); + EFSYS_ASSERT3P(outer_addr, !=, NULL); + + if ((inner_addr == NULL) && (outer_addr == NULL)) + return (EINVAL); + + if (vxlan_id != NULL) { + spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID; + memcpy(spec->efs_vni_or_vsid, vxlan_id, EFX_VNI_OR_VSID_LEN); + } + if (outer_addr != NULL) { + spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC; + memcpy(spec->efs_loc_mac, outer_addr, EFX_MAC_ADDR_LEN); + } + if (inner_addr != NULL) { + spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC; + memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN); + } + spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN; + + return (0); +} + #if EFSYS_OPT_RX_SCALE __checkReturn efx_rc_t efx_filter_spec_set_rss_context( -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 04/14] net/sfc/base: distinguish filters for encapsulated packets 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (2 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 03/14] net/sfc/base: support VXLAN filter creation Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 05/14] net/sfc: add VXLAN in flow API filters support Andrew Rybchenko ` (10 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Add filter match flag to distinguish filters applied only to encapsulated packets. Match flags set should allow to determine whether a filter is supported or not. The problem is that if specification has supported set outer match flags and specified encapsulation without any inner flags, check says that it is supported, and filter insertion is performed. However, there is no filtering of the encapsulated traffic. A new flag is added to solve this problem and separate the filters for the encapsulated packets. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Andy Moreton <amoreton@solarflare.com> Reviewed-by: Mark Spender <mspender@solarflare.com> --- drivers/net/sfc/base/ef10_filter.c | 19 +++++++++++++++++-- drivers/net/sfc/base/efx.h | 5 +++++ drivers/net/sfc/base/efx_filter.c | 3 ++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/net/sfc/base/ef10_filter.c b/drivers/net/sfc/base/ef10_filter.c index 8026b1a..54e1c35 100644 --- a/drivers/net/sfc/base/ef10_filter.c +++ b/drivers/net/sfc/base/ef10_filter.c @@ -172,6 +172,7 @@ efx_mcdi_filter_op_add( efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_FILTER_OP_EXT_IN_LEN, MC_CMD_FILTER_OP_EXT_OUT_LEN)]; + efx_filter_match_flags_t match_flags; efx_rc_t rc; memset(payload, 0, sizeof (payload)); @@ -181,6 +182,12 @@ efx_mcdi_filter_op_add( req.emr_out_buf = payload; req.emr_out_length = MC_CMD_FILTER_OP_EXT_OUT_LEN; + /* + * Remove match flag for encapsulated filters that does not correspond + * to the MCDI match flags + */ + match_flags = spec->efs_match_flags & ~EFX_FILTER_MATCH_ENCAP_TYPE; + switch (filter_op) { case MC_CMD_FILTER_OP_IN_OP_REPLACE: MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_LO, @@ -201,7 +208,7 @@ efx_mcdi_filter_op_add( MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_MATCH_FIELDS, - spec->efs_match_flags); + match_flags); MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_DEST, MC_CMD_FILTER_OP_EXT_IN_RX_DEST_HOST); MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_QUEUE, @@ -1003,13 +1010,17 @@ ef10_filter_supported_filters( EFX_FILTER_MATCH_IFRM_LOC_MAC | EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST | EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST | + EFX_FILTER_MATCH_ENCAP_TYPE | EFX_FILTER_MATCH_UNKNOWN_MCAST_DST | EFX_FILTER_MATCH_UNKNOWN_UCAST_DST); /* * Two calls to MC_CMD_GET_PARSER_DISP_INFO are needed: one to get the * list of supported filters for ordinary packets, and then another to - * get the list of supported filters for encapsulated packets. + * get the list of supported filters for encapsulated packets. To + * distinguish the second list from the first, the + * EFX_FILTER_MATCH_ENCAP_TYPE flag is added to each filter for + * encapsulated packets. */ rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, B_FALSE, &mcdi_list_length); @@ -1037,6 +1048,10 @@ ef10_filter_supported_filters( no_space = B_TRUE; else goto fail2; + } else { + for (i = next_buf_idx; + i < next_buf_idx + mcdi_encap_list_length; i++) + buffer[i] |= EFX_FILTER_MATCH_ENCAP_TYPE; } } else { mcdi_encap_list_length = 0; diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h index c0e4218..df1e23a 100644 --- a/drivers/net/sfc/base/efx.h +++ b/drivers/net/sfc/base/efx.h @@ -2323,6 +2323,11 @@ typedef uint8_t efx_filter_flags_t; #define EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST 0x01000000 /* For encapsulated packets, match all unicast inner frames */ #define EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST 0x02000000 +/* + * Match by encap type, this flag does not correspond to + * the MCDI match flags and any unoccupied value may be used + */ +#define EFX_FILTER_MATCH_ENCAP_TYPE 0x20000000 /* Match otherwise-unmatched multicast and broadcast packets */ #define EFX_FILTER_MATCH_UNKNOWN_MCAST_DST 0x40000000 /* Match otherwise-unmatched unicast packets */ diff --git a/drivers/net/sfc/base/efx_filter.c b/drivers/net/sfc/base/efx_filter.c index 4bce050..a37b5c1 100644 --- a/drivers/net/sfc/base/efx_filter.c +++ b/drivers/net/sfc/base/efx_filter.c @@ -412,7 +412,7 @@ efx_filter_spec_set_encap_type( __in efx_tunnel_protocol_t encap_type, __in efx_filter_inner_frame_match_t inner_frame_match) { - uint32_t match_flags = 0; + uint32_t match_flags = EFX_FILTER_MATCH_ENCAP_TYPE; uint8_t ip_proto; efx_rc_t rc; @@ -493,6 +493,7 @@ efx_filter_spec_set_vxlan_full( spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC; memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN); } + spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN; return (0); -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 05/14] net/sfc: add VXLAN in flow API filters support 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (3 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 04/14] net/sfc/base: distinguish filters for encapsulated packets Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 06/14] net/sfc: add NVGRE " Andrew Rybchenko ` (9 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Exact match of VXLAN network identifier is supported by parser. IP protocol match are enforced to UDP. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- doc/guides/nics/sfc_efx.rst | 2 + drivers/net/sfc/sfc_flow.c | 165 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index ccdf5ff..5a4b2a6 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -166,6 +166,8 @@ Supported pattern items: - UDP (exact match of source/destination ports) +- VXLAN (exact match of VXLAN network identifier) + Supported actions: - VOID diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 93cdf8f..20ba69d 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -57,6 +57,7 @@ static sfc_flow_item_parse sfc_flow_parse_ipv4; static sfc_flow_item_parse sfc_flow_parse_ipv6; static sfc_flow_item_parse sfc_flow_parse_tcp; static sfc_flow_item_parse sfc_flow_parse_udp; +static sfc_flow_item_parse sfc_flow_parse_vxlan; static boolean_t sfc_flow_is_zero(const uint8_t *buf, unsigned int size) @@ -696,6 +697,132 @@ sfc_flow_parse_udp(const struct rte_flow_item *item, return -rte_errno; } +/* + * Filters for encapsulated packets match based on the EtherType and IP + * protocol in the outer frame. + */ +static int +sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, + efx_filter_spec_t *efx_spec, + uint8_t ip_proto, + struct rte_flow_error *error) +{ + if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) { + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO; + efx_spec->efs_ip_proto = ip_proto; + } else if (efx_spec->efs_ip_proto != ip_proto) { + switch (ip_proto) { + case EFX_IPPROTO_UDP: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Outer IP header protocol must be UDP " + "in VxLAN pattern"); + return -rte_errno; + + default: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Only VxLAN tunneling patterns " + "are supported"); + return -rte_errno; + } + } + + if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Outer frame EtherType in pattern with tunneling " + "must be set"); + return -rte_errno; + } else if (efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 && + efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Outer frame EtherType in pattern with tunneling " + "must be IPv4 or IPv6"); + return -rte_errno; + } + + return 0; +} + +static int +sfc_flow_set_efx_spec_vni_or_vsid(efx_filter_spec_t *efx_spec, + const uint8_t *vni_or_vsid_val, + const uint8_t *vni_or_vsid_mask, + const struct rte_flow_item *item, + struct rte_flow_error *error) +{ + const uint8_t vni_or_vsid_full_mask[EFX_VNI_OR_VSID_LEN] = { + 0xff, 0xff, 0xff + }; + + if (memcmp(vni_or_vsid_mask, vni_or_vsid_full_mask, + EFX_VNI_OR_VSID_LEN) == 0) { + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID; + rte_memcpy(efx_spec->efs_vni_or_vsid, vni_or_vsid_val, + EFX_VNI_OR_VSID_LEN); + } else if (!sfc_flow_is_zero(vni_or_vsid_mask, EFX_VNI_OR_VSID_LEN)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Unsupported VNI/VSID mask"); + return -rte_errno; + } + + return 0; +} + +/** + * Convert VXLAN item to EFX filter specification. + * + * @param item[in] + * Item specification. Only VXLAN network identifier field is supported. + * If the mask is NULL, default mask will be used. + * Ranging is not supported. + * @param efx_spec[in, out] + * EFX filter specification to update. + * @param[out] error + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_parse_vxlan(const struct rte_flow_item *item, + efx_filter_spec_t *efx_spec, + struct rte_flow_error *error) +{ + int rc; + const struct rte_flow_item_vxlan *spec = NULL; + const struct rte_flow_item_vxlan *mask = NULL; + const struct rte_flow_item_vxlan supp_mask = { + .vni = { 0xff, 0xff, 0xff } + }; + + rc = sfc_flow_parse_init(item, + (const void **)&spec, + (const void **)&mask, + &supp_mask, + &rte_flow_item_vxlan_mask, + sizeof(struct rte_flow_item_vxlan), + error); + if (rc != 0) + return rc; + + rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec, + EFX_IPPROTO_UDP, error); + if (rc != 0) + return rc; + + efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN; + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; + + if (spec == NULL) + return 0; + + rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni, + mask->vni, item, error); + + return rc; +} + static const struct sfc_flow_item sfc_flow_items[] = { { .type = RTE_FLOW_ITEM_TYPE_VOID, @@ -739,6 +866,12 @@ static const struct sfc_flow_item sfc_flow_items[] = { .layer = SFC_FLOW_ITEM_L4, .parse = sfc_flow_parse_udp, }, + { + .type = RTE_FLOW_ITEM_TYPE_VXLAN, + .prev_layer = SFC_FLOW_ITEM_L4, + .layer = SFC_FLOW_ITEM_START_LAYER, + .parse = sfc_flow_parse_vxlan, + }, }; /* @@ -806,6 +939,7 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], { int rc; unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER; + boolean_t is_ifrm = B_FALSE; const struct sfc_flow_item *item; if (pattern == NULL) { @@ -837,6 +971,37 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], return -rte_errno; } + /* + * Allow only VOID pattern item in the inner frame. + * Also check that there is only one tunneling protocol. + */ + switch (item->type) { + case RTE_FLOW_ITEM_TYPE_VOID: + break; + + case RTE_FLOW_ITEM_TYPE_VXLAN: + if (is_ifrm) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + pattern, + "More than one tunneling protocol"); + return -rte_errno; + } + is_ifrm = B_TRUE; + break; + + default: + if (is_ifrm) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + pattern, + "There is an unsupported pattern item " + "in the inner frame"); + return -rte_errno; + } + break; + } + rc = item->parse(pattern, &flow->spec, error); if (rc != 0) return rc; -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 06/14] net/sfc: add NVGRE in flow API filters support 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (4 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 05/14] net/sfc: add VXLAN in flow API filters support Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 07/14] net/sfc: add GENEVE " Andrew Rybchenko ` (8 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Exact match of virtual subnet ID is supported by parser. IP protocol match are enforced to GRE. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- doc/guides/nics/sfc_efx.rst | 2 ++ drivers/net/sfc/sfc_flow.c | 68 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 5a4b2a6..05dacb3 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -168,6 +168,8 @@ Supported pattern items: - VXLAN (exact match of VXLAN network identifier) +- NVGRE (exact match of virtual subnet ID) + Supported actions: - VOID diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 20ba69d..126ec9b 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -58,6 +58,7 @@ static sfc_flow_item_parse sfc_flow_parse_ipv6; static sfc_flow_item_parse sfc_flow_parse_tcp; static sfc_flow_item_parse sfc_flow_parse_udp; static sfc_flow_item_parse sfc_flow_parse_vxlan; +static sfc_flow_item_parse sfc_flow_parse_nvgre; static boolean_t sfc_flow_is_zero(const uint8_t *buf, unsigned int size) @@ -719,10 +720,17 @@ sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, "in VxLAN pattern"); return -rte_errno; + case EFX_IPPROTO_GRE: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Outer IP header protocol must be GRE " + "in NVGRE pattern"); + return -rte_errno; + default: rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, - "Only VxLAN tunneling patterns " + "Only VxLAN/NVGRE tunneling patterns " "are supported"); return -rte_errno; } @@ -823,6 +831,57 @@ sfc_flow_parse_vxlan(const struct rte_flow_item *item, return rc; } +/** + * Convert NVGRE item to EFX filter specification. + * + * @param item[in] + * Item specification. Only virtual subnet ID field is supported. + * If the mask is NULL, default mask will be used. + * Ranging is not supported. + * @param efx_spec[in, out] + * EFX filter specification to update. + * @param[out] error + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_parse_nvgre(const struct rte_flow_item *item, + efx_filter_spec_t *efx_spec, + struct rte_flow_error *error) +{ + int rc; + const struct rte_flow_item_nvgre *spec = NULL; + const struct rte_flow_item_nvgre *mask = NULL; + const struct rte_flow_item_nvgre supp_mask = { + .tni = { 0xff, 0xff, 0xff } + }; + + rc = sfc_flow_parse_init(item, + (const void **)&spec, + (const void **)&mask, + &supp_mask, + &rte_flow_item_nvgre_mask, + sizeof(struct rte_flow_item_nvgre), + error); + if (rc != 0) + return rc; + + rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec, + EFX_IPPROTO_GRE, error); + if (rc != 0) + return rc; + + efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_NVGRE; + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; + + if (spec == NULL) + return 0; + + rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->tni, + mask->tni, item, error); + + return rc; +} + static const struct sfc_flow_item sfc_flow_items[] = { { .type = RTE_FLOW_ITEM_TYPE_VOID, @@ -872,6 +931,12 @@ static const struct sfc_flow_item sfc_flow_items[] = { .layer = SFC_FLOW_ITEM_START_LAYER, .parse = sfc_flow_parse_vxlan, }, + { + .type = RTE_FLOW_ITEM_TYPE_NVGRE, + .prev_layer = SFC_FLOW_ITEM_L3, + .layer = SFC_FLOW_ITEM_START_LAYER, + .parse = sfc_flow_parse_nvgre, + }, }; /* @@ -980,6 +1045,7 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], break; case RTE_FLOW_ITEM_TYPE_VXLAN: + case RTE_FLOW_ITEM_TYPE_NVGRE: if (is_ifrm) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 07/14] net/sfc: add GENEVE in flow API filters support 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (5 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 06/14] net/sfc: add NVGRE " Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 08/14] net/sfc: add inner frame ETH " Andrew Rybchenko ` (7 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Exact match of virtual network identifier is supported by parser. IP protocol match are enforced to UDP. Only Ethernet protocol type is supported. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- doc/guides/nics/sfc_efx.rst | 3 ++ drivers/net/sfc/sfc_flow.c | 80 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 05dacb3..943fe55 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -168,6 +168,9 @@ Supported pattern items: - VXLAN (exact match of VXLAN network identifier) +- GENEVE (exact match of virtual network identifier, only Ethernet (0x6558) + protocol type is supported) + - NVGRE (exact match of virtual subnet ID) Supported actions: diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 126ec9b..efdc664 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -58,6 +58,7 @@ static sfc_flow_item_parse sfc_flow_parse_ipv6; static sfc_flow_item_parse sfc_flow_parse_tcp; static sfc_flow_item_parse sfc_flow_parse_udp; static sfc_flow_item_parse sfc_flow_parse_vxlan; +static sfc_flow_item_parse sfc_flow_parse_geneve; static sfc_flow_item_parse sfc_flow_parse_nvgre; static boolean_t @@ -717,7 +718,7 @@ sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "Outer IP header protocol must be UDP " - "in VxLAN pattern"); + "in VxLAN/GENEVE pattern"); return -rte_errno; case EFX_IPPROTO_GRE: @@ -730,7 +731,7 @@ sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, default: rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, - "Only VxLAN/NVGRE tunneling patterns " + "Only VxLAN/GENEVE/NVGRE tunneling patterns " "are supported"); return -rte_errno; } @@ -832,6 +833,74 @@ sfc_flow_parse_vxlan(const struct rte_flow_item *item, } /** + * Convert GENEVE item to EFX filter specification. + * + * @param item[in] + * Item specification. Only Virtual Network Identifier and protocol type + * fields are supported. But protocol type can be only Ethernet (0x6558). + * If the mask is NULL, default mask will be used. + * Ranging is not supported. + * @param efx_spec[in, out] + * EFX filter specification to update. + * @param[out] error + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_parse_geneve(const struct rte_flow_item *item, + efx_filter_spec_t *efx_spec, + struct rte_flow_error *error) +{ + int rc; + const struct rte_flow_item_geneve *spec = NULL; + const struct rte_flow_item_geneve *mask = NULL; + const struct rte_flow_item_geneve supp_mask = { + .protocol = RTE_BE16(0xffff), + .vni = { 0xff, 0xff, 0xff } + }; + + rc = sfc_flow_parse_init(item, + (const void **)&spec, + (const void **)&mask, + &supp_mask, + &rte_flow_item_geneve_mask, + sizeof(struct rte_flow_item_geneve), + error); + if (rc != 0) + return rc; + + rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec, + EFX_IPPROTO_UDP, error); + if (rc != 0) + return rc; + + efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_GENEVE; + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; + + if (spec == NULL) + return 0; + + if (mask->protocol == supp_mask.protocol) { + if (spec->protocol != rte_cpu_to_be_16(ETHER_TYPE_TEB)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "GENEVE encap. protocol must be Ethernet " + "(0x6558) in the GENEVE pattern item"); + return -rte_errno; + } + } else if (mask->protocol != 0) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Unsupported mask for GENEVE encap. protocol"); + return -rte_errno; + } + + rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni, + mask->vni, item, error); + + return rc; +} + +/** * Convert NVGRE item to EFX filter specification. * * @param item[in] @@ -932,6 +1001,12 @@ static const struct sfc_flow_item sfc_flow_items[] = { .parse = sfc_flow_parse_vxlan, }, { + .type = RTE_FLOW_ITEM_TYPE_GENEVE, + .prev_layer = SFC_FLOW_ITEM_L4, + .layer = SFC_FLOW_ITEM_START_LAYER, + .parse = sfc_flow_parse_geneve, + }, + { .type = RTE_FLOW_ITEM_TYPE_NVGRE, .prev_layer = SFC_FLOW_ITEM_L3, .layer = SFC_FLOW_ITEM_START_LAYER, @@ -1045,6 +1120,7 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], break; case RTE_FLOW_ITEM_TYPE_VXLAN: + case RTE_FLOW_ITEM_TYPE_GENEVE: case RTE_FLOW_ITEM_TYPE_NVGRE: if (is_ifrm) { rte_flow_error_set(error, EINVAL, -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 08/14] net/sfc: add inner frame ETH in flow API filters support 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (6 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 07/14] net/sfc: add GENEVE " Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 09/14] net/sfc: add infrastructure to make many filters from flow Andrew Rybchenko ` (6 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Support destination MAC address match in inner frames. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- doc/guides/nics/sfc_efx.rst | 4 ++- drivers/net/sfc/sfc_flow.c | 73 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 943fe55..539ce90 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -152,7 +152,9 @@ Supported pattern items: - VOID - ETH (exact match of source/destination addresses, individual/group match - of destination address, EtherType) + of destination address, EtherType in the outer frame and exact match of + destination addresses, individual/group match of destination address in + the inner frame) - VLAN (exact match of VID, double-tagging is supported) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index efdc664..c942a36 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -187,11 +187,11 @@ sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item, * Convert Ethernet item to EFX filter specification. * * @param item[in] - * Item specification. Only source and destination addresses and - * Ethernet type fields are supported. In addition to full and - * empty masks of destination address, individual/group mask is - * also supported. If the mask is NULL, default mask will be used. - * Ranging is not supported. + * Item specification. Outer frame specification may only comprise + * source/destination addresses and Ethertype field. + * Inner frame specification may contain destination address only. + * There is support for individual/group mask as well as for empty and full. + * If the mask is NULL, default mask will be used. Ranging is not supported. * @param efx_spec[in, out] * EFX filter specification to update. * @param[out] error @@ -210,40 +210,75 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, .type = 0xffff, }; + const struct rte_flow_item_eth ifrm_supp_mask = { + .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + }; const uint8_t ig_mask[EFX_MAC_ADDR_LEN] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const struct rte_flow_item_eth *supp_mask_p; + const struct rte_flow_item_eth *def_mask_p; + uint8_t *loc_mac = NULL; + boolean_t is_ifrm = (efx_spec->efs_encap_type != + EFX_TUNNEL_PROTOCOL_NONE); + + if (is_ifrm) { + supp_mask_p = &ifrm_supp_mask; + def_mask_p = &ifrm_supp_mask; + loc_mac = efx_spec->efs_ifrm_loc_mac; + } else { + supp_mask_p = &supp_mask; + def_mask_p = &rte_flow_item_eth_mask; + loc_mac = efx_spec->efs_loc_mac; + } rc = sfc_flow_parse_init(item, (const void **)&spec, (const void **)&mask, - &supp_mask, - &rte_flow_item_eth_mask, + supp_mask_p, def_mask_p, sizeof(struct rte_flow_item_eth), error); if (rc != 0) return rc; - /* If "spec" is not set, could be any Ethernet */ - if (spec == NULL) - return 0; + /* + * If "spec" is not set, could be any Ethernet, but for the inner frame + * type of destination MAC must be set + */ + if (spec == NULL) { + if (is_ifrm) + goto fail_bad_ifrm_dst_mac; + else + return 0; + } if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) { - efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC; - rte_memcpy(efx_spec->efs_loc_mac, spec->dst.addr_bytes, + efx_spec->efs_match_flags |= is_ifrm ? + EFX_FILTER_MATCH_IFRM_LOC_MAC : + EFX_FILTER_MATCH_LOC_MAC; + rte_memcpy(loc_mac, spec->dst.addr_bytes, EFX_MAC_ADDR_LEN); } else if (memcmp(mask->dst.addr_bytes, ig_mask, EFX_MAC_ADDR_LEN) == 0) { if (is_unicast_ether_addr(&spec->dst)) - efx_spec->efs_match_flags |= + efx_spec->efs_match_flags |= is_ifrm ? + EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST : EFX_FILTER_MATCH_UNKNOWN_UCAST_DST; else - efx_spec->efs_match_flags |= + efx_spec->efs_match_flags |= is_ifrm ? + EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST : EFX_FILTER_MATCH_UNKNOWN_MCAST_DST; } else if (!is_zero_ether_addr(&mask->dst)) { goto fail_bad_mask; + } else if (is_ifrm) { + goto fail_bad_ifrm_dst_mac; } + /* + * ifrm_supp_mask ensures that the source address and + * ethertype masks are equal to zero in inner frame, + * so these fields are filled in only for the outer frame + */ if (is_same_ether_addr(&mask->src, &supp_mask.src)) { efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC; rte_memcpy(efx_spec->efs_rem_mac, spec->src.addr_bytes, @@ -270,6 +305,13 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, RTE_FLOW_ERROR_TYPE_ITEM, item, "Bad mask in the ETH pattern item"); return -rte_errno; + +fail_bad_ifrm_dst_mac: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Type of destination MAC address in inner frame " + "must be set"); + return -rte_errno; } /** @@ -1112,11 +1154,12 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], } /* - * Allow only VOID pattern item in the inner frame. + * Allow only VOID and ETH pattern items in the inner frame. * Also check that there is only one tunneling protocol. */ switch (item->type) { case RTE_FLOW_ITEM_TYPE_VOID: + case RTE_FLOW_ITEM_TYPE_ETH: break; case RTE_FLOW_ITEM_TYPE_VXLAN: -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 09/14] net/sfc: add infrastructure to make many filters from flow 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (7 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 08/14] net/sfc: add inner frame ETH " Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 10/14] net/sfc: multiply of specs with an unknown EtherType Andrew Rybchenko ` (5 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Not all flow rules can be expressed in one hardware filter, so some flow rules have to be expressed in terms of multiple hardware filters. This patch provides a means to produce a filter spec template from the flow rule which then can be used to produce a set of fully elaborated specs to be inserted. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- drivers/net/sfc/sfc_flow.c | 118 ++++++++++++++++++++++++++++++++++++--------- drivers/net/sfc/sfc_flow.h | 19 +++++++- 2 files changed, 114 insertions(+), 23 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index c942a36..a432936 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -25,10 +25,13 @@ /* * At now flow API is implemented in such a manner that each - * flow rule is converted to a hardware filter. + * flow rule is converted to one or more hardware filters. * All elements of flow rule (attributes, pattern items, actions) * correspond to one or more fields in the efx_filter_spec_s structure * that is responsible for the hardware filter. + * If some required field is unset in the flow rule, then a handful + * of filter copies will be created to cover all possible values + * of such a field. */ enum sfc_flow_item_layers { @@ -1095,8 +1098,8 @@ sfc_flow_parse_attr(const struct rte_flow_attr *attr, return -rte_errno; } - flow->spec.efs_flags |= EFX_FILTER_FLAG_RX; - flow->spec.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; + flow->spec.template.efs_flags |= EFX_FILTER_FLAG_RX; + flow->spec.template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; return 0; } @@ -1187,7 +1190,7 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], break; } - rc = item->parse(pattern, &flow->spec, error); + rc = item->parse(pattern, &flow->spec.template, error); if (rc != 0) return rc; @@ -1209,7 +1212,7 @@ sfc_flow_parse_queue(struct sfc_adapter *sa, return -EINVAL; rxq = sa->rxq_info[queue->index].rxq; - flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index; + flow->spec.template.efs_dmaq_id = (uint16_t)rxq->hw_index; return 0; } @@ -1285,13 +1288,57 @@ sfc_flow_parse_rss(struct sfc_adapter *sa, #endif /* EFSYS_OPT_RX_SCALE */ static int +sfc_flow_spec_flush(struct sfc_adapter *sa, struct sfc_flow_spec *spec, + unsigned int filters_count) +{ + unsigned int i; + int ret = 0; + + for (i = 0; i < filters_count; i++) { + int rc; + + rc = efx_filter_remove(sa->nic, &spec->filters[i]); + if (ret == 0 && rc != 0) { + sfc_err(sa, "failed to remove filter specification " + "(rc = %d)", rc); + ret = rc; + } + } + + return ret; +} + +static int +sfc_flow_spec_insert(struct sfc_adapter *sa, struct sfc_flow_spec *spec) +{ + unsigned int i; + int rc = 0; + + for (i = 0; i < spec->count; i++) { + rc = efx_filter_insert(sa->nic, &spec->filters[i]); + if (rc != 0) { + sfc_flow_spec_flush(sa, spec, i); + break; + } + } + + return rc; +} + +static int +sfc_flow_spec_remove(struct sfc_adapter *sa, struct sfc_flow_spec *spec) +{ + return sfc_flow_spec_flush(sa, spec, spec->count); +} + +static int sfc_flow_filter_insert(struct sfc_adapter *sa, struct rte_flow *flow) { - efx_filter_spec_t *spec = &flow->spec; - #if EFSYS_OPT_RX_SCALE struct sfc_flow_rss *rss = &flow->rss_conf; + uint32_t efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; + unsigned int i; int rc = 0; if (flow->rss) { @@ -1302,27 +1349,38 @@ sfc_flow_filter_insert(struct sfc_adapter *sa, rc = efx_rx_scale_context_alloc(sa->nic, EFX_RX_SCALE_EXCLUSIVE, rss_spread, - &spec->efs_rss_context); + &efs_rss_context); if (rc != 0) goto fail_scale_context_alloc; - rc = efx_rx_scale_mode_set(sa->nic, spec->efs_rss_context, + rc = efx_rx_scale_mode_set(sa->nic, efs_rss_context, EFX_RX_HASHALG_TOEPLITZ, rss->rss_hash_types, B_TRUE); if (rc != 0) goto fail_scale_mode_set; - rc = efx_rx_scale_key_set(sa->nic, spec->efs_rss_context, + rc = efx_rx_scale_key_set(sa->nic, efs_rss_context, rss->rss_key, sizeof(sa->rss_key)); if (rc != 0) goto fail_scale_key_set; - spec->efs_dmaq_id = rss->rxq_hw_index_min; - spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS; + /* + * At this point, fully elaborated filter specifications + * have been produced from the template. To make sure that + * RSS behaviour is consistent between them, set the same + * RSS context value everywhere. + */ + for (i = 0; i < flow->spec.count; i++) { + efx_filter_spec_t *spec = &flow->spec.filters[i]; + + spec->efs_rss_context = efs_rss_context; + spec->efs_dmaq_id = rss->rxq_hw_index_min; + spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS; + } } - rc = efx_filter_insert(sa->nic, spec); + rc = sfc_flow_spec_insert(sa, &flow->spec); if (rc != 0) goto fail_filter_insert; @@ -1335,7 +1393,7 @@ sfc_flow_filter_insert(struct sfc_adapter *sa, * the HW knows all the information needed to verify * the table entries, and the operation will succeed */ - rc = efx_rx_scale_tbl_set(sa->nic, spec->efs_rss_context, + rc = efx_rx_scale_tbl_set(sa->nic, efs_rss_context, rss->rss_tbl, RTE_DIM(rss->rss_tbl)); if (rc != 0) goto fail_scale_tbl_set; @@ -1344,18 +1402,18 @@ sfc_flow_filter_insert(struct sfc_adapter *sa, return 0; fail_scale_tbl_set: - efx_filter_remove(sa->nic, spec); + sfc_flow_spec_remove(sa, &flow->spec); fail_filter_insert: fail_scale_key_set: fail_scale_mode_set: - if (flow->rss) - efx_rx_scale_context_free(sa->nic, spec->efs_rss_context); + if (efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) + efx_rx_scale_context_free(sa->nic, efs_rss_context); fail_scale_context_alloc: return rc; #else /* !EFSYS_OPT_RX_SCALE */ - return efx_filter_insert(sa->nic, spec); + return sfc_flow_spec_insert(sa, &flow->spec); #endif /* EFSYS_OPT_RX_SCALE */ } @@ -1363,16 +1421,23 @@ static int sfc_flow_filter_remove(struct sfc_adapter *sa, struct rte_flow *flow) { - efx_filter_spec_t *spec = &flow->spec; int rc = 0; - rc = efx_filter_remove(sa->nic, spec); + rc = sfc_flow_spec_remove(sa, &flow->spec); if (rc != 0) return rc; #if EFSYS_OPT_RX_SCALE - if (flow->rss) + if (flow->rss) { + /* + * All specifications for a given flow rule have the same RSS + * context, so that RSS context value is taken from the first + * filter specification + */ + efx_filter_spec_t *spec = &flow->spec.filters[0]; + rc = efx_rx_scale_context_free(sa->nic, spec->efs_rss_context); + } #endif /* EFSYS_OPT_RX_SCALE */ return rc; @@ -1452,6 +1517,8 @@ sfc_flow_parse(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct sfc_adapter *sa = dev->data->dev_private; + efx_filter_match_flags_t match_flags = + flow->spec.template.efs_match_flags; int rc; rc = sfc_flow_parse_attr(attr, flow, error); @@ -1466,13 +1533,20 @@ sfc_flow_parse(struct rte_eth_dev *dev, if (rc != 0) goto fail_bad_value; - if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) { + if (!sfc_filter_is_match_supported(sa, match_flags)) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Flow rule pattern is not supported"); return -rte_errno; } + /* + * At this point, template specification simply becomes the first + * fully elaborated spec + */ + flow->spec.filters[0] = flow->spec.template; + flow->spec.count = 1; + fail_bad_value: return rc; } diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 35472ad..634c310 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -19,6 +19,13 @@ extern "C" { #endif +/* + * The maximum number of fully elaborated hardware filter specifications + * which can be produced from a template by means of multiplication, if + * missing match flags are needed to be taken into account + */ +#define SF_FLOW_SPEC_NB_FILTERS_MAX 1 + #if EFSYS_OPT_RX_SCALE /* RSS configuration storage */ struct sfc_flow_rss { @@ -30,9 +37,19 @@ struct sfc_flow_rss { }; #endif /* EFSYS_OPT_RX_SCALE */ +/* Filter specification storage */ +struct sfc_flow_spec { + /* partial specification from flow rule */ + efx_filter_spec_t template; + /* fully elaborated hardware filters specifications */ + efx_filter_spec_t filters[SF_FLOW_SPEC_NB_FILTERS_MAX]; + /* number of complete specifications */ + unsigned int count; +}; + /* PMD-specific definition of the opaque type from rte_flow.h */ struct rte_flow { - efx_filter_spec_t spec; /* filter specification */ + struct sfc_flow_spec spec; /* flow spec for hardware filter(s) */ #if EFSYS_OPT_RX_SCALE boolean_t rss; /* RSS toggle */ struct sfc_flow_rss rss_conf; /* RSS configuration */ -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 10/14] net/sfc: multiply of specs with an unknown EtherType 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (8 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 09/14] net/sfc: add infrastructure to make many filters from flow Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 11/14] net/sfc: multiply of specs w/o inner frame destination MAC Andrew Rybchenko ` (4 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Hardware filter specification for encapsulated traffic must contain EtherType. In terms of RTE flow API, this would require L3 item to be used in the flow rule. In the simplest case, if the user needs to filter encapsulated traffic without knowledge of exact EtherType, they will have to create multiple variants of the flow rule featuring all possible L3 items (IPv4, IPv6), respectively. In order to hide the gory details and avoid such a complication, this patch implements a mechanism to auto-complete the filter specifications if need be. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- drivers/net/sfc/sfc_flow.c | 306 +++++++++++++++++++++++++++++++++++++++------ drivers/net/sfc/sfc_flow.h | 2 +- 2 files changed, 266 insertions(+), 42 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index a432936..244fcdb 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -64,6 +64,21 @@ static sfc_flow_item_parse sfc_flow_parse_vxlan; static sfc_flow_item_parse sfc_flow_parse_geneve; static sfc_flow_item_parse sfc_flow_parse_nvgre; +typedef int (sfc_flow_spec_set_vals)(struct sfc_flow_spec *spec, + unsigned int filters_count_for_one_val, + struct rte_flow_error *error); + +struct sfc_flow_copy_flag { + /* EFX filter specification match flag */ + efx_filter_match_flags_t flag; + /* Number of values of corresponding field */ + unsigned int vals_count; + /* Function to set values in specifications */ + sfc_flow_spec_set_vals *set_vals; +}; + +static sfc_flow_spec_set_vals sfc_flow_set_ethertypes; + static boolean_t sfc_flow_is_zero(const uint8_t *buf, unsigned int size) { @@ -244,16 +259,9 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, if (rc != 0) return rc; - /* - * If "spec" is not set, could be any Ethernet, but for the inner frame - * type of destination MAC must be set - */ - if (spec == NULL) { - if (is_ifrm) - goto fail_bad_ifrm_dst_mac; - else - return 0; - } + /* If "spec" is not set, could be any Ethernet */ + if (spec == NULL) + return 0; if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) { efx_spec->efs_match_flags |= is_ifrm ? @@ -273,8 +281,6 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, EFX_FILTER_MATCH_UNKNOWN_MCAST_DST; } else if (!is_zero_ether_addr(&mask->dst)) { goto fail_bad_mask; - } else if (is_ifrm) { - goto fail_bad_ifrm_dst_mac; } /* @@ -308,13 +314,6 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, RTE_FLOW_ERROR_TYPE_ITEM, item, "Bad mask in the ETH pattern item"); return -rte_errno; - -fail_bad_ifrm_dst_mac: - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, item, - "Type of destination MAC address in inner frame " - "must be set"); - return -rte_errno; } /** @@ -782,14 +781,9 @@ sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, } } - if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, item, - "Outer frame EtherType in pattern with tunneling " - "must be set"); - return -rte_errno; - } else if (efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 && - efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) { + if (efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE && + efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 && + efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "Outer frame EtherType in pattern with tunneling " @@ -1508,6 +1502,246 @@ sfc_flow_parse_actions(struct sfc_adapter *sa, return 0; } +/** + * Set the EFX_FILTER_MATCH_ETHER_TYPE match flag and EFX_ETHER_TYPE_IPV4 and + * EFX_ETHER_TYPE_IPV6 values of the corresponding field in the same + * specifications after copying. + * + * @param spec[in, out] + * SFC flow specification to update. + * @param filters_count_for_one_val[in] + * How many specifications should have the same EtherType value, what is the + * number of specifications before copying. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_set_ethertypes(struct sfc_flow_spec *spec, + unsigned int filters_count_for_one_val, + struct rte_flow_error *error) +{ + unsigned int i; + static const uint16_t vals[] = { + EFX_ETHER_TYPE_IPV4, EFX_ETHER_TYPE_IPV6 + }; + + if (filters_count_for_one_val * RTE_DIM(vals) != spec->count) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Number of specifications is incorrect " + "while copying by Ethertype"); + return -rte_errno; + } + + for (i = 0; i < spec->count; i++) { + spec->filters[i].efs_match_flags |= + EFX_FILTER_MATCH_ETHER_TYPE; + + /* + * The check above ensures that + * filters_count_for_one_val is not 0 + */ + spec->filters[i].efs_ether_type = + vals[i / filters_count_for_one_val]; + } + + return 0; +} + +/* Match flags that can be automatically added to filters */ +static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = { + { + .flag = EFX_FILTER_MATCH_ETHER_TYPE, + .vals_count = 2, + .set_vals = sfc_flow_set_ethertypes, + }, +}; + +/* Get item from array sfc_flow_copy_flags */ +static const struct sfc_flow_copy_flag * +sfc_flow_get_copy_flag(efx_filter_match_flags_t flag) +{ + unsigned int i; + + for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) { + if (sfc_flow_copy_flags[i].flag == flag) + return &sfc_flow_copy_flags[i]; + } + + return NULL; +} + +/** + * Make copies of the specifications, set match flag and values + * of the field that corresponds to it. + * + * @param spec[in, out] + * SFC flow specification to update. + * @param flag[in] + * The match flag to add. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_spec_add_match_flag(struct sfc_flow_spec *spec, + efx_filter_match_flags_t flag, + struct rte_flow_error *error) +{ + unsigned int i; + unsigned int new_filters_count; + unsigned int filters_count_for_one_val; + const struct sfc_flow_copy_flag *copy_flag; + int rc; + + copy_flag = sfc_flow_get_copy_flag(flag); + if (copy_flag == NULL) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Unsupported spec field for copying"); + return -rte_errno; + } + + new_filters_count = spec->count * copy_flag->vals_count; + if (new_filters_count > SF_FLOW_SPEC_NB_FILTERS_MAX) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Too much EFX specifications in the flow rule"); + return -rte_errno; + } + + /* Copy filters specifications */ + for (i = spec->count; i < new_filters_count; i++) + spec->filters[i] = spec->filters[i - spec->count]; + + filters_count_for_one_val = spec->count; + spec->count = new_filters_count; + + rc = copy_flag->set_vals(spec, filters_count_for_one_val, error); + if (rc != 0) + return rc; + + return 0; +} + +/** + * Check that the given set of match flags missing in the original filter spec + * could be covered by adding spec copies which specify the corresponding + * flags and packet field values to match. + * + * @param miss_flags[in] + * Flags that are missing until the supported filter. + * + * @return + * Number of specifications after copy or 0, if the flags can not be added. + */ +static unsigned int +sfc_flow_check_missing_flags(efx_filter_match_flags_t miss_flags) +{ + unsigned int i; + efx_filter_match_flags_t copy_flags = 0; + efx_filter_match_flags_t flag; + unsigned int multiplier = 1; + + for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) { + flag = sfc_flow_copy_flags[i].flag; + if ((flag & miss_flags) == flag) { + copy_flags |= flag; + multiplier *= sfc_flow_copy_flags[i].vals_count; + } + } + + if (copy_flags == miss_flags) + return multiplier; + + return 0; +} + +/** + * Attempt to supplement the specification template to the minimally + * supported set of match flags. To do this, it is necessary to copy + * the specifications, filling them with the values of fields that + * correspond to the missing flags. + * The necessary and sufficient filter is built from the fewest number + * of copies which could be made to cover the minimally required set + * of flags. + * + * @param sa[in] + * SFC adapter. + * @param spec[in, out] + * SFC flow specification to update. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_spec_filters_complete(struct sfc_adapter *sa, + struct sfc_flow_spec *spec, + struct rte_flow_error *error) +{ + struct sfc_filter *filter = &sa->filter; + efx_filter_match_flags_t miss_flags; + efx_filter_match_flags_t min_miss_flags = 0; + efx_filter_match_flags_t match; + unsigned int min_multiplier = UINT_MAX; + unsigned int multiplier; + unsigned int i; + int rc; + + match = spec->template.efs_match_flags; + for (i = 0; i < filter->supported_match_num; i++) { + if ((match & filter->supported_match[i]) == match) { + miss_flags = filter->supported_match[i] & (~match); + multiplier = sfc_flow_check_missing_flags(miss_flags); + if (multiplier > 0) { + if (multiplier <= min_multiplier) { + min_multiplier = multiplier; + min_miss_flags = miss_flags; + } + } + } + } + + if (min_multiplier == UINT_MAX) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Flow rule pattern is not supported"); + return -rte_errno; + } + + for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) { + efx_filter_match_flags_t flag = sfc_flow_copy_flags[i].flag; + + if ((flag & min_miss_flags) == flag) { + rc = sfc_flow_spec_add_match_flag(spec, flag, error); + if (rc != 0) + return rc; + } + } + + return 0; +} + +static int +sfc_flow_validate_match_flags(struct sfc_adapter *sa, + struct rte_flow *flow, + struct rte_flow_error *error) +{ + efx_filter_spec_t *spec_tmpl = &flow->spec.template; + efx_filter_match_flags_t match_flags = spec_tmpl->efs_match_flags; + int rc; + + /* Initialize the first filter spec with template */ + flow->spec.filters[0] = *spec_tmpl; + flow->spec.count = 1; + + if (!sfc_filter_is_match_supported(sa, match_flags)) { + rc = sfc_flow_spec_filters_complete(sa, &flow->spec, error); + if (rc != 0) + return rc; + } + + return 0; +} + static int sfc_flow_parse(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, @@ -1517,8 +1751,6 @@ sfc_flow_parse(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct sfc_adapter *sa = dev->data->dev_private; - efx_filter_match_flags_t match_flags = - flow->spec.template.efs_match_flags; int rc; rc = sfc_flow_parse_attr(attr, flow, error); @@ -1533,19 +1765,11 @@ sfc_flow_parse(struct rte_eth_dev *dev, if (rc != 0) goto fail_bad_value; - if (!sfc_filter_is_match_supported(sa, match_flags)) { - rte_flow_error_set(error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "Flow rule pattern is not supported"); - return -rte_errno; - } + rc = sfc_flow_validate_match_flags(sa, flow, error); + if (rc != 0) + goto fail_bad_value; - /* - * At this point, template specification simply becomes the first - * fully elaborated spec - */ - flow->spec.filters[0] = flow->spec.template; - flow->spec.count = 1; + return 0; fail_bad_value: return rc; diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 634c310..c4302c7 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -24,7 +24,7 @@ extern "C" { * which can be produced from a template by means of multiplication, if * missing match flags are needed to be taken into account */ -#define SF_FLOW_SPEC_NB_FILTERS_MAX 1 +#define SF_FLOW_SPEC_NB_FILTERS_MAX 2 #if EFSYS_OPT_RX_SCALE /* RSS configuration storage */ -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 11/14] net/sfc: multiply of specs w/o inner frame destination MAC 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (9 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 10/14] net/sfc: multiply of specs with an unknown EtherType Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 12/14] net/sfc: multiply of specs with an unknown " Andrew Rybchenko ` (3 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Knowledge of a network identifier is not sufficient to construct a workable hardware filter for encapsulated traffic. It's obligatory to specify one of the match flags associated with inner frame destination MAC. If the address is unknown, then one needs to specify either unknown unicast or unknown multicast destination match flag. In terms of RTE flow API, this would require adding multiple flow rules with corresponding ETH items besides the tunnel item. In order to avoid such a complication, the patch implements a mechanism to auto-complete an underlying filter representation of a flow rule in order to create additional filter specififcations featuring the missing match flags. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- drivers/net/sfc/sfc_flow.c | 114 ++++++++++++++++++++++++++++++++++++++++++++- drivers/net/sfc/sfc_flow.h | 2 +- 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 244fcdb..2d45827 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -68,6 +68,10 @@ typedef int (sfc_flow_spec_set_vals)(struct sfc_flow_spec *spec, unsigned int filters_count_for_one_val, struct rte_flow_error *error); +typedef boolean_t (sfc_flow_spec_check)(efx_filter_match_flags_t match, + efx_filter_spec_t *spec, + struct sfc_filter *filter); + struct sfc_flow_copy_flag { /* EFX filter specification match flag */ efx_filter_match_flags_t flag; @@ -75,9 +79,16 @@ struct sfc_flow_copy_flag { unsigned int vals_count; /* Function to set values in specifications */ sfc_flow_spec_set_vals *set_vals; + /* + * Function to check that the specification is suitable + * for adding this match flag + */ + sfc_flow_spec_check *spec_check; }; static sfc_flow_spec_set_vals sfc_flow_set_ethertypes; +static sfc_flow_spec_set_vals sfc_flow_set_ifrm_unknown_dst_flags; +static sfc_flow_spec_check sfc_flow_check_ifrm_unknown_dst_flags; static boolean_t sfc_flow_is_zero(const uint8_t *buf, unsigned int size) @@ -1548,12 +1559,98 @@ sfc_flow_set_ethertypes(struct sfc_flow_spec *spec, return 0; } +/** + * Set the EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST and + * EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST match flags in the same + * specifications after copying. + * + * @param spec[in, out] + * SFC flow specification to update. + * @param filters_count_for_one_val[in] + * How many specifications should have the same match flag, what is the + * number of specifications before copying. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_set_ifrm_unknown_dst_flags(struct sfc_flow_spec *spec, + unsigned int filters_count_for_one_val, + struct rte_flow_error *error) +{ + unsigned int i; + static const efx_filter_match_flags_t vals[] = { + EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST, + EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST + }; + + if (filters_count_for_one_val * RTE_DIM(vals) != spec->count) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Number of specifications is incorrect while copying " + "by inner frame unknown destination flags"); + return -rte_errno; + } + + for (i = 0; i < spec->count; i++) { + /* The check above ensures that divisor can't be zero here */ + spec->filters[i].efs_match_flags |= + vals[i / filters_count_for_one_val]; + } + + return 0; +} + +/** + * Check that the following conditions are met: + * - the specification corresponds to a filter for encapsulated traffic + * - the list of supported filters has a filter + * with EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST flag instead of + * EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST, since this filter will also + * be inserted. + * + * @param match[in] + * The match flags of filter. + * @param spec[in] + * Specification to be supplemented. + * @param filter[in] + * SFC filter with list of supported filters. + */ +static boolean_t +sfc_flow_check_ifrm_unknown_dst_flags(efx_filter_match_flags_t match, + efx_filter_spec_t *spec, + struct sfc_filter *filter) +{ + unsigned int i; + efx_tunnel_protocol_t encap_type = spec->efs_encap_type; + efx_filter_match_flags_t match_mcast_dst; + + if (encap_type == EFX_TUNNEL_PROTOCOL_NONE) + return B_FALSE; + + match_mcast_dst = + (match & ~EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST) | + EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST; + for (i = 0; i < filter->supported_match_num; i++) { + if (match_mcast_dst == filter->supported_match[i]) + return B_TRUE; + } + + return B_FALSE; +} + /* Match flags that can be automatically added to filters */ static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = { { .flag = EFX_FILTER_MATCH_ETHER_TYPE, .vals_count = 2, .set_vals = sfc_flow_set_ethertypes, + .spec_check = NULL, + }, + { + .flag = EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST, + .vals_count = 2, + .set_vals = sfc_flow_set_ifrm_unknown_dst_flags, + .spec_check = sfc_flow_check_ifrm_unknown_dst_flags, }, }; @@ -1630,21 +1727,33 @@ sfc_flow_spec_add_match_flag(struct sfc_flow_spec *spec, * * @param miss_flags[in] * Flags that are missing until the supported filter. + * @param spec[in] + * Specification to be supplemented. + * @param filter[in] + * SFC filter. * * @return * Number of specifications after copy or 0, if the flags can not be added. */ static unsigned int -sfc_flow_check_missing_flags(efx_filter_match_flags_t miss_flags) +sfc_flow_check_missing_flags(efx_filter_match_flags_t miss_flags, + efx_filter_spec_t *spec, + struct sfc_filter *filter) { unsigned int i; efx_filter_match_flags_t copy_flags = 0; efx_filter_match_flags_t flag; + efx_filter_match_flags_t match = spec->efs_match_flags | miss_flags; + sfc_flow_spec_check *check; unsigned int multiplier = 1; for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) { flag = sfc_flow_copy_flags[i].flag; + check = sfc_flow_copy_flags[i].spec_check; if ((flag & miss_flags) == flag) { + if (check != NULL && (!check(match, spec, filter))) + continue; + copy_flags |= flag; multiplier *= sfc_flow_copy_flags[i].vals_count; } @@ -1690,7 +1799,8 @@ sfc_flow_spec_filters_complete(struct sfc_adapter *sa, for (i = 0; i < filter->supported_match_num; i++) { if ((match & filter->supported_match[i]) == match) { miss_flags = filter->supported_match[i] & (~match); - multiplier = sfc_flow_check_missing_flags(miss_flags); + multiplier = sfc_flow_check_missing_flags(miss_flags, + &spec->template, filter); if (multiplier > 0) { if (multiplier <= min_multiplier) { min_multiplier = multiplier; diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index c4302c7..2b287dd 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -24,7 +24,7 @@ extern "C" { * which can be produced from a template by means of multiplication, if * missing match flags are needed to be taken into account */ -#define SF_FLOW_SPEC_NB_FILTERS_MAX 2 +#define SF_FLOW_SPEC_NB_FILTERS_MAX 4 #if EFSYS_OPT_RX_SCALE /* RSS configuration storage */ -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 12/14] net/sfc: multiply of specs with an unknown destination MAC 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (10 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 11/14] net/sfc: multiply of specs w/o inner frame destination MAC Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 13/14] net/sfc: avoid creation of ineffective flow rules Andrew Rybchenko ` (2 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> To filter all traffic, need to create two hardware filter specifications with both unknown unicast and unknown multicast destination MAC address match flags. In terms of RTE flow API, this would require adding multiple flow rules with corresponding ETH items. In order to avoid such a complication, the patch implements a mechanism to auto-complete an underlying filter representation of a flow rule in order to create additional filter specififcations featuring the missing match flags. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- drivers/net/sfc/sfc_flow.c | 91 +++++++++++++++++++++++++++++++++++++++++++++- drivers/net/sfc/sfc_flow.h | 2 +- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 2d45827..7b26653 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -86,6 +86,8 @@ struct sfc_flow_copy_flag { sfc_flow_spec_check *spec_check; }; +static sfc_flow_spec_set_vals sfc_flow_set_unknown_dst_flags; +static sfc_flow_spec_check sfc_flow_check_unknown_dst_flags; static sfc_flow_spec_set_vals sfc_flow_set_ethertypes; static sfc_flow_spec_set_vals sfc_flow_set_ifrm_unknown_dst_flags; static sfc_flow_spec_check sfc_flow_check_ifrm_unknown_dst_flags; @@ -1514,6 +1516,80 @@ sfc_flow_parse_actions(struct sfc_adapter *sa, } /** + * Set the EFX_FILTER_MATCH_UNKNOWN_UCAST_DST + * and EFX_FILTER_MATCH_UNKNOWN_MCAST_DST match flags in the same + * specifications after copying. + * + * @param spec[in, out] + * SFC flow specification to update. + * @param filters_count_for_one_val[in] + * How many specifications should have the same match flag, what is the + * number of specifications before copying. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_set_unknown_dst_flags(struct sfc_flow_spec *spec, + unsigned int filters_count_for_one_val, + struct rte_flow_error *error) +{ + unsigned int i; + static const efx_filter_match_flags_t vals[] = { + EFX_FILTER_MATCH_UNKNOWN_UCAST_DST, + EFX_FILTER_MATCH_UNKNOWN_MCAST_DST + }; + + if (filters_count_for_one_val * RTE_DIM(vals) != spec->count) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Number of specifications is incorrect while copying " + "by unknown destination flags"); + return -rte_errno; + } + + for (i = 0; i < spec->count; i++) { + /* The check above ensures that divisor can't be zero here */ + spec->filters[i].efs_match_flags |= + vals[i / filters_count_for_one_val]; + } + + return 0; +} + +/** + * Check that the following conditions are met: + * - the list of supported filters has a filter + * with EFX_FILTER_MATCH_UNKNOWN_MCAST_DST flag instead of + * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST, since this filter will also + * be inserted. + * + * @param match[in] + * The match flags of filter. + * @param spec[in] + * Specification to be supplemented. + * @param filter[in] + * SFC filter with list of supported filters. + */ +static boolean_t +sfc_flow_check_unknown_dst_flags(efx_filter_match_flags_t match, + __rte_unused efx_filter_spec_t *spec, + struct sfc_filter *filter) +{ + unsigned int i; + efx_filter_match_flags_t match_mcast_dst; + + match_mcast_dst = + (match & ~EFX_FILTER_MATCH_UNKNOWN_UCAST_DST) | + EFX_FILTER_MATCH_UNKNOWN_MCAST_DST; + for (i = 0; i < filter->supported_match_num; i++) { + if (match_mcast_dst == filter->supported_match[i]) + return B_TRUE; + } + + return B_FALSE; +} + +/** * Set the EFX_FILTER_MATCH_ETHER_TYPE match flag and EFX_ETHER_TYPE_IPV4 and * EFX_ETHER_TYPE_IPV6 values of the corresponding field in the same * specifications after copying. @@ -1638,9 +1714,22 @@ sfc_flow_check_ifrm_unknown_dst_flags(efx_filter_match_flags_t match, return B_FALSE; } -/* Match flags that can be automatically added to filters */ +/* + * Match flags that can be automatically added to filters. + * Selecting the last minimum when searching for the copy flag ensures that the + * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST flag has a higher priority than + * EFX_FILTER_MATCH_ETHER_TYPE. This is because the filter + * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST is at the end of the list of supported + * filters. + */ static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = { { + .flag = EFX_FILTER_MATCH_UNKNOWN_UCAST_DST, + .vals_count = 2, + .set_vals = sfc_flow_set_unknown_dst_flags, + .spec_check = sfc_flow_check_unknown_dst_flags, + }, + { .flag = EFX_FILTER_MATCH_ETHER_TYPE, .vals_count = 2, .set_vals = sfc_flow_set_ethertypes, diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 2b287dd..69dd683 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -24,7 +24,7 @@ extern "C" { * which can be produced from a template by means of multiplication, if * missing match flags are needed to be taken into account */ -#define SF_FLOW_SPEC_NB_FILTERS_MAX 4 +#define SF_FLOW_SPEC_NB_FILTERS_MAX 8 #if EFSYS_OPT_RX_SCALE /* RSS configuration storage */ -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 13/14] net/sfc: avoid creation of ineffective flow rules 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (11 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 12/14] net/sfc: multiply of specs with an unknown " Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 14/14] doc: add net/sfc flow API support for tunnels Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Despite being versatile, the hardware support for filtering has a number of special properties which must be taken into account. Namely, there is a known set of valid filters which don't take any effect despite being accepted by the hardware. The combinations of match flags and field values which can describe the exceptional filters are as follows: - ETHER_TYPE or ETHER_TYPE | LOC_MAC with IPv4 or IPv6 EtherType - ETHER_TYPE | IP_PROTO or ETHER_TYPE | IP_PROTO | LOC_MAC with UDP or TCP IP protocol value - The same combinations with OUTER_VID and/or INNER_VID These exceptional filters can be expressed in terms of RTE flow rules. If the user creates such a flow rule, no traffic will hit the underlying filter, and no errors will be reported. This patch adds a means to prevent such ineffective flow rules from being created. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- doc/guides/nics/sfc_efx.rst | 17 ++++++++++ drivers/net/sfc/sfc_flow.c | 78 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 539ce90..f41ccdb 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -193,6 +193,23 @@ in the mask of destination address. If destinaton address in the spec is multicast, it matches all multicast (and broadcast) packets, oherwise it matches unicast packets that are not filtered by other flow rules. +Exceptions to flow rules +~~~~~~~~~~~~~~~~~~~~~~~~ + +There is a list of exceptional flow rule patterns which will not be +accepted by the PMD. A pattern will be rejected if at least one of the +conditions is met: + +- Filtering by IPv4 or IPv6 EtherType without pattern items of internet + layer and above. + +- The last item is IPV4 or IPV6, and it's empty. + +- Filtering by TCP or UDP IP transport protocol without pattern items of + transport layer and above. + +- The last item is TCP or UDP, and it's empty. + Supported NICs -------------- diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 7b26653..2b8bef8 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -1919,6 +1919,77 @@ sfc_flow_spec_filters_complete(struct sfc_adapter *sa, return 0; } +/** + * Check that set of match flags is referred to by a filter. Filter is + * described by match flags with the ability to add OUTER_VID and INNER_VID + * flags. + * + * @param match_flags[in] + * Set of match flags. + * @param flags_pattern[in] + * Pattern of filter match flags. + */ +static boolean_t +sfc_flow_is_match_with_vids(efx_filter_match_flags_t match_flags, + efx_filter_match_flags_t flags_pattern) +{ + if ((match_flags & flags_pattern) != flags_pattern) + return B_FALSE; + + switch (match_flags & ~flags_pattern) { + case 0: + case EFX_FILTER_MATCH_OUTER_VID: + case EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_INNER_VID: + return B_TRUE; + default: + return B_FALSE; + } +} + +/** + * Check whether the spec maps to a hardware filter which is known to be + * ineffective despite being valid. + * + * @param spec[in] + * SFC flow specification. + */ +static boolean_t +sfc_flow_is_match_flags_exception(struct sfc_flow_spec *spec) +{ + unsigned int i; + uint16_t ether_type; + uint8_t ip_proto; + efx_filter_match_flags_t match_flags; + + for (i = 0; i < spec->count; i++) { + match_flags = spec->filters[i].efs_match_flags; + + if (sfc_flow_is_match_with_vids(match_flags, + EFX_FILTER_MATCH_ETHER_TYPE) || + sfc_flow_is_match_with_vids(match_flags, + EFX_FILTER_MATCH_ETHER_TYPE | + EFX_FILTER_MATCH_LOC_MAC)) { + ether_type = spec->filters[i].efs_ether_type; + if (ether_type == EFX_ETHER_TYPE_IPV4 || + ether_type == EFX_ETHER_TYPE_IPV6) + return B_TRUE; + } else if (sfc_flow_is_match_with_vids(match_flags, + EFX_FILTER_MATCH_ETHER_TYPE | + EFX_FILTER_MATCH_IP_PROTO) || + sfc_flow_is_match_with_vids(match_flags, + EFX_FILTER_MATCH_ETHER_TYPE | + EFX_FILTER_MATCH_IP_PROTO | + EFX_FILTER_MATCH_LOC_MAC)) { + ip_proto = spec->filters[i].efs_ip_proto; + if (ip_proto == EFX_IPPROTO_TCP || + ip_proto == EFX_IPPROTO_UDP) + return B_TRUE; + } + } + + return B_FALSE; +} + static int sfc_flow_validate_match_flags(struct sfc_adapter *sa, struct rte_flow *flow, @@ -1938,6 +2009,13 @@ sfc_flow_validate_match_flags(struct sfc_adapter *sa, return rc; } + if (sfc_flow_is_match_flags_exception(&flow->spec)) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "The flow rule pattern is unsupported"); + return -rte_errno; + } + return 0; } -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH 14/14] doc: add net/sfc flow API support for tunnels 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (12 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 13/14] net/sfc: avoid creation of ineffective flow rules Andrew Rybchenko @ 2018-02-27 12:45 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-02-27 12:45 UTC (permalink / raw) To: dev Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> --- doc/guides/rel_notes/release_18_05.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/guides/rel_notes/release_18_05.rst b/doc/guides/rel_notes/release_18_05.rst index 3923dc2..894f636 100644 --- a/doc/guides/rel_notes/release_18_05.rst +++ b/doc/guides/rel_notes/release_18_05.rst @@ -41,6 +41,12 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Updated Solarflare network PMD.** + + Updated the sfc_efx driver including the following changes: + + * Added support for NVGRE, VXLAN and GENEVE filters in flow API. + API Changes ----------- -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API for tunnels 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko ` (13 preceding siblings ...) 2018-02-27 12:45 ` [dpdk-dev] [PATCH 14/14] doc: add net/sfc flow API support for tunnels Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 01/14] net/sfc/base: support filters for encapsulated packets Andrew Rybchenko ` (14 more replies) 14 siblings, 15 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev Update base driver and the PMD itself to support flow API patterns for tunnels: VXLAN, NVGRE and Geneve. Applicable to SFN8xxx NICs with full-feature firmware variant running. Andrew Rybchenko (1): doc: add net/sfc flow API support for tunnels Roman Zhukov (12): net/sfc/base: support filters for encapsulated packets net/sfc/base: support VNI/VSID and inner frame local MAC net/sfc/base: distinguish filters for encapsulated packets net/sfc: add VXLAN in flow API filters support net/sfc: add NVGRE in flow API filters support net/sfc: add GENEVE in flow API filters support net/sfc: add inner frame ETH in flow API filters support net/sfc: add infrastructure to make many filters from flow net/sfc: multiply of specs with an unknown EtherType net/sfc: multiply of specs w/o inner frame destination MAC net/sfc: multiply of specs with an unknown destination MAC net/sfc: avoid creation of ineffective flow rules Vijay Srivastava (1): net/sfc/base: support VXLAN filter creation doc/guides/nics/sfc_efx.rst | 28 +- doc/guides/rel_notes/release_18_05.rst | 6 + drivers/net/sfc/base/ef10_filter.c | 100 +++- drivers/net/sfc/base/efx.h | 20 + drivers/net/sfc/base/efx_filter.c | 39 +- drivers/net/sfc/sfc_flow.c | 1001 ++++++++++++++++++++++++++++++-- drivers/net/sfc/sfc_flow.h | 19 +- 7 files changed, 1161 insertions(+), 52 deletions(-) -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 01/14] net/sfc/base: support filters for encapsulated packets 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 02/14] net/sfc/base: support VNI/VSID and inner frame local MAC Andrew Rybchenko ` (13 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> This adds filters for encapsulated packets to the list returned by ef10_filter_supported_filters(). Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- v2: - fix assertion drivers/net/sfc/base/ef10_filter.c | 65 ++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/drivers/net/sfc/base/ef10_filter.c b/drivers/net/sfc/base/ef10_filter.c index 2b7a09c..8a6bc61 100644 --- a/drivers/net/sfc/base/ef10_filter.c +++ b/drivers/net/sfc/base/ef10_filter.c @@ -895,6 +895,7 @@ efx_mcdi_get_parser_disp_info( __in efx_nic_t *enp, __out_ecount(buffer_length) uint32_t *buffer, __in size_t buffer_length, + __in boolean_t encap, __out size_t *list_lengthp) { efx_mcdi_req_t req; @@ -911,7 +912,8 @@ efx_mcdi_get_parser_disp_info( req.emr_out_buf = payload; req.emr_out_length = MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX; - MCDI_IN_SET_DWORD(req, GET_PARSER_DISP_INFO_OUT_OP, + MCDI_IN_SET_DWORD(req, GET_PARSER_DISP_INFO_OUT_OP, encap ? + MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_ENCAP_RX_MATCHES : MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_RX_MATCHES); efx_mcdi_execute(enp, &req); @@ -971,28 +973,66 @@ ef10_filter_supported_filters( __in size_t buffer_length, __out size_t *list_lengthp) { - + efx_nic_cfg_t *encp = &(enp->en_nic_cfg); size_t mcdi_list_length; + size_t mcdi_encap_list_length; size_t list_length; uint32_t i; + uint32_t next_buf_idx; + size_t next_buf_length; efx_rc_t rc; + boolean_t no_space = B_FALSE; efx_filter_match_flags_t all_filter_flags = (EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_REM_MAC | EFX_FILTER_MATCH_REM_PORT | EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_INNER_VID | EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_IP_PROTO | + EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST | + EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST | EFX_FILTER_MATCH_UNKNOWN_MCAST_DST | EFX_FILTER_MATCH_UNKNOWN_UCAST_DST); - rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, - &mcdi_list_length); + /* + * Two calls to MC_CMD_GET_PARSER_DISP_INFO are needed: one to get the + * list of supported filters for ordinary packets, and then another to + * get the list of supported filters for encapsulated packets. + */ + rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, B_FALSE, + &mcdi_list_length); if (rc != 0) { - if (rc == ENOSPC) { - /* Pass through mcdi_list_length for the list length */ - *list_lengthp = mcdi_list_length; + if (rc == ENOSPC) + no_space = B_TRUE; + else + goto fail1; + } + + if (no_space) { + next_buf_idx = 0; + next_buf_length = 0; + } else { + EFSYS_ASSERT(mcdi_list_length <= buffer_length); + next_buf_idx = mcdi_list_length; + next_buf_length = buffer_length - mcdi_list_length; + } + + if (encp->enc_tunnel_encapsulations_supported != 0) { + rc = efx_mcdi_get_parser_disp_info(enp, &buffer[next_buf_idx], + next_buf_length, B_TRUE, &mcdi_encap_list_length); + if (rc != 0) { + if (rc == ENOSPC) + no_space = B_TRUE; + else + goto fail2; } - goto fail1; + } else { + mcdi_encap_list_length = 0; + } + + if (no_space) { + *list_lengthp = mcdi_list_length + mcdi_encap_list_length; + rc = ENOSPC; + goto fail3; } /* @@ -1005,9 +1045,10 @@ ef10_filter_supported_filters( * of the matches is preserved as they are ordered from highest to * lowest priority. */ - EFSYS_ASSERT(mcdi_list_length <= buffer_length); + EFSYS_ASSERT(mcdi_list_length + mcdi_encap_list_length <= + buffer_length); list_length = 0; - for (i = 0; i < mcdi_list_length; i++) { + for (i = 0; i < mcdi_list_length + mcdi_encap_list_length; i++) { if ((buffer[i] & ~all_filter_flags) == 0) { buffer[list_length] = buffer[i]; list_length++; @@ -1018,6 +1059,10 @@ ef10_filter_supported_filters( return (0); +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 02/14] net/sfc/base: support VNI/VSID and inner frame local MAC 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 01/14] net/sfc/base: support filters for encapsulated packets Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 03/14] net/sfc/base: support VXLAN filter creation Andrew Rybchenko ` (12 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> This supports VNI/VSID and inner frame local MAC fields to match in VXLAN, GENEVE, or NVGRE packets. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- drivers/net/sfc/base/ef10_filter.c | 18 ++++++++++++++++++ drivers/net/sfc/base/efx.h | 8 ++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/net/sfc/base/ef10_filter.c b/drivers/net/sfc/base/ef10_filter.c index 8a6bc61..e93dc13 100644 --- a/drivers/net/sfc/base/ef10_filter.c +++ b/drivers/net/sfc/base/ef10_filter.c @@ -119,6 +119,10 @@ ef10_filter_init( MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_OUTER_VLAN)); EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IP_PROTO == MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IP_PROTO)); + EFX_STATIC_ASSERT(EFX_FILTER_MATCH_VNI_OR_VSID == + MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_VNI_OR_VSID)); + EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_LOC_MAC == + MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_DST_MAC)); EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST == MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_MCAST_DST)); EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST == @@ -292,6 +296,12 @@ efx_mcdi_filter_op_add( rc = EINVAL; goto fail2; } + + memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_VNI_OR_VSID), + spec->efs_vni_or_vsid, EFX_VNI_OR_VSID_LEN); + + memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_IFRM_DST_MAC), + spec->efs_ifrm_loc_mac, EFX_MAC_ADDR_LEN); } efx_mcdi_execute(enp, &req); @@ -415,6 +425,12 @@ ef10_filter_equal( return (B_FALSE); if (left->efs_encap_type != right->efs_encap_type) return (B_FALSE); + if (memcmp(left->efs_vni_or_vsid, right->efs_vni_or_vsid, + EFX_VNI_OR_VSID_LEN)) + return (B_FALSE); + if (memcmp(left->efs_ifrm_loc_mac, right->efs_ifrm_loc_mac, + EFX_MAC_ADDR_LEN)) + return (B_FALSE); return (B_TRUE); @@ -988,6 +1004,8 @@ ef10_filter_supported_filters( EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_INNER_VID | EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_IP_PROTO | + EFX_FILTER_MATCH_VNI_OR_VSID | + EFX_FILTER_MATCH_IFRM_LOC_MAC | EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST | EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST | EFX_FILTER_MATCH_UNKNOWN_MCAST_DST | diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h index 088a896..8380d0a 100644 --- a/drivers/net/sfc/base/efx.h +++ b/drivers/net/sfc/base/efx.h @@ -454,6 +454,8 @@ typedef enum efx_link_mode_e { #define EFX_MAC_ADDR_LEN 6 +#define EFX_VNI_OR_VSID_LEN 3 + #define EFX_MAC_ADDR_IS_MULTICAST(_address) (((uint8_t *)_address)[0] & 0x01) #define EFX_MAC_MULTICAST_LIST_MAX 256 @@ -2475,6 +2477,10 @@ typedef uint8_t efx_filter_flags_t; #define EFX_FILTER_MATCH_OUTER_VID 0x00000100 /* Match by IP transport protocol */ #define EFX_FILTER_MATCH_IP_PROTO 0x00000200 +/* Match by VNI or VSID */ +#define EFX_FILTER_MATCH_VNI_OR_VSID 0x00000800 +/* For encapsulated packets, match by inner frame local MAC address */ +#define EFX_FILTER_MATCH_IFRM_LOC_MAC 0x00010000 /* For encapsulated packets, match all multicast inner frames */ #define EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST 0x01000000 /* For encapsulated packets, match all unicast inner frames */ @@ -2521,6 +2527,8 @@ typedef struct efx_filter_spec_s { uint16_t efs_rem_port; efx_oword_t efs_rem_host; efx_oword_t efs_loc_host; + uint8_t efs_vni_or_vsid[EFX_VNI_OR_VSID_LEN]; + uint8_t efs_ifrm_loc_mac[EFX_MAC_ADDR_LEN]; } efx_filter_spec_t; -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 03/14] net/sfc/base: support VXLAN filter creation 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 01/14] net/sfc/base: support filters for encapsulated packets Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 02/14] net/sfc/base: support VNI/VSID and inner frame local MAC Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 04/14] net/sfc/base: distinguish filters for encapsulated packets Andrew Rybchenko ` (11 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Vijay Srivastava From: Vijay Srivastava <vijays@solarflare.com> Signed-off-by: Vijay Srivastava <vijays@solarflare.com> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> --- drivers/net/sfc/base/efx.h | 7 +++++++ drivers/net/sfc/base/efx_filter.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h index 8380d0a..e2f49ec 100644 --- a/drivers/net/sfc/base/efx.h +++ b/drivers/net/sfc/base/efx.h @@ -2624,6 +2624,13 @@ efx_filter_spec_set_encap_type( __in efx_tunnel_protocol_t encap_type, __in efx_filter_inner_frame_match_t inner_frame_match); +extern __checkReturn efx_rc_t +efx_filter_spec_set_vxlan_full( + __inout efx_filter_spec_t *spec, + __in const uint8_t *vxlan_id, + __in const uint8_t *inner_addr, + __in const uint8_t *outer_addr); + #if EFSYS_OPT_RX_SCALE extern __checkReturn efx_rc_t efx_filter_spec_set_rss_context( diff --git a/drivers/net/sfc/base/efx_filter.c b/drivers/net/sfc/base/efx_filter.c index 8705369..2e6628b 100644 --- a/drivers/net/sfc/base/efx_filter.c +++ b/drivers/net/sfc/base/efx_filter.c @@ -468,6 +468,42 @@ efx_filter_spec_set_encap_type( return (rc); } +/* + * Specify inner and outer Ethernet address and VXLAN ID in filter + * specification. + */ + __checkReturn efx_rc_t +efx_filter_spec_set_vxlan_full( + __inout efx_filter_spec_t *spec, + __in const uint8_t *vxlan_id, + __in const uint8_t *inner_addr, + __in const uint8_t *outer_addr) +{ + EFSYS_ASSERT3P(spec, !=, NULL); + EFSYS_ASSERT3P(vxlan_id, !=, NULL); + EFSYS_ASSERT3P(inner_addr, !=, NULL); + EFSYS_ASSERT3P(outer_addr, !=, NULL); + + if ((inner_addr == NULL) && (outer_addr == NULL)) + return (EINVAL); + + if (vxlan_id != NULL) { + spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID; + memcpy(spec->efs_vni_or_vsid, vxlan_id, EFX_VNI_OR_VSID_LEN); + } + if (outer_addr != NULL) { + spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC; + memcpy(spec->efs_loc_mac, outer_addr, EFX_MAC_ADDR_LEN); + } + if (inner_addr != NULL) { + spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC; + memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN); + } + spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN; + + return (0); +} + #if EFSYS_OPT_RX_SCALE __checkReturn efx_rc_t efx_filter_spec_set_rss_context( -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 04/14] net/sfc/base: distinguish filters for encapsulated packets 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (2 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 03/14] net/sfc/base: support VXLAN filter creation Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 05/14] net/sfc: add VXLAN in flow API filters support Andrew Rybchenko ` (10 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Add filter match flag to distinguish filters applied only to encapsulated packets. Match flags set should allow to determine whether a filter is supported or not. The problem is that if specification has supported set outer match flags and specified encapsulation without any inner flags, check says that it is supported, and filter insertion is performed. However, there is no filtering of the encapsulated traffic. A new flag is added to solve this problem and separate the filters for the encapsulated packets. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Andy Moreton <amoreton@solarflare.com> Reviewed-by: Mark Spender <mspender@solarflare.com> --- drivers/net/sfc/base/ef10_filter.c | 19 +++++++++++++++++-- drivers/net/sfc/base/efx.h | 5 +++++ drivers/net/sfc/base/efx_filter.c | 3 ++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/net/sfc/base/ef10_filter.c b/drivers/net/sfc/base/ef10_filter.c index e93dc13..a627cce 100644 --- a/drivers/net/sfc/base/ef10_filter.c +++ b/drivers/net/sfc/base/ef10_filter.c @@ -174,6 +174,7 @@ efx_mcdi_filter_op_add( efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_FILTER_OP_EXT_IN_LEN, MC_CMD_FILTER_OP_EXT_OUT_LEN)]; + efx_filter_match_flags_t match_flags; efx_rc_t rc; memset(payload, 0, sizeof (payload)); @@ -183,6 +184,12 @@ efx_mcdi_filter_op_add( req.emr_out_buf = payload; req.emr_out_length = MC_CMD_FILTER_OP_EXT_OUT_LEN; + /* + * Remove match flag for encapsulated filters that does not correspond + * to the MCDI match flags + */ + match_flags = spec->efs_match_flags & ~EFX_FILTER_MATCH_ENCAP_TYPE; + switch (filter_op) { case MC_CMD_FILTER_OP_IN_OP_REPLACE: MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_LO, @@ -203,7 +210,7 @@ efx_mcdi_filter_op_add( MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_MATCH_FIELDS, - spec->efs_match_flags); + match_flags); MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_DEST, MC_CMD_FILTER_OP_EXT_IN_RX_DEST_HOST); MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_QUEUE, @@ -1008,13 +1015,17 @@ ef10_filter_supported_filters( EFX_FILTER_MATCH_IFRM_LOC_MAC | EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST | EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST | + EFX_FILTER_MATCH_ENCAP_TYPE | EFX_FILTER_MATCH_UNKNOWN_MCAST_DST | EFX_FILTER_MATCH_UNKNOWN_UCAST_DST); /* * Two calls to MC_CMD_GET_PARSER_DISP_INFO are needed: one to get the * list of supported filters for ordinary packets, and then another to - * get the list of supported filters for encapsulated packets. + * get the list of supported filters for encapsulated packets. To + * distinguish the second list from the first, the + * EFX_FILTER_MATCH_ENCAP_TYPE flag is added to each filter for + * encapsulated packets. */ rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, B_FALSE, &mcdi_list_length); @@ -1042,6 +1053,10 @@ ef10_filter_supported_filters( no_space = B_TRUE; else goto fail2; + } else { + for (i = next_buf_idx; + i < next_buf_idx + mcdi_encap_list_length; i++) + buffer[i] |= EFX_FILTER_MATCH_ENCAP_TYPE; } } else { mcdi_encap_list_length = 0; diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h index e2f49ec..bb903e5 100644 --- a/drivers/net/sfc/base/efx.h +++ b/drivers/net/sfc/base/efx.h @@ -2485,6 +2485,11 @@ typedef uint8_t efx_filter_flags_t; #define EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST 0x01000000 /* For encapsulated packets, match all unicast inner frames */ #define EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST 0x02000000 +/* + * Match by encap type, this flag does not correspond to + * the MCDI match flags and any unoccupied value may be used + */ +#define EFX_FILTER_MATCH_ENCAP_TYPE 0x20000000 /* Match otherwise-unmatched multicast and broadcast packets */ #define EFX_FILTER_MATCH_UNKNOWN_MCAST_DST 0x40000000 /* Match otherwise-unmatched unicast packets */ diff --git a/drivers/net/sfc/base/efx_filter.c b/drivers/net/sfc/base/efx_filter.c index 2e6628b..97c972c 100644 --- a/drivers/net/sfc/base/efx_filter.c +++ b/drivers/net/sfc/base/efx_filter.c @@ -418,7 +418,7 @@ efx_filter_spec_set_encap_type( __in efx_tunnel_protocol_t encap_type, __in efx_filter_inner_frame_match_t inner_frame_match) { - uint32_t match_flags = 0; + uint32_t match_flags = EFX_FILTER_MATCH_ENCAP_TYPE; uint8_t ip_proto; efx_rc_t rc; @@ -499,6 +499,7 @@ efx_filter_spec_set_vxlan_full( spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC; memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN); } + spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN; return (0); -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 05/14] net/sfc: add VXLAN in flow API filters support 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (3 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 04/14] net/sfc/base: distinguish filters for encapsulated packets Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 06/14] net/sfc: add NVGRE " Andrew Rybchenko ` (9 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Exact match of VXLAN network identifier is supported by parser. IP protocol match are enforced to UDP. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- doc/guides/nics/sfc_efx.rst | 2 + drivers/net/sfc/sfc_flow.c | 165 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index ccdf5ff..5a4b2a6 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -166,6 +166,8 @@ Supported pattern items: - UDP (exact match of source/destination ports) +- VXLAN (exact match of VXLAN network identifier) + Supported actions: - VOID diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 93cdf8f..20ba69d 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -57,6 +57,7 @@ static sfc_flow_item_parse sfc_flow_parse_ipv4; static sfc_flow_item_parse sfc_flow_parse_ipv6; static sfc_flow_item_parse sfc_flow_parse_tcp; static sfc_flow_item_parse sfc_flow_parse_udp; +static sfc_flow_item_parse sfc_flow_parse_vxlan; static boolean_t sfc_flow_is_zero(const uint8_t *buf, unsigned int size) @@ -696,6 +697,132 @@ sfc_flow_parse_udp(const struct rte_flow_item *item, return -rte_errno; } +/* + * Filters for encapsulated packets match based on the EtherType and IP + * protocol in the outer frame. + */ +static int +sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, + efx_filter_spec_t *efx_spec, + uint8_t ip_proto, + struct rte_flow_error *error) +{ + if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) { + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO; + efx_spec->efs_ip_proto = ip_proto; + } else if (efx_spec->efs_ip_proto != ip_proto) { + switch (ip_proto) { + case EFX_IPPROTO_UDP: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Outer IP header protocol must be UDP " + "in VxLAN pattern"); + return -rte_errno; + + default: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Only VxLAN tunneling patterns " + "are supported"); + return -rte_errno; + } + } + + if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Outer frame EtherType in pattern with tunneling " + "must be set"); + return -rte_errno; + } else if (efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 && + efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Outer frame EtherType in pattern with tunneling " + "must be IPv4 or IPv6"); + return -rte_errno; + } + + return 0; +} + +static int +sfc_flow_set_efx_spec_vni_or_vsid(efx_filter_spec_t *efx_spec, + const uint8_t *vni_or_vsid_val, + const uint8_t *vni_or_vsid_mask, + const struct rte_flow_item *item, + struct rte_flow_error *error) +{ + const uint8_t vni_or_vsid_full_mask[EFX_VNI_OR_VSID_LEN] = { + 0xff, 0xff, 0xff + }; + + if (memcmp(vni_or_vsid_mask, vni_or_vsid_full_mask, + EFX_VNI_OR_VSID_LEN) == 0) { + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID; + rte_memcpy(efx_spec->efs_vni_or_vsid, vni_or_vsid_val, + EFX_VNI_OR_VSID_LEN); + } else if (!sfc_flow_is_zero(vni_or_vsid_mask, EFX_VNI_OR_VSID_LEN)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Unsupported VNI/VSID mask"); + return -rte_errno; + } + + return 0; +} + +/** + * Convert VXLAN item to EFX filter specification. + * + * @param item[in] + * Item specification. Only VXLAN network identifier field is supported. + * If the mask is NULL, default mask will be used. + * Ranging is not supported. + * @param efx_spec[in, out] + * EFX filter specification to update. + * @param[out] error + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_parse_vxlan(const struct rte_flow_item *item, + efx_filter_spec_t *efx_spec, + struct rte_flow_error *error) +{ + int rc; + const struct rte_flow_item_vxlan *spec = NULL; + const struct rte_flow_item_vxlan *mask = NULL; + const struct rte_flow_item_vxlan supp_mask = { + .vni = { 0xff, 0xff, 0xff } + }; + + rc = sfc_flow_parse_init(item, + (const void **)&spec, + (const void **)&mask, + &supp_mask, + &rte_flow_item_vxlan_mask, + sizeof(struct rte_flow_item_vxlan), + error); + if (rc != 0) + return rc; + + rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec, + EFX_IPPROTO_UDP, error); + if (rc != 0) + return rc; + + efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN; + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; + + if (spec == NULL) + return 0; + + rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni, + mask->vni, item, error); + + return rc; +} + static const struct sfc_flow_item sfc_flow_items[] = { { .type = RTE_FLOW_ITEM_TYPE_VOID, @@ -739,6 +866,12 @@ static const struct sfc_flow_item sfc_flow_items[] = { .layer = SFC_FLOW_ITEM_L4, .parse = sfc_flow_parse_udp, }, + { + .type = RTE_FLOW_ITEM_TYPE_VXLAN, + .prev_layer = SFC_FLOW_ITEM_L4, + .layer = SFC_FLOW_ITEM_START_LAYER, + .parse = sfc_flow_parse_vxlan, + }, }; /* @@ -806,6 +939,7 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], { int rc; unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER; + boolean_t is_ifrm = B_FALSE; const struct sfc_flow_item *item; if (pattern == NULL) { @@ -837,6 +971,37 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], return -rte_errno; } + /* + * Allow only VOID pattern item in the inner frame. + * Also check that there is only one tunneling protocol. + */ + switch (item->type) { + case RTE_FLOW_ITEM_TYPE_VOID: + break; + + case RTE_FLOW_ITEM_TYPE_VXLAN: + if (is_ifrm) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + pattern, + "More than one tunneling protocol"); + return -rte_errno; + } + is_ifrm = B_TRUE; + break; + + default: + if (is_ifrm) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + pattern, + "There is an unsupported pattern item " + "in the inner frame"); + return -rte_errno; + } + break; + } + rc = item->parse(pattern, &flow->spec, error); if (rc != 0) return rc; -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 06/14] net/sfc: add NVGRE in flow API filters support 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (4 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 05/14] net/sfc: add VXLAN in flow API filters support Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 07/14] net/sfc: add GENEVE " Andrew Rybchenko ` (8 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Exact match of virtual subnet ID is supported by parser. IP protocol match are enforced to GRE. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- doc/guides/nics/sfc_efx.rst | 2 ++ drivers/net/sfc/sfc_flow.c | 68 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 5a4b2a6..05dacb3 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -168,6 +168,8 @@ Supported pattern items: - VXLAN (exact match of VXLAN network identifier) +- NVGRE (exact match of virtual subnet ID) + Supported actions: - VOID diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 20ba69d..126ec9b 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -58,6 +58,7 @@ static sfc_flow_item_parse sfc_flow_parse_ipv6; static sfc_flow_item_parse sfc_flow_parse_tcp; static sfc_flow_item_parse sfc_flow_parse_udp; static sfc_flow_item_parse sfc_flow_parse_vxlan; +static sfc_flow_item_parse sfc_flow_parse_nvgre; static boolean_t sfc_flow_is_zero(const uint8_t *buf, unsigned int size) @@ -719,10 +720,17 @@ sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, "in VxLAN pattern"); return -rte_errno; + case EFX_IPPROTO_GRE: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Outer IP header protocol must be GRE " + "in NVGRE pattern"); + return -rte_errno; + default: rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, - "Only VxLAN tunneling patterns " + "Only VxLAN/NVGRE tunneling patterns " "are supported"); return -rte_errno; } @@ -823,6 +831,57 @@ sfc_flow_parse_vxlan(const struct rte_flow_item *item, return rc; } +/** + * Convert NVGRE item to EFX filter specification. + * + * @param item[in] + * Item specification. Only virtual subnet ID field is supported. + * If the mask is NULL, default mask will be used. + * Ranging is not supported. + * @param efx_spec[in, out] + * EFX filter specification to update. + * @param[out] error + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_parse_nvgre(const struct rte_flow_item *item, + efx_filter_spec_t *efx_spec, + struct rte_flow_error *error) +{ + int rc; + const struct rte_flow_item_nvgre *spec = NULL; + const struct rte_flow_item_nvgre *mask = NULL; + const struct rte_flow_item_nvgre supp_mask = { + .tni = { 0xff, 0xff, 0xff } + }; + + rc = sfc_flow_parse_init(item, + (const void **)&spec, + (const void **)&mask, + &supp_mask, + &rte_flow_item_nvgre_mask, + sizeof(struct rte_flow_item_nvgre), + error); + if (rc != 0) + return rc; + + rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec, + EFX_IPPROTO_GRE, error); + if (rc != 0) + return rc; + + efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_NVGRE; + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; + + if (spec == NULL) + return 0; + + rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->tni, + mask->tni, item, error); + + return rc; +} + static const struct sfc_flow_item sfc_flow_items[] = { { .type = RTE_FLOW_ITEM_TYPE_VOID, @@ -872,6 +931,12 @@ static const struct sfc_flow_item sfc_flow_items[] = { .layer = SFC_FLOW_ITEM_START_LAYER, .parse = sfc_flow_parse_vxlan, }, + { + .type = RTE_FLOW_ITEM_TYPE_NVGRE, + .prev_layer = SFC_FLOW_ITEM_L3, + .layer = SFC_FLOW_ITEM_START_LAYER, + .parse = sfc_flow_parse_nvgre, + }, }; /* @@ -980,6 +1045,7 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], break; case RTE_FLOW_ITEM_TYPE_VXLAN: + case RTE_FLOW_ITEM_TYPE_NVGRE: if (is_ifrm) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 07/14] net/sfc: add GENEVE in flow API filters support 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (5 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 06/14] net/sfc: add NVGRE " Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 08/14] net/sfc: add inner frame ETH " Andrew Rybchenko ` (7 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Exact match of virtual network identifier is supported by parser. IP protocol match are enforced to UDP. Only Ethernet protocol type is supported. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- doc/guides/nics/sfc_efx.rst | 3 ++ drivers/net/sfc/sfc_flow.c | 80 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 05dacb3..943fe55 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -168,6 +168,9 @@ Supported pattern items: - VXLAN (exact match of VXLAN network identifier) +- GENEVE (exact match of virtual network identifier, only Ethernet (0x6558) + protocol type is supported) + - NVGRE (exact match of virtual subnet ID) Supported actions: diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 126ec9b..efdc664 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -58,6 +58,7 @@ static sfc_flow_item_parse sfc_flow_parse_ipv6; static sfc_flow_item_parse sfc_flow_parse_tcp; static sfc_flow_item_parse sfc_flow_parse_udp; static sfc_flow_item_parse sfc_flow_parse_vxlan; +static sfc_flow_item_parse sfc_flow_parse_geneve; static sfc_flow_item_parse sfc_flow_parse_nvgre; static boolean_t @@ -717,7 +718,7 @@ sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "Outer IP header protocol must be UDP " - "in VxLAN pattern"); + "in VxLAN/GENEVE pattern"); return -rte_errno; case EFX_IPPROTO_GRE: @@ -730,7 +731,7 @@ sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, default: rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, - "Only VxLAN/NVGRE tunneling patterns " + "Only VxLAN/GENEVE/NVGRE tunneling patterns " "are supported"); return -rte_errno; } @@ -832,6 +833,74 @@ sfc_flow_parse_vxlan(const struct rte_flow_item *item, } /** + * Convert GENEVE item to EFX filter specification. + * + * @param item[in] + * Item specification. Only Virtual Network Identifier and protocol type + * fields are supported. But protocol type can be only Ethernet (0x6558). + * If the mask is NULL, default mask will be used. + * Ranging is not supported. + * @param efx_spec[in, out] + * EFX filter specification to update. + * @param[out] error + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_parse_geneve(const struct rte_flow_item *item, + efx_filter_spec_t *efx_spec, + struct rte_flow_error *error) +{ + int rc; + const struct rte_flow_item_geneve *spec = NULL; + const struct rte_flow_item_geneve *mask = NULL; + const struct rte_flow_item_geneve supp_mask = { + .protocol = RTE_BE16(0xffff), + .vni = { 0xff, 0xff, 0xff } + }; + + rc = sfc_flow_parse_init(item, + (const void **)&spec, + (const void **)&mask, + &supp_mask, + &rte_flow_item_geneve_mask, + sizeof(struct rte_flow_item_geneve), + error); + if (rc != 0) + return rc; + + rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec, + EFX_IPPROTO_UDP, error); + if (rc != 0) + return rc; + + efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_GENEVE; + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE; + + if (spec == NULL) + return 0; + + if (mask->protocol == supp_mask.protocol) { + if (spec->protocol != rte_cpu_to_be_16(ETHER_TYPE_TEB)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "GENEVE encap. protocol must be Ethernet " + "(0x6558) in the GENEVE pattern item"); + return -rte_errno; + } + } else if (mask->protocol != 0) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Unsupported mask for GENEVE encap. protocol"); + return -rte_errno; + } + + rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni, + mask->vni, item, error); + + return rc; +} + +/** * Convert NVGRE item to EFX filter specification. * * @param item[in] @@ -932,6 +1001,12 @@ static const struct sfc_flow_item sfc_flow_items[] = { .parse = sfc_flow_parse_vxlan, }, { + .type = RTE_FLOW_ITEM_TYPE_GENEVE, + .prev_layer = SFC_FLOW_ITEM_L4, + .layer = SFC_FLOW_ITEM_START_LAYER, + .parse = sfc_flow_parse_geneve, + }, + { .type = RTE_FLOW_ITEM_TYPE_NVGRE, .prev_layer = SFC_FLOW_ITEM_L3, .layer = SFC_FLOW_ITEM_START_LAYER, @@ -1045,6 +1120,7 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], break; case RTE_FLOW_ITEM_TYPE_VXLAN: + case RTE_FLOW_ITEM_TYPE_GENEVE: case RTE_FLOW_ITEM_TYPE_NVGRE: if (is_ifrm) { rte_flow_error_set(error, EINVAL, -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 08/14] net/sfc: add inner frame ETH in flow API filters support 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (6 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 07/14] net/sfc: add GENEVE " Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 09/14] net/sfc: add infrastructure to make many filters from flow Andrew Rybchenko ` (6 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Support destination MAC address match in inner frames. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> Reviewed-by: Andy Moreton <amoreton@solarflare.com> --- doc/guides/nics/sfc_efx.rst | 4 ++- drivers/net/sfc/sfc_flow.c | 73 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 943fe55..539ce90 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -152,7 +152,9 @@ Supported pattern items: - VOID - ETH (exact match of source/destination addresses, individual/group match - of destination address, EtherType) + of destination address, EtherType in the outer frame and exact match of + destination addresses, individual/group match of destination address in + the inner frame) - VLAN (exact match of VID, double-tagging is supported) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index efdc664..c942a36 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -187,11 +187,11 @@ sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item, * Convert Ethernet item to EFX filter specification. * * @param item[in] - * Item specification. Only source and destination addresses and - * Ethernet type fields are supported. In addition to full and - * empty masks of destination address, individual/group mask is - * also supported. If the mask is NULL, default mask will be used. - * Ranging is not supported. + * Item specification. Outer frame specification may only comprise + * source/destination addresses and Ethertype field. + * Inner frame specification may contain destination address only. + * There is support for individual/group mask as well as for empty and full. + * If the mask is NULL, default mask will be used. Ranging is not supported. * @param efx_spec[in, out] * EFX filter specification to update. * @param[out] error @@ -210,40 +210,75 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, .type = 0xffff, }; + const struct rte_flow_item_eth ifrm_supp_mask = { + .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + }; const uint8_t ig_mask[EFX_MAC_ADDR_LEN] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const struct rte_flow_item_eth *supp_mask_p; + const struct rte_flow_item_eth *def_mask_p; + uint8_t *loc_mac = NULL; + boolean_t is_ifrm = (efx_spec->efs_encap_type != + EFX_TUNNEL_PROTOCOL_NONE); + + if (is_ifrm) { + supp_mask_p = &ifrm_supp_mask; + def_mask_p = &ifrm_supp_mask; + loc_mac = efx_spec->efs_ifrm_loc_mac; + } else { + supp_mask_p = &supp_mask; + def_mask_p = &rte_flow_item_eth_mask; + loc_mac = efx_spec->efs_loc_mac; + } rc = sfc_flow_parse_init(item, (const void **)&spec, (const void **)&mask, - &supp_mask, - &rte_flow_item_eth_mask, + supp_mask_p, def_mask_p, sizeof(struct rte_flow_item_eth), error); if (rc != 0) return rc; - /* If "spec" is not set, could be any Ethernet */ - if (spec == NULL) - return 0; + /* + * If "spec" is not set, could be any Ethernet, but for the inner frame + * type of destination MAC must be set + */ + if (spec == NULL) { + if (is_ifrm) + goto fail_bad_ifrm_dst_mac; + else + return 0; + } if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) { - efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC; - rte_memcpy(efx_spec->efs_loc_mac, spec->dst.addr_bytes, + efx_spec->efs_match_flags |= is_ifrm ? + EFX_FILTER_MATCH_IFRM_LOC_MAC : + EFX_FILTER_MATCH_LOC_MAC; + rte_memcpy(loc_mac, spec->dst.addr_bytes, EFX_MAC_ADDR_LEN); } else if (memcmp(mask->dst.addr_bytes, ig_mask, EFX_MAC_ADDR_LEN) == 0) { if (is_unicast_ether_addr(&spec->dst)) - efx_spec->efs_match_flags |= + efx_spec->efs_match_flags |= is_ifrm ? + EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST : EFX_FILTER_MATCH_UNKNOWN_UCAST_DST; else - efx_spec->efs_match_flags |= + efx_spec->efs_match_flags |= is_ifrm ? + EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST : EFX_FILTER_MATCH_UNKNOWN_MCAST_DST; } else if (!is_zero_ether_addr(&mask->dst)) { goto fail_bad_mask; + } else if (is_ifrm) { + goto fail_bad_ifrm_dst_mac; } + /* + * ifrm_supp_mask ensures that the source address and + * ethertype masks are equal to zero in inner frame, + * so these fields are filled in only for the outer frame + */ if (is_same_ether_addr(&mask->src, &supp_mask.src)) { efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC; rte_memcpy(efx_spec->efs_rem_mac, spec->src.addr_bytes, @@ -270,6 +305,13 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, RTE_FLOW_ERROR_TYPE_ITEM, item, "Bad mask in the ETH pattern item"); return -rte_errno; + +fail_bad_ifrm_dst_mac: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Type of destination MAC address in inner frame " + "must be set"); + return -rte_errno; } /** @@ -1112,11 +1154,12 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], } /* - * Allow only VOID pattern item in the inner frame. + * Allow only VOID and ETH pattern items in the inner frame. * Also check that there is only one tunneling protocol. */ switch (item->type) { case RTE_FLOW_ITEM_TYPE_VOID: + case RTE_FLOW_ITEM_TYPE_ETH: break; case RTE_FLOW_ITEM_TYPE_VXLAN: -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 09/14] net/sfc: add infrastructure to make many filters from flow 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (7 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 08/14] net/sfc: add inner frame ETH " Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 10/14] net/sfc: multiply of specs with an unknown EtherType Andrew Rybchenko ` (5 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Not all flow rules can be expressed in one hardware filter, so some flow rules have to be expressed in terms of multiple hardware filters. This patch provides a means to produce a filter spec template from the flow rule which then can be used to produce a set of fully elaborated specs to be inserted. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- drivers/net/sfc/sfc_flow.c | 118 ++++++++++++++++++++++++++++++++++++--------- drivers/net/sfc/sfc_flow.h | 19 +++++++- 2 files changed, 114 insertions(+), 23 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index c942a36..a432936 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -25,10 +25,13 @@ /* * At now flow API is implemented in such a manner that each - * flow rule is converted to a hardware filter. + * flow rule is converted to one or more hardware filters. * All elements of flow rule (attributes, pattern items, actions) * correspond to one or more fields in the efx_filter_spec_s structure * that is responsible for the hardware filter. + * If some required field is unset in the flow rule, then a handful + * of filter copies will be created to cover all possible values + * of such a field. */ enum sfc_flow_item_layers { @@ -1095,8 +1098,8 @@ sfc_flow_parse_attr(const struct rte_flow_attr *attr, return -rte_errno; } - flow->spec.efs_flags |= EFX_FILTER_FLAG_RX; - flow->spec.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; + flow->spec.template.efs_flags |= EFX_FILTER_FLAG_RX; + flow->spec.template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; return 0; } @@ -1187,7 +1190,7 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], break; } - rc = item->parse(pattern, &flow->spec, error); + rc = item->parse(pattern, &flow->spec.template, error); if (rc != 0) return rc; @@ -1209,7 +1212,7 @@ sfc_flow_parse_queue(struct sfc_adapter *sa, return -EINVAL; rxq = sa->rxq_info[queue->index].rxq; - flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index; + flow->spec.template.efs_dmaq_id = (uint16_t)rxq->hw_index; return 0; } @@ -1285,13 +1288,57 @@ sfc_flow_parse_rss(struct sfc_adapter *sa, #endif /* EFSYS_OPT_RX_SCALE */ static int +sfc_flow_spec_flush(struct sfc_adapter *sa, struct sfc_flow_spec *spec, + unsigned int filters_count) +{ + unsigned int i; + int ret = 0; + + for (i = 0; i < filters_count; i++) { + int rc; + + rc = efx_filter_remove(sa->nic, &spec->filters[i]); + if (ret == 0 && rc != 0) { + sfc_err(sa, "failed to remove filter specification " + "(rc = %d)", rc); + ret = rc; + } + } + + return ret; +} + +static int +sfc_flow_spec_insert(struct sfc_adapter *sa, struct sfc_flow_spec *spec) +{ + unsigned int i; + int rc = 0; + + for (i = 0; i < spec->count; i++) { + rc = efx_filter_insert(sa->nic, &spec->filters[i]); + if (rc != 0) { + sfc_flow_spec_flush(sa, spec, i); + break; + } + } + + return rc; +} + +static int +sfc_flow_spec_remove(struct sfc_adapter *sa, struct sfc_flow_spec *spec) +{ + return sfc_flow_spec_flush(sa, spec, spec->count); +} + +static int sfc_flow_filter_insert(struct sfc_adapter *sa, struct rte_flow *flow) { - efx_filter_spec_t *spec = &flow->spec; - #if EFSYS_OPT_RX_SCALE struct sfc_flow_rss *rss = &flow->rss_conf; + uint32_t efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; + unsigned int i; int rc = 0; if (flow->rss) { @@ -1302,27 +1349,38 @@ sfc_flow_filter_insert(struct sfc_adapter *sa, rc = efx_rx_scale_context_alloc(sa->nic, EFX_RX_SCALE_EXCLUSIVE, rss_spread, - &spec->efs_rss_context); + &efs_rss_context); if (rc != 0) goto fail_scale_context_alloc; - rc = efx_rx_scale_mode_set(sa->nic, spec->efs_rss_context, + rc = efx_rx_scale_mode_set(sa->nic, efs_rss_context, EFX_RX_HASHALG_TOEPLITZ, rss->rss_hash_types, B_TRUE); if (rc != 0) goto fail_scale_mode_set; - rc = efx_rx_scale_key_set(sa->nic, spec->efs_rss_context, + rc = efx_rx_scale_key_set(sa->nic, efs_rss_context, rss->rss_key, sizeof(sa->rss_key)); if (rc != 0) goto fail_scale_key_set; - spec->efs_dmaq_id = rss->rxq_hw_index_min; - spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS; + /* + * At this point, fully elaborated filter specifications + * have been produced from the template. To make sure that + * RSS behaviour is consistent between them, set the same + * RSS context value everywhere. + */ + for (i = 0; i < flow->spec.count; i++) { + efx_filter_spec_t *spec = &flow->spec.filters[i]; + + spec->efs_rss_context = efs_rss_context; + spec->efs_dmaq_id = rss->rxq_hw_index_min; + spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS; + } } - rc = efx_filter_insert(sa->nic, spec); + rc = sfc_flow_spec_insert(sa, &flow->spec); if (rc != 0) goto fail_filter_insert; @@ -1335,7 +1393,7 @@ sfc_flow_filter_insert(struct sfc_adapter *sa, * the HW knows all the information needed to verify * the table entries, and the operation will succeed */ - rc = efx_rx_scale_tbl_set(sa->nic, spec->efs_rss_context, + rc = efx_rx_scale_tbl_set(sa->nic, efs_rss_context, rss->rss_tbl, RTE_DIM(rss->rss_tbl)); if (rc != 0) goto fail_scale_tbl_set; @@ -1344,18 +1402,18 @@ sfc_flow_filter_insert(struct sfc_adapter *sa, return 0; fail_scale_tbl_set: - efx_filter_remove(sa->nic, spec); + sfc_flow_spec_remove(sa, &flow->spec); fail_filter_insert: fail_scale_key_set: fail_scale_mode_set: - if (flow->rss) - efx_rx_scale_context_free(sa->nic, spec->efs_rss_context); + if (efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) + efx_rx_scale_context_free(sa->nic, efs_rss_context); fail_scale_context_alloc: return rc; #else /* !EFSYS_OPT_RX_SCALE */ - return efx_filter_insert(sa->nic, spec); + return sfc_flow_spec_insert(sa, &flow->spec); #endif /* EFSYS_OPT_RX_SCALE */ } @@ -1363,16 +1421,23 @@ static int sfc_flow_filter_remove(struct sfc_adapter *sa, struct rte_flow *flow) { - efx_filter_spec_t *spec = &flow->spec; int rc = 0; - rc = efx_filter_remove(sa->nic, spec); + rc = sfc_flow_spec_remove(sa, &flow->spec); if (rc != 0) return rc; #if EFSYS_OPT_RX_SCALE - if (flow->rss) + if (flow->rss) { + /* + * All specifications for a given flow rule have the same RSS + * context, so that RSS context value is taken from the first + * filter specification + */ + efx_filter_spec_t *spec = &flow->spec.filters[0]; + rc = efx_rx_scale_context_free(sa->nic, spec->efs_rss_context); + } #endif /* EFSYS_OPT_RX_SCALE */ return rc; @@ -1452,6 +1517,8 @@ sfc_flow_parse(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct sfc_adapter *sa = dev->data->dev_private; + efx_filter_match_flags_t match_flags = + flow->spec.template.efs_match_flags; int rc; rc = sfc_flow_parse_attr(attr, flow, error); @@ -1466,13 +1533,20 @@ sfc_flow_parse(struct rte_eth_dev *dev, if (rc != 0) goto fail_bad_value; - if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) { + if (!sfc_filter_is_match_supported(sa, match_flags)) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Flow rule pattern is not supported"); return -rte_errno; } + /* + * At this point, template specification simply becomes the first + * fully elaborated spec + */ + flow->spec.filters[0] = flow->spec.template; + flow->spec.count = 1; + fail_bad_value: return rc; } diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 35472ad..634c310 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -19,6 +19,13 @@ extern "C" { #endif +/* + * The maximum number of fully elaborated hardware filter specifications + * which can be produced from a template by means of multiplication, if + * missing match flags are needed to be taken into account + */ +#define SF_FLOW_SPEC_NB_FILTERS_MAX 1 + #if EFSYS_OPT_RX_SCALE /* RSS configuration storage */ struct sfc_flow_rss { @@ -30,9 +37,19 @@ struct sfc_flow_rss { }; #endif /* EFSYS_OPT_RX_SCALE */ +/* Filter specification storage */ +struct sfc_flow_spec { + /* partial specification from flow rule */ + efx_filter_spec_t template; + /* fully elaborated hardware filters specifications */ + efx_filter_spec_t filters[SF_FLOW_SPEC_NB_FILTERS_MAX]; + /* number of complete specifications */ + unsigned int count; +}; + /* PMD-specific definition of the opaque type from rte_flow.h */ struct rte_flow { - efx_filter_spec_t spec; /* filter specification */ + struct sfc_flow_spec spec; /* flow spec for hardware filter(s) */ #if EFSYS_OPT_RX_SCALE boolean_t rss; /* RSS toggle */ struct sfc_flow_rss rss_conf; /* RSS configuration */ -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 10/14] net/sfc: multiply of specs with an unknown EtherType 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (8 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 09/14] net/sfc: add infrastructure to make many filters from flow Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 11/14] net/sfc: multiply of specs w/o inner frame destination MAC Andrew Rybchenko ` (4 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Hardware filter specification for encapsulated traffic must contain EtherType. In terms of RTE flow API, this would require L3 item to be used in the flow rule. In the simplest case, if the user needs to filter encapsulated traffic without knowledge of exact EtherType, they will have to create multiple variants of the flow rule featuring all possible L3 items (IPv4, IPv6), respectively. In order to hide the gory details and avoid such a complication, this patch implements a mechanism to auto-complete the filter specifications if need be. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- drivers/net/sfc/sfc_flow.c | 306 +++++++++++++++++++++++++++++++++++++++------ drivers/net/sfc/sfc_flow.h | 2 +- 2 files changed, 266 insertions(+), 42 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index a432936..244fcdb 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -64,6 +64,21 @@ static sfc_flow_item_parse sfc_flow_parse_vxlan; static sfc_flow_item_parse sfc_flow_parse_geneve; static sfc_flow_item_parse sfc_flow_parse_nvgre; +typedef int (sfc_flow_spec_set_vals)(struct sfc_flow_spec *spec, + unsigned int filters_count_for_one_val, + struct rte_flow_error *error); + +struct sfc_flow_copy_flag { + /* EFX filter specification match flag */ + efx_filter_match_flags_t flag; + /* Number of values of corresponding field */ + unsigned int vals_count; + /* Function to set values in specifications */ + sfc_flow_spec_set_vals *set_vals; +}; + +static sfc_flow_spec_set_vals sfc_flow_set_ethertypes; + static boolean_t sfc_flow_is_zero(const uint8_t *buf, unsigned int size) { @@ -244,16 +259,9 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, if (rc != 0) return rc; - /* - * If "spec" is not set, could be any Ethernet, but for the inner frame - * type of destination MAC must be set - */ - if (spec == NULL) { - if (is_ifrm) - goto fail_bad_ifrm_dst_mac; - else - return 0; - } + /* If "spec" is not set, could be any Ethernet */ + if (spec == NULL) + return 0; if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) { efx_spec->efs_match_flags |= is_ifrm ? @@ -273,8 +281,6 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, EFX_FILTER_MATCH_UNKNOWN_MCAST_DST; } else if (!is_zero_ether_addr(&mask->dst)) { goto fail_bad_mask; - } else if (is_ifrm) { - goto fail_bad_ifrm_dst_mac; } /* @@ -308,13 +314,6 @@ sfc_flow_parse_eth(const struct rte_flow_item *item, RTE_FLOW_ERROR_TYPE_ITEM, item, "Bad mask in the ETH pattern item"); return -rte_errno; - -fail_bad_ifrm_dst_mac: - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, item, - "Type of destination MAC address in inner frame " - "must be set"); - return -rte_errno; } /** @@ -782,14 +781,9 @@ sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item, } } - if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, item, - "Outer frame EtherType in pattern with tunneling " - "must be set"); - return -rte_errno; - } else if (efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 && - efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) { + if (efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE && + efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 && + efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "Outer frame EtherType in pattern with tunneling " @@ -1508,6 +1502,246 @@ sfc_flow_parse_actions(struct sfc_adapter *sa, return 0; } +/** + * Set the EFX_FILTER_MATCH_ETHER_TYPE match flag and EFX_ETHER_TYPE_IPV4 and + * EFX_ETHER_TYPE_IPV6 values of the corresponding field in the same + * specifications after copying. + * + * @param spec[in, out] + * SFC flow specification to update. + * @param filters_count_for_one_val[in] + * How many specifications should have the same EtherType value, what is the + * number of specifications before copying. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_set_ethertypes(struct sfc_flow_spec *spec, + unsigned int filters_count_for_one_val, + struct rte_flow_error *error) +{ + unsigned int i; + static const uint16_t vals[] = { + EFX_ETHER_TYPE_IPV4, EFX_ETHER_TYPE_IPV6 + }; + + if (filters_count_for_one_val * RTE_DIM(vals) != spec->count) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Number of specifications is incorrect " + "while copying by Ethertype"); + return -rte_errno; + } + + for (i = 0; i < spec->count; i++) { + spec->filters[i].efs_match_flags |= + EFX_FILTER_MATCH_ETHER_TYPE; + + /* + * The check above ensures that + * filters_count_for_one_val is not 0 + */ + spec->filters[i].efs_ether_type = + vals[i / filters_count_for_one_val]; + } + + return 0; +} + +/* Match flags that can be automatically added to filters */ +static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = { + { + .flag = EFX_FILTER_MATCH_ETHER_TYPE, + .vals_count = 2, + .set_vals = sfc_flow_set_ethertypes, + }, +}; + +/* Get item from array sfc_flow_copy_flags */ +static const struct sfc_flow_copy_flag * +sfc_flow_get_copy_flag(efx_filter_match_flags_t flag) +{ + unsigned int i; + + for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) { + if (sfc_flow_copy_flags[i].flag == flag) + return &sfc_flow_copy_flags[i]; + } + + return NULL; +} + +/** + * Make copies of the specifications, set match flag and values + * of the field that corresponds to it. + * + * @param spec[in, out] + * SFC flow specification to update. + * @param flag[in] + * The match flag to add. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_spec_add_match_flag(struct sfc_flow_spec *spec, + efx_filter_match_flags_t flag, + struct rte_flow_error *error) +{ + unsigned int i; + unsigned int new_filters_count; + unsigned int filters_count_for_one_val; + const struct sfc_flow_copy_flag *copy_flag; + int rc; + + copy_flag = sfc_flow_get_copy_flag(flag); + if (copy_flag == NULL) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Unsupported spec field for copying"); + return -rte_errno; + } + + new_filters_count = spec->count * copy_flag->vals_count; + if (new_filters_count > SF_FLOW_SPEC_NB_FILTERS_MAX) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Too much EFX specifications in the flow rule"); + return -rte_errno; + } + + /* Copy filters specifications */ + for (i = spec->count; i < new_filters_count; i++) + spec->filters[i] = spec->filters[i - spec->count]; + + filters_count_for_one_val = spec->count; + spec->count = new_filters_count; + + rc = copy_flag->set_vals(spec, filters_count_for_one_val, error); + if (rc != 0) + return rc; + + return 0; +} + +/** + * Check that the given set of match flags missing in the original filter spec + * could be covered by adding spec copies which specify the corresponding + * flags and packet field values to match. + * + * @param miss_flags[in] + * Flags that are missing until the supported filter. + * + * @return + * Number of specifications after copy or 0, if the flags can not be added. + */ +static unsigned int +sfc_flow_check_missing_flags(efx_filter_match_flags_t miss_flags) +{ + unsigned int i; + efx_filter_match_flags_t copy_flags = 0; + efx_filter_match_flags_t flag; + unsigned int multiplier = 1; + + for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) { + flag = sfc_flow_copy_flags[i].flag; + if ((flag & miss_flags) == flag) { + copy_flags |= flag; + multiplier *= sfc_flow_copy_flags[i].vals_count; + } + } + + if (copy_flags == miss_flags) + return multiplier; + + return 0; +} + +/** + * Attempt to supplement the specification template to the minimally + * supported set of match flags. To do this, it is necessary to copy + * the specifications, filling them with the values of fields that + * correspond to the missing flags. + * The necessary and sufficient filter is built from the fewest number + * of copies which could be made to cover the minimally required set + * of flags. + * + * @param sa[in] + * SFC adapter. + * @param spec[in, out] + * SFC flow specification to update. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_spec_filters_complete(struct sfc_adapter *sa, + struct sfc_flow_spec *spec, + struct rte_flow_error *error) +{ + struct sfc_filter *filter = &sa->filter; + efx_filter_match_flags_t miss_flags; + efx_filter_match_flags_t min_miss_flags = 0; + efx_filter_match_flags_t match; + unsigned int min_multiplier = UINT_MAX; + unsigned int multiplier; + unsigned int i; + int rc; + + match = spec->template.efs_match_flags; + for (i = 0; i < filter->supported_match_num; i++) { + if ((match & filter->supported_match[i]) == match) { + miss_flags = filter->supported_match[i] & (~match); + multiplier = sfc_flow_check_missing_flags(miss_flags); + if (multiplier > 0) { + if (multiplier <= min_multiplier) { + min_multiplier = multiplier; + min_miss_flags = miss_flags; + } + } + } + } + + if (min_multiplier == UINT_MAX) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Flow rule pattern is not supported"); + return -rte_errno; + } + + for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) { + efx_filter_match_flags_t flag = sfc_flow_copy_flags[i].flag; + + if ((flag & min_miss_flags) == flag) { + rc = sfc_flow_spec_add_match_flag(spec, flag, error); + if (rc != 0) + return rc; + } + } + + return 0; +} + +static int +sfc_flow_validate_match_flags(struct sfc_adapter *sa, + struct rte_flow *flow, + struct rte_flow_error *error) +{ + efx_filter_spec_t *spec_tmpl = &flow->spec.template; + efx_filter_match_flags_t match_flags = spec_tmpl->efs_match_flags; + int rc; + + /* Initialize the first filter spec with template */ + flow->spec.filters[0] = *spec_tmpl; + flow->spec.count = 1; + + if (!sfc_filter_is_match_supported(sa, match_flags)) { + rc = sfc_flow_spec_filters_complete(sa, &flow->spec, error); + if (rc != 0) + return rc; + } + + return 0; +} + static int sfc_flow_parse(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, @@ -1517,8 +1751,6 @@ sfc_flow_parse(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct sfc_adapter *sa = dev->data->dev_private; - efx_filter_match_flags_t match_flags = - flow->spec.template.efs_match_flags; int rc; rc = sfc_flow_parse_attr(attr, flow, error); @@ -1533,19 +1765,11 @@ sfc_flow_parse(struct rte_eth_dev *dev, if (rc != 0) goto fail_bad_value; - if (!sfc_filter_is_match_supported(sa, match_flags)) { - rte_flow_error_set(error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "Flow rule pattern is not supported"); - return -rte_errno; - } + rc = sfc_flow_validate_match_flags(sa, flow, error); + if (rc != 0) + goto fail_bad_value; - /* - * At this point, template specification simply becomes the first - * fully elaborated spec - */ - flow->spec.filters[0] = flow->spec.template; - flow->spec.count = 1; + return 0; fail_bad_value: return rc; diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 634c310..c4302c7 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -24,7 +24,7 @@ extern "C" { * which can be produced from a template by means of multiplication, if * missing match flags are needed to be taken into account */ -#define SF_FLOW_SPEC_NB_FILTERS_MAX 1 +#define SF_FLOW_SPEC_NB_FILTERS_MAX 2 #if EFSYS_OPT_RX_SCALE /* RSS configuration storage */ -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 11/14] net/sfc: multiply of specs w/o inner frame destination MAC 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (9 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 10/14] net/sfc: multiply of specs with an unknown EtherType Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 12/14] net/sfc: multiply of specs with an unknown " Andrew Rybchenko ` (3 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Knowledge of a network identifier is not sufficient to construct a workable hardware filter for encapsulated traffic. It's obligatory to specify one of the match flags associated with inner frame destination MAC. If the address is unknown, then one needs to specify either unknown unicast or unknown multicast destination match flag. In terms of RTE flow API, this would require adding multiple flow rules with corresponding ETH items besides the tunnel item. In order to avoid such a complication, the patch implements a mechanism to auto-complete an underlying filter representation of a flow rule in order to create additional filter specififcations featuring the missing match flags. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- drivers/net/sfc/sfc_flow.c | 114 ++++++++++++++++++++++++++++++++++++++++++++- drivers/net/sfc/sfc_flow.h | 2 +- 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 244fcdb..2d45827 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -68,6 +68,10 @@ typedef int (sfc_flow_spec_set_vals)(struct sfc_flow_spec *spec, unsigned int filters_count_for_one_val, struct rte_flow_error *error); +typedef boolean_t (sfc_flow_spec_check)(efx_filter_match_flags_t match, + efx_filter_spec_t *spec, + struct sfc_filter *filter); + struct sfc_flow_copy_flag { /* EFX filter specification match flag */ efx_filter_match_flags_t flag; @@ -75,9 +79,16 @@ struct sfc_flow_copy_flag { unsigned int vals_count; /* Function to set values in specifications */ sfc_flow_spec_set_vals *set_vals; + /* + * Function to check that the specification is suitable + * for adding this match flag + */ + sfc_flow_spec_check *spec_check; }; static sfc_flow_spec_set_vals sfc_flow_set_ethertypes; +static sfc_flow_spec_set_vals sfc_flow_set_ifrm_unknown_dst_flags; +static sfc_flow_spec_check sfc_flow_check_ifrm_unknown_dst_flags; static boolean_t sfc_flow_is_zero(const uint8_t *buf, unsigned int size) @@ -1548,12 +1559,98 @@ sfc_flow_set_ethertypes(struct sfc_flow_spec *spec, return 0; } +/** + * Set the EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST and + * EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST match flags in the same + * specifications after copying. + * + * @param spec[in, out] + * SFC flow specification to update. + * @param filters_count_for_one_val[in] + * How many specifications should have the same match flag, what is the + * number of specifications before copying. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_set_ifrm_unknown_dst_flags(struct sfc_flow_spec *spec, + unsigned int filters_count_for_one_val, + struct rte_flow_error *error) +{ + unsigned int i; + static const efx_filter_match_flags_t vals[] = { + EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST, + EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST + }; + + if (filters_count_for_one_val * RTE_DIM(vals) != spec->count) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Number of specifications is incorrect while copying " + "by inner frame unknown destination flags"); + return -rte_errno; + } + + for (i = 0; i < spec->count; i++) { + /* The check above ensures that divisor can't be zero here */ + spec->filters[i].efs_match_flags |= + vals[i / filters_count_for_one_val]; + } + + return 0; +} + +/** + * Check that the following conditions are met: + * - the specification corresponds to a filter for encapsulated traffic + * - the list of supported filters has a filter + * with EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST flag instead of + * EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST, since this filter will also + * be inserted. + * + * @param match[in] + * The match flags of filter. + * @param spec[in] + * Specification to be supplemented. + * @param filter[in] + * SFC filter with list of supported filters. + */ +static boolean_t +sfc_flow_check_ifrm_unknown_dst_flags(efx_filter_match_flags_t match, + efx_filter_spec_t *spec, + struct sfc_filter *filter) +{ + unsigned int i; + efx_tunnel_protocol_t encap_type = spec->efs_encap_type; + efx_filter_match_flags_t match_mcast_dst; + + if (encap_type == EFX_TUNNEL_PROTOCOL_NONE) + return B_FALSE; + + match_mcast_dst = + (match & ~EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST) | + EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST; + for (i = 0; i < filter->supported_match_num; i++) { + if (match_mcast_dst == filter->supported_match[i]) + return B_TRUE; + } + + return B_FALSE; +} + /* Match flags that can be automatically added to filters */ static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = { { .flag = EFX_FILTER_MATCH_ETHER_TYPE, .vals_count = 2, .set_vals = sfc_flow_set_ethertypes, + .spec_check = NULL, + }, + { + .flag = EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST, + .vals_count = 2, + .set_vals = sfc_flow_set_ifrm_unknown_dst_flags, + .spec_check = sfc_flow_check_ifrm_unknown_dst_flags, }, }; @@ -1630,21 +1727,33 @@ sfc_flow_spec_add_match_flag(struct sfc_flow_spec *spec, * * @param miss_flags[in] * Flags that are missing until the supported filter. + * @param spec[in] + * Specification to be supplemented. + * @param filter[in] + * SFC filter. * * @return * Number of specifications after copy or 0, if the flags can not be added. */ static unsigned int -sfc_flow_check_missing_flags(efx_filter_match_flags_t miss_flags) +sfc_flow_check_missing_flags(efx_filter_match_flags_t miss_flags, + efx_filter_spec_t *spec, + struct sfc_filter *filter) { unsigned int i; efx_filter_match_flags_t copy_flags = 0; efx_filter_match_flags_t flag; + efx_filter_match_flags_t match = spec->efs_match_flags | miss_flags; + sfc_flow_spec_check *check; unsigned int multiplier = 1; for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) { flag = sfc_flow_copy_flags[i].flag; + check = sfc_flow_copy_flags[i].spec_check; if ((flag & miss_flags) == flag) { + if (check != NULL && (!check(match, spec, filter))) + continue; + copy_flags |= flag; multiplier *= sfc_flow_copy_flags[i].vals_count; } @@ -1690,7 +1799,8 @@ sfc_flow_spec_filters_complete(struct sfc_adapter *sa, for (i = 0; i < filter->supported_match_num; i++) { if ((match & filter->supported_match[i]) == match) { miss_flags = filter->supported_match[i] & (~match); - multiplier = sfc_flow_check_missing_flags(miss_flags); + multiplier = sfc_flow_check_missing_flags(miss_flags, + &spec->template, filter); if (multiplier > 0) { if (multiplier <= min_multiplier) { min_multiplier = multiplier; diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index c4302c7..2b287dd 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -24,7 +24,7 @@ extern "C" { * which can be produced from a template by means of multiplication, if * missing match flags are needed to be taken into account */ -#define SF_FLOW_SPEC_NB_FILTERS_MAX 2 +#define SF_FLOW_SPEC_NB_FILTERS_MAX 4 #if EFSYS_OPT_RX_SCALE /* RSS configuration storage */ -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 12/14] net/sfc: multiply of specs with an unknown destination MAC 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (10 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 11/14] net/sfc: multiply of specs w/o inner frame destination MAC Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 13/14] net/sfc: avoid creation of ineffective flow rules Andrew Rybchenko ` (2 subsequent siblings) 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> To filter all traffic, need to create two hardware filter specifications with both unknown unicast and unknown multicast destination MAC address match flags. In terms of RTE flow API, this would require adding multiple flow rules with corresponding ETH items. In order to avoid such a complication, the patch implements a mechanism to auto-complete an underlying filter representation of a flow rule in order to create additional filter specififcations featuring the missing match flags. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- drivers/net/sfc/sfc_flow.c | 91 +++++++++++++++++++++++++++++++++++++++++++++- drivers/net/sfc/sfc_flow.h | 2 +- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 2d45827..7b26653 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -86,6 +86,8 @@ struct sfc_flow_copy_flag { sfc_flow_spec_check *spec_check; }; +static sfc_flow_spec_set_vals sfc_flow_set_unknown_dst_flags; +static sfc_flow_spec_check sfc_flow_check_unknown_dst_flags; static sfc_flow_spec_set_vals sfc_flow_set_ethertypes; static sfc_flow_spec_set_vals sfc_flow_set_ifrm_unknown_dst_flags; static sfc_flow_spec_check sfc_flow_check_ifrm_unknown_dst_flags; @@ -1514,6 +1516,80 @@ sfc_flow_parse_actions(struct sfc_adapter *sa, } /** + * Set the EFX_FILTER_MATCH_UNKNOWN_UCAST_DST + * and EFX_FILTER_MATCH_UNKNOWN_MCAST_DST match flags in the same + * specifications after copying. + * + * @param spec[in, out] + * SFC flow specification to update. + * @param filters_count_for_one_val[in] + * How many specifications should have the same match flag, what is the + * number of specifications before copying. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_set_unknown_dst_flags(struct sfc_flow_spec *spec, + unsigned int filters_count_for_one_val, + struct rte_flow_error *error) +{ + unsigned int i; + static const efx_filter_match_flags_t vals[] = { + EFX_FILTER_MATCH_UNKNOWN_UCAST_DST, + EFX_FILTER_MATCH_UNKNOWN_MCAST_DST + }; + + if (filters_count_for_one_val * RTE_DIM(vals) != spec->count) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Number of specifications is incorrect while copying " + "by unknown destination flags"); + return -rte_errno; + } + + for (i = 0; i < spec->count; i++) { + /* The check above ensures that divisor can't be zero here */ + spec->filters[i].efs_match_flags |= + vals[i / filters_count_for_one_val]; + } + + return 0; +} + +/** + * Check that the following conditions are met: + * - the list of supported filters has a filter + * with EFX_FILTER_MATCH_UNKNOWN_MCAST_DST flag instead of + * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST, since this filter will also + * be inserted. + * + * @param match[in] + * The match flags of filter. + * @param spec[in] + * Specification to be supplemented. + * @param filter[in] + * SFC filter with list of supported filters. + */ +static boolean_t +sfc_flow_check_unknown_dst_flags(efx_filter_match_flags_t match, + __rte_unused efx_filter_spec_t *spec, + struct sfc_filter *filter) +{ + unsigned int i; + efx_filter_match_flags_t match_mcast_dst; + + match_mcast_dst = + (match & ~EFX_FILTER_MATCH_UNKNOWN_UCAST_DST) | + EFX_FILTER_MATCH_UNKNOWN_MCAST_DST; + for (i = 0; i < filter->supported_match_num; i++) { + if (match_mcast_dst == filter->supported_match[i]) + return B_TRUE; + } + + return B_FALSE; +} + +/** * Set the EFX_FILTER_MATCH_ETHER_TYPE match flag and EFX_ETHER_TYPE_IPV4 and * EFX_ETHER_TYPE_IPV6 values of the corresponding field in the same * specifications after copying. @@ -1638,9 +1714,22 @@ sfc_flow_check_ifrm_unknown_dst_flags(efx_filter_match_flags_t match, return B_FALSE; } -/* Match flags that can be automatically added to filters */ +/* + * Match flags that can be automatically added to filters. + * Selecting the last minimum when searching for the copy flag ensures that the + * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST flag has a higher priority than + * EFX_FILTER_MATCH_ETHER_TYPE. This is because the filter + * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST is at the end of the list of supported + * filters. + */ static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = { { + .flag = EFX_FILTER_MATCH_UNKNOWN_UCAST_DST, + .vals_count = 2, + .set_vals = sfc_flow_set_unknown_dst_flags, + .spec_check = sfc_flow_check_unknown_dst_flags, + }, + { .flag = EFX_FILTER_MATCH_ETHER_TYPE, .vals_count = 2, .set_vals = sfc_flow_set_ethertypes, diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 2b287dd..69dd683 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -24,7 +24,7 @@ extern "C" { * which can be produced from a template by means of multiplication, if * missing match flags are needed to be taken into account */ -#define SF_FLOW_SPEC_NB_FILTERS_MAX 4 +#define SF_FLOW_SPEC_NB_FILTERS_MAX 8 #if EFSYS_OPT_RX_SCALE /* RSS configuration storage */ -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 13/14] net/sfc: avoid creation of ineffective flow rules 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (11 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 12/14] net/sfc: multiply of specs with an unknown " Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 14/14] doc: add net/sfc flow API support for tunnels Andrew Rybchenko 2018-03-09 10:37 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Ferruh Yigit 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev; +Cc: Roman Zhukov From: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Despite being versatile, the hardware support for filtering has a number of special properties which must be taken into account. Namely, there is a known set of valid filters which don't take any effect despite being accepted by the hardware. The combinations of match flags and field values which can describe the exceptional filters are as follows: - ETHER_TYPE or ETHER_TYPE | LOC_MAC with IPv4 or IPv6 EtherType - ETHER_TYPE | IP_PROTO or ETHER_TYPE | IP_PROTO | LOC_MAC with UDP or TCP IP protocol value - The same combinations with OUTER_VID and/or INNER_VID These exceptional filters can be expressed in terms of RTE flow rules. If the user creates such a flow rule, no traffic will hit the underlying filter, and no errors will be reported. This patch adds a means to prevent such ineffective flow rules from being created. Signed-off-by: Roman Zhukov <Roman.Zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> --- doc/guides/nics/sfc_efx.rst | 17 ++++++++++ drivers/net/sfc/sfc_flow.c | 78 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 539ce90..f41ccdb 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -193,6 +193,23 @@ in the mask of destination address. If destinaton address in the spec is multicast, it matches all multicast (and broadcast) packets, oherwise it matches unicast packets that are not filtered by other flow rules. +Exceptions to flow rules +~~~~~~~~~~~~~~~~~~~~~~~~ + +There is a list of exceptional flow rule patterns which will not be +accepted by the PMD. A pattern will be rejected if at least one of the +conditions is met: + +- Filtering by IPv4 or IPv6 EtherType without pattern items of internet + layer and above. + +- The last item is IPV4 or IPV6, and it's empty. + +- Filtering by TCP or UDP IP transport protocol without pattern items of + transport layer and above. + +- The last item is TCP or UDP, and it's empty. + Supported NICs -------------- diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 7b26653..2b8bef8 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -1919,6 +1919,77 @@ sfc_flow_spec_filters_complete(struct sfc_adapter *sa, return 0; } +/** + * Check that set of match flags is referred to by a filter. Filter is + * described by match flags with the ability to add OUTER_VID and INNER_VID + * flags. + * + * @param match_flags[in] + * Set of match flags. + * @param flags_pattern[in] + * Pattern of filter match flags. + */ +static boolean_t +sfc_flow_is_match_with_vids(efx_filter_match_flags_t match_flags, + efx_filter_match_flags_t flags_pattern) +{ + if ((match_flags & flags_pattern) != flags_pattern) + return B_FALSE; + + switch (match_flags & ~flags_pattern) { + case 0: + case EFX_FILTER_MATCH_OUTER_VID: + case EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_INNER_VID: + return B_TRUE; + default: + return B_FALSE; + } +} + +/** + * Check whether the spec maps to a hardware filter which is known to be + * ineffective despite being valid. + * + * @param spec[in] + * SFC flow specification. + */ +static boolean_t +sfc_flow_is_match_flags_exception(struct sfc_flow_spec *spec) +{ + unsigned int i; + uint16_t ether_type; + uint8_t ip_proto; + efx_filter_match_flags_t match_flags; + + for (i = 0; i < spec->count; i++) { + match_flags = spec->filters[i].efs_match_flags; + + if (sfc_flow_is_match_with_vids(match_flags, + EFX_FILTER_MATCH_ETHER_TYPE) || + sfc_flow_is_match_with_vids(match_flags, + EFX_FILTER_MATCH_ETHER_TYPE | + EFX_FILTER_MATCH_LOC_MAC)) { + ether_type = spec->filters[i].efs_ether_type; + if (ether_type == EFX_ETHER_TYPE_IPV4 || + ether_type == EFX_ETHER_TYPE_IPV6) + return B_TRUE; + } else if (sfc_flow_is_match_with_vids(match_flags, + EFX_FILTER_MATCH_ETHER_TYPE | + EFX_FILTER_MATCH_IP_PROTO) || + sfc_flow_is_match_with_vids(match_flags, + EFX_FILTER_MATCH_ETHER_TYPE | + EFX_FILTER_MATCH_IP_PROTO | + EFX_FILTER_MATCH_LOC_MAC)) { + ip_proto = spec->filters[i].efs_ip_proto; + if (ip_proto == EFX_IPPROTO_TCP || + ip_proto == EFX_IPPROTO_UDP) + return B_TRUE; + } + } + + return B_FALSE; +} + static int sfc_flow_validate_match_flags(struct sfc_adapter *sa, struct rte_flow *flow, @@ -1938,6 +2009,13 @@ sfc_flow_validate_match_flags(struct sfc_adapter *sa, return rc; } + if (sfc_flow_is_match_flags_exception(&flow->spec)) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "The flow rule pattern is unsupported"); + return -rte_errno; + } + return 0; } -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [dpdk-dev] [PATCH v2 14/14] doc: add net/sfc flow API support for tunnels 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (12 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 13/14] net/sfc: avoid creation of ineffective flow rules Andrew Rybchenko @ 2018-03-06 15:24 ` Andrew Rybchenko 2018-03-09 10:37 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Ferruh Yigit 14 siblings, 0 replies; 32+ messages in thread From: Andrew Rybchenko @ 2018-03-06 15:24 UTC (permalink / raw) To: dev Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> --- doc/guides/rel_notes/release_18_05.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/guides/rel_notes/release_18_05.rst b/doc/guides/rel_notes/release_18_05.rst index 3923dc2..894f636 100644 --- a/doc/guides/rel_notes/release_18_05.rst +++ b/doc/guides/rel_notes/release_18_05.rst @@ -41,6 +41,12 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Updated Solarflare network PMD.** + + Updated the sfc_efx driver including the following changes: + + * Added support for NVGRE, VXLAN and GENEVE filters in flow API. + API Changes ----------- -- 2.7.4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API for tunnels 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko ` (13 preceding siblings ...) 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 14/14] doc: add net/sfc flow API support for tunnels Andrew Rybchenko @ 2018-03-09 10:37 ` Ferruh Yigit 14 siblings, 0 replies; 32+ messages in thread From: Ferruh Yigit @ 2018-03-09 10:37 UTC (permalink / raw) To: Andrew Rybchenko, dev On 3/6/2018 3:24 PM, Andrew Rybchenko wrote: > Update base driver and the PMD itself to support flow API > patterns for tunnels: VXLAN, NVGRE and Geneve. > > Applicable to SFN8xxx NICs with full-feature firmware variant running. > > Andrew Rybchenko (1): > doc: add net/sfc flow API support for tunnels > > Roman Zhukov (12): > net/sfc/base: support filters for encapsulated packets > net/sfc/base: support VNI/VSID and inner frame local MAC > net/sfc/base: distinguish filters for encapsulated packets > net/sfc: add VXLAN in flow API filters support > net/sfc: add NVGRE in flow API filters support > net/sfc: add GENEVE in flow API filters support > net/sfc: add inner frame ETH in flow API filters support > net/sfc: add infrastructure to make many filters from flow > net/sfc: multiply of specs with an unknown EtherType > net/sfc: multiply of specs w/o inner frame destination MAC > net/sfc: multiply of specs with an unknown destination MAC > net/sfc: avoid creation of ineffective flow rules > > Vijay Srivastava (1): > net/sfc/base: support VXLAN filter creation Series applied to dpdk-next-net/master, thanks. ^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2018-03-09 10:37 UTC | newest] Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-02-27 12:45 [dpdk-dev] [PATCH 00/14] net/sfc: support flow API for tunnels Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 01/14] net/sfc/base: support filters for encapsulated packets Andrew Rybchenko 2018-03-06 15:13 ` Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 02/14] net/sfc/base: support VNI/VSID and inner frame local MAC Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 03/14] net/sfc/base: support VXLAN filter creation Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 04/14] net/sfc/base: distinguish filters for encapsulated packets Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 05/14] net/sfc: add VXLAN in flow API filters support Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 06/14] net/sfc: add NVGRE " Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 07/14] net/sfc: add GENEVE " Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 08/14] net/sfc: add inner frame ETH " Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 09/14] net/sfc: add infrastructure to make many filters from flow Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 10/14] net/sfc: multiply of specs with an unknown EtherType Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 11/14] net/sfc: multiply of specs w/o inner frame destination MAC Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 12/14] net/sfc: multiply of specs with an unknown " Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 13/14] net/sfc: avoid creation of ineffective flow rules Andrew Rybchenko 2018-02-27 12:45 ` [dpdk-dev] [PATCH 14/14] doc: add net/sfc flow API support for tunnels Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 01/14] net/sfc/base: support filters for encapsulated packets Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 02/14] net/sfc/base: support VNI/VSID and inner frame local MAC Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 03/14] net/sfc/base: support VXLAN filter creation Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 04/14] net/sfc/base: distinguish filters for encapsulated packets Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 05/14] net/sfc: add VXLAN in flow API filters support Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 06/14] net/sfc: add NVGRE " Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 07/14] net/sfc: add GENEVE " Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 08/14] net/sfc: add inner frame ETH " Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 09/14] net/sfc: add infrastructure to make many filters from flow Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 10/14] net/sfc: multiply of specs with an unknown EtherType Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 11/14] net/sfc: multiply of specs w/o inner frame destination MAC Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 12/14] net/sfc: multiply of specs with an unknown " Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 13/14] net/sfc: avoid creation of ineffective flow rules Andrew Rybchenko 2018-03-06 15:24 ` [dpdk-dev] [PATCH v2 14/14] doc: add net/sfc flow API support for tunnels Andrew Rybchenko 2018-03-09 10:37 ` [dpdk-dev] [PATCH v2 00/14] net/sfc: support flow API " Ferruh Yigit
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).