Module Name:    src
Committed By:   msaitoh
Date:           Thu Sep 12 12:25:46 UTC 2019

Modified Files:
        src/sys/dev/pci/ixgbe: ixgbe_type.h ixgbe_vf.c ixv.c

Log Message:
Add support ALLMULTI on ixv(4):
 - Negotiate API version up to 1.3.
 - On linux's PF driver implementation, the PF replies VF's XCAST_MODE_ALLMULTI
   message not with NACK but with ACK even if the virtual function is NOT
   marked "trust" and act as XCAST_MODE_"MULTI". If ixv(4) simply check the
   return vaule of update_xcast_mode(XCAST_MODE_ALLMULTI), SIOCSADDMULTI
   success and the user may have trouble with some addresses. Fortunately,
   the Linux's PF driver's "ACK" message has not XCAST_MODE_"ALL"MULTI but
   XCAST_MODE_MULTI, so we can check this state by checking if the send
   message's argument and the reply message's argument are different.
 - Noy yet for PROMISC.


To generate a diff of this commit:
cvs rdiff -u -r1.41 -r1.42 src/sys/dev/pci/ixgbe/ixgbe_type.h
cvs rdiff -u -r1.20 -r1.21 src/sys/dev/pci/ixgbe/ixgbe_vf.c
cvs rdiff -u -r1.133 -r1.134 src/sys/dev/pci/ixgbe/ixv.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/ixgbe/ixgbe_type.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.42
--- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41	Wed Jul 24 06:07:58 2019
+++ src/sys/dev/pci/ixgbe/ixgbe_type.h	Thu Sep 12 12:25:46 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_type.h,v 1.41 2019/07/24 06:07:58 msaitoh Exp $ */
+/* $NetBSD: ixgbe_type.h,v 1.42 2019/09/12 12:25:46 msaitoh Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -4311,6 +4311,8 @@ struct ixgbe_hw {
 #define IXGBE_ERR_FW_RESP_INVALID		-39
 #define IXGBE_ERR_TOKEN_RETRY			-40
 
+#define IXGBE_ERR_NOT_TRUSTED			-50 /* XXX NetBSD */
+
 #define IXGBE_NOT_IMPLEMENTED			0x7FFFFFFF
 
 

Index: src/sys/dev/pci/ixgbe/ixgbe_vf.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.20 src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.21
--- src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.20	Thu Sep 12 06:19:47 2019
+++ src/sys/dev/pci/ixgbe/ixgbe_vf.c	Thu Sep 12 12:25:46 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_vf.c,v 1.20 2019/09/12 06:19:47 msaitoh Exp $ */
+/* $NetBSD: ixgbe_vf.c,v 1.21 2019/09/12 12:25:46 msaitoh Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -462,6 +462,21 @@ s32 ixgbevf_update_xcast_mode(struct ixg
 	msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
 	if (msgbuf[0] == (IXGBE_VF_UPDATE_XCAST_MODE | IXGBE_VT_MSGTYPE_NACK))
 		return IXGBE_ERR_FEATURE_NOT_SUPPORTED;
+	/*
+	 *  On linux's PF driver implementation, the PF replies VF's
+	 * XCAST_MODE_ALLMULTI message not with NACK but with ACK even if the
+	 * virtual function is NOT marked "trust" and act as
+	 * XCAST_MODE_"MULTI". If ixv(4) simply check the return vaule of
+	 * update_xcast_mode(XCAST_MODE_ALLMULTI), SIOCSADDMULTI success and
+	 * the user may have trouble with some addresses. Fortunately, the
+	 * Linux's PF driver's "ACK" message has not XCAST_MODE_"ALL"MULTI but
+	 * XCAST_MODE_MULTI, so we can check this state by checking if the
+	 * send message's argument and the reply message's argument are
+	 * different.
+	 */
+	if ((xcast_mode > IXGBEVF_XCAST_MODE_MULTI)
+	    && (xcast_mode != msgbuf[1]))
+		return IXGBE_ERR_NOT_TRUSTED;
 	return IXGBE_SUCCESS;
 }
 

