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; }