svn commit: r301342 - stable/10/sys/dev/sfxge/common

Andrew Rybchenko arybchik at FreeBSD.org
Sat Jun 4 15:01:09 UTC 2016


Author: arybchik
Date: Sat Jun  4 15:01:08 2016
New Revision: 301342
URL: https://svnweb.freebsd.org/changeset/base/301342

Log:
  MFC r299594
  
  sfxge(4): avoid duplicate delivery of packets when changing multicast
  mode with multicast chaining enabled
  
  With multicast chaining, if e.g. a specific multicast filter is
  inserted and the multicast mis-match filter is then inserted, both may
  match a packet and cause it to be delivered.
  
  Copy the behaviour of the Linux driver, which is to remove the old filters
  first, on the basis that customers are more likely to be able to handle
  drops than duplicates (see bug49178 comment 4).
  
  Submitted by:   Mark Spender <mspender at solarflare.com>
  Sponsored by:   Solarflare Communications, Inc.

Modified:
  stable/10/sys/dev/sfxge/common/hunt_filter.c
  stable/10/sys/dev/sfxge/common/hunt_impl.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/sfxge/common/hunt_filter.c
==============================================================================
--- stable/10/sys/dev/sfxge/common/hunt_filter.c	Sat Jun  4 14:59:54 2016	(r301341)
+++ stable/10/sys/dev/sfxge/common/hunt_filter.c	Sat Jun  4 15:01:08 2016	(r301342)
@@ -1121,6 +1121,7 @@ ef10_filter_insert_multicast_list(
 	}
 
 	eftp->eft_mulcst_filter_count = filter_count;
+	eftp->eft_using_all_mulcst = B_FALSE;
 
 	return (0);
 
@@ -1160,6 +1161,7 @@ ef10_filter_insert_all_multicast(
 		goto fail1;
 
 	eftp->eft_mulcst_filter_count = 1;
+	eftp->eft_using_all_mulcst = B_TRUE;
 
 	/*
 	 * FIXME: If brdcst == B_FALSE, add a filter to drop broadcast traffic.
@@ -1173,6 +1175,20 @@ fail1:
 	return (rc);
 }
 
+static			void
+ef10_filter_remove_old(
+	__in		efx_nic_t *enp)
+{
+	ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
+	uint32_t i;
+
+	for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) {
+		if (ef10_filter_entry_is_auto_old(table, i)) {
+			(void) ef10_filter_delete_internal(enp, i);
+		}
+	}
+}
+
 
 static	__checkReturn	efx_rc_t
 hunt_filter_get_workarounds(
@@ -1227,6 +1243,7 @@ ef10_filter_reconfigure(
 	__in_ecount(6*count)		uint8_t const *addrs,
 	__in				uint32_t count)
 {
+	efx_nic_cfg_t *encp = &enp->en_nic_cfg;
 	ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
 	efx_filter_flag_t filter_flags;
 	unsigned i;
@@ -1316,6 +1333,18 @@ ef10_filter_reconfigure(
 	if ((rc = hunt_filter_get_workarounds(enp)) != 0)
 		goto fail2;
 
+	if ((table->eft_using_all_mulcst != all_mulcst) &&
+	    (encp->enc_bug26807_workaround == B_TRUE)) {
+		/*
+		 * Multicast filter chaining is enabled, so traffic that matches
+		 * more than one multicast filter will be replicated and
+		 * delivered to multiple recipients.  To avoid this duplicate
+		 * delivery, remove old multicast filters before inserting new
+		 * multicast filters.
+		 */
+		ef10_filter_remove_old(enp);
+	}
+
 	/* Insert or renew multicast filters */
 	if (all_mulcst == B_TRUE) {
 		/*
@@ -1342,6 +1371,17 @@ ef10_filter_reconfigure(
 		rc = ef10_filter_insert_multicast_list(enp, mulcst, brdcst,
 			    addrs, count, filter_flags, B_TRUE);
 		if (rc != 0) {
+			if ((table->eft_using_all_mulcst == B_FALSE) &&
+			    (encp->enc_bug26807_workaround == B_TRUE)) {
+				/*
+				 * Multicast filter chaining is on, so remove
+				 * old filters before inserting the multicast
+				 * all filter to avoid duplicate delivery caused
+				 * by packets matching multiple filters.
+				 */
+				ef10_filter_remove_old(enp);
+			}
+
 			rc = ef10_filter_insert_all_multicast(enp,
 							    filter_flags);
 			if (rc != 0) {
@@ -1355,11 +1395,7 @@ ef10_filter_reconfigure(
 	}
 
 	/* Remove old filters which were not renewed */
-	for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) {
-		if (ef10_filter_entry_is_auto_old(table, i)) {
-			(void) ef10_filter_delete_internal(enp, i);
-		}
-	}
+	ef10_filter_remove_old(enp);
 
 	/* report if any optional flags were rejected */
 	if (((all_unicst != B_FALSE) && (all_unicst_rc != 0)) ||

Modified: stable/10/sys/dev/sfxge/common/hunt_impl.h
==============================================================================
--- stable/10/sys/dev/sfxge/common/hunt_impl.h	Sat Jun  4 14:59:54 2016	(r301341)
+++ stable/10/sys/dev/sfxge/common/hunt_impl.h	Sat Jun  4 15:01:08 2016	(r301342)
@@ -1046,6 +1046,7 @@ typedef struct ef10_filter_table_s {
 	uint32_t 		eft_mulcst_filter_indexes[
 	    EFX_EF10_FILTER_MULTICAST_FILTERS_MAX];
 	uint32_t 		eft_mulcst_filter_count;
+	boolean_t		eft_using_all_mulcst;
 } ef10_filter_table_t;
 
 	__checkReturn	efx_rc_t


More information about the svn-src-all mailing list