From owner-svn-src-head@freebsd.org Wed May 11 06:29:08 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 947C4B36284; Wed, 11 May 2016 06:29:08 +0000 (UTC) (envelope-from arybchik@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 574C91791; Wed, 11 May 2016 06:29:08 +0000 (UTC) (envelope-from arybchik@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4B6T7A0041951; Wed, 11 May 2016 06:29:07 GMT (envelope-from arybchik@FreeBSD.org) Received: (from arybchik@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4B6T78F041949; Wed, 11 May 2016 06:29:07 GMT (envelope-from arybchik@FreeBSD.org) Message-Id: <201605110629.u4B6T78F041949@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: arybchik set sender to arybchik@FreeBSD.org using -f From: Andrew Rybchenko Date: Wed, 11 May 2016 06:29:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r299411 - head/sys/dev/sfxge/common X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 May 2016 06:29:08 -0000 Author: arybchik Date: Wed May 11 06:29:07 2016 New Revision: 299411 URL: https://svnweb.freebsd.org/changeset/base/299411 Log: sfxge(4): update unicast filter insertion algorithm As unicast filters are not chained, we should always try to insert the specific filter for our MAC address, and then try to insert the unicast mis-match filter if that fails or all unicast has been requested. Submitted by: Mark Spender Sponsored by: Solarflare Communications, Inc. MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6295 Modified: head/sys/dev/sfxge/common/hunt_filter.c head/sys/dev/sfxge/common/hunt_impl.h Modified: head/sys/dev/sfxge/common/hunt_filter.c ============================================================================== --- head/sys/dev/sfxge/common/hunt_filter.c Wed May 11 06:28:08 2016 (r299410) +++ head/sys/dev/sfxge/common/hunt_filter.c Wed May 11 06:29:07 2016 (r299411) @@ -982,19 +982,15 @@ fail1: } static __checkReturn efx_rc_t -ef10_filter_unicast_refresh( +ef10_filter_insert_unicast( __in efx_nic_t *enp, __in_ecount(6) uint8_t const *addr, - __in boolean_t all_unicst, __in efx_filter_flag_t filter_flags) { ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; efx_filter_spec_t spec; efx_rc_t rc; - if (all_unicst == B_TRUE) - goto use_uc_def; - /* Insert the filter for the local station address */ efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, @@ -1002,43 +998,48 @@ ef10_filter_unicast_refresh( efx_filter_spec_set_eth_local(&spec, EFX_FILTER_SPEC_VID_UNSPEC, addr); rc = ef10_filter_add_internal(enp, &spec, B_TRUE, - &eftp->eft_unicst_filter_index); - if (rc != 0) { - /* - * Fall back to an unknown filter. We may be able to subscribe - * to it even if we couldn't insert the unicast filter. - */ - goto use_uc_def; - } - eftp->eft_unicst_filter_set = B_TRUE; + &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]); + if (rc != 0) + goto fail1; + + eftp->eft_unicst_filter_count++; + EFSYS_ASSERT(eftp->eft_unicst_filter_count <= + EFX_EF10_FILTER_UNICAST_FILTERS_MAX); return (0); -use_uc_def: +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + +static __checkReturn efx_rc_t +ef10_filter_insert_all_unicast( + __in efx_nic_t *enp, + __in efx_filter_flag_t filter_flags) +{ + ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; + efx_filter_spec_t spec; + efx_rc_t rc; + /* Insert the unknown unicast filter */ efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, eftp->eft_default_rxq); efx_filter_spec_set_uc_def(&spec); rc = ef10_filter_add_internal(enp, &spec, B_TRUE, - &eftp->eft_unicst_filter_index); + &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]); if (rc != 0) goto fail1; - eftp->eft_unicst_filter_set = B_TRUE; + eftp->eft_unicst_filter_count++; + EFSYS_ASSERT(eftp->eft_unicst_filter_count <= + EFX_EF10_FILTER_UNICAST_FILTERS_MAX); return (0); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); - - if (eftp->eft_unicst_filter_set != B_FALSE) { - (void) ef10_filter_delete_internal(enp, - eftp->eft_unicst_filter_index); - - eftp->eft_unicst_filter_set = B_FALSE; - } - return (rc); } @@ -1207,7 +1208,7 @@ ef10_filter_reconfigure( ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; efx_filter_flag_t filter_flags; unsigned i; - int all_unicst_rc; + int all_unicst_rc = 0; int all_mulcst_rc; efx_rc_t rc; @@ -1218,11 +1219,12 @@ ef10_filter_reconfigure( * filters must be removed (ignore errors in case the MC * has rebooted, which removes hardware filters). */ - if (table->eft_unicst_filter_set != B_FALSE) { + for (i = 0; i < table->eft_unicst_filter_count; i++) { (void) ef10_filter_delete_internal(enp, - table->eft_unicst_filter_index); - table->eft_unicst_filter_set = B_FALSE; + table->eft_unicst_filter_indexes[i]); } + table->eft_unicst_filter_count = 0; + for (i = 0; i < table->eft_mulcst_filter_count; i++) { (void) ef10_filter_delete_internal(enp, table->eft_mulcst_filter_indexes[i]); @@ -1238,27 +1240,39 @@ ef10_filter_reconfigure( filter_flags = 0; /* Mark old filters which may need to be removed */ - if (table->eft_unicst_filter_set != B_FALSE) { + for (i = 0; i < table->eft_unicst_filter_count; i++) { ef10_filter_set_entry_auto_old(table, - table->eft_unicst_filter_index); + table->eft_unicst_filter_indexes[i]); } for (i = 0; i < table->eft_mulcst_filter_count; i++) { ef10_filter_set_entry_auto_old(table, table->eft_mulcst_filter_indexes[i]); } - /* Insert or renew unicast filters */ - if ((all_unicst_rc = ef10_filter_unicast_refresh(enp, mac_addr, - all_unicst, filter_flags)) != 0) { - if (all_unicst == B_FALSE) { - rc = all_unicst_rc; + /* + * Insert or renew unicast filters. + * + * Frimware does not perform chaining on unicast filters. As traffic is + * therefore only delivered to the first matching filter, we should + * always insert the specific filter for our MAC address, to try and + * ensure we get that traffic. + * + * (If the filter for our MAC address has already been inserted by + * another function, we won't receive traffic sent to us, even if we + * insert a unicast mismatch filter. To prevent traffic stealing, this + * therefore relies on the privilege model only allowing functions to + * insert filters for their own MAC address unless explicitly given + * additional privileges by the user. This also means that, even on a + * priviliged function, inserting a unicast mismatch filter may not + * catch all traffic in multi PCI function scenarios.) + */ + table->eft_unicst_filter_count = 0; + rc = ef10_filter_insert_unicast(enp, mac_addr, filter_flags); + if (all_unicst || (rc != 0)) { + all_unicst_rc = ef10_filter_insert_all_unicast(enp, + filter_flags); + if ((rc != 0) && (all_unicst_rc != 0)) goto fail1; - } - /* Retry without all_unicast flag */ - rc = ef10_filter_unicast_refresh(enp, mac_addr, - B_FALSE, filter_flags); - if (rc != 0) - goto fail2; } /* @@ -1278,7 +1292,7 @@ ef10_filter_reconfigure( * FIXME: On Medford multicast chaining should always be on. */ if ((rc = hunt_filter_get_workarounds(enp)) != 0) - goto fail3; + goto fail2; /* Insert or renew multicast filters */ if ((all_mulcst_rc = ef10_filter_multicast_refresh(enp, mulcst, @@ -1286,14 +1300,14 @@ ef10_filter_reconfigure( addrs, count, filter_flags)) != 0) { if (all_mulcst == B_FALSE) { rc = all_mulcst_rc; - goto fail4; + goto fail3; } /* Retry without all_mulcast flag */ rc = ef10_filter_multicast_refresh(enp, mulcst, B_FALSE, brdcst, addrs, count, filter_flags); if (rc != 0) - goto fail5; + goto fail4; } /* Remove old filters which were not renewed */ @@ -1311,8 +1325,6 @@ ef10_filter_reconfigure( return (rc); -fail5: - EFSYS_PROBE(fail5); fail4: EFSYS_PROBE(fail4); fail3: Modified: head/sys/dev/sfxge/common/hunt_impl.h ============================================================================== --- head/sys/dev/sfxge/common/hunt_impl.h Wed May 11 06:28:08 2016 (r299410) +++ head/sys/dev/sfxge/common/hunt_impl.h Wed May 11 06:29:07 2016 (r299411) @@ -1030,6 +1030,9 @@ typedef struct ef10_filter_entry_s { */ #define EFX_EF10_FILTER_TBL_ROWS 8192 +/* Only need to allow for one directed and one unknown unicast filter */ +#define EFX_EF10_FILTER_UNICAST_FILTERS_MAX 2 + /* Allow for the broadcast address to be added to the multicast list */ #define EFX_EF10_FILTER_MULTICAST_FILTERS_MAX (EFX_MAC_MULTICAST_LIST_MAX + 1) @@ -1037,8 +1040,9 @@ typedef struct ef10_filter_table_s { ef10_filter_entry_t eft_entry[EFX_EF10_FILTER_TBL_ROWS]; efx_rxq_t * eft_default_rxq; boolean_t eft_using_rss; - uint32_t eft_unicst_filter_index; - boolean_t eft_unicst_filter_set; + uint32_t eft_unicst_filter_indexes[ + EFX_EF10_FILTER_UNICAST_FILTERS_MAX]; + boolean_t eft_unicst_filter_count; uint32_t eft_mulcst_filter_indexes[ EFX_EF10_FILTER_MULTICAST_FILTERS_MAX]; uint32_t eft_mulcst_filter_count;