The branch main has been updated by kbowling:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=1ccf543b21eff6e0828142e5c1d09519247143f4

commit 1ccf543b21eff6e0828142e5c1d09519247143f4
Author:     Eric Joyner <[email protected]>
AuthorDate: 2019-03-18 18:30:00 +0000
Commit:     Kevin Bowling <[email protected]>
CommitDate: 2026-08-09 06:46:29 +0000

    ifconfig: Add SR-IOV VF status output
    
    - Adds SR-IOV VF status to the existing ifconfig "-v" output
    - Adds ioctl command for reporting VF status info from drivers
    - Adds support to iflib for drivers to handle this new ioctl
    - Add support for ioctl in ixl(4)
    
    Signed-off-by: Eric Joyner <[email protected]>
    
    Relnotes:       yes
    Differential Revision:  https://reviews.freebsd.org/D19647
---
 sbin/ifconfig/Makefile           |  1 +
 sbin/ifconfig/ifconfig.c         |  2 ++
 sbin/ifconfig/ifconfig.h         |  1 +
 sbin/ifconfig/ifconfig_netlink.c |  3 +-
 sbin/ifconfig/ifvfstatus.c       | 78 ++++++++++++++++++++++++++++++++++++++++
 sys/dev/ixl/if_ixl.c             | 35 +++++++++++++++++-
 sys/net/if.h                     | 15 ++++++++
 sys/net/ifdi_if.m                | 12 +++++++
 sys/net/iflib.c                  | 12 +++++++
 sys/sys/sockio.h                 |  2 ++
 10 files changed, 159 insertions(+), 2 deletions(-)

diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile
index 26391023d54a..759b5d6f1438 100644
--- a/sbin/ifconfig/Makefile
+++ b/sbin/ifconfig/Makefile
@@ -35,6 +35,7 @@ SRCS+=        ifgif.c                 # GIF reversed header 
workaround
 SRCS+= ifipsec.c               # IPsec VTI
 
 SRCS+= sfp.c                   # SFP/SFP+ information
+SRCS+= ifvfstatus.c            # VF status information
 LIBADD+=       ifconfig m util
 CFLAGS+=       -I${SRCTOP}/lib/libifconfig -I${OBJTOP}/lib/libifconfig
 
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 0e839eeafc5b..52aa5696804e 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -1891,6 +1891,8 @@ status(if_ctx *ctx, const struct sockaddr_dl *sdl 
__unused, struct ifaddrs *ifa)
                args->afp->af_other_status(ctx);
 
        print_ifstatus(ctx);
+       if (args->verbose > 0)
+               vf_status(ctx);
        if (args->verbose > 0)
                sfp_status(ctx);
 
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
index 672020443b8c..75778e27a340 100644
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -281,6 +281,7 @@ void        clone_setdefcallback_prefix(const char *, 
clone_callback_func *);
 void   clone_setdefcallback_filter(clone_match_func *, clone_callback_func *);
 
 void   sfp_status(if_ctx *ctx);
+void   vf_status(if_ctx *ctx);
 
 struct sockaddr_dl;
 bool   match_ether(const struct sockaddr_dl *sdl);
diff --git a/sbin/ifconfig/ifconfig_netlink.c b/sbin/ifconfig/ifconfig_netlink.c
index b1467fde4c93..565a1ac91e20 100644
--- a/sbin/ifconfig/ifconfig_netlink.c
+++ b/sbin/ifconfig/ifconfig_netlink.c
@@ -414,6 +414,8 @@ status_nl(if_ctx *ctx, struct iface *iface)
                args->afp->af_other_status(ctx);
 
        print_ifstatus(ctx);
