git: 1ccf543b21ef - main - ifconfig: Add SR-IOV VF status output

Kevin Bowling <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.current.scm
Message-ID <[email protected]>
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_ */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.