Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164678314
D40331.id122603.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D40331.id122603.diff
View Options
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -274,7 +274,6 @@
bool match_if_flags(struct ifconfig_args *args, int if_flags);
int ifconfig(if_ctx *ctx, int iscreate, const struct afswtch *uafp);
bool group_member(const char *ifname, const char *match, const char *nomatch);
-void print_ifcap(struct ifconfig_args *args, int s);
void tunnel_status(int s);
struct afswtch *af_getbyfamily(int af);
void af_other_status(if_ctx *ctx);
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -1633,7 +1633,7 @@
Perror("ioctl (SIOCGIFCAP)");
}
-void
+static void
print_ifcap(struct ifconfig_args *args, int s)
{
if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
diff --git a/sbin/ifconfig/ifconfig_netlink.c b/sbin/ifconfig/ifconfig_netlink.c
--- a/sbin/ifconfig/ifconfig_netlink.c
+++ b/sbin/ifconfig/ifconfig_netlink.c
@@ -346,6 +346,28 @@
}
}
+static void
+print_ifcaps(if_ctx *ctx, if_link_t *link)
+{
+ uint32_t sz_u32 = roundup2(link->iflaf_caps.nla_bitset_size, 32) / 32;
+
+ if (sz_u32 > 0) {
+ uint32_t *caps = link->iflaf_caps.nla_bitset_value;
+
+ printf("\toptions=%x", caps[0]);
+ print_bits("IFCAPS", caps, sz_u32, ifcap_bit_names, nitems(ifcap_bit_names));
+ putchar('\n');
+ }
+
+ if (ctx->args->supmedia && sz_u32 > 0) {
+ uint32_t *caps = link->iflaf_caps.nla_bitset_mask;
+
+ printf("\tcapabilities=%x", caps[0]);
+ print_bits("IFCAPS", caps, sz_u32, ifcap_bit_names, nitems(ifcap_bit_names));
+ putchar('\n');
+ }
+}
+
static void
status_nl(if_ctx *ctx, struct iface *iface)
{
@@ -363,9 +385,7 @@
if (link->ifla_ifalias != NULL)
printf("\tdescription: %s\n", link->ifla_ifalias);
- /* TODO: convert to netlink */
- strlcpy(ifr.ifr_name, link->ifla_ifname, sizeof(ifr.ifr_name));
- print_ifcap(args, ctx->io_s);
+ print_ifcaps(ctx, link);
tunnel_status(ctx->io_s);
if (args->allfamilies | (args->afp != NULL && args->afp->af_af == AF_LINK)) {
diff --git a/sys/net/if.h b/sys/net/if.h
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -260,6 +260,47 @@
#define IFCAP2_BIT(x) (1UL << (x))
+/* IFCAP values as bit indexes */
+#define IFCAP_B_RXCSUM 0 /* can offload checksum on RX */
+#define IFCAP_B_TXCSUM 1 /* can offload checksum on TX */
+#define IFCAP_B_NETCONS 2 /* can be a network console */
+#define IFCAP_B_VLAN_MTU 3 /* VLAN-compatible MTU */
+#define IFCAP_B_VLAN_HWTAGGING 4 /* hardware VLAN tag support */
+#define IFCAP_B_JUMBO_MTU 5 /* 9000 byte MTU supported */
+#define IFCAP_B_POLLING 6 /* driver supports polling */
+#define IFCAP_B_VLAN_HWCSUM 7 /* can do IFCAP_HWCSUM on VLANs */
+#define IFCAP_B_TSO4 8 /* can do TCP Segmentation Offload */
+#define IFCAP_B_TSO6 9 /* can do TCP6 Segmentation Offload */
+#define IFCAP_B_LRO 10 /* can do Large Receive Offload */
+#define IFCAP_B_WOL_UCAST 11 /* wake on any unicast frame */
+#define IFCAP_B_WOL_MCAST 12 /* wake on any multicast frame */
+#define IFCAP_B_WOL_MAGIC 13 /* wake on any Magic Packet */
+#define IFCAP_B_TOE4 14 /* interface can offload TCP */
+#define IFCAP_B_TOE6 15 /* interface can offload TCP6 */
+#define IFCAP_B_VLAN_HWFILTER 16 /* interface hw can filter vlan tag */
+#define IFCAP_B_NV 17 /* can do SIOCGIFCAPNV/SIOCSIFCAPNV */
+#define IFCAP_B_VLAN_HWTSO 18 /* can do IFCAP_TSO on VLANs */
+#define IFCAP_B_LINKSTATE 19 /* the runtime link state is dynamic */
+#define IFCAP_B_NETMAP 20 /* netmap mode supported/enabled */
+#define IFCAP_B_RXCSUM_IPV6 21 /* can offload checksum on IPv6 RX */
+#define IFCAP_B_TXCSUM_IPV6 22 /* can offload checksum on IPv6 TX */
+#define IFCAP_B_HWSTATS 23 /* manages counters internally */
+#define IFCAP_B_TXRTLMT 24 /* hardware supports TX rate limiting */
+#define IFCAP_B_HWRXTSTMP 25 /* hardware rx timestamping */
+#define IFCAP_B_MEXTPG 26 /* understands M_EXTPG mbufs */
+#define IFCAP_B_TXTLS4 27 /* can do TLS encryption and segmentation for TCP */
+#define IFCAP_B_TXTLS6 28 /* can do TLS encryption and segmentation for TCP6 */
+#define IFCAP_B_VXLAN_HWCSUM 29 /* can do IFCAN_HWCSUM on VXLANs */
+#define IFCAP_B_VXLAN_HWTSO 30 /* can do IFCAP_TSO on VXLANs */
+#define IFCAP_B_TXTLS_RTLMT 31 /* can do TLS with rate limiting */
+#define IFCAP_B_RXTLS4 32 /* can to TLS receive for TCP */
+#define IFCAP_B_RXTLS6 33 /* can to TLS receive for TCP6 */
+#define __IFCAP_B_SIZE 34
+
+#define IFCAP_B_MAX (__IFCAP_B_MAX - 1)
+#define IFCAP_B_SIZE (__IFCAP_B_SIZE)
+
+
#define IFCAP_HWCSUM_IPV6 (IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6)
#define IFCAP_HWCSUM (IFCAP_RXCSUM | IFCAP_TXCSUM)
@@ -288,6 +329,7 @@
#define IFCAP_TOE4_NAME "TOE4"
#define IFCAP_TOE6_NAME "TOE6"
#define IFCAP_VLAN_HWFILTER_NAME "VLAN_HWFILTER"
+#define IFCAP_NV_NAME "NV"
#define IFCAP_VLAN_HWTSO_NAME "VLAN_HWTSO"
#define IFCAP_LINKSTATE_NAME "LINKSTATE"
#define IFCAP_NETMAP_NAME "NETMAP"
@@ -305,6 +347,45 @@
#define IFCAP2_RXTLS4_NAME "RXTLS4"
#define IFCAP2_RXTLS6_NAME "RXTLS6"
+static const char *ifcap_bit_names[] = {
+ IFCAP_RXCSUM_NAME,
+ IFCAP_TXCSUM_NAME,
+ IFCAP_NETCONS_NAME,
+ IFCAP_VLAN_MTU_NAME,
+ IFCAP_VLAN_HWTAGGING_NAME,
+ IFCAP_JUMBO_MTU_NAME,
+ IFCAP_POLLING_NAME,
+ IFCAP_VLAN_HWCSUM_NAME,
+ IFCAP_TSO4_NAME,
+ IFCAP_TSO6_NAME,
+ IFCAP_LRO_NAME,
+ IFCAP_WOL_UCAST_NAME,
+ IFCAP_WOL_MCAST_NAME,
+ IFCAP_WOL_MAGIC_NAME,
+ IFCAP_TOE4_NAME,
+ IFCAP_TOE6_NAME,
+ IFCAP_VLAN_HWFILTER_NAME,
+ IFCAP_NV_NAME,
+ IFCAP_VLAN_HWTSO_NAME,
+ IFCAP_LINKSTATE_NAME,
+ IFCAP_NETMAP_NAME,
+ IFCAP_RXCSUM_IPV6_NAME,
+ IFCAP_TXCSUM_IPV6_NAME,
+ IFCAP_HWSTATS_NAME,
+ IFCAP_TXRTLMT_NAME,
+ IFCAP_HWRXTSTMP_NAME,
+ IFCAP_MEXTPG_NAME,
+ IFCAP_TXTLS4_NAME,
+ IFCAP_TXTLS6_NAME,
+ IFCAP_VXLAN_HWCSUM_NAME,
+ IFCAP_VXLAN_HWTSO_NAME,
+ IFCAP_TXTLS_RTLMT_NAME,
+ IFCAP2_RXTLS4_NAME,
+ IFCAP2_RXTLS6_NAME,
+};
+_Static_assert(sizeof(ifcap_bit_names) >= IFCAP_B_SIZE * sizeof(char *),
+ "ifcap bit names missing from ifcap_bit_names");
+
#define IFQ_MAXLEN 50
#define IFNET_SLOWHZ 1 /* granularity is 1 second */
diff --git a/sys/netlink/netlink_route.h b/sys/netlink/netlink_bitset.h
copy from sys/netlink/netlink_route.h
copy to sys/netlink/netlink_bitset.h
--- a/sys/netlink/netlink_route.h
+++ b/sys/netlink/netlink_bitset.h
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2022 Alexander V. Chernikov <melifaro@FreeBSD.org>
+ * Copyright (c) 2023 Alexander V. Chernikov <melifaro@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,20 +24,34 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifndef _NETLINK_NETLINK_ROUTE_H_
-#define _NETLINK_NETLINK_ROUTE_H_
-#include <sys/types.h>
+/*
+ * Generic netlink message header and attributes
+ */
+#ifndef _NETLINK_NETLINK_BITSET_H_
+#define _NETLINK_NETLINK_BITSET_H_
+
+#include <netlink/netlink.h>
-#include <net/if.h>
-#include <net/if_types.h>
-#include <net/if_var.h>
+/* Bitset type nested attributes */
+enum {
+ NLA_BITSET_UNSPEC,
+ NLA_BITSET_NOMASK = 1, /* flag: mask of valid bits not provided */
+ NLA_BITSET_SIZE = 2, /* u32: max valid bit # */
+ NLA_BITSET_BITS = 3, /* nested: array of NLA_BITSET_BIT */
+ NLA_BITSET_VALUE = 4, /* binary: array of bit values */
+ NLA_BITSET_MASK = 5, /* binary: array of valid bits */
+ __NLA_BITSET_MAX,
+};
+#define NLA_BITSET_MAX (__NLA_BITSET_MAX - 1)
-#include <netlink/route/common.h>
-#include <netlink/route/ifaddrs.h>
-#include <netlink/route/interface.h>
-#include <netlink/route/neigh.h>
-#include <netlink/route/route.h>
-#include <netlink/route/nexthop.h>
+enum {
+ NLA_BITSET_BIT_UNSPEC,
+ NLA_BITSET_BIT_INDEX = 1, /* u32: index of the bit */
+ NLA_BITSET_BIT_NAME = 2, /* string: bit description */
+ NLA_BITSET_BIT_VALUE = 3, /* flag: provided if bit is set */
+ __NLA_BITSET_BIT_MAX,
+};
+#define NLA_BITSET_BIT_MAX (__NLA_BITSET_BIT_MAX - 1)
#endif
diff --git a/sys/netlink/netlink_route.h b/sys/netlink/netlink_route.h
--- a/sys/netlink/netlink_route.h
+++ b/sys/netlink/netlink_route.h
@@ -33,6 +33,7 @@
#include <net/if_types.h>
#include <net/if_var.h>
+#include <netlink/netlink_bitset.h>
#include <netlink/route/common.h>
#include <netlink/route/ifaddrs.h>
#include <netlink/route/interface.h>
diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h
--- a/sys/netlink/netlink_snl.h
+++ b/sys/netlink/netlink_snl.h
@@ -43,6 +43,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netlink/netlink.h>
+#include <netlink/netlink_bitset.h>
#define _roundup2(x, y) (((x)+((y)-1))&(~((y)-1)))
@@ -732,7 +733,7 @@
}
static inline bool
-snl_attr_dup_nla(struct snl_state *ss __unused, struct nlattr *nla,
+snl_attr_dup_nla(struct snl_state *ss, struct nlattr *nla,
const void *arg __unused, void *target)
{
void *ptr = snl_allocz(ss, nla->nla_len);
@@ -773,6 +774,89 @@
return (false);
}
+struct snl_attr_bit {
+ uint32_t bit_index;
+ char *bit_name;
+ int bit_value;
+};
+
+struct snl_attr_bits {
+ uint32_t num_bits;
+ struct snl_attr_bit **bits;
+};
+
+#define _OUT(_field) offsetof(struct snl_attr_bit, _field)
+static const struct snl_attr_parser _nla_p_bit[] = {
+ { .type = NLA_BITSET_BIT_INDEX, .off = _OUT(bit_index), .cb = snl_attr_get_uint32 },
+ { .type = NLA_BITSET_BIT_NAME, .off = _OUT(bit_name), .cb = snl_attr_dup_string },
+ { .type = NLA_BITSET_BIT_VALUE, .off = _OUT(bit_value), .cb = snl_attr_get_flag },
+};
+#undef _OUT
+SNL_DECLARE_ATTR_PARSER_EXT(_nla_bit_parser, sizeof(struct snl_attr_bit), _nla_p_bit, NULL);
+
+struct snl_attr_bitset {
+ uint32_t nla_bitset_size;
+ uint32_t *nla_bitset_mask;
+ uint32_t *nla_bitset_value;
+ struct snl_attr_bits bits;
+};
+
+#define _OUT(_field) offsetof(struct snl_attr_bitset, _field)
+static const struct snl_attr_parser _nla_p_bitset[] = {
+ { .type = NLA_BITSET_SIZE, .off = _OUT(nla_bitset_size), .cb = snl_attr_get_uint32 },
+ { .type = NLA_BITSET_BITS, .off = _OUT(bits), .cb = snl_attr_get_parray, .arg = &_nla_bit_parser },
+ { .type = NLA_BITSET_VALUE, .off = _OUT(nla_bitset_mask), .cb = snl_attr_dup_nla },
+ { .type = NLA_BITSET_MASK, .off = _OUT(nla_bitset_value), .cb = snl_attr_dup_nla },
+};
+
+static inline bool
+_cb_p_bitset(struct snl_state *ss __unused, void *_target)
+{
+ struct snl_attr_bitset *target = _target;
+
+ uint32_t sz_bytes = _roundup2(target->nla_bitset_size, 32) / 8;
+
+ if (target->nla_bitset_mask != NULL) {
+ struct nlattr *nla = (struct nlattr *)target->nla_bitset_mask;
+ uint32_t data_len = NLA_DATA_LEN(nla);
+
+ if (data_len != sz_bytes || _roundup2(data_len, 4) != data_len)
+ return (false);
+ target->nla_bitset_mask = (uint32_t *)NLA_DATA(nla);
+ }
+
+ if (target->nla_bitset_value != NULL) {
+ struct nlattr *nla = (struct nlattr *)target->nla_bitset_value;
+ uint32_t data_len = NLA_DATA_LEN(nla);
+
+ if (data_len != sz_bytes || _roundup2(data_len, 4) != data_len)
+ return (false);
+ target->nla_bitset_value = (uint32_t *)NLA_DATA(nla);
+ }
+ return (true);
+}
+#undef _OUT
+SNL_DECLARE_ATTR_PARSER_EXT(_nla_bitset_parser,
+ sizeof(struct snl_attr_bitset),
+ _nla_p_bitset, _cb_p_bitset);
+
+/*
+ * Parses the compact bitset representation.
+ */
+static inline bool
+snl_attr_get_bitset_c(struct snl_state *ss, struct nlattr *nla, const void *arg, void *_target)
+{
+ const struct snl_hdr_parser *p = &_nla_bitset_parser;
+ struct snl_attr_bitset *target = _target;
+
+ /* Assumes target points to the beginning of the structure */
+ if (!snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), p, _target))
+ return (false);
+ if (target->nla_bitset_mask == NULL || target->nla_bitset_value == NULL)
+ return (false);
+ return (true);
+}
+
static inline void
snl_field_get_uint8(struct snl_state *ss __unused, void *src, void *target)
{
@@ -1184,6 +1268,7 @@
static const struct snl_hdr_parser *snl_all_core_parsers[] = {
&snl_errmsg_parser, &snl_donemsg_parser,
+ &_nla_bit_parser, &_nla_bitset_parser,
};
#endif
diff --git a/sys/netlink/netlink_snl_route_parsers.h b/sys/netlink/netlink_snl_route_parsers.h
--- a/sys/netlink/netlink_snl_route_parsers.h
+++ b/sys/netlink/netlink_snl_route_parsers.h
@@ -186,12 +186,14 @@
uint32_t ifla_promiscuity;
struct rtnl_link_stats64 *ifla_stats64;
struct nlattr *iflaf_orig_hwaddr;
+ struct snl_attr_bitset iflaf_caps;
};
#define _IN(_field) offsetof(struct ifinfomsg, _field)
#define _OUT(_field) offsetof(struct snl_parsed_link, _field)
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 },
};
SNL_DECLARE_ATTR_PARSER(_link_fbsd_parser, _nla_p_link_fbsd);
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -253,6 +253,33 @@
return (nlattr_add(nw, attr, addr_len, addr_data));
}
+static bool
+dump_iface_caps(struct nl_writer *nw, struct ifnet *ifp)
+{
+ int off = nlattr_add_nested(nw, IFLAF_CAPS);
+ uint32_t active_caps[roundup2(NL_IFCAP_SIZE, 32) / 32] = {};
+ uint32_t all_caps[roundup2(NL_IFCAP_SIZE, 32) / 32] = {};
+
+ MPASS(sizeof(active_caps) >= 8);
+ MPASS(sizeof(all_caps) >= 8);
+
+ if (off == 0)
+ return (false);
+
+ active_caps[0] = (uint32_t)if_getcapabilities(ifp);
+ all_caps[0] = (uint32_t)if_getcapenable(ifp);
+ active_caps[1] = (uint32_t)if_getcapabilities2(ifp);
+ all_caps[1] = (uint32_t)if_getcapenable2(ifp);
+
+ nlattr_add_u32(nw, NLA_BITSET_SIZE, NL_IFCAP_SIZE);
+ nlattr_add(nw, NLA_BITSET_MASK, sizeof(all_caps), all_caps);
+ nlattr_add(nw, NLA_BITSET_VALUE, sizeof(active_caps), active_caps);
+
+ nlattr_set_len(nw, off);
+
+ return (true);
+}
+
/*
* Dumps interface state, properties and metrics.
* @nw: message writer
@@ -320,6 +347,7 @@
int off = nlattr_add_nested(nw, IFLA_FREEBSD);
if (off != 0) {
get_hwaddr(nw, ifp);
+ dump_iface_caps(nw, ifp);
nlattr_set_len(nw, off);
}
diff --git a/sys/netlink/route/interface.h b/sys/netlink/route/interface.h
--- a/sys/netlink/route/interface.h
+++ b/sys/netlink/route/interface.h
@@ -151,6 +151,7 @@
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_MAX
};
#define IFLAF_MAX (__IFLAF_MAX - 1)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Aug 4, 3:23 AM (16 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35931218
Default Alt Text
D40331.id122603.diff (14 KB)
Attached To
Mode
D40331: netlink: dump interface capabilities with other interface data
Attached
Detach File
Event Timeline
Log In to Comment