Skip to content

Commit 197258f

Browse files
TaeheeYookuba-moo
authored andcommitted
net: ethtool: add hds_config member in ethtool_netdev_state
When tcp-data-split is UNKNOWN mode, drivers arbitrarily handle it. For example, bnxt_en driver automatically enables if at least one of LRO/GRO/JUMBO is enabled. If tcp-data-split is UNKNOWN and LRO is enabled, a driver returns ENABLES of tcp-data-split, not UNKNOWN. So, `ethtool -g eth0` shows tcp-data-split is enabled. The problem is in the setting situation. In the ethnl_set_rings(), it first calls get_ringparam() to get the current driver's config. At that moment, if driver's tcp-data-split config is UNKNOWN, it returns ENABLE if LRO/GRO/JUMBO is enabled. Then, it sets values from the user and driver's current config to kernel_ethtool_ringparam. Last it calls .set_ringparam(). The driver, especially bnxt_en driver receives ETHTOOL_TCP_DATA_SPLIT_ENABLED. But it can't distinguish whether it is set by the user or just the current config. When user updates ring parameter, the new hds_config value is updated and current hds_config value is stored to old_hdsconfig. Driver's .set_ringparam() callback can distinguish a passed tcp-data-split value is came from user explicitly. If .set_ringparam() is failed, hds_config is rollbacked immediately. Suggested-by: Jakub Kicinski <[email protected]> Reviewed-by: Jakub Kicinski <[email protected]> Signed-off-by: Taehee Yoo <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 2248c05 commit 197258f

File tree

4 files changed

+27
-0
lines changed

4 files changed

+27
-0
lines changed

include/linux/ethtool.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,12 +1157,14 @@ int ethtool_virtdev_set_link_ksettings(struct net_device *dev,
11571157
* @rss_ctx: XArray of custom RSS contexts
11581158
* @rss_lock: Protects entries in @rss_ctx. May be taken from
11591159
* within RTNL.
1160+
* @hds_config: HDS value from userspace.
11601161
* @wol_enabled: Wake-on-LAN is enabled
11611162
* @module_fw_flash_in_progress: Module firmware flashing is in progress.
11621163
*/
11631164
struct ethtool_netdev_state {
11641165
struct xarray rss_ctx;
11651166
struct mutex rss_lock;
1167+
u8 hds_config;
11661168
unsigned wol_enabled:1;
11671169
unsigned module_fw_flash_in_progress:1;
11681170
};

include/linux/netdevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4082,6 +4082,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
40824082
int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
40834083
u8 dev_xdp_prog_count(struct net_device *dev);
40844084
int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf);
4085+
u8 dev_xdp_sb_prog_count(struct net_device *dev);
40854086
u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode);
40864087

40874088
u32 dev_get_min_mp_channel_count(const struct net_device *dev);

net/core/dev.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9550,6 +9550,18 @@ u8 dev_xdp_prog_count(struct net_device *dev)
95509550
}
95519551
EXPORT_SYMBOL_GPL(dev_xdp_prog_count);
95529552

9553+
u8 dev_xdp_sb_prog_count(struct net_device *dev)
9554+
{
9555+
u8 count = 0;
9556+
int i;
9557+
9558+
for (i = 0; i < __MAX_XDP_MODE; i++)
9559+
if (dev->xdp_state[i].prog &&
9560+
!dev->xdp_state[i].prog->aux->xdp_has_frags)
9561+
count++;
9562+
return count;
9563+
}
9564+
95539565
int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
95549566
{
95559567
if (!dev->netdev_ops->ndo_bpf)

net/ethtool/rings.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info)
203203

204204
dev->ethtool_ops->get_ringparam(dev, &ringparam,
205205
&kernel_ringparam, info->extack);
206+
kernel_ringparam.tcp_data_split = dev->ethtool->hds_config;
206207

207208
ethnl_update_u32(&ringparam.rx_pending, tb[ETHTOOL_A_RINGS_RX], &mod);
208209
ethnl_update_u32(&ringparam.rx_mini_pending,
@@ -225,6 +226,14 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info)
225226
if (!mod)
226227
return 0;
227228

229+
if (kernel_ringparam.tcp_data_split == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
230+
dev_xdp_sb_prog_count(dev)) {
231+
NL_SET_ERR_MSG_ATTR(info->extack,
232+
tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT],
233+
"tcp-data-split can not be enabled with single buffer XDP");
234+
return -EINVAL;
235+
}
236+
228237
/* ensure new ring parameters are within limits */
229238
if (ringparam.rx_pending > ringparam.rx_max_pending)
230239
err_attr = tb[ETHTOOL_A_RINGS_RX];
@@ -252,6 +261,9 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info)
252261

253262
ret = dev->ethtool_ops->set_ringparam(dev, &ringparam,
254263
&kernel_ringparam, info->extack);
264+
if (!ret)
265+
dev->ethtool->hds_config = kernel_ringparam.tcp_data_split;
266+
255267
return ret < 0 ? ret : 1;
256268
}
257269

0 commit comments

Comments
 (0)