svn commit: r299411 - head/sys/dev/sfxge/common

Andrew Rybchenko arybchik at FreeBSD.org
Wed May 11 06:29:08 UTC 2016


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 <mspender at solarflare.com>
  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;


More information about the svn-src-head mailing list