Page MenuHomeFreeBSD

D32551.id97797.diff
No OneTemporary

D32551.id97797.diff

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
@@ -1335,6 +1335,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/sys/dev/mlx5/mlx5_en/en.h b/sys/dev/mlx5/mlx5_en/en.h
--- a/sys/dev/mlx5/mlx5_en/en.h
+++ b/sys/dev/mlx5/mlx5_en/en.h
@@ -1077,6 +1077,35 @@
bool sw_is_port_buf_owner;
struct pfil_head *pfil;
+
+ bool ifcap_rxcsum : 1;
+ bool ifcap_txcsum : 1;
+ bool ifcap_vlan_mtu : 1;
+ bool ifcap_vlan_hwtagging : 1;
+ bool ifcap_jumbo_mtu : 1;
+ bool ifcap_vlan_hwcsum : 1;
+ bool ifcap_tso4 : 1;
+ bool ifcap_tso6 : 1;
+ bool ifcap_lro : 1;
+ bool ifcap_vlan_hwfilter : 1;
+ bool ifcap_vlan_hwtso : 1;
+ bool ifcap_linkstate : 1;
+ bool ifcap_rxcsum_ipv6 : 1;
+ bool ifcap_txcsum_ipv6 : 1;
+ bool ifcap_hwstats_name : 1;
+#ifdef RATELIMIT
+ bool ifcap_txrtlmt : 1;
+#endif
+ bool ifcap_hwrxtstmp : 1;
+ bool ifcap_mextpg : 1;
+ bool ifcap_txtls4 : 1;
+ bool ifcap_txtls6 : 1;
+ bool ifcap_vxlan_hwcsum : 1;
+ bool ifcap_vxlan_hwtso : 1;
+#ifdef RATELIMIT
+ bool ifcap_txtls_rtlmt : 1;
+#endif
+
struct mlx5e_channel channel[];
};
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
@@ -30,6 +30,7 @@
#include "en.h"
#include <sys/eventhandler.h>
+#include <sys/nv.h>
#include <sys/sockio.h>
#include <machine/atomic.h>
@@ -3279,6 +3280,54 @@
queue_work(priv->wq, &priv->set_rx_mode_work);
}
+static int
+mlx5e_if_caps(struct mlx5e_priv *priv)
+{
+ int res;
+
+ res = IFCAP_NV;
+ if (priv->ifcap_rxcsum)
+ res |= IFCAP_RXCSUM;
+ if (priv->ifcap_txcsum)
+ res |= IFCAP_TXCSUM;
+ if (priv->ifcap_rxcsum_ipv6)
+ res |= IFCAP_RXCSUM_IPV6;
+ if (priv->ifcap_txcsum_ipv6)
+ res |= IFCAP_TXCSUM_IPV6;
+ if (priv->ifcap_vlan_mtu)
+ res |= IFCAP_VLAN_MTU;
+ if (priv->ifcap_vlan_hwfilter)
+ res |= IFCAP_VLAN_HWFILTER;
+ if (priv->ifcap_vlan_hwtagging)
+ res |= IFCAP_VLAN_HWTAGGING;
+ if (priv->ifcap_txtls4)
+ res |= IFCAP_TXTLS4;
+ if (priv->ifcap_txtls6)
+ res |= IFCAP_TXTLS6;
+#ifdef RATELIMIT
+ if (priv->ifcap_txrtlmt)
+ res |= IFCAP_TXRTLMT;
+ if (priv->ifcap_txtls_rtlmt)
+ res |= IFCAP_TXTLS_RTLMT;
+#endif
+ if (priv->ifcap_vxlan_hwcsum)
+ res |= IFCAP_VXLAN_HWCSUM;
+ if (priv->ifcap_vxlan_hwtso)
+ res |= IFCAP_VXLAN_HWTSO;
+ if (priv->ifcap_mextpg)
+ res |= IFCAP_MEXTPG;
+ if (priv->ifcap_tso4)
+ res |= IFCAP_TSO4;
+ if (priv->ifcap_tso6)
+ res |= IFCAP_TSO6;
+ if (priv->ifcap_lro)
+ res |= IFCAP_LRO;
+ if (priv->ifcap_hwrxtstmp)
+ res |= IFCAP_HWRXTSTMP;
+
+ return (res);
+}
+
static int
mlx5e_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
@@ -3288,8 +3337,8 @@
struct ifi2creq i2c;
struct ifrsskey *ifrk;
struct ifrsshash *ifrh;
+ nvlist_t *nv;
int error = 0;
- int mask = 0;
int size_read = 0;
int module_status;
int module_num;
@@ -3366,121 +3415,205 @@
ifr = (struct ifreq *)data;
error = ifmedia_ioctl(ifp, ifr, &priv->media, command);
break;
- case SIOCSIFCAP:
- ifr = (struct ifreq *)data;
+ case SIOCGIFCAPNV:
+ nv = (nvlist_t *)data;
+ PRIV_LOCK(priv);
+ nvlist_add_bool(nv, IFCAP_RXCSUM_NAME, priv->ifcap_rxcsum);
+ nvlist_add_bool(nv, IFCAP_TXCSUM_NAME, priv->ifcap_txcsum);
+ nvlist_add_bool(nv, IFCAP_VLAN_MTU_NAME, priv->ifcap_vlan_mtu);
+ nvlist_add_bool(nv, IFCAP_VLAN_HWTAGGING_NAME,
+ priv->ifcap_vlan_hwtagging);
+ nvlist_add_bool(nv, IFCAP_JUMBO_MTU_NAME,
+ priv->ifcap_jumbo_mtu);
+ nvlist_add_bool(nv, IFCAP_VLAN_HWCSUM_NAME,
+ priv->ifcap_vlan_hwcsum);
+ nvlist_add_bool(nv, IFCAP_TSO4_NAME, priv->ifcap_tso4);
+ nvlist_add_bool(nv, IFCAP_TSO6_NAME, priv->ifcap_tso6);
+ nvlist_add_bool(nv, IFCAP_LRO_NAME, priv->ifcap_lro);
+ nvlist_add_bool(nv, IFCAP_VLAN_HWFILTER_NAME,
+ priv->ifcap_vlan_hwfilter);
+ nvlist_add_bool(nv, IFCAP_VLAN_HWTSO_NAME,
+ priv->ifcap_vlan_hwtso);
+ nvlist_add_bool(nv, IFCAP_LINKSTATE_NAME,
+ priv->ifcap_linkstate);
+ nvlist_add_bool(nv, IFCAP_RXCSUM_IPV6_NAME,
+ priv->ifcap_rxcsum_ipv6);
+ nvlist_add_bool(nv, IFCAP_TXCSUM_IPV6_NAME,
+ priv->ifcap_txcsum_ipv6);
+ nvlist_add_bool(nv, IFCAP_HWSTATS_NAME,
+ priv->ifcap_hwstats_name);
+#ifdef RATELIMIT
+ nvlist_add_bool(nv, IFCAP_TXRTLMT_NAME, priv->ifcap_txrtlmt);
+#endif
+ nvlist_add_bool(nv, IFCAP_HWRXTSTMP_NAME,
+ priv->ifcap_hwrxtstmp);
+ nvlist_add_bool(nv, IFCAP_MEXTPG_NAME, priv->ifcap_mextpg);
+ nvlist_add_bool(nv, IFCAP_TXTLS4_NAME, priv->ifcap_txtls4);
+ nvlist_add_bool(nv, IFCAP_TXTLS6_NAME, priv->ifcap_txtls6);
+ nvlist_add_bool(nv, IFCAP_VXLAN_HWCSUM_NAME,
+ priv->ifcap_vxlan_hwcsum);
+ nvlist_add_bool(nv, IFCAP_VXLAN_HWTSO_NAME,
+ priv->ifcap_vxlan_hwtso);
+#ifdef RATELIMIT
+ nvlist_add_bool(nv, IFCAP_TXTLS_RTLMT_NAME,
+ priv->ifcap_txtls_rtlmt);
+#endif
+ PRIV_UNLOCK(priv);
+ break;
+ case SIOCSIFCAPNV:
+ nv = (nvlist_t *)data;
PRIV_LOCK(priv);
- mask = ifr->ifr_reqcap ^ ifp->if_capenable;
-
- if (mask & IFCAP_TXCSUM) {
- ifp->if_capenable ^= IFCAP_TXCSUM;
- ifp->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP);
- if (IFCAP_TSO4 & ifp->if_capenable &&
- !(IFCAP_TXCSUM & ifp->if_capenable)) {
- mask &= ~IFCAP_TSO4;
- ifp->if_capenable &= ~IFCAP_TSO4;
- ifp->if_hwassist &= ~CSUM_IP_TSO;
- mlx5_en_err(ifp,
- "tso4 disabled due to -txcsum.\n");
+ if (nvlist_exists_bool(nv, IFCAP_TXCSUM_NAME)) {
+ if (nvlist_get_bool(nv, IFCAP_TXCSUM_NAME)) {
+ priv->ifcap_txcsum = true;
+ ifp->if_hwassist |= CSUM_TCP | CSUM_UDP |
+ CSUM_IP;
+ } else {
+ priv->ifcap_txcsum = false;
+ ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP |
+ CSUM_IP);
+ if (priv->ifcap_tso4) {
+ nvlist_free_bool(nv, IFCAP_TSO4_NAME);
+ nvlist_add_bool(nv, IFCAP_TSO4_NAME,
+ false);
+ priv->ifcap_tso4 = false;
+ ifp->if_hwassist &= ~CSUM_IP_TSO;
+ mlx5_en_err(ifp,
+ "tso4 disabled due to -txcsum.\n");
+ }
}
}
- if (mask & IFCAP_TXCSUM_IPV6) {
- ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
- ifp->if_hwassist ^= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
-
- if (IFCAP_TSO6 & ifp->if_capenable &&
- !(IFCAP_TXCSUM_IPV6 & ifp->if_capenable)) {
- mask &= ~IFCAP_TSO6;
- ifp->if_capenable &= ~IFCAP_TSO6;
- ifp->if_hwassist &= ~CSUM_IP6_TSO;
- mlx5_en_err(ifp,
+ if (nvlist_exists_bool(nv, IFCAP_TXCSUM_IPV6_NAME)) {
+ if (nvlist_get_bool(nv, IFCAP_TXCSUM_IPV6_NAME)) {
+ priv->ifcap_txcsum_ipv6 = true;
+ ifp->if_hwassist |= CSUM_UDP_IPV6 |
+ CSUM_TCP_IPV6;
+ } else {
+ priv->ifcap_txcsum_ipv6 = false;
+ ifp->if_hwassist &= ~(CSUM_UDP_IPV6 |
+ CSUM_TCP_IPV6);
+ if (priv->ifcap_tso6) {
+ nvlist_free_bool(nv, IFCAP_TSO6_NAME);
+ nvlist_add_bool(nv, IFCAP_TSO6_NAME,
+ false);
+ priv->ifcap_tso6 = false;
+ ifp->if_hwassist &= ~CSUM_IP6_TSO;
+ mlx5_en_err(ifp,
"tso6 disabled due to -txcsum6.\n");
+ }
}
}
- if (mask & IFCAP_MEXTPG)
- ifp->if_capenable ^= IFCAP_MEXTPG;
- if (mask & IFCAP_TXTLS4)
- ifp->if_capenable ^= IFCAP_TXTLS4;
- if (mask & IFCAP_TXTLS6)
- ifp->if_capenable ^= IFCAP_TXTLS6;
+ if (nvlist_exists_bool(nv, IFCAP_MEXTPG_NAME))
+ priv->ifcap_mextpg = nvlist_get_bool(nv,
+ IFCAP_MEXTPG_NAME);
+ if (nvlist_exists_bool(nv, IFCAP_TXTLS4_NAME))
+ priv->ifcap_txtls4 = nvlist_get_bool(nv,
+ IFCAP_TXTLS4_NAME);
+ if (nvlist_exists_bool(nv, IFCAP_TXTLS6_NAME))
+ priv->ifcap_txtls6 = nvlist_get_bool(nv,
+ IFCAP_TXTLS6_NAME);
#ifdef RATELIMIT
- if (mask & IFCAP_TXTLS_RTLMT)
- ifp->if_capenable ^= IFCAP_TXTLS_RTLMT;
+ if (nvlist_exists_bool(nv, IFCAP_TXTLS_RTLMT_NAME))
+ priv->ifcap_txtls_rtlmt = nvlist_get_bool(nv,
+ IFCAP_TXTLS_RTLMT_NAME);
#endif
- if (mask & IFCAP_RXCSUM)
- ifp->if_capenable ^= IFCAP_RXCSUM;
- if (mask & IFCAP_RXCSUM_IPV6)
- ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
- if (mask & IFCAP_TSO4) {
- if (!(IFCAP_TSO4 & ifp->if_capenable) &&
- !(IFCAP_TXCSUM & ifp->if_capenable)) {
- mlx5_en_err(ifp, "enable txcsum first.\n");
- error = EAGAIN;
- goto out;
+ if (nvlist_exists_bool(nv, IFCAP_RXCSUM_NAME))
+ priv->ifcap_rxcsum = nvlist_get_bool(nv,
+ IFCAP_RXCSUM_NAME);
+ if (nvlist_exists_bool(nv, IFCAP_RXCSUM_IPV6_NAME))
+ priv->ifcap_rxcsum_ipv6 = nvlist_get_bool(nv,
+ IFCAP_RXCSUM_IPV6_NAME);
+ if (nvlist_exists_bool(nv, IFCAP_TSO4_NAME)) {
+ if (nvlist_get_bool(nv, IFCAP_TSO4_NAME)) {
+ if (!priv->ifcap_txcsum) {
+ mlx5_en_err(ifp,
+ "enable txcsum first.\n");
+ error = EAGAIN;
+ goto out;
+ }
+ priv->ifcap_tso4 = true;
+ ifp->if_hwassist |= CSUM_IP_TSO;
+ } else {
+ priv->ifcap_tso4 = false;
+ ifp->if_hwassist &= ~CSUM_IP_TSO;
}
- ifp->if_capenable ^= IFCAP_TSO4;
- ifp->if_hwassist ^= CSUM_IP_TSO;
}
- if (mask & IFCAP_TSO6) {
- if (!(IFCAP_TSO6 & ifp->if_capenable) &&
- !(IFCAP_TXCSUM_IPV6 & ifp->if_capenable)) {
- mlx5_en_err(ifp, "enable txcsum6 first.\n");
- error = EAGAIN;
- goto out;
+ if (nvlist_exists_bool(nv, IFCAP_TSO6_NAME)) {
+ if (nvlist_get_bool(nv, IFCAP_TSO6_NAME)) {
+ if (!priv->ifcap_txcsum_ipv6) {
+ mlx5_en_err(ifp,
+ "enable txcsum6 first.\n");
+ error = EAGAIN;
+ goto out;
+ }
+ priv->ifcap_tso6 = true;
+ ifp->if_hwassist |= CSUM_IP6_TSO;
+ } else {
+ priv->ifcap_tso6 = false;
+ ifp->if_hwassist &= ~CSUM_IP6_TSO;
}
- ifp->if_capenable ^= IFCAP_TSO6;
- ifp->if_hwassist ^= CSUM_IP6_TSO;
}
- if (mask & IFCAP_VLAN_HWTSO)
- ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
- if (mask & IFCAP_VLAN_HWFILTER) {
- if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
+ if (nvlist_exists_bool(nv, IFCAP_VLAN_HWTSO_NAME))
+ priv->ifcap_vlan_hwtso = nvlist_get_bool(nv,
+ IFCAP_VLAN_HWTSO_NAME);
+ if (nvlist_exists_bool(nv, IFCAP_VLAN_HWFILTER_NAME)) {
+ priv->ifcap_vlan_hwfilter = nvlist_get_bool(nv,
+ IFCAP_VLAN_HWFILTER_NAME);
+ if (priv->ifcap_vlan_hwfilter)
mlx5e_disable_vlan_filter(priv);
else
mlx5e_enable_vlan_filter(priv);
-
- ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
}
- if (mask & IFCAP_VLAN_HWTAGGING)
- ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- if (mask & IFCAP_WOL_MAGIC)
- ifp->if_capenable ^= IFCAP_WOL_MAGIC;
- if (mask & IFCAP_VXLAN_HWCSUM) {
+ if (nvlist_exists_bool(nv, IFCAP_VLAN_HWTAGGING_NAME))
+ priv->ifcap_vlan_hwtagging = nvlist_get_bool(nv,
+ IFCAP_VLAN_HWTAGGING_NAME);
+ if (nvlist_exists_bool(nv, IFCAP_VXLAN_HWCSUM_NAME)) {
int was_opened = test_bit(MLX5E_STATE_OPENED,
&priv->state);
if (was_opened)
mlx5e_close_locked(ifp);
- ifp->if_capenable ^= IFCAP_VXLAN_HWCSUM;
- ifp->if_hwassist ^= CSUM_INNER_IP | CSUM_INNER_IP_UDP |
- CSUM_INNER_IP_TCP | CSUM_INNER_IP6_UDP |
- CSUM_INNER_IP6_TCP;
- if (was_opened)
- mlx5e_open_locked(ifp);
+ if (nvlist_get_bool(nv, IFCAP_VXLAN_HWCSUM_NAME)) {
+ priv->ifcap_vxlan_hwcsum = true;
+ ifp->if_hwassist |= CSUM_INNER_IP |
+ CSUM_INNER_IP_UDP | CSUM_INNER_IP_TCP |
+ CSUM_INNER_IP6_UDP |
+ CSUM_INNER_IP6_TCP;
+ } else {
+ priv->ifcap_vxlan_hwcsum = false;
+ ifp->if_hwassist &= ~(CSUM_INNER_IP |
+ CSUM_INNER_IP_UDP | CSUM_INNER_IP_TCP |
+ CSUM_INNER_IP6_UDP |
+ CSUM_INNER_IP6_TCP);
+ }
}
- if (mask & IFCAP_VXLAN_HWTSO) {
- ifp->if_capenable ^= IFCAP_VXLAN_HWTSO;
- ifp->if_hwassist ^= CSUM_INNER_IP_TSO |
- CSUM_INNER_IP6_TSO;
+ if (nvlist_exists_bool(nv, IFCAP_VXLAN_HWTSO_NAME)) {
+ if (nvlist_get_bool(nv, IFCAP_VXLAN_HWTSO_NAME)) {
+ priv->ifcap_vxlan_hwtso = true;
+ ifp->if_hwassist |= CSUM_INNER_IP_TSO |
+ CSUM_INNER_IP6_TSO;
+ } else {
+ priv->ifcap_vxlan_hwtso = false;
+ ifp->if_hwassist &= ~(CSUM_INNER_IP_TSO |
+ CSUM_INNER_IP6_TSO);
+ }
}
- VLAN_CAPABILITIES(ifp);
/* turn off LRO means also turn of HW LRO - if it's on */
- if (mask & IFCAP_LRO) {
+ if (nvlist_exists_bool(nv, IFCAP_LRO_NAME)) {
int was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
bool need_restart = false;
- ifp->if_capenable ^= IFCAP_LRO;
-
- /* figure out if updating HW LRO is needed */
- if (!(ifp->if_capenable & IFCAP_LRO)) {
+ if (nvlist_get_bool(nv, IFCAP_LRO_NAME)) {
+ priv->ifcap_lro = true;
if (priv->params.hw_lro_en) {
- priv->params.hw_lro_en = false;
+ priv->params.hw_lro_en = true;
need_restart = true;
}
} else {
- if (priv->params.hw_lro_en == false &&
- priv->params_ethtool.hw_lro != 0) {
- priv->params.hw_lro_en = true;
+ priv->ifcap_lro = false;
+ if (priv->params.hw_lro_en) {
+ priv->params.hw_lro_en = false;
need_restart = true;
}
}
@@ -3489,16 +3622,19 @@
mlx5e_open_locked(ifp);
}
}
- if (mask & IFCAP_HWRXTSTMP) {
- ifp->if_capenable ^= IFCAP_HWRXTSTMP;
- if (ifp->if_capenable & IFCAP_HWRXTSTMP) {
+ if (nvlist_exists_bool(nv, IFCAP_HWRXTSTMP_NAME)) {
+ if (nvlist_get_bool(nv, IFCAP_HWRXTSTMP_NAME)) {
+ priv->ifcap_hwrxtstmp = true;
if (priv->clbr_done == 0)
mlx5e_reset_calibration_callout(priv);
} else {
+ priv->ifcap_hwrxtstmp = false;
callout_drain(&priv->tstmp_clbr);
priv->clbr_done = 0;
}
}
+ ifp->if_capenable = mlx5e_if_caps(priv);
+ VLAN_CAPABILITIES(ifp);
out:
PRIV_UNLOCK(priv);
break;
@@ -4387,19 +4523,33 @@
/*
* Set driver features
*/
- 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;
- ifp->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
- ifp->if_capabilities |= IFCAP_LRO;
- ifp->if_capabilities |= IFCAP_TSO | IFCAP_VLAN_HWTSO;
- ifp->if_capabilities |= IFCAP_HWSTATS | IFCAP_HWRXTSTMP;
- ifp->if_capabilities |= IFCAP_MEXTPG;
- ifp->if_capabilities |= IFCAP_TXTLS4 | IFCAP_TXTLS6;
+ priv->ifcap_rxcsum = true;
+ priv->ifcap_txcsum = true;
+ priv->ifcap_vlan_mtu = true;
+ priv->ifcap_vlan_hwtagging = true;
+ priv->ifcap_jumbo_mtu = true;
+ priv->ifcap_vlan_hwcsum = true;
+ priv->ifcap_tso4 = true;
+ priv->ifcap_tso6 = true;
+ priv->ifcap_lro = true;
+ priv->ifcap_vlan_hwfilter = true;
+ priv->ifcap_vlan_hwtso = true;
+ priv->ifcap_linkstate = true;
+ priv->ifcap_rxcsum_ipv6 = true;
+ priv->ifcap_txcsum_ipv6 = true;
+ priv->ifcap_hwstats_name = true;
+#ifdef RATELIMIT
+ priv->ifcap_txrtlmt = true;
+#endif
+ priv->ifcap_hwrxtstmp = true;
+ priv->ifcap_mextpg = true;
+ priv->ifcap_txtls4 = true;
+ priv->ifcap_txtls6 = true;
+ priv->ifcap_vxlan_hwcsum = true;
+ priv->ifcap_vxlan_hwtso = true;
#ifdef RATELIMIT
- ifp->if_capabilities |= IFCAP_TXRTLMT | IFCAP_TXTLS_RTLMT;
+ priv->ifcap_txtls_rtlmt = true;
#endif
- ifp->if_capabilities |= IFCAP_VXLAN_HWCSUM | IFCAP_VXLAN_HWTSO;
ifp->if_snd_tag_alloc = mlx5e_snd_tag_alloc;
#ifdef RATELIMIT
ifp->if_ratelimit_query = mlx5e_ratelimit_query;
@@ -4409,7 +4559,7 @@
ifp->if_hw_tsomaxsegcount = MLX5E_MAX_TX_MBUF_FRAGS - 1 /* hdr */;
ifp->if_hw_tsomaxsegsize = MLX5E_MAX_TX_MBUF_SIZE;
- ifp->if_capenable = ifp->if_capabilities;
+ ifp->if_capenable = ifp->if_capabilities = mlx5e_if_caps(priv);
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 */
@@ -260,7 +260,40 @@
#define IFCAP_TOE (IFCAP_TOE4 | IFCAP_TOE6)
#define IFCAP_TXTLS (IFCAP_TXTLS4 | IFCAP_TXTLS6)
-#define IFCAP_CANTCHANGE (IFCAP_NETMAP)
+#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 IFQ_MAXLEN 50
#define IFNET_SLOWHZ 1 /* granularity is 1 second */
@@ -387,6 +420,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 +453,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 +477,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 +649,10 @@
extern struct sx ifnet_detach_sxlock;
+struct nvlist;
+int if_capnv_to_capint(const struct nvlist *nv, bool all);
+void if_capint_to_capnv(struct nvlist *nv, int ifr_cap, int ifr_req);
+
#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
@@ -56,6 +56,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>
@@ -2461,6 +2462,78 @@
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),
+};
+#undef CAPNV
+
+int
+if_capnv_to_capint(const nvlist_t *nv, bool all)
+{
+ const struct ifcap_nv_bit_name *nn;
+ int i, res;
+
+ res = 0;
+ for (i = 0; i < nitems(ifcap_nv_bit_names); i++) {
+ nn = &ifcap_nv_bit_names[i];
+ if (nvlist_exists_bool(nv, nn->cap_name) && (all ||
+ nvlist_get_bool(nv, nn->cap_name)))
+ res |= nn->cap_bit;
+ }
+ return (res);
+}
+
+void
+if_capint_to_capnv(nvlist_t *nv, int ifr_cap, int ifr_req)
+{
+ const struct ifcap_nv_bit_name *nn;
+ int i;
+
+ for (i = 0; i < nitems(ifcap_nv_bit_names); i++) {
+ nn = &ifcap_nv_bit_names[i];
+ if ((nn->cap_bit & ifr_cap) != 0) {
+ nvlist_add_bool(nv, nn->cap_name,
+ (nn->cap_bit & ifr_req) != 0);
+ }
+ }
+}
+
/*
* Hardware specific interface ioctls.
*/
@@ -2471,12 +2544,14 @@
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;
ifr = (struct ifreq *)data;
switch (cmd) {
@@ -2491,8 +2566,64 @@
break;
case SIOCGIFCAP:
- ifr->ifr_reqcap = ifp->if_capabilities;
- ifr->ifr_curcap = ifp->if_capenable;
+ if ((ifp->if_capabilities & IFCAP_NV) == 0) {
+ ifr->ifr_reqcap = ifp->if_capabilities;
+ ifr->ifr_curcap = ifp->if_capenable;
+ break;
+ }
+ nvcap = nvlist_create(0);
+ error = (*ifp->if_ioctl)(ifp, SIOCGIFCAPNV,
+ __DECONST(caddr_t, nvcap));
+ while (error == 0) {
+ error = nvlist_error(nvcap);
+ if (error != 0) {
+ if_printf(ifp,
+ "SIOCGIFPCAPNV driver mistake: nvlist error %d\n",
+ error);
+ break;
+ }
+ ifr->ifr_reqcap = if_capnv_to_capint(nvcap, true);
+ ifr->ifr_curcap = if_capnv_to_capint(nvcap, false);
+ break;
+ }
+ nvlist_destroy(nvcap);
+ break;
+
+ case SIOCGIFCAPNV:
+ if ((ifp->if_capabilities & IFCAP_NV) != 0) {
+ error = EINVAL;
+ break;
+ }
+ buf = NULL;
+ nvcap = nvlist_create(0);
+ for (;;) {
+ error = (*ifp->if_ioctl)(ifp, SIOCGIFCAPNV,
+ __DECONST(caddr_t, nvcap));
+ if (error != 0)
+ break;
+ if (error != 0) {
+ if_printf(ifp,
+ "SIOCSIFCAPNV driver mistake: nvlist error %d\n",
+ error);
+ break;
+ }
+ buf = nvlist_pack(nvcap, &nvbuflen);
+ if (buf == NULL) {
+ 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:
@@ -2633,13 +2764,60 @@
case SIOCSIFCAP:
error = priv_check(td, PRIV_NET_SETIFCAP);
- if (error)
+ if (error != 0)
+ return (error);
+ if (ifp->if_ioctl == NULL)
+ return (EOPNOTSUPP);
+ if ((ifp->if_capabilities & IFCAP_NV) == 0) {
+ if (ifr->ifr_reqcap & ~ifp->if_capabilities) {
+ error = EINVAL;
+ break;
+ }
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
+ break;
+ } else {
+ nvcap = nvlist_create(0);
+ for (;;) {
+ if_capint_to_capnv(nvcap, IFCAP_ALLCAPS,
+ ifr->ifr_reqcap);
+ error = (*ifp->if_ioctl)(ifp, SIOCSIFCAPNV,
+ __DECONST(caddr_t, nvcap));
+ break;
+ }
+ nvlist_destroy(nvcap);
+ }
+ if (error == 0)
+ getmicrotime(&ifp->if_lastchange);
+ break;
+
+ case SIOCSIFCAPNV:
+ error = priv_check(td, PRIV_NET_SETIFCAP);
+ if (error != 0)
return (error);
if (ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
- if (ifr->ifr_reqcap & ~ifp->if_capabilities)
+ if ((ifp->if_capabilities & IFCAP_NV) == 0)
return (EINVAL);
- error = (*ifp->if_ioctl)(ifp, cmd, data);
+ 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;
+ }
+ error = (*ifp->if_ioctl)(ifp, cmd,
+ __DECONST(caddr_t, nvcap));
+ break;
+ }
+ nvlist_destroy(nvcap);
+ free(buf, M_TEMP);
if (error == 0)
getmicrotime(&ifp->if_lastchange);
break;
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,7 @@
#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 */
+
#endif /* !_SYS_SOCKIO_H_ */

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 20, 2:38 AM (5 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25703578
Default Alt Text
D32551.id97797.diff (25 KB)

Event Timeline