Index: src/sys/dev/pci/ixgbe/ixv.c
diff -u src/sys/dev/pci/ixgbe/ixv.c:1.133 src/sys/dev/pci/ixgbe/ixv.c:1.134
--- src/sys/dev/pci/ixgbe/ixv.c:1.133	Thu Sep 12 11:48:44 2019
+++ src/sys/dev/pci/ixgbe/ixv.c	Thu Sep 12 12:25:46 2019
@@ -1,4 +1,4 @@
-/*$NetBSD: ixv.c,v 1.133 2019/09/12 11:48:44 msaitoh Exp $*/
+/*$NetBSD: ixv.c,v 1.134 2019/09/12 12:25:46 msaitoh Exp $*/
 
 /******************************************************************************
 
@@ -1085,7 +1085,9 @@ static int
 ixv_negotiate_api(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	int		mbx_api[] = { ixgbe_mbox_api_11,
+	int		mbx_api[] = { ixgbe_mbox_api_13,
+				      ixgbe_mbox_api_12,
+				      ixgbe_mbox_api_11,
 				      ixgbe_mbox_api_10,
 				      ixgbe_mbox_api_unknown };
 	int		i = 0;
@@ -1108,12 +1110,16 @@ ixv_negotiate_api(struct adapter *adapte
 static void
 ixv_set_multi(struct adapter *adapter)
 {
+	struct ixgbe_hw *hw = &adapter->hw;
 	struct ether_multi *enm;
 	struct ether_multistep step;
 	struct ethercom *ec = &adapter->osdep.ec;
 	u8	mta[IXGBE_MAX_VF_MC * IXGBE_ETH_LENGTH_OF_ADDRESS];
 	u8		   *update_ptr;
 	int		   mcnt = 0;
+	bool overflow = false;
+	bool allmulti = false;
+	int error;
 
 	KASSERT(mutex_owned(&adapter->core_mtx));
 	IOCTL_DEBUGOUT("ixv_set_multi: begin");
@@ -1121,17 +1127,48 @@ ixv_set_multi(struct adapter *adapter)
 	ETHER_LOCK(ec);
 	ETHER_FIRST_MULTI(step, ec, enm);
 	while (enm != NULL) {
+		if (mcnt >= IXGBE_MAX_VF_MC) {
+			overflow = true;
+			break;
+		}
 		bcopy(enm->enm_addrlo,
 		    &mta[mcnt * IXGBE_ETH_LENGTH_OF_ADDRESS],
 		    IXGBE_ETH_LENGTH_OF_ADDRESS);
 		mcnt++;
-		/* XXX This might be required --msaitoh */
-		if (mcnt >= IXGBE_MAX_VF_MC)
-			break;
 		ETHER_NEXT_MULTI(step, enm);
 	}
 	ETHER_UNLOCK(ec);
 
+	if (overflow) {
+		error = hw->mac.ops.update_xcast_mode(hw,
+		    IXGBEVF_XCAST_MODE_ALLMULTI);
+		if (error == IXGBE_ERR_NOT_TRUSTED) {
+			device_printf(adapter->dev,
+			    "this interface is not trusted\n");
+			error = ENOSPC;
+		} else if (error) {
+			device_printf(adapter->dev,
+			    "number of Ethernet multicast addresses "
+			    "exceeds the limit (%d). error = %d\n",
+			    IXGBE_MAX_VF_MC, error);
+			error = ENOSPC;
+		} else {
+			allmulti = true;
+			ec->ec_flags |= ETHER_F_ALLMULTI;
+		}
+	}
+
+	if (!allmulti) {
+		error = hw->mac.ops.update_xcast_mode(hw,
+		    IXGBEVF_XCAST_MODE_MULTI);
+		if (error) {
+			device_printf(adapter->dev,
+			    "failed to set Ethernet multicast address "
+			    "operation to normal. error = %d\n", error);
+		}
+		ec->ec_flags &= ~ETHER_F_ALLMULTI;
+	}
+
 	update_ptr = mta;
 
 	adapter->hw.mac.ops.update_mc_addr_list(&adapter->hw, update_ptr, mcnt,
@@ -2910,8 +2947,9 @@ static int
 ixv_ioctl(struct ifnet *ifp, u_long command, void *data)
 {
 	struct adapter	*adapter = ifp->if_softc;
+	struct ixgbe_hw *hw = &adapter->hw;
 	struct ifcapreq *ifcr = data;
-	int		error = 0;
+	int		error;
 	int l4csum_en;
 	const int l4csum = IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx |
 	     IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx;
@@ -2924,6 +2962,7 @@ ixv_ioctl(struct ifnet *ifp, u_long comm
 		struct ether_multi *enm;
 		struct ether_multistep step;
 		struct ethercom *ec = &adapter->osdep.ec;
+		bool overflow = false;
 		int mcnt = 0;
 
 		/*
@@ -2941,16 +2980,29 @@ ixv_ioctl(struct ifnet *ifp, u_long comm
 			 * at least.
 			 */
 			if (mcnt > (IXGBE_MAX_VF_MC - 1)) {
-				device_printf(adapter->dev,
-				    "number of Ethernet multicast addresses "
-				    "exceeds the limit (%d)\n",
-				    IXGBE_MAX_VF_MC);
-				error = ENOSPC;
+				overflow = true;
 				break;
 			}
 			ETHER_NEXT_MULTI(step, enm);
 		}
 		ETHER_UNLOCK(ec);
+		error = 0;
+		if (overflow && ((ec->ec_flags & ETHER_F_ALLMULTI) == 0)) {
+			error = hw->mac.ops.update_xcast_mode(hw,
+			    IXGBEVF_XCAST_MODE_ALLMULTI);
+			if (error == IXGBE_ERR_NOT_TRUSTED) {
+				device_printf(adapter->dev,
+				    "this interface is not trusted\n");
+				error = ENOSPC;
+			} else if (error) {
+				device_printf(adapter->dev,
+				    "number of Ethernet multicast addresses "
+				    "exceeds the limit (%d). error = %d\n",
+				    IXGBE_MAX_VF_MC, error);
+				error = ENOSPC;
+			} else
+				ec->ec_flags |= ETHER_F_ALLMULTI;
+		}
 		if (error)
 			return error;
 	}

Reply via email to