Page MenuHomeFreeBSD

D40331.id122603.diff
No OneTemporary

D40331.id122603.diff

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

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)

Event Timeline