Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F139671114
D32551.id105072.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
D32551.id105072.diff
View Options
diff --git a/rescue/rescue/Makefile b/rescue/rescue/Makefile
--- a/rescue/rescue/Makefile
+++ b/rescue/rescue/Makefile
@@ -137,8 +137,18 @@
CRUNCH_LIBS+= -l80211 -lalias -lcam -lncursesw -ldevstat -lipsec -llzma
.if ${MK_ZFS} != "no"
-CRUNCH_LIBS+= -lavl -lzpool -lzfs_core -lzfs -lnvpair -lpthread -luutil -lumem
-CRUNCH_LIBS+= -lbe -lzfsbootenv -lzutil -ltpool -lspl -licp_rescue
+CRUNCH_LIBS+= -lavl -lpthread -luutil -lumem -ltpool -lspl
+CRUNCH_LIBS_zfs+= ${LIBBE} \
+ ${LIBZPOOL} \
+ ${LIBZUTIL} \
+ ${LIBZFS} \
+ ${LIBZFS_CORE} \
+ ${LIBZFSBOOTENV} \
+ ${LIBICP_RESCUE} \
+ ${LIBNVPAIR}
+CRUNCH_LIBS_bectl+= ${CRUNCH_LIBS_zfs}
+CRUNCH_LIBS_zpool+= ${CRUNCH_LIBS_zfs}
+CRUNCH_LIBS_zdb+= ${CRUNCH_LIBS_zfs}
.else
# liblzma needs pthread
CRUNCH_LIBS+= -lpthread
@@ -235,6 +245,8 @@
CRUNCH_LIBS+= ${OBJTOP}/lib/libifconfig/libifconfig.a
CRUNCH_BUILDOPTS+= CRUNCH_CFLAGS+=-I${OBJTOP}/lib/libifconfig
+CRUNCH_LIBS_ifconfig+= ${LIBNV}
+
CRUNCH_LIBS+= -lm
.if ${MK_ISCSI} != "no"
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -46,7 +46,10 @@
struct cmd;
typedef void c_func(const char *cmd, int arg, int s, const struct afswtch *afp);
-typedef void c_func2(const char *arg1, const char *arg2, int s, const struct afswtch *afp);
+typedef void c_func2(const char *arg1, const char *arg2, int s,
+ const struct afswtch *afp);
+typedef void c_func3(const char *cmd, const char *arg, int s,
+ const struct afswtch *afp);
struct cmd {
const char *c_name;
@@ -54,9 +57,12 @@
#define NEXTARG 0xffffff /* has following arg */
#define NEXTARG2 0xfffffe /* has 2 following args */
#define OPTARG 0xfffffd /* has optional following arg */
+#define SPARAM 0xfffffc /* parameter is string c_sparameter */
+ const char *c_sparameter;
union {
c_func *c_func;
c_func2 *c_func2;
+ c_func3 *c_func3;
} c_u;
int c_iscloneop;
struct cmd *c_next;
@@ -72,15 +78,66 @@
#define DECL_CMD_FUNC(name, cmd, arg) \
void name(const char *cmd, int arg, int s, const struct afswtch *afp)
#define DECL_CMD_FUNC2(name, arg1, arg2) \
- void name(const char *arg1, const char *arg2, int s, const struct afswtch *afp)
-
-#define DEF_CMD(name, param, func) { name, param, { .c_func = func }, 0, NULL }
-#define DEF_CMD_ARG(name, func) { name, NEXTARG, { .c_func = func }, 0, NULL }
-#define DEF_CMD_OPTARG(name, func) { name, OPTARG, { .c_func = func }, 0, NULL }
-#define DEF_CMD_ARG2(name, func) { name, NEXTARG2, { .c_func2 = func }, 0, NULL }
-#define DEF_CLONE_CMD(name, param, func) { name, param, { .c_func = func }, 1, NULL }
-#define DEF_CLONE_CMD_ARG(name, func) { name, NEXTARG, { .c_func = func }, 1, NULL }
-#define DEF_CLONE_CMD_ARG2(name, func) { name, NEXTARG2, { .c_func2 = func }, 1, NULL }
+ void name(const char *arg1, const char *arg2, int s, \
+ const struct afswtch *afp)
+
+#define DEF_CMD(name, param, func) { \
+ .c_name = (name), \
+ .c_parameter = (param), \
+ .c_u = { .c_func = (func) }, \
+ .c_iscloneop = 0, \
+ .c_next = NULL, \
+}
+#define DEF_CMD_ARG(name, func) { \
+ .c_name = (name), \
+ .c_parameter = NEXTARG, \
+ .c_u = { .c_func = (func) }, \
+ .c_iscloneop = 0, \
+ .c_next = NULL, \
+}
+#define DEF_CMD_OPTARG(name, func) { \
+ .c_name = (name), \
+ .c_parameter = OPTARG, \
+ .c_u = { .c_func = (func) }, \
+ .c_iscloneop = 0, \
+ .c_next = NULL, \
+}
+#define DEF_CMD_ARG2(name, func) { \
+ .c_name = (name), \
+ .c_parameter = NEXTARG2, \
+ .c_u = { .c_func2 = (func) }, \
+ .c_iscloneop = 0, \
+ .c_next = NULL, \
+}
+#define DEF_CMD_SARG(name, sparam, func) { \
+ .c_name = (name), \
+ .c_parameter = SPARAM, \
+ .c_sparameter = (sparam), \
+ .c_u = { .c_func3 = (func) }, \
+ .c_iscloneop = 0, \
+ .c_next = NULL, \
+}
+#define DEF_CLONE_CMD(name, param, func) { \
+ .c_name = (name), \
+ .c_parameter = (param), \
+ .c_u = { .c_func = (func) }, \
+ .c_iscloneop = 1, \
+ .c_next = NULL, \
+}
+#define DEF_CLONE_CMD_ARG(name, func) { \
+ .c_name = (name), \
+ .c_parameter = NEXTARG, \
+ .c_u = { .c_func = (func) }, \
+ .c_iscloneop = 1, \
+ .c_next = NULL, \
+}
+#define DEF_CLONE_CMD_ARG2(name, func) { \
+ .c_name = (name), \
+ .c_parameter = NEXTARG2, \
+ .c_u = { .c_func2 = (func) }, \
+ .c_iscloneop = 1, \
+ .c_next = NULL, \
+}
struct ifaddrs;
struct addrinfo;
@@ -145,6 +202,8 @@
extern int exit_code;
void setifcap(const char *, int value, int s, const struct afswtch *);
+void setifcapnv(const char *vname, const char *arg, int s,
+ const struct afswtch *afp);
void Perror(const char *cmd);
void printb(const char *s, unsigned value, const char *bits);
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -44,6 +44,7 @@
#include <sys/ioctl.h>
#include <sys/module.h>
#include <sys/linker.h>
+#include <sys/nv.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/time.h>
@@ -991,6 +992,8 @@
p->c_name);
p->c_u.c_func2(argv[1], argv[2], s, afp);
argc -= 2, argv += 2;
+ } else if (p->c_parameter == SPARAM && p->c_u.c_func3) {
+ p->c_u.c_func3(*argv, p->c_sparameter, s, afp);
} else if (p->c_u.c_func)
p->c_u.c_func(*argv, p->c_parameter, s, afp);
argc--, argv++;
@@ -1251,6 +1254,53 @@
Perror(vname);
}
+void
+setifcapnv(const char *vname, const char *arg, int s, const struct afswtch *afp)
+{
+ nvlist_t *nvcap;
+ void *buf;
+ char *marg, *mopt;
+ size_t nvbuflen;
+ bool neg;
+
+ if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0)
+ Perror("ioctl (SIOCGIFCAP)");
+ if ((ifr.ifr_curcap & IFCAP_NV) == 0) {
+ warnx("IFCAP_NV not supported");
+ return; /* Not exit() */
+ }
+
+ marg = strdup(arg);
+ if (marg == NULL)
+ Perror("strdup");
+ nvcap = nvlist_create(0);
+ if (nvcap == NULL)
+ Perror("nvlist_create");
+ while ((mopt = strsep(&marg, ",")) != NULL) {
+ neg = *mopt == '-';
+ if (neg)
+ mopt++;
+ if (strcmp(mopt, "rxtls") == 0) {
+ nvlist_add_bool(nvcap, "rxtls4", !neg);
+ nvlist_add_bool(nvcap, "rxtls6", !neg);
+ } else {
+ nvlist_add_bool(nvcap, mopt, !neg);
+ }
+ }
+ buf = nvlist_pack(nvcap, &nvbuflen);
+ if (buf == NULL) {
+ errx(1, "nvlist_pack error");
+ exit(1);
+ }
+ ifr.ifr_cap_nv.buf_length = ifr.ifr_cap_nv.length = nvbuflen;
+ ifr.ifr_cap_nv.buffer = buf;
+ if (ioctl(s, SIOCSIFCAPNV, (caddr_t)&ifr) < 0)
+ Perror(vname);
+ free(buf);
+ nvlist_destroy(nvcap);
+ free(marg);
+}
+
static void
setifmetric(const char *val, int dummy __unused, int s,
const struct afswtch *afp)
@@ -1375,8 +1425,12 @@
struct ifaddrs *ifa)
{
struct ifaddrs *ift;
- int allfamilies, s;
struct ifstat ifs;
+ nvlist_t *nvcap;
+ const char *nvname;
+ void *buf, *cookie;
+ int allfamilies, s, type;
+ bool first, val;
if (afp == NULL) {
allfamilies = 1;
@@ -1421,7 +1475,40 @@
}
if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
- if (ifr.ifr_curcap != 0) {
+ if ((ifr.ifr_curcap & IFCAP_NV) != 0) {
+ buf = malloc(IFR_CAP_NV_MAXBUFSIZE);
+ if (buf == NULL)
+ Perror("malloc");
+ ifr.ifr_cap_nv.buffer = buf;
+ ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE;
+ if (ioctl(s, SIOCGIFCAPNV, (caddr_t)&ifr) != 0)
+ Perror("ioctl (SIOCGIFCAPNV)");
+ nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer,
+ ifr.ifr_cap_nv.length, 0);
+ if (nvcap == NULL)
+ Perror("nvlist_unpack");
+ printf("\toptions");
+ cookie = NULL;
+ for (first = true;; first = false) {
+ nvname = nvlist_next(nvcap, &type, &cookie);
+ if (nvname == NULL) {
+ printf("\n");
+ break;
+ }
+ if (type == NV_TYPE_BOOL) {
+ val = nvlist_get_bool(nvcap, nvname);
+ if (val) {
+ printf("%c%s",
+ first ? ' ' : ',', nvname);
+ }
+ }
+ }
+ nvlist_destroy(nvcap);
+ free(buf);
+
+ if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
+ Perror("ioctl (SIOCGIFCAP)");
+ } else if (ifr.ifr_curcap != 0) {
printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
putchar('\n');
}
@@ -1694,6 +1781,10 @@
DEF_CMD("-lro", -IFCAP_LRO, setifcap),
DEF_CMD("txtls", IFCAP_TXTLS, setifcap),
DEF_CMD("-txtls", -IFCAP_TXTLS, setifcap),
+ DEF_CMD_SARG("rxtls", IFCAP2_RXTLS4_NAME "," IFCAP2_RXTLS6_NAME,
+ setifcapnv),
+ DEF_CMD_SARG("-rxtls", "-"IFCAP2_RXTLS4_NAME ",-" IFCAP2_RXTLS6_NAME,
+ setifcapnv),
DEF_CMD("wol", IFCAP_WOL, setifcap),
DEF_CMD("-wol", -IFCAP_WOL, setifcap),
DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap),
diff --git a/share/man/man9/ifnet.9 b/share/man/man9/ifnet.9
--- a/share/man/man9/ifnet.9
+++ b/share/man/man9/ifnet.9
@@ -1334,6 +1334,74 @@
.Va if_data.ifi_hwassist
appropriately.
.Pp
+.It Dv SIOCGIFCAPNV
+.Xr NV 9
+version of the
+.Dv SIOCGIFCAP
+ioctl.
+Caller must provide the pointer to
+.Vt struct ifreq_cap_nv
+as
+.Fa data ,
+where the member
+.Dv buffer
+points to some buffer containing
+.Dv buf_length
+bytes.
+The serialized nvlist with description of the device capabilities
+is written to the buffer.
+If buffer is too short, then the structure is updated with
+.Dv buffer
+member set to
+.Dv NULL,
+.Dv length
+set to the minimal required length, and error
+.Er EFBIG
+is returned.
+.Pp
+Elements of the returned nvlist for simple capabilities are boolean,
+identified by names.
+Presence of the boolean element means that corresponding capability is
+supported by the interface.
+Element's value describes the current configured state:
+.Dv true
+means that the capability is enabled, and
+.Dv false
+that it is disabled.
+.Pp
+Driver indicates support for both
+.Dv SIOCGIFCAPNV
+and
+.Dv SIOCSIFCAPNV
+requests by setting
+.Dv IFCAP_NV
+non-modifiable capability bit in
+.Dv if_capabilities .
+.Pp
+.It Dv SIOCSIFCAPNV
+.Xr NV 9
+version of the
+.Dv SIOCSIFCAP
+ioctl.
+Caller must provide the pointer to
+.Vt struct ifreq_cap_nv
+as
+.Fa data ,
+where the member
+.Dv buffer
+points to unpacked nvlist of
+.Dv length
+bytes.
+Each element of nvlist describes a requested update of one capability,
+identified by the element name.
+For simple capabilities, the element must be boolean.
+Its
+.Dv true
+value means that the caller asks to enable the capability, and
+.Dv false
+value to disable.
+Only capabilities listed in the nvlist are affected by the call.
+.Pp
.It Dv SIOCSIFFIB
Sets interface FIB.
Caller must have appropriate privilege.
diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk
--- a/share/mk/src.libnames.mk
+++ b/share/mk/src.libnames.mk
@@ -567,6 +567,9 @@
LIBIPFDIR= ${_LIB_OBJTOP}/sbin/ipf/libipf
LIBIPF?= ${LIBIPFDIR}/libipf${PIE_SUFFIX}.a
+LIBJNVDIR= ${_LIB_OBJTOP}/lib/libnv
+LIBNV?= ${LIBNVDIR}/libnv${PIE_SUFFIX}.a
+
LIBISCSIUTILDIR= ${_LIB_OBJTOP}/lib/libiscsiutil
LIBISCSIUTIL?= ${LIBISCSIUTILDIR}/libiscsiutil${PIE_SUFFIX}.a
@@ -660,14 +663,23 @@
LIBCTFDIR= ${OBJTOP}/cddl/lib/libctf
LIBDTRACEDIR= ${OBJTOP}/cddl/lib/libdtrace
LIBICPDIR= ${OBJTOP}/cddl/lib/libicp
+LIBICP?= ${LIBICPDIR}/libicp${PIE_SUFFIX}.a
+LIBICP_RESCUEDIR= ${OBJTOP}/cddl/lib/libicp_rescue
+LIBICP_RESCUE?= ${LIBICP_RESCUEDIR}/libicp_rescue${PIE_SUFFIX}.a
LIBNVPAIRDIR= ${OBJTOP}/cddl/lib/libnvpair
+LIBNVPAIR?= ${LIBNVPAIRDIR}/libnvpair${PIE_SUFFIX}.a
LIBUMEMDIR= ${OBJTOP}/cddl/lib/libumem
LIBUUTILDIR= ${OBJTOP}/cddl/lib/libuutil
LIBZFSDIR= ${OBJTOP}/cddl/lib/libzfs
+LIBZFS?= ${LIBZFSDIR}/libzfs${PIE_SUFFIX}.a
LIBZFS_COREDIR= ${OBJTOP}/cddl/lib/libzfs_core
+LIBZFS_CORE?= ${LIBZFS_COREDIR}/libzfs_core${PIE_SUFFIX}.a
LIBZFSBOOTENVDIR= ${OBJTOP}/cddl/lib/libzfsbootenv
+LIBZFSBOOTENV?= ${LIBZFSBOOTENVDIR}/libzfsbootenv${PIE_SUFFIX}.a
LIBZPOOLDIR= ${OBJTOP}/cddl/lib/libzpool
+LIBZPOOL?= ${LIBZPOOLDIR}/libzpool${PIE_SUFFIX}.a
LIBZUTILDIR= ${OBJTOP}/cddl/lib/libzutil
+LIBZUTIL?= ${LIBZUTILDIR}/libzutil${PIE_SUFFIX}.a
LIBTPOOLDIR= ${OBJTOP}/cddl/lib/libtpool
# OFED support
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
@@ -3434,6 +3434,7 @@
struct ifi2creq i2c;
struct ifrsskey *ifrk;
struct ifrsshash *ifrh;
+ struct siocsifcapnv_driver_data *drv_ioctl_data, drv_ioctl_data_d;
int error = 0;
int mask = 0;
int size_read = 0;
@@ -3512,10 +3513,22 @@
ifr = (struct ifreq *)data;
error = ifmedia_ioctl(ifp, ifr, &priv->media, command);
break;
+ case SIOCGIFCAPNV:
+ error = 0;
+ break;
case SIOCSIFCAP:
ifr = (struct ifreq *)data;
+ drv_ioctl_data = &drv_ioctl_data_d;
+ drv_ioctl_data->reqcap = ifr->ifr_reqcap;
+ PRIV_LOCK(priv);
+ drv_ioctl_data->reqcap2 = ifp->if_capabilities2;
+ drv_ioctl_data->nvcap = NULL;
+ goto siocsifcap_driver;
+ case SIOCSIFCAPNV_DRIVER:
+ drv_ioctl_data = (struct siocsifcapnv_driver_data *)data;
PRIV_LOCK(priv);
- mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+siocsifcap_driver:
+ mask = drv_ioctl_data->reqcap ^ ifp->if_capenable;
if (mask & IFCAP_TXCSUM) {
ifp->if_capenable ^= IFCAP_TXCSUM;
@@ -4518,6 +4531,7 @@
/*
* Set driver features
*/
+ ifp->if_capabilities |= IFCAP_NV;
ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6;
ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
ifp->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER;
@@ -4531,6 +4545,7 @@
ifp->if_capabilities |= IFCAP_TXRTLMT | IFCAP_TXTLS_RTLMT;
#endif
ifp->if_capabilities |= IFCAP_VXLAN_HWCSUM | IFCAP_VXLAN_HWTSO;
+ ifp->if_capabilities2 |= IFCAP2_RXTLS4 | IFCAP2_RXTLS6;
ifp->if_snd_tag_alloc = mlx5e_snd_tag_alloc;
#ifdef RATELIMIT
ifp->if_ratelimit_query = mlx5e_ratelimit_query;
@@ -4541,6 +4556,7 @@
ifp->if_hw_tsomaxsegsize = MLX5E_MAX_TX_MBUF_SIZE;
ifp->if_capenable = ifp->if_capabilities;
+ ifp->if_capenable2 = ifp->if_capabilities2;
ifp->if_hwassist = 0;
if (ifp->if_capenable & IFCAP_TSO)
ifp->if_hwassist |= CSUM_TSO;
diff --git a/sys/net/if.h b/sys/net/if.h
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -236,7 +236,7 @@
#define IFCAP_TOE4 0x04000 /* interface can offload TCP */
#define IFCAP_TOE6 0x08000 /* interface can offload TCP6 */
#define IFCAP_VLAN_HWFILTER 0x10000 /* interface hw can filter vlan tag */
-/* available 0x20000 */
+#define IFCAP_NV 0x20000 /* can do SIOCGIFCAPNV/SIOCSIFCAPNV */
#define IFCAP_VLAN_HWTSO 0x40000 /* can do IFCAP_TSO on VLANs */
#define IFCAP_LINKSTATE 0x80000 /* the runtime link state is dynamic */
#define IFCAP_NETMAP 0x100000 /* netmap mode supported/enabled */
@@ -252,6 +252,9 @@
#define IFCAP_VXLAN_HWTSO 0x40000000 /* can do IFCAP_TSO on VXLANs */
#define IFCAP_TXTLS_RTLMT 0x80000000 /* can do TLS with rate limiting */
+#define IFCAP2_RXTLS4 0x00001
+#define IFCAP2_RXTLS6 0x00002
+
#define IFCAP_HWCSUM_IPV6 (IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6)
#define IFCAP_HWCSUM (IFCAP_RXCSUM | IFCAP_TXCSUM)
@@ -259,8 +262,44 @@
#define IFCAP_WOL (IFCAP_WOL_UCAST | IFCAP_WOL_MCAST | IFCAP_WOL_MAGIC)
#define IFCAP_TOE (IFCAP_TOE4 | IFCAP_TOE6)
#define IFCAP_TXTLS (IFCAP_TXTLS4 | IFCAP_TXTLS6)
-
-#define IFCAP_CANTCHANGE (IFCAP_NETMAP)
+#define IFCAP2_RXTLS (IFCAP2_RXTLS4 | IFCAP2_RXTLS6)
+
+#define IFCAP_CANTCHANGE (IFCAP_NETMAP | IFCAP_NV)
+#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 IFNET_SLOWHZ 1 /* granularity is 1 second */
@@ -387,6 +426,15 @@
void *buffer;
};
+struct ifreq_nv_req {
+ u_int buf_length; /* Total size of buffer,
+ u_int for ABI struct ifreq */
+ u_int length; /* Length of the filled part */
+ void *buffer; /* Buffer itself, containing packed nv */
+};
+
+#define IFR_CAP_NV_MAXBUFSIZE (2 * 1024 * 1024)
+
/*
* Interface request structure used for socket
* ioctl's. All interface ioctl's must have parameter
@@ -411,6 +459,7 @@
int ifru_cap[2];
u_int ifru_fib;
u_char ifru_vlan_pcp;
+ struct ifreq_nv_req ifru_nv;
} ifr_ifru;
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */
@@ -434,6 +483,7 @@
#define ifr_fib ifr_ifru.ifru_fib /* interface fib */
#define ifr_vlan_pcp ifr_ifru.ifru_vlan_pcp /* VLAN priority */
#define ifr_lan_pcp ifr_ifru.ifru_vlan_pcp /* VLAN priority */
+#define ifr_cap_nv ifr_ifru.ifru_nv /* nv-based cap interface */
};
#define _SIZEOF_ADDR_IFREQ(ifr) \
@@ -605,6 +655,17 @@
extern struct sx ifnet_detach_sxlock;
+struct nvlist;
+struct ifcap_nv_bit_name;
+int if_capnv_to_capint(const struct nvlist *nv, int *old_cap,
+ const struct ifcap_nv_bit_name *nn, bool all);
+void if_capint_to_capnv(struct nvlist *nv,
+ const struct ifcap_nv_bit_name *nn, int ifr_cap, int ifr_req);
+struct siocsifcapnv_driver_data {
+ int reqcap;
+ int reqcap2;
+ struct nvlist *nvcap;
+};
#endif
#ifndef _KERNEL
diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -58,6 +58,7 @@
#include <sys/lock.h>
#include <sys/refcount.h>
#include <sys/module.h>
+#include <sys/nv.h>
#include <sys/rwlock.h>
#include <sys/sockio.h>
#include <sys/syslog.h>
@@ -2373,6 +2374,88 @@
return (ifrup->ifr.ifr_ifru.ifru_data);
}
+struct ifcap_nv_bit_name {
+ int cap_bit;
+ const char *cap_name;
+};
+#define CAPNV(x) {.cap_bit = IFCAP_##x, \
+ .cap_name = __CONCAT(IFCAP_, __CONCAT(x, _NAME)) }
+const struct ifcap_nv_bit_name ifcap_nv_bit_names[] = {
+ CAPNV(RXCSUM),
+ CAPNV(TXCSUM),
+ CAPNV(NETCONS),
+ CAPNV(VLAN_MTU),
+ CAPNV(VLAN_HWTAGGING),
+ CAPNV(JUMBO_MTU),
+ CAPNV(POLLING),
+ CAPNV(VLAN_HWCSUM),
+ CAPNV(TSO4),
+ CAPNV(TSO6),
+ CAPNV(LRO),
+ CAPNV(WOL_UCAST),
+ CAPNV(WOL_MCAST),
+ CAPNV(WOL_MAGIC),
+ CAPNV(TOE4),
+ CAPNV(TOE6),
+ CAPNV(VLAN_HWFILTER),
+ CAPNV(VLAN_HWTSO),
+ CAPNV(LINKSTATE),
+ CAPNV(NETMAP),
+ CAPNV(RXCSUM_IPV6),
+ CAPNV(TXCSUM_IPV6),
+ CAPNV(HWSTATS),
+ CAPNV(TXRTLMT),
+ CAPNV(HWRXTSTMP),
+ CAPNV(MEXTPG),
+ CAPNV(TXTLS4),
+ CAPNV(TXTLS6),
+ CAPNV(VXLAN_HWCSUM),
+ CAPNV(VXLAN_HWTSO),
+ CAPNV(TXTLS_RTLMT),
+ {0, NULL}
+};
+#define CAP2NV(x) {.cap_bit = IFCAP2_##x, \
+ .cap_name = __CONCAT(IFCAP2_, __CONCAT(x, _NAME)) }
+const struct ifcap_nv_bit_name ifcap2_nv_bit_names[] = {
+ CAP2NV(RXTLS4),
+ CAP2NV(RXTLS6),
+ {0, NULL}
+};
+#undef CAPNV
+#undef CAP2NV
+
+int
+if_capnv_to_capint(const nvlist_t *nv, int *old_cap,
+ const struct ifcap_nv_bit_name *nn, bool all)
+{
+ int i, res;
+
+ res = 0;
+ for (i = 0; nn[i].cap_name != NULL; i++) {
+ if (nvlist_exists_bool(nv, nn[i].cap_name)) {
+ if (all || nvlist_get_bool(nv, nn[i].cap_name))
+ res |= nn[i].cap_bit;
+ } else {
+ res |= *old_cap & nn[i].cap_bit;
+ }
+ }
+ return (res);
+}
+
+void
+if_capint_to_capnv(nvlist_t *nv, const struct ifcap_nv_bit_name *nn,
+ int ifr_cap, int ifr_req)
+{
+ int i;
+
+ for (i = 0; nn[i].cap_name != NULL; i++) {
+ if ((nn[i].cap_bit & ifr_cap) != 0) {
+ nvlist_add_bool(nv, nn[i].cap_name,
+ (nn[i].cap_bit & ifr_req) != 0);
+ }
+ }
+}
+
/*
* Hardware specific interface ioctls.
*/
@@ -2383,12 +2466,15 @@
int error = 0, do_ifup = 0;
int new_flags, temp_flags;
size_t namelen, onamelen;
- size_t descrlen;
+ size_t descrlen, nvbuflen;
char *descrbuf, *odescrbuf;
char new_name[IFNAMSIZ];
char old_name[IFNAMSIZ], strbuf[IFNAMSIZ + 8];
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
+ void *buf;
+ nvlist_t *nvcap;
+ struct siocsifcapnv_driver_data drv_ioctl_data;
ifr = (struct ifreq *)data;
switch (cmd) {
@@ -2407,6 +2493,47 @@
ifr->ifr_curcap = ifp->if_capenable;
break;
+ case SIOCGIFCAPNV:
+ if ((ifp->if_capabilities & IFCAP_NV) == 0) {
+ error = EINVAL;
+ break;
+ }
+ buf = NULL;
+ nvcap = nvlist_create(0);
+ for (;;) {
+ if_capint_to_capnv(nvcap, ifcap_nv_bit_names,
+ ifp->if_capabilities, ifp->if_capenable);
+ if_capint_to_capnv(nvcap, ifcap2_nv_bit_names,
+ ifp->if_capabilities2, ifp->if_capenable2);
+ error = (*ifp->if_ioctl)(ifp, SIOCGIFCAPNV,
+ __DECONST(caddr_t, nvcap));
+ if (error != 0) {
+ if_printf(ifp,
+ "SIOCGIFCAPNV driver mistake: nvlist error %d\n",
+ error);
+ break;
+ }
+ buf = nvlist_pack(nvcap, &nvbuflen);
+ if (buf == NULL) {
+ error = nvlist_error(nvcap);
+ if (error == 0)
+ error = EDOOFUS;
+ break;
+ }
+ if (nvbuflen > ifr->ifr_cap_nv.buf_length) {
+ ifr->ifr_cap_nv.length = nvbuflen;
+ ifr->ifr_cap_nv.buffer = NULL;
+ error = EFBIG;
+ break;
+ }
+ ifr->ifr_cap_nv.length = nvbuflen;
+ error = copyout(buf, ifr->ifr_cap_nv.buffer, nvbuflen);
+ break;
+ }
+ free(buf, M_NVLIST);
+ nvlist_destroy(nvcap);
+ break;
+
case SIOCGIFDATA:
{
struct if_data ifd;
@@ -2545,7 +2672,7 @@
case SIOCSIFCAP:
error = priv_check(td, PRIV_NET_SETIFCAP);
- if (error)
+ if (error != 0)
return (error);
if (ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
@@ -2556,6 +2683,56 @@
getmicrotime(&ifp->if_lastchange);
break;
+ case SIOCSIFCAPNV_DRIVER:
+ return (ENOSYS);
+
+ case SIOCSIFCAPNV:
+ error = priv_check(td, PRIV_NET_SETIFCAP);
+ if (error != 0)
+ return (error);
+ if (ifp->if_ioctl == NULL)
+ return (EOPNOTSUPP);
+ if ((ifp->if_capabilities & IFCAP_NV) == 0)
+ return (EINVAL);
+ if (ifr->ifr_cap_nv.length > IFR_CAP_NV_MAXBUFSIZE)
+ return (EINVAL);
+ nvcap = NULL;
+ buf = malloc(ifr->ifr_cap_nv.length, M_TEMP, M_WAITOK);
+ for (;;) {
+ error = copyin(ifr->ifr_cap_nv.buffer, buf,
+ ifr->ifr_cap_nv.length);
+ if (error != 0)
+ break;
+ nvcap = nvlist_unpack(buf, ifr->ifr_cap_nv.length, 0);
+ if (nvcap == NULL) {
+ error = EINVAL;
+ break;
+ }
+ drv_ioctl_data.reqcap = if_capnv_to_capint(nvcap,
+ &ifp->if_capenable, ifcap_nv_bit_names, false);
+ if ((drv_ioctl_data.reqcap &
+ ~ifp->if_capabilities) != 0) {
+ error = EINVAL;
+ break;
+ }
+ drv_ioctl_data.reqcap2 = if_capnv_to_capint(nvcap,
+ &ifp->if_capenable2, ifcap2_nv_bit_names, false);
+ if ((drv_ioctl_data.reqcap2 &
+ ~ifp->if_capabilities2) != 0) {
+ error = EINVAL;
+ break;
+ }
+ drv_ioctl_data.nvcap = nvcap;
+ error = (*ifp->if_ioctl)(ifp, SIOCSIFCAPNV_DRIVER,
+ (caddr_t)&drv_ioctl_data);
+ break;
+ }
+ nvlist_destroy(nvcap);
+ free(buf, M_TEMP);
+ if (error == 0)
+ getmicrotime(&ifp->if_lastchange);
+ break;
+
#ifdef MAC
case SIOCSIFMAC:
error = mac_ifnet_ioctl_set(td->td_ucred, ifr, ifp);
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -342,7 +342,9 @@
int if_flags; /* up/down, broadcast, etc. */
int if_drv_flags; /* driver-managed status flags */
int if_capabilities; /* interface features & capabilities */
+ int if_capabilities2; /* part 2 */
int if_capenable; /* enabled features & capabilities */
+ int if_capenable2; /* part 2 */
void *if_linkmib; /* link-type-specific MIB data */
size_t if_linkmiblen; /* length of above data */
u_int if_refcount; /* reference count */
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -147,4 +147,9 @@
#define SIOCGIFDOWNREASON _IOWR('i', 154, struct ifdownreason)
+#define SIOCSIFCAPNV _IOW('i', 155, struct ifreq) /* set IF features */
+#define SIOCGIFCAPNV _IOWR('i', 156, struct ifreq) /* get IF features */
+#define SIOCSIFCAPNV_DRIVER _IOW('i', 157, void *)
+ /* internal if driver interface */
+
#endif /* !_SYS_SOCKIO_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Dec 15, 6:44 PM (7 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26996787
Default Alt Text
D32551.id105072.diff (24 KB)
Attached To
Mode
D32551: if(9): Implement support for nvlist-based set- and get- network interface capabilities.
Attached
Detach File
Event Timeline
Log In to Comment