Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F136728688
D32551.id97797.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
25 KB
Referenced Files
None
Subscribers
None
D32551.id97797.diff
View Options
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
Details
Attached
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)
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