mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
netlink: dump interface capabilities with other interface data.
This change exports interface capabilities using the standard Netlink attribute type, bitset, and switches `ifconfig(8)` to use it when displaying interface data. Bitset comes in two representations. The first one is "compact", where the bits are exported via two arrays - "mask" listing the "valid" bits and "values, providing the values for those bits. The second one is more verbose, listing each bit as a separate item, with its name, id and value. The latter option is handy when submitting update requests. The support for setting capabilities will be added in the upcoming diffs. Differential Revision: https://reviews.freebsd.org/D40331
This commit is contained in:
parent
e5d7100c09
commit
c344eff910
|
@ -55,6 +55,7 @@ static const char rcsid[] =
|
||||||
#include <net/ethernet.h>
|
#include <net/ethernet.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/if_dl.h>
|
#include <net/if_dl.h>
|
||||||
|
#include <net/if_strings.h>
|
||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
|
|
||||||
|
@ -1585,6 +1586,8 @@ unsetifdescr(if_ctx *ctx, const char *val __unused, int value __unused)
|
||||||
setifdescr(ctx, "", 0);
|
setifdescr(ctx, "", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITHOUT_NETLINK
|
||||||
|
|
||||||
#define IFFBITS \
|
#define IFFBITS \
|
||||||
"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \
|
"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \
|
||||||
"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
|
"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
|
||||||
|
@ -1656,7 +1659,7 @@ print_ifcap_nv(if_ctx *ctx)
|
||||||
Perror("ioctl (SIOCGIFCAP)");
|
Perror("ioctl (SIOCGIFCAP)");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
print_ifcap(if_ctx *ctx)
|
print_ifcap(if_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct ifreq ifr = {};
|
struct ifreq ifr = {};
|
||||||
|
@ -1675,6 +1678,7 @@ print_ifcap(if_ctx *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
print_ifstatus(if_ctx *ctx)
|
print_ifstatus(if_ctx *ctx)
|
||||||
|
|
|
@ -275,7 +275,6 @@ bool match_ether(const struct sockaddr_dl *sdl);
|
||||||
bool match_if_flags(struct ifconfig_args *args, int if_flags);
|
bool match_if_flags(struct ifconfig_args *args, int if_flags);
|
||||||
int ifconfig_ioctl(if_ctx *ctx, int iscreate, const struct afswtch *uafp);
|
int ifconfig_ioctl(if_ctx *ctx, int iscreate, const struct afswtch *uafp);
|
||||||
bool group_member(const char *ifname, const char *match, const char *nomatch);
|
bool group_member(const char *ifname, const char *match, const char *nomatch);
|
||||||
void print_ifcap(if_ctx *ctx);
|
|
||||||
void tunnel_status(if_ctx *ctx);
|
void tunnel_status(if_ctx *ctx);
|
||||||
struct afswtch *af_getbyfamily(int af);
|
struct afswtch *af_getbyfamily(int af);
|
||||||
void af_other_status(if_ctx *ctx);
|
void af_other_status(if_ctx *ctx);
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include <net/ethernet.h>
|
#include <net/ethernet.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/if_dl.h>
|
#include <net/if_dl.h>
|
||||||
|
#include <net/if_strings.h>
|
||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
#include "ifconfig.h"
|
#include "ifconfig.h"
|
||||||
#include "ifconfig_netlink.h"
|
#include "ifconfig_netlink.h"
|
||||||
|
@ -343,6 +344,28 @@ sort_iface_ifaddrs(struct snl_state *ss, struct iface *iface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
status_nl(if_ctx *ctx, struct iface *iface)
|
status_nl(if_ctx *ctx, struct iface *iface)
|
||||||
{
|
{
|
||||||
|
@ -360,8 +383,7 @@ status_nl(if_ctx *ctx, struct iface *iface)
|
||||||
if (link->ifla_ifalias != NULL)
|
if (link->ifla_ifalias != NULL)
|
||||||
printf("\tdescription: %s\n", link->ifla_ifalias);
|
printf("\tdescription: %s\n", link->ifla_ifalias);
|
||||||
|
|
||||||
/* TODO: convert to netlink */
|
print_ifcaps(ctx, link);
|
||||||
print_ifcap(ctx);
|
|
||||||
tunnel_status(ctx);
|
tunnel_status(ctx);
|
||||||
|
|
||||||
if (args->allfamilies | (args->afp != NULL && args->afp->af_af == AF_LINK)) {
|
if (args->allfamilies | (args->afp != NULL && args->afp->af_af == AF_LINK)) {
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
#include <net/if_arp.h>
|
#include <net/if_arp.h>
|
||||||
#include <net/if_clone.h>
|
#include <net/if_clone.h>
|
||||||
#include <net/if_dl.h>
|
#include <net/if_dl.h>
|
||||||
|
#include <net/if_strings.h>
|
||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
#include <net/if_var.h>
|
#include <net/if_var.h>
|
||||||
#include <net/if_media.h>
|
#include <net/if_media.h>
|
||||||
|
|
146
sys/net/if.h
146
sys/net/if.h
|
@ -221,42 +221,86 @@ struct if_data {
|
||||||
* to do the right thing. However, having the filter here
|
* to do the right thing. However, having the filter here
|
||||||
* avoids replication of the same code in all individual drivers.
|
* avoids replication of the same code in all individual drivers.
|
||||||
*/
|
*/
|
||||||
#define IFCAP_RXCSUM 0x00001 /* can offload checksum on RX */
|
|
||||||
#define IFCAP_TXCSUM 0x00002 /* can offload checksum on TX */
|
/* IFCAP values as bit indexes */
|
||||||
#define IFCAP_NETCONS 0x00004 /* can be a network console */
|
|
||||||
#define IFCAP_VLAN_MTU 0x00008 /* VLAN-compatible MTU */
|
#define IFCAP_B_RXCSUM 0 /* can offload checksum on RX */
|
||||||
#define IFCAP_VLAN_HWTAGGING 0x00010 /* hardware VLAN tag support */
|
#define IFCAP_B_TXCSUM 1 /* can offload checksum on TX */
|
||||||
#define IFCAP_JUMBO_MTU 0x00020 /* 9000 byte MTU supported */
|
#define IFCAP_B_NETCONS 2 /* can be a network console */
|
||||||
#define IFCAP_POLLING 0x00040 /* driver supports polling */
|
#define IFCAP_B_VLAN_MTU 3 /* VLAN-compatible MTU */
|
||||||
#define IFCAP_VLAN_HWCSUM 0x00080 /* can do IFCAP_HWCSUM on VLANs */
|
#define IFCAP_B_VLAN_HWTAGGING 4 /* hardware VLAN tag support */
|
||||||
#define IFCAP_TSO4 0x00100 /* can do TCP Segmentation Offload */
|
#define IFCAP_B_JUMBO_MTU 5 /* 9000 byte MTU supported */
|
||||||
#define IFCAP_TSO6 0x00200 /* can do TCP6 Segmentation Offload */
|
#define IFCAP_B_POLLING 6 /* driver supports polling */
|
||||||
#define IFCAP_LRO 0x00400 /* can do Large Receive Offload */
|
#define IFCAP_B_VLAN_HWCSUM 7 /* can do IFCAP_HWCSUM on VLANs */
|
||||||
#define IFCAP_WOL_UCAST 0x00800 /* wake on any unicast frame */
|
#define IFCAP_B_TSO4 8 /* can do TCP Segmentation Offload */
|
||||||
#define IFCAP_WOL_MCAST 0x01000 /* wake on any multicast frame */
|
#define IFCAP_B_TSO6 9 /* can do TCP6 Segmentation Offload */
|
||||||
#define IFCAP_WOL_MAGIC 0x02000 /* wake on any Magic Packet */
|
#define IFCAP_B_LRO 10 /* can do Large Receive Offload */
|
||||||
#define IFCAP_TOE4 0x04000 /* interface can offload TCP */
|
#define IFCAP_B_WOL_UCAST 11 /* wake on any unicast frame */
|
||||||
#define IFCAP_TOE6 0x08000 /* interface can offload TCP6 */
|
#define IFCAP_B_WOL_MCAST 12 /* wake on any multicast frame */
|
||||||
#define IFCAP_VLAN_HWFILTER 0x10000 /* interface hw can filter vlan tag */
|
#define IFCAP_B_WOL_MAGIC 13 /* wake on any Magic Packet */
|
||||||
#define IFCAP_NV 0x20000 /* can do SIOCGIFCAPNV/SIOCSIFCAPNV */
|
#define IFCAP_B_TOE4 14 /* interface can offload TCP */
|
||||||
#define IFCAP_VLAN_HWTSO 0x40000 /* can do IFCAP_TSO on VLANs */
|
#define IFCAP_B_TOE6 15 /* interface can offload TCP6 */
|
||||||
#define IFCAP_LINKSTATE 0x80000 /* the runtime link state is dynamic */
|
#define IFCAP_B_VLAN_HWFILTER 16 /* interface hw can filter vlan tag */
|
||||||
#define IFCAP_NETMAP 0x100000 /* netmap mode supported/enabled */
|
#define IFCAP_B_NV 17 /* can do SIOCGIFCAPNV/SIOCSIFCAPNV */
|
||||||
#define IFCAP_RXCSUM_IPV6 0x200000 /* can offload checksum on IPv6 RX */
|
#define IFCAP_B_VLAN_HWTSO 18 /* can do IFCAP_TSO on VLANs */
|
||||||
#define IFCAP_TXCSUM_IPV6 0x400000 /* can offload checksum on IPv6 TX */
|
#define IFCAP_B_LINKSTATE 19 /* the runtime link state is dynamic */
|
||||||
#define IFCAP_HWSTATS 0x800000 /* manages counters internally */
|
#define IFCAP_B_NETMAP 20 /* netmap mode supported/enabled */
|
||||||
#define IFCAP_TXRTLMT 0x1000000 /* hardware supports TX rate limiting */
|
#define IFCAP_B_RXCSUM_IPV6 21 /* can offload checksum on IPv6 RX */
|
||||||
#define IFCAP_HWRXTSTMP 0x2000000 /* hardware rx timestamping */
|
#define IFCAP_B_TXCSUM_IPV6 22 /* can offload checksum on IPv6 TX */
|
||||||
#define IFCAP_MEXTPG 0x4000000 /* understands M_EXTPG mbufs */
|
#define IFCAP_B_HWSTATS 23 /* manages counters internally */
|
||||||
#define IFCAP_TXTLS4 0x8000000 /* can do TLS encryption and segmentation for TCP */
|
#define IFCAP_B_TXRTLMT 24 /* hardware supports TX rate limiting */
|
||||||
#define IFCAP_TXTLS6 0x10000000 /* can do TLS encryption and segmentation for TCP6 */
|
#define IFCAP_B_HWRXTSTMP 25 /* hardware rx timestamping */
|
||||||
#define IFCAP_VXLAN_HWCSUM 0x20000000 /* can do IFCAN_HWCSUM on VXLANs */
|
#define IFCAP_B_MEXTPG 26 /* understands M_EXTPG mbufs */
|
||||||
#define IFCAP_VXLAN_HWTSO 0x40000000 /* can do IFCAP_TSO on VXLANs */
|
#define IFCAP_B_TXTLS4 27 /* can do TLS encryption and segmentation for TCP */
|
||||||
#define IFCAP_TXTLS_RTLMT 0x80000000 /* can do TLS with rate limiting */
|
#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_BIT(x) (1 << (x))
|
||||||
|
|
||||||
|
#define IFCAP_RXCSUM IFCAP_BIT(IFCAP_B_RXCSUM)
|
||||||
|
#define IFCAP_TXCSUM IFCAP_BIT(IFCAP_B_TXCSUM)
|
||||||
|
#define IFCAP_NETCONS IFCAP_BIT(IFCAP_B_NETCONS)
|
||||||
|
#define IFCAP_VLAN_MTU IFCAP_BIT(IFCAP_B_VLAN_MTU)
|
||||||
|
#define IFCAP_VLAN_HWTAGGING IFCAP_BIT(IFCAP_B_VLAN_HWTAGGING)
|
||||||
|
#define IFCAP_JUMBO_MTU IFCAP_BIT(IFCAP_B_JUMBO_MTU)
|
||||||
|
#define IFCAP_POLLING IFCAP_BIT(IFCAP_B_POLLING)
|
||||||
|
#define IFCAP_VLAN_HWCSUM IFCAP_BIT(IFCAP_B_VLAN_HWCSUM)
|
||||||
|
#define IFCAP_TSO4 IFCAP_BIT(IFCAP_B_TSO4)
|
||||||
|
#define IFCAP_TSO6 IFCAP_BIT(IFCAP_B_TSO6)
|
||||||
|
#define IFCAP_LRO IFCAP_BIT(IFCAP_B_LRO)
|
||||||
|
#define IFCAP_WOL_UCAST IFCAP_BIT(IFCAP_B_WOL_UCAST)
|
||||||
|
#define IFCAP_WOL_MCAST IFCAP_BIT(IFCAP_B_WOL_MCAST)
|
||||||
|
#define IFCAP_WOL_MAGIC IFCAP_BIT(IFCAP_B_WOL_MAGIC)
|
||||||
|
#define IFCAP_TOE4 IFCAP_BIT(IFCAP_B_TOE4)
|
||||||
|
#define IFCAP_TOE6 IFCAP_BIT(IFCAP_B_TOE6)
|
||||||
|
#define IFCAP_VLAN_HWFILTER IFCAP_BIT(IFCAP_B_VLAN_HWFILTER)
|
||||||
|
#define IFCAP_NV IFCAP_BIT(IFCAP_B_NV)
|
||||||
|
#define IFCAP_VLAN_HWTSO IFCAP_BIT(IFCAP_B_VLAN_HWTSO)
|
||||||
|
#define IFCAP_LINKSTATE IFCAP_BIT(IFCAP_B_LINKSTATE)
|
||||||
|
#define IFCAP_NETMAP IFCAP_BIT(IFCAP_B_NETMAP)
|
||||||
|
#define IFCAP_RXCSUM_IPV6 IFCAP_BIT(IFCAP_B_RXCSUM_IPV6)
|
||||||
|
#define IFCAP_TXCSUM_IPV6 IFCAP_BIT(IFCAP_B_TXCSUM_IPV6)
|
||||||
|
#define IFCAP_HWSTATS IFCAP_BIT(IFCAP_B_HWSTATS)
|
||||||
|
#define IFCAP_TXRTLMT IFCAP_BIT(IFCAP_B_TXRTLMT)
|
||||||
|
#define IFCAP_HWRXTSTMP IFCAP_BIT(IFCAP_B_HWRXTSTMP)
|
||||||
|
#define IFCAP_MEXTPG IFCAP_BIT(IFCAP_B_MEXTPG)
|
||||||
|
#define IFCAP_TXTLS4 IFCAP_BIT(IFCAP_B_TXTLS4)
|
||||||
|
#define IFCAP_TXTLS6 IFCAP_BIT(IFCAP_B_TXTLS6)
|
||||||
|
#define IFCAP_VXLAN_HWCSUM IFCAP_BIT(IFCAP_B_VXLAN_HWCSUM)
|
||||||
|
#define IFCAP_VXLAN_HWTSO IFCAP_BIT(IFCAP_B_VXLAN_HWTSO)
|
||||||
|
#define IFCAP_TXTLS_RTLMT IFCAP_BIT(IFCAP_B_TXTLS_RTLMT)
|
||||||
|
|
||||||
/* IFCAP2_* are integers, not bits. */
|
/* IFCAP2_* are integers, not bits. */
|
||||||
#define IFCAP2_RXTLS4 0
|
#define IFCAP2_RXTLS4 (IFCAP_B_RXTLS4 - 32)
|
||||||
#define IFCAP2_RXTLS6 1
|
#define IFCAP2_RXTLS6 (IFCAP_B_RXTLS6 - 32)
|
||||||
|
|
||||||
#define IFCAP2_BIT(x) (1UL << (x))
|
#define IFCAP2_BIT(x) (1UL << (x))
|
||||||
|
|
||||||
|
@ -271,40 +315,6 @@ struct if_data {
|
||||||
#define IFCAP_CANTCHANGE (IFCAP_NETMAP | IFCAP_NV)
|
#define IFCAP_CANTCHANGE (IFCAP_NETMAP | IFCAP_NV)
|
||||||
#define IFCAP_ALLCAPS 0xffffffff
|
#define IFCAP_ALLCAPS 0xffffffff
|
||||||
|
|
||||||
#define IFCAP_RXCSUM_NAME "RXCSUM"
|
|
||||||
#define IFCAP_TXCSUM_NAME "TXCSUM"
|
|
||||||
#define IFCAP_NETCONS_NAME "NETCONS"
|
|
||||||
#define IFCAP_VLAN_MTU_NAME "VLAN_MTU"
|
|
||||||
#define IFCAP_VLAN_HWTAGGING_NAME "VLAN_HWTAGGING"
|
|
||||||
#define IFCAP_JUMBO_MTU_NAME "JUMBO_MTU"
|
|
||||||
#define IFCAP_POLLING_NAME "POLLING"
|
|
||||||
#define IFCAP_VLAN_HWCSUM_NAME "VLAN_HWCSUM"
|
|
||||||
#define IFCAP_TSO4_NAME "TSO4"
|
|
||||||
#define IFCAP_TSO6_NAME "TSO6"
|
|
||||||
#define IFCAP_LRO_NAME "LRO"
|
|
||||||
#define IFCAP_WOL_UCAST_NAME "WOL_UCAST"
|
|
||||||
#define IFCAP_WOL_MCAST_NAME "WOL_MCAST"
|
|
||||||
#define IFCAP_WOL_MAGIC_NAME "WOL_MAGIC"
|
|
||||||
#define IFCAP_TOE4_NAME "TOE4"
|
|
||||||
#define IFCAP_TOE6_NAME "TOE6"
|
|
||||||
#define IFCAP_VLAN_HWFILTER_NAME "VLAN_HWFILTER"
|
|
||||||
#define IFCAP_VLAN_HWTSO_NAME "VLAN_HWTSO"
|
|
||||||
#define IFCAP_LINKSTATE_NAME "LINKSTATE"
|
|
||||||
#define IFCAP_NETMAP_NAME "NETMAP"
|
|
||||||
#define IFCAP_RXCSUM_IPV6_NAME "RXCSUM_IPV6"
|
|
||||||
#define IFCAP_TXCSUM_IPV6_NAME "TXCSUM_IPV6"
|
|
||||||
#define IFCAP_HWSTATS_NAME "HWSTATS"
|
|
||||||
#define IFCAP_TXRTLMT_NAME "TXRTLMT"
|
|
||||||
#define IFCAP_HWRXTSTMP_NAME "HWRXTSTMP"
|
|
||||||
#define IFCAP_MEXTPG_NAME "MEXTPG"
|
|
||||||
#define IFCAP_TXTLS4_NAME "TXTLS4"
|
|
||||||
#define IFCAP_TXTLS6_NAME "TXTLS6"
|
|
||||||
#define IFCAP_VXLAN_HWCSUM_NAME "VXLAN_HWCSUM"
|
|
||||||
#define IFCAP_VXLAN_HWTSO_NAME "VXLAN_HWTSO"
|
|
||||||
#define IFCAP_TXTLS_RTLMT_NAME "TXTLS_RTLMT"
|
|
||||||
#define IFCAP2_RXTLS4_NAME "RXTLS4"
|
|
||||||
#define IFCAP2_RXTLS6_NAME "RXTLS6"
|
|
||||||
|
|
||||||
#define IFQ_MAXLEN 50
|
#define IFQ_MAXLEN 50
|
||||||
#define IFNET_SLOWHZ 1 /* granularity is 1 second */
|
#define IFNET_SLOWHZ 1 /* granularity is 1 second */
|
||||||
|
|
||||||
|
|
106
sys/net/if_strings.h
Normal file
106
sys/net/if_strings.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*-
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_IF_STRINGS_H_
|
||||||
|
#define _NET_IF_STRINGS_H_
|
||||||
|
|
||||||
|
#define IFCAP_RXCSUM_NAME "RXCSUM"
|
||||||
|
#define IFCAP_TXCSUM_NAME "TXCSUM"
|
||||||
|
#define IFCAP_NETCONS_NAME "NETCONS"
|
||||||
|
#define IFCAP_VLAN_MTU_NAME "VLAN_MTU"
|
||||||
|
#define IFCAP_VLAN_HWTAGGING_NAME "VLAN_HWTAGGING"
|
||||||
|
#define IFCAP_JUMBO_MTU_NAME "JUMBO_MTU"
|
||||||
|
#define IFCAP_POLLING_NAME "POLLING"
|
||||||
|
#define IFCAP_VLAN_HWCSUM_NAME "VLAN_HWCSUM"
|
||||||
|
#define IFCAP_TSO4_NAME "TSO4"
|
||||||
|
#define IFCAP_TSO6_NAME "TSO6"
|
||||||
|
#define IFCAP_LRO_NAME "LRO"
|
||||||
|
#define IFCAP_WOL_UCAST_NAME "WOL_UCAST"
|
||||||
|
#define IFCAP_WOL_MCAST_NAME "WOL_MCAST"
|
||||||
|
#define IFCAP_WOL_MAGIC_NAME "WOL_MAGIC"
|
||||||
|
#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"
|
||||||
|
#define IFCAP_RXCSUM_IPV6_NAME "RXCSUM_IPV6"
|
||||||
|
#define IFCAP_TXCSUM_IPV6_NAME "TXCSUM_IPV6"
|
||||||
|
#define IFCAP_HWSTATS_NAME "HWSTATS"
|
||||||
|
#define IFCAP_TXRTLMT_NAME "TXRTLMT"
|
||||||
|
#define IFCAP_HWRXTSTMP_NAME "HWRXTSTMP"
|
||||||
|
#define IFCAP_MEXTPG_NAME "MEXTPG"
|
||||||
|
#define IFCAP_TXTLS4_NAME "TXTLS4"
|
||||||
|
#define IFCAP_TXTLS6_NAME "TXTLS6"
|
||||||
|
#define IFCAP_VXLAN_HWCSUM_NAME "VXLAN_HWCSUM"
|
||||||
|
#define IFCAP_VXLAN_HWTSO_NAME "VXLAN_HWTSO"
|
||||||
|
#define IFCAP_TXTLS_RTLMT_NAME "TXTLS_RTLMT"
|
||||||
|
#define IFCAP_RXTLS4_NAME "RXTLS4"
|
||||||
|
#define IFCAP_RXTLS6_NAME "RXTLS6"
|
||||||
|
|
||||||
|
#define IFCAP2_RXTLS4_NAME IFCAP_RXTLS4_NAME
|
||||||
|
#define IFCAP2_RXTLS6_NAME IFCAP_RXTLS6_NAME
|
||||||
|
|
||||||
|
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,
|
||||||
|
IFCAP_RXTLS4_NAME,
|
||||||
|
IFCAP_RXTLS6_NAME,
|
||||||
|
};
|
||||||
|
_Static_assert(sizeof(ifcap_bit_names) >= IFCAP_B_SIZE * sizeof(char *),
|
||||||
|
"ifcap bit names missing from ifcap_bit_names");
|
||||||
|
|
||||||
|
#endif
|
57
sys/netlink/netlink_bitset.h
Normal file
57
sys/netlink/netlink_bitset.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*-
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic netlink message header and attributes
|
||||||
|
*/
|
||||||
|
#ifndef _NETLINK_NETLINK_BITSET_H_
|
||||||
|
#define _NETLINK_NETLINK_BITSET_H_
|
||||||
|
|
||||||
|
#include <netlink/netlink.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)
|
||||||
|
|
||||||
|
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
|
|
@ -33,6 +33,7 @@
|
||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
#include <net/if_var.h>
|
#include <net/if_var.h>
|
||||||
|
|
||||||
|
#include <netlink/netlink_bitset.h>
|
||||||
#include <netlink/route/common.h>
|
#include <netlink/route/common.h>
|
||||||
#include <netlink/route/ifaddrs.h>
|
#include <netlink/route/ifaddrs.h>
|
||||||
#include <netlink/route/interface.h>
|
#include <netlink/route/interface.h>
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netlink/netlink.h>
|
#include <netlink/netlink.h>
|
||||||
|
#include <netlink/netlink_bitset.h>
|
||||||
|
|
||||||
#define _roundup2(x, y) (((x)+((y)-1))&(~((y)-1)))
|
#define _roundup2(x, y) (((x)+((y)-1))&(~((y)-1)))
|
||||||
|
|
||||||
|
@ -732,7 +733,7 @@ snl_attr_get_nla(struct snl_state *ss __unused, struct nlattr *nla,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
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)
|
const void *arg __unused, void *target)
|
||||||
{
|
{
|
||||||
void *ptr = snl_allocz(ss, nla->nla_len);
|
void *ptr = snl_allocz(ss, nla->nla_len);
|
||||||
|
@ -773,6 +774,90 @@ snl_attr_dup_struct(struct snl_state *ss, struct nlattr *nla,
|
||||||
return (false);
|
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 __unused, 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
|
static inline void
|
||||||
snl_field_get_uint8(struct snl_state *ss __unused, void *src, void *target)
|
snl_field_get_uint8(struct snl_state *ss __unused, void *src, void *target)
|
||||||
{
|
{
|
||||||
|
@ -1184,6 +1269,7 @@ snl_send_msgs(struct snl_writer *nw)
|
||||||
|
|
||||||
static const struct snl_hdr_parser *snl_all_core_parsers[] = {
|
static const struct snl_hdr_parser *snl_all_core_parsers[] = {
|
||||||
&snl_errmsg_parser, &snl_donemsg_parser,
|
&snl_errmsg_parser, &snl_donemsg_parser,
|
||||||
|
&_nla_bit_parser, &_nla_bitset_parser,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -186,12 +186,14 @@ struct snl_parsed_link {
|
||||||
uint32_t ifla_promiscuity;
|
uint32_t ifla_promiscuity;
|
||||||
struct rtnl_link_stats64 *ifla_stats64;
|
struct rtnl_link_stats64 *ifla_stats64;
|
||||||
struct nlattr *iflaf_orig_hwaddr;
|
struct nlattr *iflaf_orig_hwaddr;
|
||||||
|
struct snl_attr_bitset iflaf_caps;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define _IN(_field) offsetof(struct ifinfomsg, _field)
|
#define _IN(_field) offsetof(struct ifinfomsg, _field)
|
||||||
#define _OUT(_field) offsetof(struct snl_parsed_link, _field)
|
#define _OUT(_field) offsetof(struct snl_parsed_link, _field)
|
||||||
static const struct snl_attr_parser _nla_p_link_fbsd[] = {
|
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_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);
|
SNL_DECLARE_ATTR_PARSER(_link_fbsd_parser, _nla_p_link_fbsd);
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,33 @@ dump_sa(struct nl_writer *nw, int attr, const struct sockaddr *sa)
|
||||||
return (nlattr_add(nw, attr, addr_len, addr_data));
|
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(IFCAP_B_SIZE, 32) / 32] = {};
|
||||||
|
uint32_t all_caps[roundup2(IFCAP_B_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, IFCAP_B_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.
|
* Dumps interface state, properties and metrics.
|
||||||
* @nw: message writer
|
* @nw: message writer
|
||||||
|
@ -320,6 +347,7 @@ dump_iface(struct nl_writer *nw, struct ifnet *ifp, const struct nlmsghdr *hdr,
|
||||||
int off = nlattr_add_nested(nw, IFLA_FREEBSD);
|
int off = nlattr_add_nested(nw, IFLA_FREEBSD);
|
||||||
if (off != 0) {
|
if (off != 0) {
|
||||||
get_hwaddr(nw, ifp);
|
get_hwaddr(nw, ifp);
|
||||||
|
dump_iface_caps(nw, ifp);
|
||||||
|
|
||||||
nlattr_set_len(nw, off);
|
nlattr_set_len(nw, off);
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,6 +151,7 @@ enum {
|
||||||
IFLAF_UNSPEC = 0,
|
IFLAF_UNSPEC = 0,
|
||||||
IFLAF_ORIG_IFNAME = 1, /* string, original interface name at creation */
|
IFLAF_ORIG_IFNAME = 1, /* string, original interface name at creation */
|
||||||
IFLAF_ORIG_HWADDR = 2, /* binary, original hardware address */
|
IFLAF_ORIG_HWADDR = 2, /* binary, original hardware address */
|
||||||
|
IFLAF_CAPS = 3, /* bitset, interface capabilities */
|
||||||
__IFLAF_MAX
|
__IFLAF_MAX
|
||||||
};
|
};
|
||||||
#define IFLAF_MAX (__IFLAF_MAX - 1)
|
#define IFLAF_MAX (__IFLAF_MAX - 1)
|
||||||
|
|
Loading…
Reference in a new issue