Index: sbin/ifconfig/Makefile =================================================================== --- sbin/ifconfig/Makefile +++ sbin/ifconfig/Makefile @@ -37,6 +37,7 @@ SRCS+= ifipsec.c # IPsec VTI SRCS+= sfp.c # SFP/SFP+ information +SRCS+= ifvfstatus.c # VF status information LIBADD+= m .if ${MK_WIRELESS_SUPPORT} != "no" Index: sbin/ifconfig/ifconfig.h =================================================================== --- sbin/ifconfig/ifconfig.h +++ sbin/ifconfig/ifconfig.h @@ -150,6 +150,8 @@ void sfp_status(int s, struct ifreq *ifr, int verbose); +void vf_status(int s); + /* * XXX expose this so modules that neeed to know of any pending * operations on ifmedia can avoid cmd line ordering confusion. Index: sbin/ifconfig/ifconfig.c =================================================================== --- sbin/ifconfig/ifconfig.c +++ sbin/ifconfig/ifconfig.c @@ -96,6 +96,7 @@ int verbose; int noload; int printifname = 0; +int vfstatus = 0; int supmedia = 0; int printkeys = 0; /* Print keying material for interfaces. */ @@ -387,7 +388,7 @@ atexit(printifnamemaybe); /* Parse leading line options */ - strlcpy(options, "f:adklmnuv", sizeof(options)); + strlcpy(options, "f:adklmnsuv", sizeof(options)); for (p = opts; p != NULL; p = p->next) strlcat(options, p->opt, sizeof(options)); while ((c = getopt(argc, argv, options)) != -1) { @@ -415,6 +416,9 @@ case 'n': /* suppress module loading */ noload++; break; + case 's': /* print vf status, if any */ + vfstatus++; + break; case 'u': /* restrict scan to "up" interfaces */ uponly++; break; @@ -1328,9 +1332,12 @@ afp->af_other_status(s); strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name); - if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) + if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) printf("%s", ifs.ascii); + if (vfstatus) + vf_status(s); + if (verbose > 0) sfp_status(s, &ifr, verbose); Index: sbin/ifconfig/ifvfstatus.c =================================================================== --- /dev/null +++ sbin/ifconfig/ifvfstatus.c @@ -0,0 +1,94 @@ +/****************************************************************************** + + 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. + + 3. Neither the name of the Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + 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. + +******************************************************************************/ +/*$FreeBSD$*/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include "ifconfig.h" + +void +vf_status(int s) +{ + struct ifvfstatus ifvfs; + struct ifvfstatus_entry *entries; + + (void)memset(&ifvfs, 0, sizeof(ifvfs)); + (void)strlcpy(ifvfs.ifvfs_name, name, sizeof(ifvfs.ifvfs_name)); + + if (ioctl(s, SIOCGIFVFSTATUS, (caddr_t)&ifvfs) < 0) + return; + + if (ifvfs.ifvfs_count == 0) { + warnx("%s: No Virtual Functions?", name); + return; + } + + entries = (struct ifvfstatus_entry *)malloc( + ifvfs.ifvfs_count * sizeof(struct ifvfstatus_entry)); + if (entries == NULL) + err(1, "malloc"); + + ifvfs.ifvfs_list = entries; + + if (ioctl(s, SIOCGIFVFSTATUS, (caddr_t)&ifvfs) < 0) { + free(entries); + warn("SIOCGIFVFSTATUS error"); + } + + printf("\tvirtual functions: %d\n", ifvfs.ifvfs_count); + for (int i = 0; i < ifvfs.ifvfs_count; i++) { + printf("\t\tvf %3d:", i); + printf(" mac %s", + ether_ntoa((struct ether_addr *)entries[i].mac_addr); + if (entries[i].vlan > -1) + printf(" vlan %d\n", entries[i].vlan); + if (entries[i].active) + printf(" active"); + printf("\n"); + } + + free(entries); +} Index: sys/dev/ixl/if_ixl.c =================================================================== --- sys/dev/ixl/if_ixl.c +++ sys/dev/ixl/if_ixl.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2013-2018, Intel Corporation + Copyright (c) 2013-2019, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -117,6 +117,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 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 @@ DEVMETHOD(ifdi_iov_vf_add, ixl_if_iov_vf_add), DEVMETHOD(ifdi_vflr_handle, ixl_if_vflr_handle), #endif + DEVMETHOD(ifdi_vfstat_ioctl, ixl_if_vfstat_ioctl), // ifdi_led_func // ifdi_debug DEVMETHOD_END @@ -1634,6 +1636,41 @@ return (error); } +static int +ixl_if_vfstat_ioctl(if_ctx_t ctx, struct ifvfstatus *ifvfs) +{ + struct ixl_pf *pf = iflib_get_softc(ctx); + struct ifvfstatus_entry ent; + struct ixl_vf *vf; + + 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) { + device_printf(pf->dev, "%s: Invalid count: ioctl=%d vs driver=%d\n", + __func__, ifvfs->ifvfs_count, pf->num_vfs); + return (EINVAL); + } + + for (int i = 0; i < pf->num_vfs; i++) { + vf = &pf->vfs[i]; + + ent.active = !!(vf->vf_flags & VF_FLAG_ENABLED); + memcpy(ent.mac_addr, vf->mac, sizeof(ent.mac_addr)); + /* No host VLAN support, yet */ + ent.vlan = 0; + + copyout(&ent, &ifvfs->ifvfs_list[i], sizeof(ent)); + } + + return (0); +} + static int ixl_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count __unused) { @@ -1641,7 +1678,7 @@ if (ifma->ifma_addr->sa_family != AF_LINK) return (0); - ixl_add_mc_filter(vsi, + ixl_add_mc_filter(vsi, (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr)); return (1); } Index: sys/dev/ixl/ixl_pf.h =================================================================== --- sys/dev/ixl/ixl_pf.h +++ sys/dev/ixl/ixl_pf.h @@ -44,6 +44,7 @@ #define VF_FLAG_VLAN_CAP 0x04 #define VF_FLAG_PROMISC_CAP 0x08 #define VF_FLAG_MAC_ANTI_SPOOF 0x10 +#define VF_FLAG_PASSTHROUGH 0x20 #define IXL_ICR0_CRIT_ERR_MASK \ (I40E_PFINT_ICR0_PCI_EXCEPTION_MASK | \ Index: sys/net/if.h =================================================================== --- sys/net/if.h +++ sys/net/if.h @@ -541,7 +541,7 @@ uint8_t spare0; uint32_t spare1; uint8_t data[8]; /* read buffer */ -}; +}; /* * RSS hash. @@ -581,6 +581,24 @@ #define IFNET_PCP_NONE 0xff /* PCP disabled */ +/* + * Structures used to request VF status data from an interface + */ +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 */ #ifdef _KERNEL Index: sys/net/ifdi_if.m =================================================================== --- sys/net/ifdi_if.m +++ sys/net/ifdi_if.m @@ -133,6 +133,12 @@ return (ENOTSUP); } + static int + null_vfstat_ioctl(if_ctx_t _ctx __unused, struct ifvfstatus *_ifvfs __unused) + { + return (ENOTSUP); + } + static void null_media_status(if_ctx_t ctx __unused, struct ifmediareq *ifmr) { @@ -453,6 +459,11 @@ if_int_delay_info_t _iidi; } DEFAULT null_sysctl_int_delay; +METHOD int vfstat_ioctl { + if_ctx_t _ctx; + struct ifvfstatus *_ifvfs; +} DEFAULT null_vfstat_ioctl; + METHOD void debug { if_ctx_t _ctx; } DEFAULT null_void_op; Index: sys/net/iflib.c =================================================================== --- sys/net/iflib.c +++ sys/net/iflib.c @@ -4217,6 +4217,18 @@ err = IFDI_PRIV_IOCTL(ctx, command, data); CTX_UNLOCK(ctx); break; + case SIOCGIFVFSTATUS: + { + struct ifvfstatus *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; Index: sys/sys/sockio.h =================================================================== --- sys/sys/sockio.h +++ sys/sys/sockio.h @@ -143,4 +143,6 @@ #define SIOCGLANPCP _IOWR('i', 152, struct ifreq) /* Get (V)LAN PCP */ #define SIOCSLANPCP _IOW('i', 153, struct ifreq) /* Set (V)LAN PCP */ +#define SIOCGIFVFSTATUS _IOWR('i', 154, struct ifvfstatus) /* Get VF status */ + #endif /* !_SYS_SOCKIO_H_ */