+       if (args->verbose > 0)
+               vf_status(ctx);
        if (args->drivername || args->verbose) {
                if (ifconfig_get_orig_name(lifh, link->ifla_ifname,
                    &drivername) != 0) {
@@ -492,4 +494,3 @@ list_interfaces_nl(struct ifconfig_args *args)
        close(ctx->io_s);
        snl_free(&ss);
 }
-
diff --git a/sbin/ifconfig/ifvfstatus.c b/sbin/ifconfig/ifvfstatus.c
new file mode 100644
index 000000000000..0c90d667855c
--- /dev/null
+++ b/sbin/ifconfig/ifvfstatus.c
@@ -0,0 +1,78 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ifconfig.h"
+
+void
+vf_status(if_ctx *ctx)
+{
+       struct ifvfstatus_entry *entries;
+       struct ifvfstatus ifvfs;
+
+       memset(&ifvfs, 0, sizeof(ifvfs));
+       strlcpy(ifvfs.ifvfs_name, ctx->ifname, sizeof(ifvfs.ifvfs_name));
+       if (ioctl_ctx(ctx, SIOCGIFVFSTATUS, &ifvfs) < 0)
+               return;
+       if (ifvfs.ifvfs_count == 0)
+               return;
+
+       entries = calloc(ifvfs.ifvfs_count, sizeof(*entries));
+       if (entries == NULL)
+               err(1, "calloc");
+       ifvfs.ifvfs_list = entries;
+       if (ioctl_ctx(ctx, SIOCGIFVFSTATUS, &ifvfs) < 0) {
+               free(entries);
+               warn("SIOCGIFVFSTATUS");
+               return;
+       }
+
+       printf("\tvirtual functions: %d\n", ifvfs.ifvfs_count);
+       for (int i = 0; i < ifvfs.ifvfs_count; i++) {
+               printf("\t\tvf %3d: mac %s", i,
+                   ether_ntoa((const struct ether_addr *)entries[i].mac_addr));
+               if (entries[i].vlan > -1)
+                       printf(" vlan %d", entries[i].vlan);
+               if (entries[i].active)
+                       printf(" active");
+               putchar('\n');
+       }
+
+       free(entries);
+}
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index bfaf6cd69e58..439b93f0b80a 100644
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -122,6 +122,7 @@ static uint64_t      ixl_if_get_counter(if_ctx_t ctx, 
ift_counter cnt);
 static int      ixl_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req);
 static int      ixl_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data);
 static bool     ixl_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event 
event);
+static int      ixl_if_vfstat_ioctl(if_ctx_t ctx, struct ifvfstatus *ifvfs);
 #ifdef PCI_IOV
 static void     ixl_if_vflr_handle(if_ctx_t ctx);
 #endif
@@ -193,6 +194,7 @@ static device_method_t ixl_if_methods[] = {
        DEVMETHOD(ifdi_i2c_req, ixl_if_i2c_req),
        DEVMETHOD(ifdi_priv_ioctl, ixl_if_priv_ioctl),
        DEVMETHOD(ifdi_needs_restart, ixl_if_needs_restart),
+       DEVMETHOD(ifdi_vfstat_ioctl, ixl_if_vfstat_ioctl),
 #ifdef PCI_IOV
        DEVMETHOD(ifdi_iov_init, ixl_if_iov_init),
        DEVMETHOD(ifdi_iov_uninit, ixl_if_iov_uninit),
@@ -1908,6 +1910,38 @@ ixl_if_needs_restart(if_ctx_t ctx __unused, enum 
iflib_restart_event event)
        }
 }
 
+static int
+ixl_if_vfstat_ioctl(if_ctx_t ctx, struct ifvfstatus *ifvfs)
+{
+       struct ixl_pf *pf;
+       struct ifvfstatus_entry ent;
+       struct ixl_vf *vf;
+       int error;
+
+       pf = iflib_get_softc(ctx);
+       if (pf->num_vfs < 1)
+               return (ENXIO);
+       if (ifvfs->ifvfs_count == 0) {
+               ifvfs->ifvfs_count = pf->num_vfs;
+               return (0);
+       }
+       if (ifvfs->ifvfs_count != pf->num_vfs)
+               return (EINVAL);
+
+       for (int i = 0; i < pf->num_vfs; i++) {
+               vf = &pf->vfs[i];
+               memset(&ent, 0, sizeof(ent));
+               ent.active = !!(vf->vf_flags & VF_FLAG_ENABLED);
+               memcpy(ent.mac_addr, vf->mac, sizeof(ent.mac_addr));
+               /* No host VLAN support. */
+               ent.vlan = -1;
+               error = copyout(&ent, &ifvfs->ifvfs_list[i], sizeof(ent));
+               if (error != 0)
+                       return (error);
+       }
+       return (0);
+}
+
 /*
  * Sanity check and save off tunable values.
  */
