Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci/ixgbe Add support ALLMULTI on ixv(4):



details:   https://anonhg.NetBSD.org/src/rev/e38ef9dfc25b
branches:  trunk
changeset: 459450:e38ef9dfc25b
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Sep 12 12:25:46 2019 +0000

description:
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.

diffstat:

 sys/dev/pci/ixgbe/ixgbe_type.h |   4 +-
 sys/dev/pci/ixgbe/ixgbe_vf.c   |  17 +++++++++-
 sys/dev/pci/ixgbe/ixv.c        |  74 +++++++++++++++++++++++++++++++++++------
 3 files changed, 82 insertions(+), 13 deletions(-)

diffs (192 lines):

diff -r 702462918674 -r e38ef9dfc25b sys/dev/pci/ixgbe/ixgbe_type.h
--- a/sys/dev/pci/ixgbe/ixgbe_type.h    Thu Sep 12 11:48:44 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe_type.h    Thu Sep 12 12:25:46 2019 +0000
@@ -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 @@
 #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
 
 
diff -r 702462918674 -r e38ef9dfc25b sys/dev/pci/ixgbe/ixgbe_vf.c
--- a/sys/dev/pci/ixgbe/ixgbe_vf.c      Thu Sep 12 11:48:44 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe_vf.c      Thu Sep 12 12:25:46 2019 +0000
@@ -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 @@
        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;
 }
 
diff -r 702462918674 -r e38ef9dfc25b sys/dev/pci/ixgbe/ixv.c
--- a/sys/dev/pci/ixgbe/ixv.c   Thu Sep 12 11:48:44 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixv.c   Thu Sep 12 12:25:46 2019 +0000
@@ -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 @@
 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 @@
 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 @@
        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 @@
 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 @@
                struct ether_multi *enm;
                struct ether_multistep step;
                struct ethercom *ec = &adapter->osdep.ec;
+               bool overflow = false;
                int mcnt = 0;
 
                /*
@@ -2941,16 +2980,29 @@
                         * 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;
        }



Home | Main Index | Thread Index | Old Index