diff options
| -rw-r--r-- | sbin/ifconfig/Makefile | 1 | ||||
| -rw-r--r-- | sbin/ifconfig/ifconfig.8 | 68 | ||||
| -rw-r--r-- | sbin/ifconfig/ifconfig.h | 3 | ||||
| -rw-r--r-- | sbin/ifconfig/ifconfig_netlink.c | 8 | ||||
| -rw-r--r-- | sbin/ifconfig/ifvfstatus.c | 300 | ||||
| -rw-r--r-- | usr.sbin/iovctl/iovctl.8 | 10 | ||||
| -rw-r--r-- | usr.sbin/iovctl/iovctl.conf.5 | 10 |
7 files changed, 395 insertions, 5 deletions
diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile index 2553e61b5e9e..ba1c30df79cf 100644 --- a/sbin/ifconfig/Makefile +++ b/sbin/ifconfig/Makefile @@ -70,6 +70,7 @@ LIBADD+= nv .if ${MK_NETLINK_SUPPORT} != "no" SRCS+= ifconfig_netlink.c +SRCS+= ifvfstatus.c # VF status information .else CFLAGS+=-DWITHOUT_NETLINK .endif diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index f062ddec774d..d8f20b93d0bb 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 12, 2025 +.Dd September 6, 2026 .Dt IFCONFIG 8 .Os .Sh NAME @@ -325,6 +325,72 @@ will attempt to load it. Display only the interfaces that are up. .It Fl v Get more verbose status for an interface. +When supported, this includes the status of configured SR-IOV virtual +functions. +Fields that the PF driver cannot observe are omitted; an omitted field does +not mean false or zero. +The status begins with the PF link state and speed normally advertised to +VFs, followed by the number of VFs and one record for each VF. +PF link status does not demonstrate that a VF driver is operational. +.Pp +Per-VF fields are arranged in the following groups: +.Bl -tag -width "driver.*" +.It Cm identity +The primary MAC address known to the PF. +.It Cm state +.Cm configured=yes +means that the PF accepted the VF configuration. +.Cm initialized=yes +means that the VF completed its driver or mailbox handshake since its last +reset. +When available, this group also reports whether the PF permits traffic, +whether fault containment blocked the VF, and whether it is quarantined. +Traffic permission does not imply that the VF has enabled queues, has link, +or is actively passing packets. +.It Cm resources +The numbers of transmit and receive queues allocated to the VF. +These are not necessarily the numbers of queues currently used by its driver. +When available, configured minimum and maximum aggregate transmit rates are +also shown. +A zero minimum is displayed as +.Cm min-tx-rate=none +(no guaranteed allocation), while a zero maximum is displayed as +.Cm max-tx-rate=unlimited . +.It Cm vlan +An access VLAN is imposed by the PF; trunk mode means that no access VLAN is +imposed and does not promise unlimited filter capacity. +Access mode may also report the priority code point and VLAN protocol. +The VLAN identifier can be zero when the PF imposes priority tagging only. +The filter count includes explicit filters recorded by the PF and excludes +implicit untagged and priority-tag membership. +.It Cm policy +Administrative permissions for VF requests, MAC anti-spoofing state, and an +optional per-VF link-state policy. +Permissions describe what the VF may request, not its current requests. +.It Cm protocol +The negotiated PF/VF mailbox API version, when known. +.It Cm driver.* +Driver-specific extension namespaces. +The namespace version and scalar boolean, numeric, string, and binary fields +are displayed using their stable schema names. +See the PF driver's manual page for their meanings. +.El +.Pp +For example: +.Bd -literal -offset indent +VF-visible PF link: state=up speed=10000Mbps +virtual functions: 1 + vf 0: + identity: mac=02:00:00:00:00:01 + state: configured=yes initialized=yes traffic=allowed + resources: tx-queues=4 rx-queues=4 + vlan: mode=trunk filters=0 + policy: set-mac=denied set-vlan=allowed anti-spoof=on +.Ed +.Pp +See +.Xr iovctl.conf 5 +for VF configuration. .It Ar address For the inet family, the address is either a host name present in the host name data diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h index 672020443b8c..45e5b108accb 100644 --- a/sbin/ifconfig/ifconfig.h +++ b/sbin/ifconfig/ifconfig.h @@ -281,6 +281,9 @@ 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); +#ifndef WITHOUT_NETLINK +void vf_status(if_ctx *); +#endif 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 457aa9227bdb..458735b17d87 100644 --- a/sbin/ifconfig/ifconfig_netlink.c +++ b/sbin/ifconfig/ifconfig_netlink.c @@ -150,8 +150,8 @@ prepare_ifmap(struct snl_state *ss, const char *ifname) struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK); hdr->nlmsg_flags |= NLM_F_DUMP; snl_reserve_msg_object(&nw, struct ifinfomsg); - if (ifname != NULL) - snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname); + if (ifname != NULL) + snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname); if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr)) return (NULL); @@ -450,6 +450,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) { @@ -493,7 +495,7 @@ list_interfaces_nl(struct ifconfig_args *args) nl_init_socket(&ss); - struct ifmap *ifmap = prepare_ifmap(&ss, args->ifname); + struct ifmap *ifmap = prepare_ifmap(&ss, args->ifname); struct iface **sorted_ifaces = snl_allocz(&ss, ifmap->count * sizeof(void *)); for (uint32_t i = 0, num = 0; i < ifmap->size; i++) { if (ifmap->ifaces[i] != NULL) { diff --git a/sbin/ifconfig/ifvfstatus.c b/sbin/ifconfig/ifvfstatus.c new file mode 100644 index 000000000000..82cf0c5400d7 --- /dev/null +++ b/sbin/ifconfig/ifvfstatus.c @@ -0,0 +1,300 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Intel Corporation + * Copyright (c) 2026 Kevin Bowling <kbowling@FreeBSD.org> + */ + +#include <sys/types.h> + +#include <net/ethernet.h> +#include <net/if.h> + +#include <err.h> +#include <errno.h> +#include <inttypes.h> +#include <stdio.h> + +#include "ifconfig.h" + +static void +vf_group_begin(bool *printed, const char *name) +{ + + if (!*printed) { + printf("\t\t\t%s:", name); + *printed = true; + } +} + +static void +vf_group_end(bool printed) +{ + + if (printed) + putchar('\n'); +} + +static void +vf_print_rate(const char *name, uint64_t rate, const char *zero) +{ + + if (rate == 0) + printf(" %s=%s", name, zero); + else if (rate % IF_Mbps(1) == 0) + printf(" %s=%" PRIu64 "Mbps", name, rate / IF_Mbps(1)); + else + printf(" %s=%" PRIu64 "bps", name, rate); +} + +static const char * +vf_link_state_name(enum ifconfig_vf_link_state state) +{ + + switch (state) { + case IFCONFIG_VF_LINK_DOWN: + return ("down"); + case IFCONFIG_VF_LINK_UP: + return ("up"); + case IFCONFIG_VF_LINK_AUTO: + return ("auto"); + default: + return ("unknown"); + } +} + +static const char * +vf_vlan_mode_name(enum ifconfig_vf_vlan_mode mode) +{ + + switch (mode) { + case IFCONFIG_VF_VLAN_ACCESS: + return ("access"); + case IFCONFIG_VF_VLAN_TRUNK: + return ("trunk"); + default: + return ("unknown"); + } +} + +static void +vf_print_vlan_proto(uint16_t proto) +{ + + switch (proto) { + case ETHERTYPE_VLAN: + printf("802.1q"); + break; + case ETHERTYPE_QINQ: + printf("802.1ad"); + break; + default: + printf("0x%04x", proto); + break; + } +} + +static void +vf_driver_field(const struct ifconfig_vf_extension_field *field) +{ + const uint8_t *data; + size_t i, length; + + printf(" %s=", field->name); + switch (field->type) { + case IFCONFIG_VF_EXT_BOOL: + printf("%s", field->value.boolean ? "yes" : "no"); + break; + case IFCONFIG_VF_EXT_NUMBER: + printf("%" PRIu64, field->value.number); + break; + case IFCONFIG_VF_EXT_STRING: + printf("%s", field->value.string); + break; + case IFCONFIG_VF_EXT_BINARY: + data = field->value.binary.data; + length = field->value.binary.length; + printf("0x"); + for (i = 0; i < length; i++) + printf("%02x", data[i]); + break; + default: + break; + } +} + +static void +vf_driver_status(const struct ifconfig_vf_info *vf) +{ + const struct ifconfig_vf_extension *driver; + const struct ifconfig_vf_extension_field *field; + size_t i, j; + + for (i = 0; i < vf->num_extensions; i++) { + driver = &vf->extensions[i]; + printf("\t\t\t%s: version=%u", driver->name, + driver->version); + for (j = 0; j < driver->num_fields; j++) { + field = &driver->fields[j]; + vf_driver_field(field); + } + putchar('\n'); + } +} + +void +vf_status(if_ctx *ctx) +{ + struct ifconfig_vf_status *status; + const struct ifconfig_vf_info *vf; + const struct ether_addr *mac; + const char *mode; + uint64_t speed; + bool printed; + size_t i; + int error; + + if (ifconfig_get_vf_status(lifh, ctx->ifname, &status) != 0) { + error = ifconfig_err_errno(lifh); + if (error != EOPNOTSUPP) + warnc(error, "%s: VF status", ctx->ifname); + return; + } + + if (status->pf_link_state_present) { + printf("\tVF-visible PF link: state=%s", + vf_link_state_name(status->pf_link_state)); + } + speed = status->pf_link_speed; + if (status->pf_link_speed_present) { + if (speed % IF_Mbps(1) == 0) + printf(" speed=%" PRIu64 "Mbps", speed / IF_Mbps(1)); + else + printf(" speed=%" PRIu64 "bps", speed); + } + if (status->pf_link_state_present || status->pf_link_speed_present) + putchar('\n'); + + printf("\tvirtual functions: %zu\n", status->num_vfs); + for (i = 0; i < status->num_vfs; i++) { + vf = status->vfs[i]; + printf("\t\tvf %3u:\n", vf->index); + + printed = false; + if ((vf->fields & (1ULL << IFLAF_VF_MAC)) != 0) { + mac = (const struct ether_addr *)(const void *)vf->mac; + vf_group_begin(&printed, "identity"); + printf(" mac=%s", ether_ntoa(mac)); + } + vf_group_end(printed); + + printed = false; + if ((vf->fields & (1ULL << IFLAF_VF_CONFIGURED)) != 0) { + vf_group_begin(&printed, "state"); + printf(" configured=%s", vf->configured ? "yes" : "no"); + } + if ((vf->fields & (1ULL << IFLAF_VF_INITIALIZED)) != 0) { + vf_group_begin(&printed, "state"); + printf(" initialized=%s", vf->initialized ? "yes" : "no"); + } + if ((vf->fields & (1ULL << IFLAF_VF_TRAFFIC_ALLOWED)) != 0) { + vf_group_begin(&printed, "state"); + printf(" traffic=%s", vf->traffic_allowed ? + "allowed" : "denied"); + } + if ((vf->fields & (1ULL << IFLAF_VF_FAULT_BLOCKED)) != 0) { + vf_group_begin(&printed, "state"); + printf(" fault-blocked=%s", vf->fault_blocked ? + "yes" : "no"); + } + if ((vf->fields & (1ULL << IFLAF_VF_QUARANTINED)) != 0) { + vf_group_begin(&printed, "state"); + printf(" quarantined=%s", vf->quarantined ? "yes" : "no"); + } + vf_group_end(printed); + + printed = false; + if ((vf->fields & (1ULL << IFLAF_VF_NUM_TX_QUEUES)) != 0) { + vf_group_begin(&printed, "resources"); + printf(" tx-queues=%u", vf->tx_queue_count); + } + if ((vf->fields & (1ULL << IFLAF_VF_NUM_RX_QUEUES)) != 0) { + vf_group_begin(&printed, "resources"); + printf(" rx-queues=%u", vf->rx_queue_count); + } + if ((vf->fields & (1ULL << IFLAF_VF_MIN_TX_RATE)) != 0) { + vf_group_begin(&printed, "resources"); + vf_print_rate("min-tx-rate", vf->min_tx_rate_bps, "none"); + } + if ((vf->fields & (1ULL << IFLAF_VF_MAX_TX_RATE)) != 0) { + vf_group_begin(&printed, "resources"); + vf_print_rate("max-tx-rate", vf->max_tx_rate_bps, + "unlimited"); + } + vf_group_end(printed); + + printed = false; + if ((vf->fields & (1ULL << IFLAF_VF_VLAN_MODE)) != 0) { + mode = vf_vlan_mode_name(vf->vlan_mode); + vf_group_begin(&printed, "vlan"); + printf(" mode=%s", mode); + if (vf->vlan_mode == IFCONFIG_VF_VLAN_ACCESS && + (vf->fields & (1ULL << IFLAF_VF_VLAN)) != 0) + printf(" vid=%u", vf->vlan); + if (vf->vlan_mode == IFCONFIG_VF_VLAN_ACCESS && + (vf->fields & (1ULL << IFLAF_VF_VLAN_PCP)) != 0) + printf(" pcp=%u", vf->vlan_pcp); + if (vf->vlan_mode == IFCONFIG_VF_VLAN_ACCESS && + (vf->fields & (1ULL << IFLAF_VF_VLAN_PROTO)) != 0) { + printf(" proto="); + vf_print_vlan_proto(vf->vlan_proto); + } + } + if ((vf->fields & (1ULL << IFLAF_VF_VLAN_COUNT)) != 0) { + vf_group_begin(&printed, "vlan"); + printf(" filters=%u", vf->vlan_count); + } + if ((vf->fields & (1ULL << IFLAF_VF_VLAN_LIMIT)) != 0) { + vf_group_begin(&printed, "vlan"); + printf(" limit=%u", vf->vlan_limit); + } + vf_group_end(printed); + + printed = false; + if ((vf->fields & (1ULL << IFLAF_VF_ALLOW_SET_MAC)) != 0) { + vf_group_begin(&printed, "policy"); + printf(" set-mac=%s", vf->allow_set_mac ? + "allowed" : "denied"); + } + if ((vf->fields & (1ULL << IFLAF_VF_ALLOW_SET_VLAN)) != 0) { + vf_group_begin(&printed, "policy"); + printf(" set-vlan=%s", vf->allow_set_vlan ? + "allowed" : "denied"); + } + if ((vf->fields & (1ULL << IFLAF_VF_MAC_ANTI_SPOOF)) != 0) { + vf_group_begin(&printed, "policy"); + printf(" anti-spoof=%s", vf->mac_anti_spoof ? "on" : "off"); + } + if ((vf->fields & (1ULL << IFLAF_VF_ALLOW_PROMISC)) != 0) { + vf_group_begin(&printed, "policy"); + printf(" promisc=%s", vf->allow_promisc ? + "allowed" : "denied"); + } + if ((vf->fields & (1ULL << IFLAF_VF_LINK_STATE_POLICY)) != 0) { + vf_group_begin(&printed, "policy"); + printf(" link-state=%s", + vf_link_state_name(vf->link_state_policy)); + } + vf_group_end(printed); + + printed = false; + if ((vf->fields & (1ULL << IFLAF_VF_API_VERSION)) != 0) { + vf_group_begin(&printed, "protocol"); + printf(" api=%s", vf->api_version); + } + vf_group_end(printed); + + vf_driver_status(vf); + } + ifconfig_free_vf_status(status); +} diff --git a/usr.sbin/iovctl/iovctl.8 b/usr.sbin/iovctl/iovctl.8 index 2574503e5ae7..2c8523dbc1af 100644 --- a/usr.sbin/iovctl/iovctl.8 +++ b/usr.sbin/iovctl/iovctl.8 @@ -113,9 +113,17 @@ to stdout. This action may be used to discover the configuration parameters supported on a given PF device. .El +.Pp +For network devices, use +.Xr ifconfig 8 +with the +.Fl v +option on the PF interface to display NIC-specific VF initialization, +resource, and policy state. .Sh SEE ALSO .Xr iovctl.conf 5 , -.Xr rc.conf 5 +.Xr rc.conf 5 , +.Xr ifconfig 8 .Sh AUTHORS This manual page was written by .An Ryan Stone Aq Mt rstone@FreeBSD.org . diff --git a/usr.sbin/iovctl/iovctl.conf.5 b/usr.sbin/iovctl/iovctl.conf.5 index 1bae96e150ba..36eed68903c7 100644 --- a/usr.sbin/iovctl/iovctl.conf.5 +++ b/usr.sbin/iovctl/iovctl.conf.5 @@ -140,6 +140,15 @@ The default value of this parameter is false. .Pp See the PF driver manual page for configuration parameters specific to particular hardware. +.Pp +For network devices, display NIC-specific initialization, resources, and +policy state with: +.Bd -literal -offset indent +ifconfig -v ix0 +.Ed +See +.Xr ifconfig 8 +for the meaning of the reported fields. .Sh EXAMPLES This sample file will create 3 VFs as children of the ix0 device. VF-1 and VF-2 are set as @@ -166,6 +175,7 @@ VF-0 { .Ed .Sh SEE ALSO .Xr rc.conf 5 , +.Xr ifconfig 8 , .Xr iovctl 8 .Sh AUTHORS This manual page was written by |
