Re: git: d15f2551b25f - main - rtnetlink: Report SR-IOV VF status
Pouria Mousavizadeh Tehrani <[email protected]>
| Newsgroups | gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.current.scm |
|---|---|
| Message-ID | <[email protected]> |
On 8/10/26 22:56, Kevin Bowling wrote: > On Mon, Aug 10, 2026 at 12:18 PM Pouria Mousavizadeh Tehrani > <[email protected]> wrote: >> >> Hi >> >> On 8/9/26 10:17, Kevin Bowling wrote: >>> The branch main has been updated by kbowling: >>> >>> URL: https://cgit.FreeBSD.org/src/commit/?id=d15f2551b25f79ddcbe289faa95e655100b952da >>> >>> commit d15f2551b25f79ddcbe289faa95e655100b952da >>> Author: Kevin Bowling <[email protected]> >>> AuthorDate: 2026-08-09 02:04:11 +0000 >>> Commit: Kevin Bowling <[email protected]> >>> CommitDate: 2026-08-09 06:46:57 +0000 >>> >>> rtnetlink: Report SR-IOV VF status >>> >>> Honor RTEXT_FILTER_VF on RTM_GETLINK requests and expose the versioned >>> SR-IOV VF status through typed nested FreeBSD attributes. Report >>> IFLA_NUM_VF with a successful requested query and preserve per-provider >>> errors in the status container. >>> >>> Map the common nvlist schema to native integer, boolean, string, and >>> binary attributes. Carry namespaced driver extensions as packed >>> versioned nvlists so adding a driver-specific field does not expand the >>> common netlink ABI. >>> >>> Add SNL parsers, parser verification, a constructed nested-status test, >>> and an RTM_GETLINK test for an interface without SR-IOV support. >>> Document the query contract and every attribute. >>> --- >>> share/man/man4/rtnetlink.4 | 118 ++++++++++- >>> sys/netlink/netlink_snl_route_parsers.h | 112 ++++++++++ >>> sys/netlink/route/iface.c | 284 +++++++++++++++++++++++++- >>> sys/netlink/route/interface.h | 82 +++++++- >>> sys/netlink/route/route_var.h | 1 + >>> tests/atf_python/sys/netlink/attrs.py | 28 +++ >>> tests/atf_python/sys/netlink/netlink_route.py | 117 +++++++++++ >>> tests/sys/netlink/test_rtnl_iface.py | 13 +- >>> tests/sys/netlink/test_snl.c | 89 ++++++++ >>> 9 files changed, 835 insertions(+), 9 deletions(-) >>> >>> diff --git a/share/man/man4/rtnetlink.4 b/share/man/man4/rtnetlink.4 >>> index 3d76c66c1917..5d5e69cdbbf0 100644 >>> --- a/share/man/man4/rtnetlink.4 >>> +++ b/share/man/man4/rtnetlink.4 >>> @@ -22,7 +22,7 @@ >>> .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >>> .\" SUCH DAMAGE. >>> .\" >>> -.Dd July 28, 2026 >>> +.Dd August 8, 2026 >>> .Dt RTNETLINK 4 >>> .Os >>> .Sh NAME >>> @@ -325,7 +325,17 @@ The following filters are recognised by the kernel: >>> ifi_index interface index >>> IFLA_IFNAME interface name >>> IFLA_ALT_IFNAME interface name >>> +IFLA_EXT_MASK extended information selection bitmap >>> .Ed >>> +.Pp >>> +Setting the >>> +.Dv RTEXT_FILTER_VF >>> +bit in >>> +.Dv IFLA_EXT_MASK >>> +requests SR-IOV VF status. >>> +The query is opt-in because obtaining status can require entering the PF >>> +driver. >>> +VF status is not included in unsolicited link notifications. >>> .Ss TLVs >>> .Bl -tag -width indent >>> .It Dv IFLA_ADDRESS >>> @@ -340,6 +350,112 @@ IFLA_ALT_IFNAME interface name >>> (uint32_t) (readonly) Interface index. >>> .It Dv IFLA_MASTER >>> (uint32_t) Parent interface index. >>> +.It Dv IFLA_NUM_VF >>> +(uint32_t) (readonly) Number of active VFs. >>> +This attribute is returned with a successful >>> +.Dv RTEXT_FILTER_VF >>> +query. >>> +.It Dv IFLA_FREEBSD >>> +(nested) Local interface attributes. >>> +When requested, >>> +.Dv IFLAF_VF_STATUS >>> +contains the following nested attributes: >>> +.Bd -literal -offset indent -compact >>> +IFLAF_VFS_VERSION (uint32_t) VF status schema version >>> +IFLAF_VFS_ERROR (uint32_t) errno if the PF query failed >>> +IFLAF_VFS_PF_LINK_STATE (uint8_t) IFLAF_VF_LINK_* >>> +IFLAF_VFS_PF_LINK_SPEED (uint64_t) bits per second >>> +IFLAF_VFS_LIST (nested) repeated IFLAF_VF_LIST_ENTRY >>> +.Ed >>> +.Pp >>> +On a successful query, >>> +.Dv IFLAF_VFS_VERSION >>> +and >>> +.Dv IFLAF_VFS_LIST >>> +are present. >>> +If the PF status query fails, >>> +.Dv IFLAF_VFS_ERROR >>> +contains the errno value and the other status attributes are omitted. >>> +.Pp >>> +Each >>> +.Dv IFLAF_VF_LIST_ENTRY >>> +may contain the following attributes: >>> +.Bd -literal -offset indent -compact >>> +IFLAF_VF_INDEX (uint32_t) PF-local VF index >>> +IFLAF_VF_CONFIGURED (uint8_t) PF accepted configuration >>> +IFLAF_VF_INITIALIZED (uint8_t) VF handshake completed >>> +IFLAF_VF_MAC (binary) PF-known primary MAC address >>> +IFLAF_VF_VLAN_MODE (uint8_t) IFLAF_VF_VLAN_* >>> +IFLAF_VF_VLAN (uint16_t) access VLAN identifier >>> +IFLAF_VF_VLAN_COUNT (uint32_t) explicit VLAN filters >>> +IFLAF_VF_VLAN_LIMIT (uint32_t) explicit VLAN-filter limit >>> +IFLAF_VF_NUM_QUEUES (uint32_t) allocated RX/TX queue pairs >>> +IFLAF_VF_ALLOW_SET_MAC (uint8_t) administrative permission >>> +IFLAF_VF_ALLOW_SET_VLAN (uint8_t) administrative permission >>> +IFLAF_VF_MAC_ANTI_SPOOF (uint8_t) MAC anti-spoofing enabled >>> +IFLAF_VF_ALLOW_PROMISC (uint8_t) administrative permission >>> +IFLAF_VF_TRAFFIC_ENABLED (uint8_t) VF traffic enabled >>> +IFLAF_VF_MDD_BLOCKED (uint8_t) malicious-driver block active >>> +IFLAF_VF_QUARANTINED (uint8_t) persistent quarantine active >>> +IFLAF_VF_API_VERSION (string) negotiated mailbox API >>> +IFLAF_VF_LINK_STATE_POLICY (uint8_t) IFLAF_VF_LINK_* >>> +IFLAF_VF_EXTENSIONS (nested) driver-specific namespaces >>> +.Ed >>> +.Pp >>> +.Dv IFLAF_VF_INDEX >>> +is required in every list entry. >>> +Other fields are optional and are omitted when the PF driver cannot observe >>> +them; omission does not mean false or zero. >>> +Boolean attributes contain zero or one. >>> +.Dv IFLAF_VF_CONFIGURED >>> +means that the PF accepted the VF configuration, while >>> +.Dv IFLAF_VF_INITIALIZED >>> +means that the VF completed its driver or mailbox handshake since its last >>> +reset. >>> +.Pp >>> +.Dv IFLAF_VF_NUM_QUEUES >>> +is the number of allocated symmetric RX/TX queue pairs, not necessarily the >>> +number currently used by the VF driver. >>> +Access VLAN mode means that the PF imposes >>> +.Dv IFLAF_VF_VLAN ; >>> +trunk mode means that no access VLAN is imposed and does not promise unlimited >>> +filter capacity. >>> +.Dv IFLAF_VF_VLAN_COUNT >>> +counts explicit filters recorded by the PF and excludes implicit untagged and >>> +priority-tag membership. >>> +The permission attributes describe requests the VF may make, not requests it >>> +has made. >>> +The top-level PF link state and speed are values normally advertised to VFs, >>> +not evidence that a VF driver is operational. >>> +.Pp >>> +Link-state values are: >>> +.Bd -literal -offset indent -compact >>> +IFLAF_VF_LINK_UNKNOWN state is unavailable >>> +IFLAF_VF_LINK_DOWN link is forced or observed down >>> +IFLAF_VF_LINK_UP link is forced or observed up >>> +IFLAF_VF_LINK_AUTO VF follows PF link state >>> +.Ed >>> +.Pp >>> +VLAN-mode values are: >>> +.Bd -literal -offset indent -compact >>> +IFLAF_VF_VLAN_UNKNOWN mode is unavailable >>> +IFLAF_VF_VLAN_ACCESS PF imposes an access VLAN >>> +IFLAF_VF_VLAN_TRUNK no access VLAN is imposed >>> +.Ed >>> +.Pp >>> +Driver-specific data is returned under >>> +.Dv IFLAF_VF_EXTENSIONS >>> +as repeated >>> +.Dv IFLAF_VF_EXT_LIST_ENTRY >>> +objects. >>> +Each object contains a stable namespace string in >>> +.Dv IFLAF_VF_EXT_NAME >>> +and its packed, versioned >>> +.Xr nvlist 9 >>> +in >>> +.Dv IFLAF_VF_EXT_DATA . >>> +Each namespace contains a version number. >>> +Consumers must ignore unknown namespaces and fields. >>> .It Dv IFLA_LINKINFO >>> (nested) Interface type-specific attributes: >>> .Bd -literal -offset indent -compact >>> diff --git a/sys/netlink/netlink_snl_route_parsers.h b/sys/netlink/netlink_snl_route_parsers.h >>> index f0849884ec97..9f699ef528a3 100644 >>> --- a/sys/netlink/netlink_snl_route_parsers.h >>> +++ b/sys/netlink/netlink_snl_route_parsers.h >>> @@ -178,6 +178,113 @@ SNL_DECLARE_PARSER_EXT(snl_rtm_route_parser, sizeof(struct rtmsg), >>> _cb_p_route); >>> >>> /* RTM_<NEW|DEL|GET>LINK message parser */ >>> +struct snl_parsed_vf_extension { >>> + char *name; >>> + struct nlattr *data; >>> +}; >>> + >>> +#define _OUT(_field) offsetof(struct snl_parsed_vf_extension, _field) >>> +static const struct snl_attr_parser _nla_p_vf_extension[] = { >>> + { .type = IFLAF_VF_EXT_NAME, .off = _OUT(name), >>> + .cb = snl_attr_dup_string }, >>> + { .type = IFLAF_VF_EXT_DATA, .off = _OUT(data), >>> + .cb = snl_attr_dup_nla }, >>> +}; >>> +#undef _OUT >>> +SNL_DECLARE_ATTR_PARSER_EXT(_vf_extension_parser, >>> + sizeof(struct snl_parsed_vf_extension), _nla_p_vf_extension, NULL); >>> + >>> +struct snl_parsed_vf { >>> + uint32_t index; >>> + uint32_t vlan_count; >>> + uint32_t vlan_limit; >>> + uint32_t num_queues; >>> + uint16_t vlan; >>> + uint8_t configured; >>> + uint8_t initialized; >>> + uint8_t vlan_mode; >>> + uint8_t allow_set_mac; >>> + uint8_t allow_set_vlan; >>> + uint8_t mac_anti_spoof; >>> + uint8_t allow_promisc; >>> + uint8_t traffic_enabled; >>> + uint8_t mdd_blocked; >>> + uint8_t quarantined; >>> + uint8_t link_state_policy; >>> + char *api_version; >>> + struct nlattr *mac; >>> + struct snl_parray extensions; >>> +}; >>> + >>> +#define _OUT(_field) offsetof(struct snl_parsed_vf, _field) >>> +static const struct snl_attr_parser _nla_p_vf[] = { >>> + { .type = IFLAF_VF_INDEX, .off = _OUT(index), >>> + .cb = snl_attr_get_uint32 }, >>> + { .type = IFLAF_VF_CONFIGURED, .off = _OUT(configured), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_INITIALIZED, .off = _OUT(initialized), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_MAC, .off = _OUT(mac), .cb = snl_attr_dup_nla }, >>> + { .type = IFLAF_VF_VLAN_MODE, .off = _OUT(vlan_mode), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_VLAN, .off = _OUT(vlan), >>> + .cb = snl_attr_get_uint16 }, >>> + { .type = IFLAF_VF_VLAN_COUNT, .off = _OUT(vlan_count), >>> + .cb = snl_attr_get_uint32 }, >>> + { .type = IFLAF_VF_VLAN_LIMIT, .off = _OUT(vlan_limit), >>> + .cb = snl_attr_get_uint32 }, >>> + { .type = IFLAF_VF_NUM_QUEUES, .off = _OUT(num_queues), >>> + .cb = snl_attr_get_uint32 }, >>> + { .type = IFLAF_VF_ALLOW_SET_MAC, .off = _OUT(allow_set_mac), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_ALLOW_SET_VLAN, .off = _OUT(allow_set_vlan), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_MAC_ANTI_SPOOF, .off = _OUT(mac_anti_spoof), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_ALLOW_PROMISC, .off = _OUT(allow_promisc), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_TRAFFIC_ENABLED, .off = _OUT(traffic_enabled), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_MDD_BLOCKED, .off = _OUT(mdd_blocked), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_QUARANTINED, .off = _OUT(quarantined), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_API_VERSION, .off = _OUT(api_version), >>> + .cb = snl_attr_dup_string }, >>> + { .type = IFLAF_VF_LINK_STATE_POLICY, >>> + .off = _OUT(link_state_policy), .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VF_EXTENSIONS, .off = _OUT(extensions), >>> + .arg = &_vf_extension_parser, .cb = snl_attr_get_parray }, >>> +}; >>> +#undef _OUT >>> +SNL_DECLARE_ATTR_PARSER_EXT(_vf_parser, sizeof(struct snl_parsed_vf), >>> + _nla_p_vf, NULL); >>> + >>> +struct snl_parsed_vf_status { >>> + uint64_t pf_link_speed; >>> + uint32_t version; >>> + uint32_t error; >>> + uint8_t pf_link_state; >>> + struct snl_parray vfs; >>> +}; >>> + >>> +#define _OUT(_field) offsetof(struct snl_parsed_vf_status, _field) >>> +static const struct snl_attr_parser _nla_p_vf_status[] = { >>> + { .type = IFLAF_VFS_VERSION, .off = _OUT(version), >>> + .cb = snl_attr_get_uint32 }, >>> + { .type = IFLAF_VFS_ERROR, .off = _OUT(error), >>> + .cb = snl_attr_get_uint32 }, >>> + { .type = IFLAF_VFS_PF_LINK_STATE, .off = _OUT(pf_link_state), >>> + .cb = snl_attr_get_uint8 }, >>> + { .type = IFLAF_VFS_PF_LINK_SPEED, .off = _OUT(pf_link_speed), >>> + .cb = snl_attr_get_uint64 }, >>> + { .type = IFLAF_VFS_LIST, .off = _OUT(vfs), >>> + .arg = &_vf_parser, .cb = snl_attr_get_parray }, >>> +}; >>> +#undef _OUT >>> +SNL_DECLARE_ATTR_PARSER_EXT(_vf_status_parser, >>> + sizeof(struct snl_parsed_vf_status), _nla_p_vf_status, NULL); >>> + >>> struct snl_parsed_link { >>> uint32_t ifi_index; >>> uint32_t ifi_flags; >>> @@ -191,9 +298,11 @@ struct snl_parsed_link { >>> struct nlattr *ifla_broadcast; >>> char *ifla_ifalias; >>> uint32_t ifla_promiscuity; >>> + uint32_t ifla_num_vf; >>> struct rtnl_link_stats64 *ifla_stats64; >>> struct nlattr *iflaf_orig_hwaddr; >>> struct snl_attr_bitset iflaf_caps; >>> + struct snl_parsed_vf_status iflaf_vf_status; >>> }; >>> >>> #define _IN(_field) offsetof(struct ifinfomsg, _field) >>> @@ -201,6 +310,8 @@ struct snl_parsed_link { >>> static const struct snl_attr_parser _nla_p_link_fbsd[] = { >>> { .type = IFLAF_ORIG_HWADDR, .off = _OUT(iflaf_orig_hwaddr), .cb = snl_attr_dup_nla }, >>> { .type = IFLAF_CAPS, .off = _OUT(iflaf_caps), .cb = snl_attr_get_bitset_c }, >>> + { .type = IFLAF_VF_STATUS, .off = _OUT(iflaf_vf_status), >>> + .arg = &_vf_status_parser, .cb = snl_attr_get_nested }, >>> }; >>> SNL_DECLARE_ATTR_PARSER(_link_fbsd_parser, _nla_p_link_fbsd); >>> >>> @@ -211,6 +322,7 @@ static const struct snl_attr_parser _nla_p_link[] = { >>> { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 }, >>> { .type = IFLA_OPERSTATE, .off = _OUT(ifla_operstate), .cb = snl_attr_get_uint8 }, >>> { .type = IFLA_IFALIAS, .off = _OUT(ifla_ifalias), .cb = snl_attr_dup_string }, >>> + { .type = IFLA_NUM_VF, .off = _OUT(ifla_num_vf), .cb = snl_attr_get_uint32 }, >>> { .type = IFLA_STATS64, .off = _OUT(ifla_stats64), .cb = snl_attr_dup_struct }, >>> { .type = IFLA_PROMISCUITY, .off = _OUT(ifla_promiscuity), .cb = snl_attr_get_uint32 }, >>> { .type = IFLA_CARRIER, .off = _OUT(ifla_carrier), .cb = snl_attr_get_uint8 }, >>> diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c >>> index 5b6e58a598aa..bb04c2a94c1e 100644 >>> --- a/sys/netlink/route/iface.c >>> +++ b/sys/netlink/route/iface.c >>> @@ -33,6 +33,7 @@ >>> #include <sys/kernel.h> >>> #include <sys/jail.h> >>> #include <sys/malloc.h> >>> +#include <sys/nv.h> >>> #include <sys/socket.h> >>> #include <sys/sockio.h> >>> #include <sys/syslog.h> >>> @@ -65,6 +66,7 @@ struct netlink_walkargs { >>> struct nlpcb *so; >>> struct ucred *cred; >>> uint32_t fibnum; >>> + uint32_t ext_mask; >>> int family; >>> int error; >>> int count; >>> @@ -279,6 +281,245 @@ dump_iface_caps(struct nl_writer *nw, struct ifnet *ifp) >>> return (true); >>> } >>> >>> +static uint8_t >>> +vf_link_state(const char *state) >>> +{ >>> + >>> + if (strcmp(state, IFVF_LINK_STATE_DOWN) == 0) >>> + return (IFLAF_VF_LINK_DOWN); >>> + if (strcmp(state, IFVF_LINK_STATE_UP) == 0) >>> + return (IFLAF_VF_LINK_UP); >>> + if (strcmp(state, IFVF_LINK_STATE_AUTO) == 0) >>> + return (IFLAF_VF_LINK_AUTO); >>> + return (IFLAF_VF_LINK_UNKNOWN); >>> +} >>> + >>> +static bool >>> +dump_vf_bool(struct nl_writer *nw, const nvlist_t *vf, const char *name, >>> + uint16_t attr) >>> +{ >>> + >>> + if (!nvlist_exists_bool(vf, name)) >>> + return (true); >>> + return (nlattr_add_u8(nw, attr, nvlist_get_bool(vf, name) ? 1 : 0)); >>> +} >>> + >>> +static bool >>> +dump_vf_u16(struct nl_writer *nw, const nvlist_t *vf, const char *name, >>> + uint16_t attr) >>> +{ >>> + uint64_t value; >>> + >>> + if (!nvlist_exists_number(vf, name)) >>> + return (true); >>> + value = nvlist_get_number(vf, name); >>> + if (value > UINT16_MAX) >>> + return (false); >>> + return (nlattr_add_u16(nw, attr, (uint16_t)value)); >>> +} >>> + >>> +static bool >>> +dump_vf_u32(struct nl_writer *nw, const nvlist_t *vf, const char *name, >>> + uint16_t attr) >>> +{ >>> + uint64_t value; >>> + >>> + if (!nvlist_exists_number(vf, name)) >>> + return (true); >>> + value = nvlist_get_number(vf, name); >>> + if (value > UINT32_MAX) >>> + return (false); >>> + return (nlattr_add_u32(nw, attr, (uint32_t)value)); >>> +} >>> + >>> +static bool >>> +dump_vf_string(struct nl_writer *nw, const nvlist_t *vf, const char *name, >>> + uint16_t attr) >>> +{ >>> + >>> + if (!nvlist_exists_string(vf, name)) >>> + return (true); >>> + return (nlattr_add_string(nw, attr, nvlist_get_string(vf, name))); >>> +} >>> + >>> +static bool >>> +dump_vf_extensions(struct nl_writer *nw, const nvlist_t *vf) >>> +{ >>> + const nvlist_t *extension, *extensions; >>> + const char *name; >>> + void *buf, *cookie; >>> + size_t buflen; >>> + int entry_off, extensions_off, type; >>> + bool ok; >>> + >>> + if (!nvlist_exists(vf, IFVF_STATUS_EXTENSIONS)) >>> + return (true); >>> + if (!nvlist_exists_nvlist(vf, IFVF_STATUS_EXTENSIONS)) >>> + return (false); >>> + >>> + extensions = nvlist_get_nvlist(vf, IFVF_STATUS_EXTENSIONS); >>> + extensions_off = nlattr_add_nested(nw, IFLAF_VF_EXTENSIONS); >>> + if (extensions_off == 0) >>> + return (false); >>> + cookie = NULL; >>> + while ((name = nvlist_next(extensions, &type, &cookie)) != NULL) { >>> + if (type != NV_TYPE_NVLIST) >>> + return (false); >>> + extension = nvlist_get_nvlist(extensions, name); >>> + if (!nvlist_exists_number(extension, >>> + IFVF_STATUS_EXT_VERSION)) >>> + return (false); >>> + buf = nvlist_pack(extension, &buflen); >>> + if (buf == NULL) >>> + return (false); >>> + if (buflen > UINT16_MAX - sizeof(struct nlattr)) { >>> + free(buf, M_NVLIST); >>> + return (false); >>> + } >>> + entry_off = nlattr_add_nested(nw, >>> + IFLAF_VF_EXT_LIST_ENTRY); >>> + if (entry_off == 0) { >>> + free(buf, M_NVLIST); >>> + return (false); >>> + } >>> + ok = nlattr_add_string(nw, IFLAF_VF_EXT_NAME, name) && >>> + nlattr_add(nw, IFLAF_VF_EXT_DATA, (uint16_t)buflen, buf); >>> + free(buf, M_NVLIST); >>> + if (!ok) >>> + return (false); >>> + nlattr_set_len(nw, entry_off); >>> + } >>> + nlattr_set_len(nw, extensions_off); >>> + return (true); >>> +} >>> + >>> +static bool >>> +dump_vf_entry(struct nl_writer *nw, const nvlist_t *vf) >>> +{ >>> + const void *mac; >>> + const char *mode, *policy; >>> + size_t maclen; >>> + uint8_t vlan_mode; >>> + int off; >>> + bool ok; >>> + >>> + off = nlattr_add_nested(nw, IFLAF_VF_LIST_ENTRY); >>> + if (off == 0) >>> + return (false); >>> + ok = dump_vf_u32(nw, vf, IFVF_STATUS_INDEX, IFLAF_VF_INDEX) && >>> + dump_vf_bool(nw, vf, IFVF_STATUS_CONFIGURED, >>> + IFLAF_VF_CONFIGURED) && >>> + dump_vf_bool(nw, vf, IFVF_STATUS_INITIALIZED, >>> + IFLAF_VF_INITIALIZED); >>> + if (!ok) >>> + return (false); >>> + >>> + if (nvlist_exists_binary(vf, IFVF_STATUS_MAC)) { >>> + mac = nvlist_get_binary(vf, IFVF_STATUS_MAC, &maclen); >>> + if (maclen > UINT16_MAX - sizeof(struct nlattr) || >>> + !nlattr_add(nw, IFLAF_VF_MAC, (uint16_t)maclen, mac)) >>> + return (false); >>> + } >>> + if (nvlist_exists_string(vf, IFVF_STATUS_VLAN_MODE)) { >>> + mode = nvlist_get_string(vf, IFVF_STATUS_VLAN_MODE); >>> + if (strcmp(mode, IFVF_VLAN_MODE_ACCESS) == 0) >>> + vlan_mode = IFLAF_VF_VLAN_ACCESS; >>> + else if (strcmp(mode, IFVF_VLAN_MODE_TRUNK) == 0) >>> + vlan_mode = IFLAF_VF_VLAN_TRUNK; >>> + else >>> + vlan_mode = IFLAF_VF_VLAN_UNKNOWN; >>> + if (!nlattr_add_u8(nw, IFLAF_VF_VLAN_MODE, vlan_mode)) >>> + return (false); >>> + } >>> + ok = dump_vf_u16(nw, vf, IFVF_STATUS_VLAN, IFLAF_VF_VLAN) && >>> + dump_vf_u32(nw, vf, IFVF_STATUS_VLAN_COUNT, >>> + IFLAF_VF_VLAN_COUNT) && >>> + dump_vf_u32(nw, vf, IFVF_STATUS_VLAN_LIMIT, >>> + IFLAF_VF_VLAN_LIMIT) && >>> + dump_vf_u32(nw, vf, IFVF_STATUS_NUM_QUEUES, >>> + IFLAF_VF_NUM_QUEUES) && >>> + dump_vf_bool(nw, vf, IFVF_STATUS_ALLOW_SET_MAC, >>> + IFLAF_VF_ALLOW_SET_MAC) && >>> + dump_vf_bool(nw, vf, IFVF_STATUS_ALLOW_SET_VLAN, >>> + IFLAF_VF_ALLOW_SET_VLAN) && >>> + dump_vf_bool(nw, vf, IFVF_STATUS_MAC_ANTI_SPOOF, >>> + IFLAF_VF_MAC_ANTI_SPOOF) && >>> + dump_vf_bool(nw, vf, IFVF_STATUS_ALLOW_PROMISC, >>> + IFLAF_VF_ALLOW_PROMISC) && >>> + dump_vf_bool(nw, vf, IFVF_STATUS_TRAFFIC_ENABLED, >>> + IFLAF_VF_TRAFFIC_ENABLED) && >>> + dump_vf_bool(nw, vf, IFVF_STATUS_MDD_BLOCKED, >>> + IFLAF_VF_MDD_BLOCKED) && >>> + dump_vf_bool(nw, vf, IFVF_STATUS_QUARANTINED, >>> + IFLAF_VF_QUARANTINED) && >>> + dump_vf_string(nw, vf, IFVF_STATUS_API_VERSION, >>> + IFLAF_VF_API_VERSION); >>> + if (!ok) >>> + return (false); >>> + if (nvlist_exists_string(vf, IFVF_STATUS_LINK_STATE_POLICY)) { >>> + policy = nvlist_get_string(vf, >>> + IFVF_STATUS_LINK_STATE_POLICY); >>> + if (!nlattr_add_u8(nw, IFLAF_VF_LINK_STATE_POLICY, >>> + vf_link_state(policy))) >>> + return (false); >>> + } >>> + if (!dump_vf_extensions(nw, vf)) >>> + return (false); >>> + nlattr_set_len(nw, off); >>> + return (true); >>> +} >>> + >>> +static bool >>> +dump_vf_status(struct nl_writer *nw, const nvlist_t *status, int error) >>> +{ >>> + const nvlist_t * const *vfs; >>> + const char *state; >>> + size_t i, num_vfs; >>> + uint64_t version; >>> + int list_off, off; >>> + >>> + off = nlattr_add_nested(nw, IFLAF_VF_STATUS); >>> + if (off == 0) >>> + return (false); >>> + if (error != 0) { >>> + if (!nlattr_add_u32(nw, IFLAF_VFS_ERROR, (uint32_t)error)) >>> + return (false); >>> + nlattr_set_len(nw, off); >>> + return (true); >>> + } >>> + >>> + if (!nvlist_exists_number(status, IFVF_STATUS_VERSION_KEY)) >>> + return (false); >>> + version = nvlist_get_number(status, IFVF_STATUS_VERSION_KEY); >>> + if (version > UINT32_MAX || >>> + !nlattr_add_u32(nw, IFLAF_VFS_VERSION, (uint32_t)version)) >>> + return (false); >>> + if (nvlist_exists_string(status, IFVF_STATUS_PF_LINK_STATE)) { >>> + state = nvlist_get_string(status, IFVF_STATUS_PF_LINK_STATE); >>> + if (!nlattr_add_u8(nw, IFLAF_VFS_PF_LINK_STATE, >>> + vf_link_state(state))) >>> + return (false); >>> + } >>> + if (nvlist_exists_number(status, IFVF_STATUS_PF_LINK_SPEED) && >>> + !nlattr_add_u64(nw, IFLAF_VFS_PF_LINK_SPEED, >>> + nvlist_get_number(status, IFVF_STATUS_PF_LINK_SPEED))) >>> + return (false); >>> + if (!nvlist_exists_nvlist_array(status, IFVF_STATUS_VFS)) >>> + return (false); >>> + >>> + vfs = nvlist_get_nvlist_array(status, IFVF_STATUS_VFS, &num_vfs); >>> + list_off = nlattr_add_nested(nw, IFLAF_VFS_LIST); >>> + if (list_off == 0) >>> + return (false); >>> + for (i = 0; i < num_vfs; i++) { >>> + if (!dump_vf_entry(nw, vfs[i])) >>> + return (false); >>> + } >>> + nlattr_set_len(nw, list_off); >>> + nlattr_set_len(nw, off); >>> + return (true); >>> +} >>> + >>> /* >>> * Dumps interface state, properties and metrics. >>> * @nw: message writer >>> @@ -290,12 +531,26 @@ dump_iface_caps(struct nl_writer *nw, struct ifnet *ifp) >>> */ >>> static bool >>> dump_iface(struct nl_writer *nw, if_t ifp, const struct nlmsghdr *hdr, >>> - int if_flags_mask, const char *ifname) >>> + int if_flags_mask, const char *ifname, uint32_t ext_mask) >>> { >>> struct epoch_tracker et; >>> + nvlist_t *vf_status; >>> + size_t num_vfs; >>> struct ifinfomsg *ifinfo; >>> + bool include_vf_status; >>> + int vf_error; >>> >>> NL_LOG(LOG_DEBUG3, "dumping interface %s data", if_name(ifp)); >>> + vf_status = NULL; >>> + vf_error = 0; >>> + include_vf_status = (ext_mask & RTEXT_FILTER_VF) != 0; >>> + if (include_vf_status) { >>> + vf_error = if_get_vf_status(ifp, &vf_status); >>> + if (vf_error == EINVAL || vf_error == ENOTTY || >>> + vf_error == ENXIO || vf_error == ENOTSUP || >>> + vf_error == EOPNOTSUPP) >>> + include_vf_status = false; >>> + } >>> >>> if (!nlmsg_reply(nw, hdr, sizeof(struct ifinfomsg))) >>> goto enomem; >>> @@ -341,6 +596,14 @@ dump_iface(struct nl_writer *nw, if_t ifp, const struct nlmsghdr *hdr, >>> } >>> >>> nlattr_add_u32(nw, IFLA_MTU, if_getmtu(ifp)); >>> + if (vf_status != NULL && >>> + nvlist_exists_nvlist_array(vf_status, IFVF_STATUS_VFS)) { >>> + (void)nvlist_get_nvlist_array(vf_status, IFVF_STATUS_VFS, >>> + &num_vfs); >>> + if (num_vfs > UINT32_MAX || >>> + !nlattr_add_u32(nw, IFLA_NUM_VF, (uint32_t)num_vfs)) >>> + goto enomem; >>> + } >>> /* >>> nlattr_add_u32(nw, IFLA_MIN_MTU, 60); >>> nlattr_add_u32(nw, IFLA_MAX_MTU, 9000); >>> @@ -355,6 +618,9 @@ dump_iface(struct nl_writer *nw, if_t ifp, const struct nlmsghdr *hdr, >>> if (off != 0) { >>> get_hwaddr(nw, ifp); >>> dump_iface_caps(nw, ifp); >>> + if (include_vf_status && >>> + !dump_vf_status(nw, vf_status, vf_error)) >>> + goto enomem; >>> >>> nlattr_set_len(nw, off); >>> } >>> @@ -368,11 +634,14 @@ dump_iface(struct nl_writer *nw, if_t ifp, const struct nlmsghdr *hdr, >>> >>> nw->ifp = ifp; >>> >>> - if (nlmsg_end(nw)) >>> + if (nlmsg_end(nw)) { >>> + nvlist_destroy(vf_status); >>> return (true); >>> + } >>> >>> enomem: >>> - NL_LOG(LOG_DEBUG, "unable to dump interface %s state (ENOMEM)", if_name(ifp)); >>> + nvlist_destroy(vf_status); >>> + NL_LOG(LOG_DEBUG, "unable to dump interface %s state", if_name(ifp)); >>> nlmsg_abort(nw); >>> return (false); >>> } >>> @@ -415,6 +684,7 @@ static const struct nlattr_parser nla_p_if[] = { >>> { .type = IFLA_LINKINFO, .arg = &linfo_parser, .cb = nlattr_get_nested }, >>> { .type = IFLA_IFALIAS, .off = _OUT(ifla_ifalias), .cb = nlattr_get_string }, >>> { .type = IFLA_GROUP, .off = _OUT(ifla_group), .cb = nlattr_get_string }, >>> + { .type = IFLA_EXT_MASK, .off = _OUT(ifla_ext_mask), .cb = nlattr_get_uint32 }, >>> { .type = IFLA_ALT_IFNAME, .off = _OUT(ifla_ifname), .cb = nlattr_get_string }, >>> }; >>> #undef _IN >>> @@ -441,7 +711,7 @@ static int >>> dump_cb(if_t ifp, void *_arg) >>> { >>> struct netlink_walkargs *wa = (struct netlink_walkargs *)_arg; >>> - if (!dump_iface(wa->nw, ifp, &wa->hdr, 0, NULL)) >>> + if (!dump_iface(wa->nw, ifp, &wa->hdr, 0, NULL, wa->ext_mask)) >>> return (ENOMEM); >>> return (0); >>> } >>> @@ -473,6 +743,7 @@ rtnl_handle_getlink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *n >>> .hdr.nlmsg_seq = hdr->nlmsg_seq, >>> .hdr.nlmsg_flags = hdr->nlmsg_flags, >>> .hdr.nlmsg_type = NL_RTM_NEWLINK, >>> + .ext_mask = attrs.ifla_ext_mask, >>> }; >>> >>> /* Fast track for an interface w/ explicit name or index match */ >>> @@ -491,7 +762,8 @@ rtnl_handle_getlink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *n >>> >>> if (ifp != NULL) { >>> if (match_iface(ifp, &attrs)) { >>> - if (!dump_iface(wa.nw, ifp, &wa.hdr, 0, NULL)) >>> + if (!dump_iface(wa.nw, ifp, &wa.hdr, 0, NULL, >>> + wa.ext_mask)) >>> error = ENOMEM; >>> } else >>> error = ENODEV; >>> @@ -1418,7 +1690,7 @@ rtnl_handle_ifevent(if_t ifp, int nlmsg_type, int if_flags_mask, >>> NL_LOG(LOG_DEBUG, "error allocating group writer"); >>> return; >>> } >>> - dump_iface(&nw, ifp, &hdr, if_flags_mask, ifname); >>> + dump_iface(&nw, ifp, &hdr, if_flags_mask, ifname, 0); >>> nlmsg_flush(&nw); >>> } >>> >>> diff --git a/sys/netlink/route/interface.h b/sys/netlink/route/interface.h >>> index c018a0adb20d..66bab24067df 100644 >>> --- a/sys/netlink/route/interface.h >>> +++ b/sys/netlink/route/interface.h >>> @@ -94,7 +94,7 @@ enum { >>> #define IFLA_NET_NS_PID IFLA_NET_NS_PID >>> IFLA_IFALIAS = 20, /* string: interface description */ >>> #define IFLA_IFALIAS IFLA_IFALIAS >>> - IFLA_NUM_VF = 21, /* not supported */ >>> + IFLA_NUM_VF = 21, /* u32: active VFs, when requested */ >>> #define IFLA_NUM_VF IFLA_NUM_VF >>> IFLA_VFINFO_LIST= 22, /* not supported */ >>> #define IFLA_VFINFO_LIST IFLA_VFINFO_LIST >>> @@ -147,15 +147,95 @@ enum { >>> }; >>> #define IFLA_MAX (__IFLA_MAX - 1) >>> >>> +/* IFLA_EXT_MASK values. */ >>> +#define RTEXT_FILTER_VF (1U << 0) >>> + >>> enum { >>> IFLAF_UNSPEC = 0, >>> IFLAF_ORIG_IFNAME = 1, /* string, original interface name at creation */ >>> IFLAF_ORIG_HWADDR = 2, /* binary, original hardware address */ >>> IFLAF_CAPS = 3, /* bitset, interface capabilities */ >>> + IFLAF_VF_STATUS = 4, /* nested, IFLAF_VFS_* */ >>> __IFLAF_MAX >>> }; >>> #define IFLAF_MAX (__IFLAF_MAX - 1) >>> >>> +/* IFLAF_VF_STATUS attributes. */ >>> +enum { >>> + IFLAF_VFS_UNSPEC = 0, >>> + IFLAF_VFS_VERSION = 1, /* u32: IFVF_STATUS_VERSION */ >>> + IFLAF_VFS_ERROR = 2, /* u32: errno from requested query */ >>> + IFLAF_VFS_PF_LINK_STATE = 3, /* u8: IFLAF_VF_LINK_* */ >>> + IFLAF_VFS_PF_LINK_SPEED = 4, /* u64: bits per second */ >>> + IFLAF_VFS_LIST = 5, /* nested, IFLAF_VF_LIST_* */ >>> + __IFLAF_VFS_MAX >>> +}; >>> +#define IFLAF_VFS_MAX (__IFLAF_VFS_MAX - 1) >>> + >>> +/* IFLAF_VFS_LIST attributes. */ >>> +enum { >>> + IFLAF_VF_LIST_UNSPEC = 0, >>> + IFLAF_VF_LIST_ENTRY = 1, /* nested, IFLAF_VF_*; repeated */ >>> + __IFLAF_VF_LIST_MAX >>> +}; >>> +#define IFLAF_VF_LIST_MAX (__IFLAF_VF_LIST_MAX - 1) >>> + >>> +/* IFLAF_VF_LIST_ENTRY attributes. */ >>> +enum { >>> + IFLAF_VF_UNSPEC = 0, >>> + IFLAF_VF_INDEX = 1, /* u32 */ >>> + IFLAF_VF_CONFIGURED = 2, /* u8 boolean */ >>> + IFLAF_VF_INITIALIZED = 3, /* u8 boolean */ >>> + IFLAF_VF_MAC = 4, /* binary */ >>> + IFLAF_VF_VLAN_MODE = 5, /* u8: IFLAF_VF_VLAN_* */ >>> + IFLAF_VF_VLAN = 6, /* u16 */ >>> + IFLAF_VF_VLAN_COUNT = 7, /* u32 */ >>> + IFLAF_VF_VLAN_LIMIT = 8, /* u32 */ >>> + IFLAF_VF_NUM_QUEUES = 9, /* u32 */ >>> + IFLAF_VF_ALLOW_SET_MAC = 10, /* u8 boolean */ >>> + IFLAF_VF_ALLOW_SET_VLAN = 11, /* u8 boolean */ >>> + IFLAF_VF_MAC_ANTI_SPOOF = 12, /* u8 boolean */ >>> + IFLAF_VF_ALLOW_PROMISC = 13, /* u8 boolean */ >>> + IFLAF_VF_TRAFFIC_ENABLED = 14, /* u8 boolean */ >>> + IFLAF_VF_MDD_BLOCKED = 15, /* u8 boolean */ >>> + IFLAF_VF_QUARANTINED = 16, /* u8 boolean */ >>> + IFLAF_VF_API_VERSION = 17, /* string */ >>> + IFLAF_VF_LINK_STATE_POLICY = 18, /* u8: IFLAF_VF_LINK_* */ >>> + IFLAF_VF_EXTENSIONS = 19, /* nested, IFLAF_VF_EXT_LIST_* */ >>> + __IFLAF_VF_MAX >>> +}; >>> +#define IFLAF_VF_MAX (__IFLAF_VF_MAX - 1) >>> + >>> +/* IFLAF_VF_EXTENSIONS attributes. */ >>> +enum { >>> + IFLAF_VF_EXT_LIST_UNSPEC = 0, >>> + IFLAF_VF_EXT_LIST_ENTRY = 1, /* nested; repeated */ >>> + __IFLAF_VF_EXT_LIST_MAX >>> +}; >>> +#define IFLAF_VF_EXT_LIST_MAX (__IFLAF_VF_EXT_LIST_MAX - 1) >>> + >>> +/* IFLAF_VF_EXT_LIST_ENTRY attributes. */ >>> +enum { >>> + IFLAF_VF_EXT_UNSPEC = 0, >>> + IFLAF_VF_EXT_NAME = 1, /* string: stable namespace */ >>> + IFLAF_VF_EXT_DATA = 2, /* binary: packed namespace nvlist */ >>> + __IFLAF_VF_EXT_MAX >>> +}; >>> +#define IFLAF_VF_EXT_MAX (__IFLAF_VF_EXT_MAX - 1) >>> + >>> +enum { >>> + IFLAF_VF_LINK_UNKNOWN = 0, >>> + IFLAF_VF_LINK_DOWN = 1, >>> + IFLAF_VF_LINK_UP = 2, >>> + IFLAF_VF_LINK_AUTO = 3, >>> +}; >>> + >>> +enum { >>> + IFLAF_VF_VLAN_UNKNOWN = 0, >>> + IFLAF_VF_VLAN_ACCESS = 1, >>> + IFLAF_VF_VLAN_TRUNK = 2, >>> +}; >>> + >>> /* >>> * Attributes that can be used as filters: >>> * IFLA_IFNAME, IFLA_GROUP, IFLA_ALT_IFNAME >>> diff --git a/sys/netlink/route/route_var.h b/sys/netlink/route/route_var.h >>> index 012dc5ad0594..23adf012733f 100644 >>> --- a/sys/netlink/route/route_var.h >>> +++ b/sys/netlink/route/route_var.h >>> @@ -74,6 +74,7 @@ struct nl_parsed_link { >>> int ifi_index; >>> uint32_t ifla_link; >>> uint32_t ifla_mtu; >>> + uint32_t ifla_ext_mask; >>> uint32_t ifi_flags; >>> uint32_t ifi_change; >>> }; >>> diff --git a/tests/atf_python/sys/netlink/attrs.py b/tests/atf_python/sys/netlink/attrs.py >>> index 36dd8191df1c..b0e03e50258e 100644 >>> --- a/tests/atf_python/sys/netlink/attrs.py >>> +++ b/tests/atf_python/sys/netlink/attrs.py >>> @@ -137,6 +137,34 @@ class NlAttrU32(NlAttr): >>> return self._to_bytes(struct.pack("@I", self.u32)) >>> >>> >>> +class NlAttrU64(NlAttr): >>> + def __init__(self, nla_type, val): >>> + self.u64 = enum_or_int(val) >>> + super().__init__(nla_type, b"") >>> + >>> + @property >>> + def nla_len(self): >>> + return 12 >>> + >>> + def _print_attr_value(self): >>> + return " val={}".format(self.u64) >>> + >>> + @staticmethod >>> + def _validate(data): >>> + assert len(data) == 12 >>> + nla_len, nla_type = struct.unpack("@HH", data[:4]) >>> + assert nla_len == 12 >>> + >>> + @classmethod >>> + def _parse(cls, data): >>> + nla_len, nla_type = struct.unpack("@HH", data[:4]) >>> + val = struct.unpack("@Q", data[4:])[0] >>> + return cls(nla_type, val) >>> + >>> + def __bytes__(self): >>> + return self._to_bytes(struct.pack("@Q", self.u64)) >>> + >>> + >>> class NlAttrS32(NlAttr): >>> def __init__(self, nla_type, val): >>> self.s32 = enum_or_int(val) >>> diff --git a/tests/atf_python/sys/netlink/netlink_route.py b/tests/atf_python/sys/netlink/netlink_route.py >>> index 2cfeb57da13f..d6edc6ad875d 100644 >>> --- a/tests/atf_python/sys/netlink/netlink_route.py >>> +++ b/tests/atf_python/sys/netlink/netlink_route.py >>> @@ -13,7 +13,9 @@ from atf_python.sys.netlink.attrs import NlAttr >>> from atf_python.sys.netlink.attrs import NlAttrIp >>> from atf_python.sys.netlink.attrs import NlAttrNested >>> from atf_python.sys.netlink.attrs import NlAttrStr >>> +from atf_python.sys.netlink.attrs import NlAttrU16 >>> from atf_python.sys.netlink.attrs import NlAttrU32 >>> +from atf_python.sys.netlink.attrs import NlAttrU64 >>> from atf_python.sys.netlink.attrs import NlAttrU8 >>> from atf_python.sys.netlink.message import StdNetlinkMessage >>> from atf_python.sys.netlink.message import NlMsgProps >>> @@ -361,6 +363,56 @@ class IflafAttrType(Enum): >>> IFLAF_UNSPEC = 0 >>> IFLAF_ORIG_IFNAME = 1 >>> IFLAF_ORIG_HWADDR = 2 >>> + IFLAF_CAPS = 3 >>> + IFLAF_VF_STATUS = 4 >>> + >>> + >>> +class IflafVfStatusType(Enum): >>> + IFLAF_VFS_UNSPEC = 0 >>> + IFLAF_VFS_VERSION = 1 >>> + IFLAF_VFS_ERROR = 2 >>> + IFLAF_VFS_PF_LINK_STATE = 3 >>> + IFLAF_VFS_PF_LINK_SPEED = 4 >>> + IFLAF_VFS_LIST = 5 >>> + >>> + >>> +class IflafVfListType(Enum): >>> + IFLAF_VF_LIST_UNSPEC = 0 >>> + IFLAF_VF_LIST_ENTRY = 1 >>> + >>> + >>> +class IflafVfType(Enum): >>> + IFLAF_VF_UNSPEC = 0 >>> + IFLAF_VF_INDEX = 1 >>> + IFLAF_VF_CONFIGURED = 2 >>> + IFLAF_VF_INITIALIZED = 3 >>> + IFLAF_VF_MAC = 4 >>> + IFLAF_VF_VLAN_MODE = 5 >>> + IFLAF_VF_VLAN = 6 >>> + IFLAF_VF_VLAN_COUNT = 7 >>> + IFLAF_VF_VLAN_LIMIT = 8 >>> + IFLAF_VF_NUM_QUEUES = 9 >>> + IFLAF_VF_ALLOW_SET_MAC = 10 >>> + IFLAF_VF_ALLOW_SET_VLAN = 11 >>> + IFLAF_VF_MAC_ANTI_SPOOF = 12 >>> + IFLAF_VF_ALLOW_PROMISC = 13 >>> + IFLAF_VF_TRAFFIC_ENABLED = 14 >>> + IFLAF_VF_MDD_BLOCKED = 15 >>> + IFLAF_VF_QUARANTINED = 16 >>> + IFLAF_VF_API_VERSION = 17 >>> + IFLAF_VF_LINK_STATE_POLICY = 18 >>> + IFLAF_VF_EXTENSIONS = 19 >>> + >>> + >>> +class IflafVfExtListType(Enum): >>> + IFLAF_VF_EXT_LIST_UNSPEC = 0 >>> + IFLAF_VF_EXT_LIST_ENTRY = 1 >>> + >>> + >>> +class IflafVfExtType(Enum): >>> + IFLAF_VF_EXT_UNSPEC = 0 >>> + IFLAF_VF_EXT_NAME = 1 >>> + IFLAF_VF_EXT_DATA = 2 >>> >>> >>> class IflinkInfo(Enum): >>> @@ -621,6 +673,65 @@ rtnl_route_attrs = prepare_attrs_map( >>> ] >>> ) >>> >>> +rtnl_iflaf_vf_ext_attrs = [ >>> + AttrDescr(IflafVfExtType.IFLAF_VF_EXT_NAME, NlAttrStr), >>> + AttrDescr(IflafVfExtType.IFLAF_VF_EXT_DATA, NlAttr), >>> +] >>> + >>> +rtnl_iflaf_vf_ext_list_attrs = [ >>> + AttrDescr( >>> + IflafVfExtListType.IFLAF_VF_EXT_LIST_ENTRY, >>> + NlAttrNested, >>> + rtnl_iflaf_vf_ext_attrs, >>> + ), >>> +] >>> + >>> +rtnl_iflaf_vf_attrs = [ >>> + AttrDescr(IflafVfType.IFLAF_VF_INDEX, NlAttrU32), >>> + AttrDescr(IflafVfType.IFLAF_VF_CONFIGURED, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_INITIALIZED, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_MAC, NlAttrMac), >>> + AttrDescr(IflafVfType.IFLAF_VF_VLAN_MODE, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_VLAN, NlAttrU16), >>> + AttrDescr(IflafVfType.IFLAF_VF_VLAN_COUNT, NlAttrU32), >>> + AttrDescr(IflafVfType.IFLAF_VF_VLAN_LIMIT, NlAttrU32), >>> + AttrDescr(IflafVfType.IFLAF_VF_NUM_QUEUES, NlAttrU32), >>> + AttrDescr(IflafVfType.IFLAF_VF_ALLOW_SET_MAC, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_ALLOW_SET_VLAN, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_MAC_ANTI_SPOOF, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_ALLOW_PROMISC, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_TRAFFIC_ENABLED, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_MDD_BLOCKED, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_QUARANTINED, NlAttrU8), >>> + AttrDescr(IflafVfType.IFLAF_VF_API_VERSION, NlAttrStr), >>> + AttrDescr(IflafVfType.IFLAF_VF_LINK_STATE_POLICY, NlAttrU8), >>> + AttrDescr( >>> + IflafVfType.IFLAF_VF_EXTENSIONS, >>> + NlAttrNested, >>> + rtnl_iflaf_vf_ext_list_attrs, >>> + ), >>> +] >>> + >>> +rtnl_iflaf_vf_list_attrs = [ >>> + AttrDescr( >>> + IflafVfListType.IFLAF_VF_LIST_ENTRY, >>> + NlAttrNested, >>> + rtnl_iflaf_vf_attrs, >>> *** 195 LINES SKIPPED *** >>> >> >> I think we should minimize our use of nvlist(9) in the new code, >> especially under netlink. >> IMO, Using nvlist under netlink defeats the purpose. > > Hi, > > Is there a better way to do something like this > https://reviews.freebsd.org/D58739#change-0sX8k3Z9eTKs? I see, I had the same problem on geneve implementation. I asked on the mailing list and kp@ gave me some advice on it. See this thread: https://mail-archive.freebsd.org/cgi/getmsg.cgi?fetch=270856+0+archive/2025/freebsd-net/20251020.freebsd-net Somehow, I managed to implement it directly with netlink: https://reviews.freebsd.org/D54172?vs=174551&id=175142#toc Hope it helps! >> looI don't think snl_attr_get_parray is appropriate for parser-only >> attributes. >> We should use multi-attr instead to avoid too many nested netlink >> attributes. (e.g. /* nested, IFLAF_VF_*; repeated */) >> https://docs.kernel.org/userspace-api/netlink/genetlink-legacy.html >> >> We might also want to use snl_attr_get_bool or snl_attr_get_flag for >> many of the data structures above. >> >> I wish there were a phabricator review for this change. >> >> -- >> Pouria >> > -- Pouria
OpenPGP_signature.asc
(application/pgp-signature, 265 B)
-----BEGIN PGP SIGNATURE----- iJEEARYKADkWIQSqt7cppfvJ816gj0lUwVnUeMwagAUCanorlBsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDMACgkQVMFZ1HjMGoCcswEA8n2zwbOVDkOe+TFz5Xan TAr3nlE7eJtdoWppieRxuCUA/A7hafMsZcsOEyadW3Qcb6tUSeGE4+Slu2odSctX qJsJ =Uqyy -----END PGP SIGNATURE-----