ethtool: add header/data split indication
For applications running on a mix of platforms it's useful to have a clear indication whether host's NIC supports the geometry requirements of TCP zero-copy. TCP zero-copy Rx requires data to be neatly placed into memory pages. Most NICs can't do that. This patch is adding GET support only, since the NICs I work with either always have the feature enabled or enable it whenever MTU is set to jumbo. In other words I don't need SET. But adding set should be trivial. (The only note on SET is that we will likely want the setting to be "sticky" and use 0 / `unknown` to reset it back to driver default.) Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1a918a32cd
commit
9690ae6042
|
@ -860,8 +860,16 @@ Kernel response contents:
|
||||||
``ETHTOOL_A_RINGS_RX_JUMBO`` u32 size of RX jumbo ring
|
``ETHTOOL_A_RINGS_RX_JUMBO`` u32 size of RX jumbo ring
|
||||||
``ETHTOOL_A_RINGS_TX`` u32 size of TX ring
|
``ETHTOOL_A_RINGS_TX`` u32 size of TX ring
|
||||||
``ETHTOOL_A_RINGS_RX_BUF_LEN`` u32 size of buffers on the ring
|
``ETHTOOL_A_RINGS_RX_BUF_LEN`` u32 size of buffers on the ring
|
||||||
|
``ETHTOOL_A_RINGS_TCP_DATA_SPLIT`` u8 TCP header / data split
|
||||||
==================================== ====== ===========================
|
==================================== ====== ===========================
|
||||||
|
|
||||||
|
``ETHTOOL_A_RINGS_TCP_DATA_SPLIT`` indicates whether the device is usable with
|
||||||
|
page-flipping TCP zero-copy receive (``getsockopt(TCP_ZEROCOPY_RECEIVE)``).
|
||||||
|
If enabled the device is configured to place frame headers and data into
|
||||||
|
separate buffers. The device configuration must make it possible to receive
|
||||||
|
full memory pages of data, for example because MTU is high enough or through
|
||||||
|
HW-GRO.
|
||||||
|
|
||||||
|
|
||||||
RINGS_SET
|
RINGS_SET
|
||||||
=========
|
=========
|
||||||
|
|
|
@ -70,9 +70,11 @@ enum {
|
||||||
/**
|
/**
|
||||||
* struct kernel_ethtool_ringparam - RX/TX ring configuration
|
* struct kernel_ethtool_ringparam - RX/TX ring configuration
|
||||||
* @rx_buf_len: Current length of buffers on the rx ring.
|
* @rx_buf_len: Current length of buffers on the rx ring.
|
||||||
|
* @tcp_data_split: Scatter packet headers and data to separate buffers
|
||||||
*/
|
*/
|
||||||
struct kernel_ethtool_ringparam {
|
struct kernel_ethtool_ringparam {
|
||||||
u32 rx_buf_len;
|
u32 rx_buf_len;
|
||||||
|
u8 tcp_data_split;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -318,6 +318,12 @@ enum {
|
||||||
|
|
||||||
/* RINGS */
|
/* RINGS */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ETHTOOL_TCP_DATA_SPLIT_UNKNOWN = 0,
|
||||||
|
ETHTOOL_TCP_DATA_SPLIT_DISABLED,
|
||||||
|
ETHTOOL_TCP_DATA_SPLIT_ENABLED,
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ETHTOOL_A_RINGS_UNSPEC,
|
ETHTOOL_A_RINGS_UNSPEC,
|
||||||
ETHTOOL_A_RINGS_HEADER, /* nest - _A_HEADER_* */
|
ETHTOOL_A_RINGS_HEADER, /* nest - _A_HEADER_* */
|
||||||
|
@ -330,6 +336,7 @@ enum {
|
||||||
ETHTOOL_A_RINGS_RX_JUMBO, /* u32 */
|
ETHTOOL_A_RINGS_RX_JUMBO, /* u32 */
|
||||||
ETHTOOL_A_RINGS_TX, /* u32 */
|
ETHTOOL_A_RINGS_TX, /* u32 */
|
||||||
ETHTOOL_A_RINGS_RX_BUF_LEN, /* u32 */
|
ETHTOOL_A_RINGS_RX_BUF_LEN, /* u32 */
|
||||||
|
ETHTOOL_A_RINGS_TCP_DATA_SPLIT, /* u8 */
|
||||||
|
|
||||||
/* add new constants above here */
|
/* add new constants above here */
|
||||||
__ETHTOOL_A_RINGS_CNT,
|
__ETHTOOL_A_RINGS_CNT,
|
||||||
|
|
|
@ -53,7 +53,8 @@ static int rings_reply_size(const struct ethnl_req_info *req_base,
|
||||||
nla_total_size(sizeof(u32)) + /* _RINGS_RX_MINI */
|
nla_total_size(sizeof(u32)) + /* _RINGS_RX_MINI */
|
||||||
nla_total_size(sizeof(u32)) + /* _RINGS_RX_JUMBO */
|
nla_total_size(sizeof(u32)) + /* _RINGS_RX_JUMBO */
|
||||||
nla_total_size(sizeof(u32)) + /* _RINGS_TX */
|
nla_total_size(sizeof(u32)) + /* _RINGS_TX */
|
||||||
nla_total_size(sizeof(u32)); /* _RINGS_RX_BUF_LEN */
|
nla_total_size(sizeof(u32)) + /* _RINGS_RX_BUF_LEN */
|
||||||
|
nla_total_size(sizeof(u8)); /* _RINGS_TCP_DATA_SPLIT */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rings_fill_reply(struct sk_buff *skb,
|
static int rings_fill_reply(struct sk_buff *skb,
|
||||||
|
@ -61,9 +62,11 @@ static int rings_fill_reply(struct sk_buff *skb,
|
||||||
const struct ethnl_reply_data *reply_base)
|
const struct ethnl_reply_data *reply_base)
|
||||||
{
|
{
|
||||||
const struct rings_reply_data *data = RINGS_REPDATA(reply_base);
|
const struct rings_reply_data *data = RINGS_REPDATA(reply_base);
|
||||||
const struct kernel_ethtool_ringparam *kernel_ringparam = &data->kernel_ringparam;
|
const struct kernel_ethtool_ringparam *kr = &data->kernel_ringparam;
|
||||||
const struct ethtool_ringparam *ringparam = &data->ringparam;
|
const struct ethtool_ringparam *ringparam = &data->ringparam;
|
||||||
|
|
||||||
|
WARN_ON(kr->tcp_data_split > ETHTOOL_TCP_DATA_SPLIT_ENABLED);
|
||||||
|
|
||||||
if ((ringparam->rx_max_pending &&
|
if ((ringparam->rx_max_pending &&
|
||||||
(nla_put_u32(skb, ETHTOOL_A_RINGS_RX_MAX,
|
(nla_put_u32(skb, ETHTOOL_A_RINGS_RX_MAX,
|
||||||
ringparam->rx_max_pending) ||
|
ringparam->rx_max_pending) ||
|
||||||
|
@ -84,9 +87,11 @@ static int rings_fill_reply(struct sk_buff *skb,
|
||||||
ringparam->tx_max_pending) ||
|
ringparam->tx_max_pending) ||
|
||||||
nla_put_u32(skb, ETHTOOL_A_RINGS_TX,
|
nla_put_u32(skb, ETHTOOL_A_RINGS_TX,
|
||||||
ringparam->tx_pending))) ||
|
ringparam->tx_pending))) ||
|
||||||
(kernel_ringparam->rx_buf_len &&
|
(kr->rx_buf_len &&
|
||||||
(nla_put_u32(skb, ETHTOOL_A_RINGS_RX_BUF_LEN,
|
(nla_put_u32(skb, ETHTOOL_A_RINGS_RX_BUF_LEN, kr->rx_buf_len))) ||
|
||||||
kernel_ringparam->rx_buf_len))))
|
(kr->tcp_data_split &&
|
||||||
|
(nla_put_u8(skb, ETHTOOL_A_RINGS_TCP_DATA_SPLIT,
|
||||||
|
kr->tcp_data_split))))
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue