History

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.

Taehee Yoo committed 1 year ago

Commit 197258f1 parent 2248c054 files · +27 −0Browse files

Unified · Split

4 files
  1. include/linux/ethtool.h +2 −0
  2. include/linux/netdevice.h +1 −0
  3. net/core/dev.c +12 −0
  4. net/ethtool/rings.c +12 −0
include/linux/ethtool.h+2−0
@@ -1157,12 +1157,14 @@ int ethtool_virtdev_set_link_ksettings(struct net_device *dev, · 1156 unmodified lines
1157 * @rss_ctx: XArray of custom RSS contexts1157 * @rss_ctx: XArray of custom RSS contexts
1158 * @rss_lock: Protects entries in @rss_ctx. May be taken from1158 * @rss_lock: Protects entries in @rss_ctx. May be taken from
1159 * within RTNL.1159 * within RTNL.
1160 * @hds_config: HDS value from userspace.
1160 * @wol_enabled: Wake-on-LAN is enabled1161 * @wol_enabled: Wake-on-LAN is enabled
1161 * @module_fw_flash_in_progress: Module firmware flashing is in progress.1162 * @module_fw_flash_in_progress: Module firmware flashing is in progress.
1162 */1163 */
1163struct ethtool_netdev_state {1164struct ethtool_netdev_state {
1164 struct xarray rss_ctx;1165 struct xarray rss_ctx;
1165 struct mutex rss_lock;1166 struct mutex rss_lock;
1167 u8 hds_config;
1166 unsigned wol_enabled:1;1168 unsigned wol_enabled:1;
1167 unsigned module_fw_flash_in_progress:1;1169 unsigned module_fw_flash_in_progress:1;
1168};1170};
include/linux/netdevice.h+1−0
@@ -4082,6 +4082,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, · 4081 unmodified lines
4082int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);4082int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
4083u8 dev_xdp_prog_count(struct net_device *dev);4083u8 dev_xdp_prog_count(struct net_device *dev);
4084int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf);4084int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf);
4085u8 dev_xdp_sb_prog_count(struct net_device *dev);
4085u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode);4086u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode);
4086 4087
4087u32 dev_get_min_mp_channel_count(const struct net_device *dev);4088u32 dev_get_min_mp_channel_count(const struct net_device *dev);
net/core/dev.c+12−0
@@ -9550,6 +9550,18 @@ u8 dev_xdp_prog_count(struct net_device *dev) · 9549 unmodified lines
9550}9550}
9551EXPORT_SYMBOL_GPL(dev_xdp_prog_count);9551EXPORT_SYMBOL_GPL(dev_xdp_prog_count);
9552 9552
9553u8 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
9553int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)9565int dev_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
9554{9566{
9555 if (!dev->netdev_ops->ndo_bpf)9567 if (!dev->netdev_ops->ndo_bpf)
net/ethtool/rings.c+12−0
@@ -203,6 +203,7 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info) · 202 unmodified lines
203 203
204 dev->ethtool_ops->get_ringparam(dev, &ringparam,204 dev->ethtool_ops->get_ringparam(dev, &ringparam,
205 &kernel_ringparam, info->extack);205 &kernel_ringparam, info->extack);
206 kernel_ringparam.tcp_data_split = dev->ethtool->hds_config;
206 207
207 ethnl_update_u32(&ringparam.rx_pending, tb[ETHTOOL_A_RINGS_RX], &mod);208 ethnl_update_u32(&ringparam.rx_pending, tb[ETHTOOL_A_RINGS_RX], &mod);
208 ethnl_update_u32(&ringparam.rx_mini_pending,209 ethnl_update_u32(&ringparam.rx_mini_pending,
@@ -225,6 +226,14 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info) · 16 unmodified lines
225 if (!mod)226 if (!mod)
226 return 0;227 return 0;
227 228
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
228 /* ensure new ring parameters are within limits */237 /* ensure new ring parameters are within limits */
229 if (ringparam.rx_pending > ringparam.rx_max_pending)238 if (ringparam.rx_pending > ringparam.rx_max_pending)
230 err_attr = tb[ETHTOOL_A_RINGS_RX];239 err_attr = tb[ETHTOOL_A_RINGS_RX];
@@ -252,6 +261,9 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info) · 21 unmodified lines
252 261
253 ret = dev->ethtool_ops->set_ringparam(dev, &ringparam,262 ret = dev->ethtool_ops->set_ringparam(dev, &ringparam,
254 &kernel_ringparam, info->extack);263 &kernel_ringparam, info->extack);
264 if (!ret)
265 dev->ethtool->hds_config = kernel_ringparam.tcp_data_split;
266
255 return ret < 0 ? ret : 1;267 return ret < 0 ? ret : 1;
256}268}
257 269