Page MenuHomeFreeBSD

D32551.id105072.diff
No OneTemporary

D32551.id105072.diff

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

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)

Event Timeline