@@ -1976,4 +2010,3 @@ ixl_save_pf_tunables(struct ixl_pf *pf)
                        pf->fc = ixl_flow_control;
        }
 }
-
diff --git a/sys/net/if.h b/sys/net/if.h
index 4bb6a2659ce7..c5b7768f033d 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -662,6 +662,21 @@ struct ifdownreason {
        char            ifdr_msg[IFDR_MSG_SIZE];
 };
 
+struct ifvfstatus_entry {
+       uint8_t         mac_addr[6];
+       int16_t         vlan;
+       uint8_t         active;
+       uint8_t         spare0;
+       uint16_t        spare1;
+       uint32_t        spare2;
+};
+
+struct ifvfstatus {
+       char            ifvfs_name[IFNAMSIZ];
+       int             ifvfs_count;
+       struct ifvfstatus_entry *ifvfs_list;
+};
+
 #endif /* __BSD_VISIBLE */
 
 /*
diff --git a/sys/net/ifdi_if.m b/sys/net/ifdi_if.m
index cb24ba36ee60..65a130d64ee4 100644
--- a/sys/net/ifdi_if.m
+++ b/sys/net/ifdi_if.m
@@ -112,6 +112,13 @@ CODE {
                return (ENOTSUP);
        }
 
+       static int
+       null_vfstat_ioctl(if_ctx_t _ctx __unused,
+           struct ifvfstatus *_ifvfs __unused)
+       {
+               return (ENOTSUP);
+       }
+
        static bool
        null_needs_restart(if_ctx_t _ctx __unused, enum iflib_restart_event 
_event __unused)
        {
@@ -375,3 +382,8 @@ METHOD int get_downreason {
        if_ctx_t _ctx;
        struct ifdownreason *_ifdr;
 } DEFAULT null_get_downreason;
+
+METHOD int vfstat_ioctl {
+       if_ctx_t _ctx;
+       struct ifvfstatus *_ifvfs;
+} DEFAULT null_vfstat_ioctl;
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index c56f15cc00bc..314e8e527628 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -4657,6 +4657,18 @@ iflib_if_ioctl(if_t ifp, u_long command, caddr_t data)
                err = IFDI_GET_DOWNREASON(ctx, (struct ifdownreason *)data);
                CTX_UNLOCK(ctx);
                break;
+       case SIOCGIFVFSTATUS:
+       {
+               struct ifvfstatus *ifvfs;
+
+               ifvfs = (struct ifvfstatus *)data;
+               if (ifvfs->ifvfs_count < 0)
+                       return (EINVAL);
+               CTX_LOCK(ctx);
+               err = IFDI_VFSTAT_IOCTL(ctx, ifvfs);
+               CTX_UNLOCK(ctx);
+               break;
+       }
        default:
                err = ether_ioctl(ifp, command, data);
                break;
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
index 121acd5ba287..a3ce196c7959 100644
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -152,4 +152,6 @@
 #define        SIOCSUMBPARAM    _IOW('i', 158, struct ifreq)   /* set MBIM 
param */
 #define        SIOCGUMBPARAM   _IOWR('i', 159, struct ifreq)   /* get MBIM 
param */
 
+#define        SIOCGIFVFSTATUS _IOWR('i', 163, struct ifvfstatus) /* get VF 
status */
+
 #endif /* !_SYS_SOCKIO_H_ */

Reply via email to