From patchwork Thu Mar 2 16:03:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Rybchenko X-Patchwork-Id: 21140 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 96729F614; Thu, 2 Mar 2017 17:04:15 +0100 (CET) Received: from nbfkord-smmo01.seg.att.com (nbfkord-smmo01.seg.att.com [209.65.160.76]) by dpdk.org (Postfix) with ESMTP id D932B2952 for ; Thu, 2 Mar 2017 17:03:48 +0100 (CET) Received: from unknown [12.187.104.26] by nbfkord-smmo01.seg.att.com(mxl_mta-7.2.4-7) with SMTP id 46248b85.0.805630.00-2341.2324231.nbfkord-smmo01.seg.att.com (envelope-from ); Thu, 02 Mar 2017 16:03:49 +0000 (UTC) X-MXL-Hash: 58b842650659cd2d-0b3e40f223eadf59334c54586cc6d1357bf5cf69 Received: from ocex03.SolarFlarecom.com (10.20.40.36) by ocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server (TLS) id 15.0.1044.25; Thu, 2 Mar 2017 08:03:41 -0800 Received: from opal.uk.solarflarecom.com (10.17.10.1) by ocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server (TLS) id 15.0.1044.25 via Frontend Transport; Thu, 2 Mar 2017 08:03:40 -0800 Received: from uklogin.uk.solarflarecom.com (uklogin.uk.solarflarecom.com [10.17.10.10]) by opal.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id v22G3dd0007949; Thu, 2 Mar 2017 16:03:39 GMT Received: from uklogin.uk.solarflarecom.com (localhost.localdomain [127.0.0.1]) by uklogin.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id v22G3dWl005942; Thu, 2 Mar 2017 16:03:39 GMT From: Andrew Rybchenko To: CC: Mark Spender Date: Thu, 2 Mar 2017 16:03:02 +0000 Message-ID: <1488470591-5853-3-git-send-email-arybchenko@solarflare.com> X-Mailer: git-send-email 1.8.2.3 In-Reply-To: <1488470591-5853-1-git-send-email-arybchenko@solarflare.com> References: <1488470591-5853-1-git-send-email-arybchenko@solarflare.com> MIME-Version: 1.0 X-AnalysisOut: [v=2.1 cv=LaQ6n2ri c=1 sm=1 tr=0 a=8BlWFWvVlq5taO8ncb8nKg==] X-AnalysisOut: [:17 a=6Iz7jQTuP9IA:10 a=zRKbQ67AAAAA:8 a=2uROUVfLlKyts5k6O] X-AnalysisOut: [Y8A:9 a=hQHmqYwCie8EHdUt:21 a=iEp2qHqSOV2Z8eOM:21 a=TV43RA] X-AnalysisOut: [2N5QS5ylXj:21 a=PA03WX8tBzeizutn5_OT:22] X-Spam: [F=0.4999352646; CM=0.500; S=0.499(2015072901)] X-MAIL-FROM: X-SOURCE-IP: [12.187.104.26] Subject: [dpdk-dev] [PATCH 02/11] net/sfc/base: improve API to get supported filter matches X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Mark Spender The previous API had various problems, including the length of the caller provided buffer not being specified, no means being available to discover how big the buffer needs to be, and a lack of clarity of what the resulting list contains. To improve it: - add the buffer length as a parameter - if the provided buffer is too short, fail with ENOSPC and return the required length - ensure that the list contents are valid and add comments describing it It is safe to change this API as, unsuprisingly, it has no users. Signed-off-by: Mark Spender Signed-off-by: Andrew Rybchenko --- drivers/net/sfc/base/ef10_filter.c | 90 +++++++++++++++++++++++++++++++------- drivers/net/sfc/base/ef10_impl.h | 7 +-- drivers/net/sfc/base/efx.h | 7 +-- drivers/net/sfc/base/efx_filter.c | 68 +++++++++++++++++++--------- drivers/net/sfc/base/efx_impl.h | 3 +- 5 files changed, 132 insertions(+), 43 deletions(-) diff --git a/drivers/net/sfc/base/ef10_filter.c b/drivers/net/sfc/base/ef10_filter.c index f520147..695bb84 100644 --- a/drivers/net/sfc/base/ef10_filter.c +++ b/drivers/net/sfc/base/ef10_filter.c @@ -868,13 +868,16 @@ ef10_filter_delete( static __checkReturn efx_rc_t efx_mcdi_get_parser_disp_info( - __in efx_nic_t *enp, - __out uint32_t *list, - __out size_t *length) + __in efx_nic_t *enp, + __out_ecount(buffer_length) uint32_t *buffer, + __in size_t buffer_length, + __out size_t *list_lengthp) { efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_GET_PARSER_DISP_INFO_IN_LEN, MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX)]; + size_t matches_count; + size_t list_size; efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); @@ -894,25 +897,41 @@ efx_mcdi_get_parser_disp_info( goto fail1; } - *length = MCDI_OUT_DWORD(req, + matches_count = MCDI_OUT_DWORD(req, GET_PARSER_DISP_INFO_OUT_NUM_SUPPORTED_MATCHES); if (req.emr_out_length_used < - MC_CMD_GET_PARSER_DISP_INFO_OUT_LEN(*length)) { + MC_CMD_GET_PARSER_DISP_INFO_OUT_LEN(matches_count)) { rc = EMSGSIZE; goto fail2; } - memcpy(list, - MCDI_OUT2(req, - uint32_t, - GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES), - (*length) * sizeof (uint32_t)); + *list_lengthp = matches_count; + + if (buffer_length < matches_count) { + rc = ENOSPC; + goto fail3; + } + + /* + * Check that the elements in the list in the MCDI response are the size + * we expect, so we can just copy them directly. Any conversion of the + * flags is handled by the caller. + */ EFX_STATIC_ASSERT(sizeof (uint32_t) == MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN); + list_size = matches_count * + MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN; + memcpy(buffer, + MCDI_OUT2(req, uint32_t, + GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES), + list_size); + return (0); +fail3: + EFSYS_PROBE(fail3); fail2: EFSYS_PROBE(fail2); fail1: @@ -923,14 +942,55 @@ efx_mcdi_get_parser_disp_info( __checkReturn efx_rc_t ef10_filter_supported_filters( - __in efx_nic_t *enp, - __out uint32_t *list, - __out size_t *length) + __in efx_nic_t *enp, + __out_ecount(buffer_length) uint32_t *buffer, + __in size_t buffer_length, + __out size_t *list_lengthp) { - efx_rc_t rc; - if ((rc = efx_mcdi_get_parser_disp_info(enp, list, length)) != 0) + size_t mcdi_list_length; + size_t list_length; + uint32_t i; + efx_rc_t rc; + uint32_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_UNKNOWN_MCAST_DST | + EFX_FILTER_MATCH_UNKNOWN_UCAST_DST); + + rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, + &mcdi_list_length); + if (rc != 0) { + if (rc == ENOSPC) { + /* Pass through mcdi_list_length for the list length */ + *list_lengthp = mcdi_list_length; + } goto fail1; + } + + /* + * The static assertions in ef10_filter_init() ensure that the values of + * the EFX_FILTER_MATCH flags match those used by MCDI, so they don't + * need to be converted. + * + * In case support is added to MCDI for additional flags, remove any + * matches from the list which include flags we don't support. The order + * of the matches is preserved as they are ordered from highest to + * lowest priority. + */ + EFSYS_ASSERT(mcdi_list_length <= buffer_length); + list_length = 0; + for (i = 0; i < mcdi_list_length; i++) { + if ((buffer[i] & ~all_filter_flags) == 0) { + buffer[list_length] = buffer[i]; + list_length++; + } + } + + *list_lengthp = list_length; return (0); diff --git a/drivers/net/sfc/base/ef10_impl.h b/drivers/net/sfc/base/ef10_impl.h index 192be5d..8c3dffe 100644 --- a/drivers/net/sfc/base/ef10_impl.h +++ b/drivers/net/sfc/base/ef10_impl.h @@ -1043,9 +1043,10 @@ ef10_filter_delete( extern __checkReturn efx_rc_t ef10_filter_supported_filters( - __in efx_nic_t *enp, - __out uint32_t *list, - __out size_t *length); + __in efx_nic_t *enp, + __out_ecount(buffer_length) uint32_t *buffer, + __in size_t buffer_length, + __out size_t *list_lengthp); extern __checkReturn efx_rc_t ef10_filter_reconfigure( diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h index 3c26f70..e67bf37 100644 --- a/drivers/net/sfc/base/efx.h +++ b/drivers/net/sfc/base/efx.h @@ -2289,9 +2289,10 @@ efx_filter_restore( extern __checkReturn efx_rc_t efx_filter_supported_filters( - __in efx_nic_t *enp, - __out uint32_t *list, - __out size_t *length); + __in efx_nic_t *enp, + __out_ecount(buffer_length) uint32_t *buffer, + __in size_t buffer_length, + __out size_t *list_lengthp); extern void efx_filter_spec_init_rx( diff --git a/drivers/net/sfc/base/efx_filter.c b/drivers/net/sfc/base/efx_filter.c index 4f58a7d..ba31026 100644 --- a/drivers/net/sfc/base/efx_filter.c +++ b/drivers/net/sfc/base/efx_filter.c @@ -61,9 +61,10 @@ siena_filter_delete( static __checkReturn efx_rc_t siena_filter_supported_filters( - __in efx_nic_t *enp, - __out uint32_t *list, - __out size_t *length); + __in efx_nic_t *enp, + __out_ecount(buffer_length) uint32_t *buffer, + __in size_t buffer_length, + __out size_t *list_lengthp); #endif /* EFSYS_OPT_SIENA */ @@ -209,11 +210,22 @@ efx_filter_fini( enp->en_mod_flags &= ~EFX_MOD_FILTER; } +/* + * Query the possible combinations of match flags which can be filtered on. + * These are returned as a list, of which each 32 bit element is a bitmask + * formed of EFX_FILTER_MATCH flags. + * + * The combinations are ordered in priority from highest to lowest. + * + * If the provided buffer is too short to hold the list, the call with fail with + * ENOSPC and *list_lengthp will be set to the buffer length required. + */ __checkReturn efx_rc_t efx_filter_supported_filters( - __in efx_nic_t *enp, - __out uint32_t *list, - __out size_t *length) + __in efx_nic_t *enp, + __out_ecount(buffer_length) uint32_t *buffer, + __in size_t buffer_length, + __out size_t *list_lengthp) { efx_rc_t rc; @@ -222,11 +234,20 @@ efx_filter_supported_filters( EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER); EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL); - if ((rc = enp->en_efop->efo_supported_filters(enp, list, length)) != 0) + if (buffer == NULL) { + rc = EINVAL; goto fail1; + } + + rc = enp->en_efop->efo_supported_filters(enp, buffer, buffer_length, + list_lengthp); + if (rc != 0) + goto fail2; return (0); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); @@ -1346,23 +1367,20 @@ siena_filter_delete( return (rc); } -#define MAX_SUPPORTED 4 +#define SIENA_MAX_SUPPORTED_MATCHES 4 static __checkReturn efx_rc_t siena_filter_supported_filters( - __in efx_nic_t *enp, - __out uint32_t *list, - __out size_t *length) + __in efx_nic_t *enp, + __out_ecount(buffer_length) uint32_t *buffer, + __in size_t buffer_length, + __out size_t *list_lengthp) { - int index = 0; - uint32_t rx_matches[MAX_SUPPORTED]; + uint32_t index = 0; + uint32_t rx_matches[SIENA_MAX_SUPPORTED_MATCHES]; + size_t list_length; efx_rc_t rc; - if (list == NULL) { - rc = EINVAL; - goto fail1; - } - rx_matches[index++] = EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT | @@ -1379,14 +1397,22 @@ siena_filter_supported_filters( rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC; } - EFSYS_ASSERT3U(index, <=, MAX_SUPPORTED); + EFSYS_ASSERT3U(index, <=, SIENA_MAX_SUPPORTED_MATCHES); + list_length = index; + + *list_lengthp = list_length; + + if (buffer_length < list_length) { + rc = ENOSPC; + goto fail1; + } - *length = index; - memcpy(list, rx_matches, *length); + memcpy(buffer, rx_matches, list_length * sizeof (rx_matches[0])); return (0); fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } diff --git a/drivers/net/sfc/base/efx_impl.h b/drivers/net/sfc/base/efx_impl.h index 3a520a8..01304f2 100644 --- a/drivers/net/sfc/base/efx_impl.h +++ b/drivers/net/sfc/base/efx_impl.h @@ -234,7 +234,8 @@ typedef struct efx_filter_ops_s { efx_rc_t (*efo_add)(efx_nic_t *, efx_filter_spec_t *, boolean_t may_replace); efx_rc_t (*efo_delete)(efx_nic_t *, efx_filter_spec_t *); - efx_rc_t (*efo_supported_filters)(efx_nic_t *, uint32_t *, size_t *); + efx_rc_t (*efo_supported_filters)(efx_nic_t *, uint32_t *, + size_t, size_t *); efx_rc_t (*efo_reconfigure)(efx_nic_t *, uint8_t const *, boolean_t, boolean_t, boolean_t, boolean_t, uint8_t const *, uint32_t);