All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
To: Vladimir Oltean <vladimir.oltean@nxp.com>
Cc: "netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	"jhs@mojatatu.com" <jhs@mojatatu.com>,
	"xiyou.wangcong@gmail.com" <xiyou.wangcong@gmail.com>,
	"jiri@resnulli.us" <jiri@resnulli.us>,
	"kuba@kernel.org" <kuba@kernel.org>, Po Liu <po.liu@nxp.com>,
	"intel-wired-lan@lists.osuosl.org"
	<intel-wired-lan@lists.osuosl.org>,
	"anthony.l.nguyen@intel.com" <anthony.l.nguyen@intel.com>,
	"mkubecek@suse.cz" <mkubecek@suse.cz>
Subject: Re: [PATCH net-next v4 01/12] ethtool: Add support for configuring frame preemption
Date: Mon, 11 Apr 2022 15:39:20 -0700	[thread overview]
Message-ID: <878rsbdz3b.fsf@intel.com> (raw)
In-Reply-To: <20210627194335.vrhwurg43esnodi3@skbuf>

Hi,

(bringing an old thread back to life)

Vladimir Oltean <vladimir.oltean@nxp.com> writes:

> On Fri, Jun 25, 2021 at 05:33:03PM -0700, Vinicius Costa Gomes wrote:
>> Frame preemption (described in IEEE 802.3-2018, Section 99 in
>> particular) defines the concept of preemptible and express queues. It
>> allows traffic from express queues to "interrupt" traffic from
>> preemptible queues, which are "resumed" after the express traffic has
>> finished transmitting.
>> 
>> Frame preemption can only be used when both the local device and the
>> link partner support it.
>> 
>> Only parameters for enabling/disabling frame preemption and
>> configuring the minimum fragment size are included here. Expressing
>> which queues are marked as preemptible is left to mqprio/taprio, as
>> having that information there should be easier on the user.
>> 
>> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
>> ---
>>  Documentation/networking/ethtool-netlink.rst |  38 +++++
>>  include/linux/ethtool.h                      |  22 +++
>>  include/uapi/linux/ethtool_netlink.h         |  17 +++
>>  net/ethtool/Makefile                         |   2 +-
>>  net/ethtool/common.c                         |  25 ++++
>>  net/ethtool/netlink.c                        |  19 +++
>>  net/ethtool/netlink.h                        |   4 +
>>  net/ethtool/preempt.c                        | 146 +++++++++++++++++++
>>  8 files changed, 272 insertions(+), 1 deletion(-)
>>  create mode 100644 net/ethtool/preempt.c
>> 
>> diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
>> index 6ea91e41593f..a87f1716944e 100644
>> --- a/Documentation/networking/ethtool-netlink.rst
>> +++ b/Documentation/networking/ethtool-netlink.rst
>> @@ -1477,6 +1477,44 @@ Low and high bounds are inclusive, for example:
>>   etherStatsPkts512to1023Octets 512  1023
>>   ============================= ==== ====
>
> I think you need to add some extra documentation bits to the
>
> List of message types
> =====================
>
> and
>
> Request translation
> ===================
>
> sections.
>

Will add some more documentation.

>>  
>> +PREEMPT_GET
>> +===========
>> +
>> +Get information about frame preemption state.
>> +
>> +Request contents:
>> +
>> +  ====================================  ======  ==========================
>> +  ``ETHTOOL_A_PREEMPT_HEADER``          nested  request header
>> +  ====================================  ======  ==========================
>> +
>> +Request contents:
>> +
>> +  =====================================  ======  ==========================
>> +  ``ETHTOOL_A_PREEMPT_HEADER``           nested  reply header
>> +  ``ETHTOOL_A_PREEMPT_ENABLED``          u8      frame preemption enabled
>> +  ``ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE``    u32     Min additional frag size
>> +  =====================================  ======  ==========================
>> +
>> +``ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE`` configures the minimum non-final
>> +fragment size that the receiver device supports.
>> +
>> +PREEMPT_SET
>> +===========
>> +
>> +Sets frame preemption parameters.
>> +
>> +Request contents:
>> +
>> +  =====================================  ======  ==========================
>> +  ``ETHTOOL_A_CHANNELS_HEADER``          nested  reply header
>> +  ``ETHTOOL_A_PREEMPT_ENABLED``          u8      frame preemption enabled
>> +  ``ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE``    u32     Min additional frag size
>> +  =====================================  ======  ==========================
>> +
>> +``ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE`` configures the minimum non-final
>> +fragment size that the receiver device supports.
>> +
>>  Request translation
>>  ===================
>>  
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index 29dbb603bc91..7e449be8f335 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -409,6 +409,19 @@ struct ethtool_module_eeprom {
>>  	u8	*data;
>>  };
>>  
>> +/**
>> + * struct ethtool_fp - Frame Preemption information
>> + *
>> + * @enabled: Enable frame preemption.
>> + * @add_frag_size: Minimum size for additional (non-final) fragments
>> + * in bytes, for the value defined in the IEEE 802.3-2018 standard see
>> + * ethtool_frag_size_to_mult().
>> + */
>> +struct ethtool_fp {
>> +	u8 enabled;
>> +	u32 add_frag_size;
>
> Strange that the verify_disable bit is not in here? I haven't looked at
> further patches in detail but I saw in the commit message that you added
> support for it, maybe it needs to be squashed with this?

Will squash the commit that exposes verification config via netlink into this.

>
> Can we make "enabled" a bool?

It seems that the current convention is to use u32 to represent booleans
in the ethtool/netlink API. See ethnl_update_bool32(), will use this instead.

>
>> +};
>> +
>>  /**
>>   * struct ethtool_ops - optional netdev operations
>>   * @cap_link_lanes_supported: indicates if the driver supports lanes
>> @@ -561,6 +574,8 @@ struct ethtool_module_eeprom {
>>   *	not report statistics.
>>   * @get_fecparam: Get the network device Forward Error Correction parameters.
>>   * @set_fecparam: Set the network device Forward Error Correction parameters.
>> + * @get_preempt: Get the network device Frame Preemption parameters.
>> + * @set_preempt: Set the network device Frame Preemption parameters.
>>   * @get_ethtool_phy_stats: Return extended statistics about the PHY device.
>>   *	This is only useful if the device maintains PHY statistics and
>>   *	cannot use the standard PHY library helpers.
>> @@ -675,6 +690,10 @@ struct ethtool_ops {
>>  				      struct ethtool_fecparam *);
>>  	int	(*set_fecparam)(struct net_device *,
>>  				      struct ethtool_fecparam *);
>> +	int	(*get_preempt)(struct net_device *,
>> +			       struct ethtool_fp *);
>> +	int	(*set_preempt)(struct net_device *, struct ethtool_fp *,
>> +			       struct netlink_ext_ack *);
>>  	void	(*get_ethtool_phy_stats)(struct net_device *,
>>  					 struct ethtool_stats *, u64 *);
>>  	int	(*get_phy_tunable)(struct net_device *,
>> @@ -766,4 +785,7 @@ ethtool_params_from_link_mode(struct ethtool_link_ksettings *link_ksettings,
>>   * next string.
>>   */
>>  extern __printf(2, 3) void ethtool_sprintf(u8 **data, const char *fmt, ...);
>> +
>> +u8 ethtool_frag_size_to_mult(u32 frag_size);
>> +
>>  #endif /* _LINUX_ETHTOOL_H */
>> diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
>> index c7135c9c37a5..4600aba1c693 100644
>> --- a/include/uapi/linux/ethtool_netlink.h
>> +++ b/include/uapi/linux/ethtool_netlink.h
>> @@ -44,6 +44,8 @@ enum {
>>  	ETHTOOL_MSG_TUNNEL_INFO_GET,
>>  	ETHTOOL_MSG_FEC_GET,
>>  	ETHTOOL_MSG_FEC_SET,
>> +	ETHTOOL_MSG_PREEMPT_GET,
>> +	ETHTOOL_MSG_PREEMPT_SET,
>>  	ETHTOOL_MSG_MODULE_EEPROM_GET,
>>  	ETHTOOL_MSG_STATS_GET,
>>  
>> @@ -86,6 +88,8 @@ enum {
>>  	ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY,
>>  	ETHTOOL_MSG_FEC_GET_REPLY,
>>  	ETHTOOL_MSG_FEC_NTF,
>> +	ETHTOOL_MSG_PREEMPT_GET_REPLY,
>> +	ETHTOOL_MSG_PREEMPT_NTF,
>>  	ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY,
>>  	ETHTOOL_MSG_STATS_GET_REPLY,
>
> Correct me if I'm wrong, but enums in uapi should always be added at the
> end, otherwise you break value with user space binaries which use
> ETHTOOL_MSG_MODULE_EEPROM_GET and are compiled against old kernel
> headers.

Fixed.

>
>>  
>> @@ -664,6 +668,19 @@ enum {
>>  	ETHTOOL_A_FEC_STAT_MAX = (__ETHTOOL_A_FEC_STAT_CNT - 1)
>>  };
>>  
>> +/* FRAME PREEMPTION */
>> +
>> +enum {
>> +	ETHTOOL_A_PREEMPT_UNSPEC,
>> +	ETHTOOL_A_PREEMPT_HEADER,			/* nest - _A_HEADER_* */
>> +	ETHTOOL_A_PREEMPT_ENABLED,			/* u8 */
>> +	ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE,		/* u32 */
>> +
>> +	/* add new constants above here */
>> +	__ETHTOOL_A_PREEMPT_CNT,
>> +	ETHTOOL_A_PREEMPT_MAX = (__ETHTOOL_A_PREEMPT_CNT - 1)
>> +};
>> +
>>  /* MODULE EEPROM */
>>  
>>  enum {
>> diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
>> index 723c9a8a8cdf..4b84b2d34c7a 100644
>> --- a/net/ethtool/Makefile
>> +++ b/net/ethtool/Makefile
>> @@ -7,4 +7,4 @@ obj-$(CONFIG_ETHTOOL_NETLINK)	+= ethtool_nl.o
>>  ethtool_nl-y	:= netlink.o bitset.o strset.o linkinfo.o linkmodes.o \
>>  		   linkstate.o debug.o wol.o features.o privflags.o rings.o \
>>  		   channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \
>> -		   tunnels.o fec.o eeprom.o stats.o
>> +		   tunnels.o fec.o preempt.o eeprom.o stats.o
>> diff --git a/net/ethtool/common.c b/net/ethtool/common.c
>> index f9dcbad84788..68d123dd500b 100644
>> --- a/net/ethtool/common.c
>> +++ b/net/ethtool/common.c
>> @@ -579,3 +579,28 @@ ethtool_params_from_link_mode(struct ethtool_link_ksettings *link_ksettings,
>>  	link_ksettings->base.duplex = link_info->duplex;
>>  }
>>  EXPORT_SYMBOL_GPL(ethtool_params_from_link_mode);
>> +
>> +/**
>> + * ethtool_frag_size_to_mult() - Convert from a Frame Preemption
>> + * Additional Fragment size in bytes to a multiplier.
>> + * @frag_size: minimum non-final fragment size in bytes.
>> + *
>> + * The multiplier is defined as:
>> + *	"A 2-bit integer value used to indicate the minimum size of
>> + *	non-final fragments supported by the receiver on the given port
>> + *	associated with the local System. This value is expressed in units
>> + *	of 64 octets of additional fragment length."
>> + *	Equivalent to `30.14.1.7 aMACMergeAddFragSize` from the IEEE 802.3-2018
>> + *	standard.
>> + *
>> + * Return: the multiplier is a number in the [0, 2] interval.
>> + */
>> +u8 ethtool_frag_size_to_mult(u32 frag_size)
>> +{
>> +	u8 mult = (frag_size / 64) - 1;
>> +
>> +	mult = clamp_t(u8, mult, 0, 3);
>> +
>> +	return mult;
>
> I think it would look better as "return clamp_t(u8, mult, 0, 3);"

Fixed.

>
>> +}
>> +EXPORT_SYMBOL_GPL(ethtool_frag_size_to_mult);
>> diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
>> index a7346346114f..f4e07b740790 100644
>> --- a/net/ethtool/netlink.c
>> +++ b/net/ethtool/netlink.c
>> @@ -246,6 +246,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
>>  	[ETHTOOL_MSG_EEE_GET]		= &ethnl_eee_request_ops,
>>  	[ETHTOOL_MSG_FEC_GET]		= &ethnl_fec_request_ops,
>>  	[ETHTOOL_MSG_TSINFO_GET]	= &ethnl_tsinfo_request_ops,
>> +	[ETHTOOL_MSG_PREEMPT_GET]	= &ethnl_preempt_request_ops,
>>  	[ETHTOOL_MSG_MODULE_EEPROM_GET]	= &ethnl_module_eeprom_request_ops,
>>  	[ETHTOOL_MSG_STATS_GET]		= &ethnl_stats_request_ops,
>>  };
>> @@ -561,6 +562,7 @@ ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = {
>>  	[ETHTOOL_MSG_PAUSE_NTF]		= &ethnl_pause_request_ops,
>>  	[ETHTOOL_MSG_EEE_NTF]		= &ethnl_eee_request_ops,
>>  	[ETHTOOL_MSG_FEC_NTF]		= &ethnl_fec_request_ops,
>> +	[ETHTOOL_MSG_PREEMPT_NTF]	= &ethnl_preempt_request_ops,
>>  };
>>  
>>  /* default notification handler */
>> @@ -654,6 +656,7 @@ static const ethnl_notify_handler_t ethnl_notify_handlers[] = {
>>  	[ETHTOOL_MSG_PAUSE_NTF]		= ethnl_default_notify,
>>  	[ETHTOOL_MSG_EEE_NTF]		= ethnl_default_notify,
>>  	[ETHTOOL_MSG_FEC_NTF]		= ethnl_default_notify,
>> +	[ETHTOOL_MSG_PREEMPT_NTF]	= ethnl_default_notify,
>>  };
>>  
>>  void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data)
>> @@ -958,6 +961,22 @@ static const struct genl_ops ethtool_genl_ops[] = {
>>  		.policy = ethnl_stats_get_policy,
>>  		.maxattr = ARRAY_SIZE(ethnl_stats_get_policy) - 1,
>>  	},
>> +	{
>> +		.cmd	= ETHTOOL_MSG_PREEMPT_GET,
>> +		.doit	= ethnl_default_doit,
>> +		.start	= ethnl_default_start,
>> +		.dumpit	= ethnl_default_dumpit,
>> +		.done	= ethnl_default_done,
>> +		.policy = ethnl_preempt_get_policy,
>> +		.maxattr = ARRAY_SIZE(ethnl_preempt_get_policy) - 1,
>> +	},
>> +	{
>> +		.cmd	= ETHTOOL_MSG_PREEMPT_SET,
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= ethnl_set_preempt,
>> +		.policy = ethnl_preempt_set_policy,
>> +		.maxattr = ARRAY_SIZE(ethnl_preempt_set_policy) - 1,
>> +	},
>>  };
>>  
>>  static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
>> diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
>> index 3e25a47fd482..cc90a463a81c 100644
>> --- a/net/ethtool/netlink.h
>> +++ b/net/ethtool/netlink.h
>> @@ -345,6 +345,7 @@ extern const struct ethnl_request_ops ethnl_pause_request_ops;
>>  extern const struct ethnl_request_ops ethnl_eee_request_ops;
>>  extern const struct ethnl_request_ops ethnl_tsinfo_request_ops;
>>  extern const struct ethnl_request_ops ethnl_fec_request_ops;
>> +extern const struct ethnl_request_ops ethnl_preempt_request_ops;
>>  extern const struct ethnl_request_ops ethnl_module_eeprom_request_ops;
>>  extern const struct ethnl_request_ops ethnl_stats_request_ops;
>>  
>> @@ -381,6 +382,8 @@ extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNNEL_INF
>>  extern const struct nla_policy ethnl_fec_get_policy[ETHTOOL_A_FEC_HEADER + 1];
>>  extern const struct nla_policy ethnl_fec_set_policy[ETHTOOL_A_FEC_AUTO + 1];
>>  extern const struct nla_policy ethnl_module_eeprom_get_policy[ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS + 1];
>> +extern const struct nla_policy ethnl_preempt_get_policy[ETHTOOL_A_PREEMPT_HEADER + 1];
>> +extern const struct nla_policy ethnl_preempt_set_policy[ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE + 1];
>>  extern const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_GROUPS + 1];
>>  
>>  int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
>> @@ -400,6 +403,7 @@ int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info);
>>  int ethnl_tunnel_info_start(struct netlink_callback *cb);
>>  int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
>>  int ethnl_set_fec(struct sk_buff *skb, struct genl_info *info);
>> +int ethnl_set_preempt(struct sk_buff *skb, struct genl_info *info);
>>  
>>  extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];
>>  extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];
>> diff --git a/net/ethtool/preempt.c b/net/ethtool/preempt.c
>> new file mode 100644
>> index 000000000000..4f96d3c2b1d5
>> --- /dev/null
>> +++ b/net/ethtool/preempt.c
>> @@ -0,0 +1,146 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +
>> +#include "netlink.h"
>> +#include "common.h"
>> +
>> +struct preempt_req_info {
>> +	struct ethnl_req_info		base;
>> +};
>> +
>> +struct preempt_reply_data {
>> +	struct ethnl_reply_data		base;
>> +	struct ethtool_fp		fp;
>> +};
>> +
>> +#define PREEMPT_REPDATA(__reply_base) \
>> +	container_of(__reply_base, struct preempt_reply_data, base)
>> +
>> +const struct nla_policy
>> +ethnl_preempt_get_policy[] = {
>> +	[ETHTOOL_A_PREEMPT_HEADER]		= NLA_POLICY_NESTED(ethnl_header_policy),
>> +};
>> +
>> +static int preempt_prepare_data(const struct ethnl_req_info *req_base,
>> +				struct ethnl_reply_data *reply_base,
>> +				struct genl_info *info)
>> +{
>> +	struct preempt_reply_data *data = PREEMPT_REPDATA(reply_base);
>> +	struct net_device *dev = reply_base->dev;
>> +	int ret;
>> +
>> +	if (!dev->ethtool_ops->get_preempt)
>> +		return -EOPNOTSUPP;
>> +
>> +	ret = ethnl_ops_begin(dev);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = dev->ethtool_ops->get_preempt(dev, &data->fp);
>> +	ethnl_ops_complete(dev);
>> +
>> +	return ret;
>> +}
>> +
>> +static int preempt_reply_size(const struct ethnl_req_info *req_base,
>> +			      const struct ethnl_reply_data *reply_base)
>> +{
>> +	int len = 0;
>> +
>> +	len += nla_total_size(sizeof(u8)); /* _PREEMPT_ENABLED */
>> +	len += nla_total_size(sizeof(u32)); /* _PREEMPT_ADD_FRAG_SIZE */
>> +
>> +	return len;
>> +}
>> +
>> +static int preempt_fill_reply(struct sk_buff *skb,
>> +			      const struct ethnl_req_info *req_base,
>> +			      const struct ethnl_reply_data *reply_base)
>> +{
>> +	const struct preempt_reply_data *data = PREEMPT_REPDATA(reply_base);
>> +	const struct ethtool_fp *preempt = &data->fp;
>> +
>> +	if (nla_put_u8(skb, ETHTOOL_A_PREEMPT_ENABLED, preempt->enabled))
>> +		return -EMSGSIZE;
>> +
>> +	if (nla_put_u32(skb, ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE,
>> +			preempt->add_frag_size))
>> +		return -EMSGSIZE;
>> +
>> +	return 0;
>> +}
>> +
>> +const struct ethnl_request_ops ethnl_preempt_request_ops = {
>> +	.request_cmd		= ETHTOOL_MSG_PREEMPT_GET,
>> +	.reply_cmd		= ETHTOOL_MSG_PREEMPT_GET_REPLY,
>> +	.hdr_attr		= ETHTOOL_A_PREEMPT_HEADER,
>> +	.req_info_size		= sizeof(struct preempt_req_info),
>> +	.reply_data_size	= sizeof(struct preempt_reply_data),
>> +
>> +	.prepare_data		= preempt_prepare_data,
>> +	.reply_size		= preempt_reply_size,
>> +	.fill_reply		= preempt_fill_reply,
>> +};
>> +
>> +const struct nla_policy
>> +ethnl_preempt_set_policy[ETHTOOL_A_PREEMPT_MAX + 1] = {
>> +	[ETHTOOL_A_PREEMPT_HEADER]			= NLA_POLICY_NESTED(ethnl_header_policy),
>> +	[ETHTOOL_A_PREEMPT_ENABLED]			= NLA_POLICY_RANGE(NLA_U8, 0, 1),
>> +	[ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE]		= { .type = NLA_U32 },
>> +};
>> +
>> +int ethnl_set_preempt(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct ethnl_req_info req_info = {};
>> +	struct nlattr **tb = info->attrs;
>> +	struct ethtool_fp preempt = {};
>> +	struct net_device *dev;
>> +	bool mod = false;
>> +	int ret;
>> +
>> +	ret = ethnl_parse_header_dev_get(&req_info,
>> +					 tb[ETHTOOL_A_PREEMPT_HEADER],
>> +					 genl_info_net(info), info->extack,
>> +					 true);
>> +	if (ret < 0)
>> +		return ret;
>> +	dev = req_info.dev;
>> +	ret = -EOPNOTSUPP;
>
> Some new lines around here please? And maybe it would look a bit cleaner
> if you could assign "ret = -EOPNOTSUPP" in the "preempt ops not present"
> if condition body?
>

I will add more vertical spaces. About the error returning idioms, even
if they are not my preferred style, they are consistent with the other
files in net/ethtool, so will keep that as it is.

>> +	if (!dev->ethtool_ops->get_preempt ||
>> +	    !dev->ethtool_ops->set_preempt)
>> +		goto out_dev;
>> +
>> +	rtnl_lock();
>> +	ret = ethnl_ops_begin(dev);
>> +	if (ret < 0)
>> +		goto out_rtnl;
>> +
>> +	ret = dev->ethtool_ops->get_preempt(dev, &preempt);
>
> I don't know much about the background of ethtool netlink, but why does
> the .doit of ETHTOOL_MSG_*_SET go through a getter first? Is it because
> all the netlink attributes from the message are optional, and we need to
> default to the current state?
>

Yes, and there's the "optimization" that the setter will only be called
if there's any modification, so we need to know the current state.

>> +	if (ret < 0) {
>> +		GENL_SET_ERR_MSG(info, "failed to retrieve frame preemption settings");
>> +		goto out_ops;
>> +	}
>> +
>> +	ethnl_update_u8(&preempt.enabled,
>> +			tb[ETHTOOL_A_PREEMPT_ENABLED], &mod);
>> +	ethnl_update_u32(&preempt.add_frag_size,
>> +			 tb[ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE], &mod);
>> +	ret = 0;
>
> This reinitialization of ret to zero is interesting. It implies
> ->get_preempt() is allowed to return > 0 as a success error code.
> However ->set_preempt() below isn't? (its return value is directly
> propagated to callers of ethnl_set_preempt().
>

It also applies to other "commands" in net/ethtool. My feeling is that
this is more like a undocumented convention than a bug (following what
the first command did). Will leave as it is, unless there are strong
feelings.


>> +	if (!mod)
>> +		goto out_ops;
>> +
>> +	ret = dev->ethtool_ops->set_preempt(dev, &preempt, info->extack);
>> +	if (ret < 0) {
>> +		GENL_SET_ERR_MSG(info, "frame preemption settings update failed");
>> +		goto out_ops;
>> +	}
>> +
>> +	ethtool_notify(dev, ETHTOOL_MSG_PREEMPT_NTF, NULL);
>> +
>> +out_ops:
>> +	ethnl_ops_complete(dev);
>> +out_rtnl:
>> +	rtnl_unlock();
>> +out_dev:
>> +	dev_put(dev);
>> +	return ret;
>> +}
>> -- 
>> 2.32.0
>> 


Cheers,
-- 
Vinicius

WARNING: multiple messages have this Message-ID (diff)
From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
To: intel-wired-lan@osuosl.org
Subject: [Intel-wired-lan] [PATCH net-next v4 01/12] ethtool: Add support for configuring frame preemption
Date: Mon, 11 Apr 2022 15:39:20 -0700	[thread overview]
Message-ID: <878rsbdz3b.fsf@intel.com> (raw)
In-Reply-To: <20210627194335.vrhwurg43esnodi3@skbuf>

Hi,

(bringing an old thread back to life)

Vladimir Oltean <vladimir.oltean@nxp.com> writes:

> On Fri, Jun 25, 2021 at 05:33:03PM -0700, Vinicius Costa Gomes wrote:
>> Frame preemption (described in IEEE 802.3-2018, Section 99 in
>> particular) defines the concept of preemptible and express queues. It
>> allows traffic from express queues to "interrupt" traffic from
>> preemptible queues, which are "resumed" after the express traffic has
>> finished transmitting.
>> 
>> Frame preemption can only be used when both the local device and the
>> link partner support it.
>> 
>> Only parameters for enabling/disabling frame preemption and
>> configuring the minimum fragment size are included here. Expressing
>> which queues are marked as preemptible is left to mqprio/taprio, as
>> having that information there should be easier on the user.
>> 
>> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
>> ---
>>  Documentation/networking/ethtool-netlink.rst |  38 +++++
>>  include/linux/ethtool.h                      |  22 +++
>>  include/uapi/linux/ethtool_netlink.h         |  17 +++
>>  net/ethtool/Makefile                         |   2 +-
>>  net/ethtool/common.c                         |  25 ++++
>>  net/ethtool/netlink.c                        |  19 +++
>>  net/ethtool/netlink.h                        |   4 +
>>  net/ethtool/preempt.c                        | 146 +++++++++++++++++++
>>  8 files changed, 272 insertions(+), 1 deletion(-)
>>  create mode 100644 net/ethtool/preempt.c
>> 
>> diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
>> index 6ea91e41593f..a87f1716944e 100644
>> --- a/Documentation/networking/ethtool-netlink.rst
>> +++ b/Documentation/networking/ethtool-netlink.rst
>> @@ -1477,6 +1477,44 @@ Low and high bounds are inclusive, for example:
>>   etherStatsPkts512to1023Octets 512  1023
>>   ============================= ==== ====
>
> I think you need to add some extra documentation bits to the
>
> List of message types
> =====================
>
> and
>
> Request translation
> ===================
>
> sections.
>

Will add some more documentation.

>>  
>> +PREEMPT_GET
>> +===========
>> +
>> +Get information about frame preemption state.
>> +
>> +Request contents:
>> +
>> +  ====================================  ======  ==========================
>> +  ``ETHTOOL_A_PREEMPT_HEADER``          nested  request header
>> +  ====================================  ======  ==========================
>> +
>> +Request contents:
>> +
>> +  =====================================  ======  ==========================
>> +  ``ETHTOOL_A_PREEMPT_HEADER``           nested  reply header
>> +  ``ETHTOOL_A_PREEMPT_ENABLED``          u8      frame preemption enabled
>> +  ``ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE``    u32     Min additional frag size
>> +  =====================================  ======  ==========================
>> +
>> +``ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE`` configures the minimum non-final
>> +fragment size that the receiver device supports.
>> +
>> +PREEMPT_SET
>> +===========
>> +
>> +Sets frame preemption parameters.
>> +
>> +Request contents:
>> +
>> +  =====================================  ======  ==========================
>> +  ``ETHTOOL_A_CHANNELS_HEADER``          nested  reply header
>> +  ``ETHTOOL_A_PREEMPT_ENABLED``          u8      frame preemption enabled
>> +  ``ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE``    u32     Min additional frag size
>> +  =====================================  ======  ==========================
>> +
>> +``ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE`` configures the minimum non-final
>> +fragment size that the receiver device supports.
>> +
>>  Request translation
>>  ===================
>>  
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index 29dbb603bc91..7e449be8f335 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -409,6 +409,19 @@ struct ethtool_module_eeprom {
>>  	u8	*data;
>>  };
>>  
>> +/**
>> + * struct ethtool_fp - Frame Preemption information
>> + *
>> + * @enabled: Enable frame preemption.
>> + * @add_frag_size: Minimum size for additional (non-final) fragments
>> + * in bytes, for the value defined in the IEEE 802.3-2018 standard see
>> + * ethtool_frag_size_to_mult().
>> + */
>> +struct ethtool_fp {
>> +	u8 enabled;
>> +	u32 add_frag_size;
>
> Strange that the verify_disable bit is not in here? I haven't looked at
> further patches in detail but I saw in the commit message that you added
> support for it, maybe it needs to be squashed with this?

Will squash the commit that exposes verification config via netlink into this.

>
> Can we make "enabled" a bool?

It seems that the current convention is to use u32 to represent booleans
in the ethtool/netlink API. See ethnl_update_bool32(), will use this instead.

>
>> +};
>> +
>>  /**
>>   * struct ethtool_ops - optional netdev operations
>>   * @cap_link_lanes_supported: indicates if the driver supports lanes
>> @@ -561,6 +574,8 @@ struct ethtool_module_eeprom {
>>   *	not report statistics.
>>   * @get_fecparam: Get the network device Forward Error Correction parameters.
>>   * @set_fecparam: Set the network device Forward Error Correction parameters.
>> + * @get_preempt: Get the network device Frame Preemption parameters.
>> + * @set_preempt: Set the network device Frame Preemption parameters.
>>   * @get_ethtool_phy_stats: Return extended statistics about the PHY device.
>>   *	This is only useful if the device maintains PHY statistics and
>>   *	cannot use the standard PHY library helpers.
>> @@ -675,6 +690,10 @@ struct ethtool_ops {
>>  				      struct ethtool_fecparam *);
>>  	int	(*set_fecparam)(struct net_device *,
>>  				      struct ethtool_fecparam *);
>> +	int	(*get_preempt)(struct net_device *,
>> +			       struct ethtool_fp *);
>> +	int	(*set_preempt)(struct net_device *, struct ethtool_fp *,
>> +			       struct netlink_ext_ack *);
>>  	void	(*get_ethtool_phy_stats)(struct net_device *,
>>  					 struct ethtool_stats *, u64 *);
>>  	int	(*get_phy_tunable)(struct net_device *,
>> @@ -766,4 +785,7 @@ ethtool_params_from_link_mode(struct ethtool_link_ksettings *link_ksettings,
>>   * next string.
>>   */
>>  extern __printf(2, 3) void ethtool_sprintf(u8 **data, const char *fmt, ...);
>> +
>> +u8 ethtool_frag_size_to_mult(u32 frag_size);
>> +
>>  #endif /* _LINUX_ETHTOOL_H */
>> diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
>> index c7135c9c37a5..4600aba1c693 100644
>> --- a/include/uapi/linux/ethtool_netlink.h
>> +++ b/include/uapi/linux/ethtool_netlink.h
>> @@ -44,6 +44,8 @@ enum {
>>  	ETHTOOL_MSG_TUNNEL_INFO_GET,
>>  	ETHTOOL_MSG_FEC_GET,
>>  	ETHTOOL_MSG_FEC_SET,
>> +	ETHTOOL_MSG_PREEMPT_GET,
>> +	ETHTOOL_MSG_PREEMPT_SET,
>>  	ETHTOOL_MSG_MODULE_EEPROM_GET,
>>  	ETHTOOL_MSG_STATS_GET,
>>  
>> @@ -86,6 +88,8 @@ enum {
>>  	ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY,
>>  	ETHTOOL_MSG_FEC_GET_REPLY,
>>  	ETHTOOL_MSG_FEC_NTF,
>> +	ETHTOOL_MSG_PREEMPT_GET_REPLY,
>> +	ETHTOOL_MSG_PREEMPT_NTF,
>>  	ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY,
>>  	ETHTOOL_MSG_STATS_GET_REPLY,
>
> Correct me if I'm wrong, but enums in uapi should always be added at the
> end, otherwise you break value with user space binaries which use
> ETHTOOL_MSG_MODULE_EEPROM_GET and are compiled against old kernel
> headers.

Fixed.

>
>>  
>> @@ -664,6 +668,19 @@ enum {
>>  	ETHTOOL_A_FEC_STAT_MAX = (__ETHTOOL_A_FEC_STAT_CNT - 1)
>>  };
>>  
>> +/* FRAME PREEMPTION */
>> +
>> +enum {
>> +	ETHTOOL_A_PREEMPT_UNSPEC,
>> +	ETHTOOL_A_PREEMPT_HEADER,			/* nest - _A_HEADER_* */
>> +	ETHTOOL_A_PREEMPT_ENABLED,			/* u8 */
>> +	ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE,		/* u32 */
>> +
>> +	/* add new constants above here */
>> +	__ETHTOOL_A_PREEMPT_CNT,
>> +	ETHTOOL_A_PREEMPT_MAX = (__ETHTOOL_A_PREEMPT_CNT - 1)
>> +};
>> +
>>  /* MODULE EEPROM */
>>  
>>  enum {
>> diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
>> index 723c9a8a8cdf..4b84b2d34c7a 100644
>> --- a/net/ethtool/Makefile
>> +++ b/net/ethtool/Makefile
>> @@ -7,4 +7,4 @@ obj-$(CONFIG_ETHTOOL_NETLINK)	+= ethtool_nl.o
>>  ethtool_nl-y	:= netlink.o bitset.o strset.o linkinfo.o linkmodes.o \
>>  		   linkstate.o debug.o wol.o features.o privflags.o rings.o \
>>  		   channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \
>> -		   tunnels.o fec.o eeprom.o stats.o
>> +		   tunnels.o fec.o preempt.o eeprom.o stats.o
>> diff --git a/net/ethtool/common.c b/net/ethtool/common.c
>> index f9dcbad84788..68d123dd500b 100644
>> --- a/net/ethtool/common.c
>> +++ b/net/ethtool/common.c
>> @@ -579,3 +579,28 @@ ethtool_params_from_link_mode(struct ethtool_link_ksettings *link_ksettings,
>>  	link_ksettings->base.duplex = link_info->duplex;
>>  }
>>  EXPORT_SYMBOL_GPL(ethtool_params_from_link_mode);
>> +
>> +/**
>> + * ethtool_frag_size_to_mult() - Convert from a Frame Preemption
>> + * Additional Fragment size in bytes to a multiplier.
>> + * @frag_size: minimum non-final fragment size in bytes.
>> + *
>> + * The multiplier is defined as:
>> + *	"A 2-bit integer value used to indicate the minimum size of
>> + *	non-final fragments supported by the receiver on the given port
>> + *	associated with the local System. This value is expressed in units
>> + *	of 64 octets of additional fragment length."
>> + *	Equivalent to `30.14.1.7 aMACMergeAddFragSize` from the IEEE 802.3-2018
>> + *	standard.
>> + *
>> + * Return: the multiplier is a number in the [0, 2] interval.
>> + */
>> +u8 ethtool_frag_size_to_mult(u32 frag_size)
>> +{
>> +	u8 mult = (frag_size / 64) - 1;
>> +
>> +	mult = clamp_t(u8, mult, 0, 3);
>> +
>> +	return mult;
>
> I think it would look better as "return clamp_t(u8, mult, 0, 3);"

Fixed.

>
>> +}
>> +EXPORT_SYMBOL_GPL(ethtool_frag_size_to_mult);
>> diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
>> index a7346346114f..f4e07b740790 100644
>> --- a/net/ethtool/netlink.c
>> +++ b/net/ethtool/netlink.c
>> @@ -246,6 +246,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
>>  	[ETHTOOL_MSG_EEE_GET]		= &ethnl_eee_request_ops,
>>  	[ETHTOOL_MSG_FEC_GET]		= &ethnl_fec_request_ops,
>>  	[ETHTOOL_MSG_TSINFO_GET]	= &ethnl_tsinfo_request_ops,
>> +	[ETHTOOL_MSG_PREEMPT_GET]	= &ethnl_preempt_request_ops,
>>  	[ETHTOOL_MSG_MODULE_EEPROM_GET]	= &ethnl_module_eeprom_request_ops,
>>  	[ETHTOOL_MSG_STATS_GET]		= &ethnl_stats_request_ops,
>>  };
>> @@ -561,6 +562,7 @@ ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = {
>>  	[ETHTOOL_MSG_PAUSE_NTF]		= &ethnl_pause_request_ops,
>>  	[ETHTOOL_MSG_EEE_NTF]		= &ethnl_eee_request_ops,
>>  	[ETHTOOL_MSG_FEC_NTF]		= &ethnl_fec_request_ops,
>> +	[ETHTOOL_MSG_PREEMPT_NTF]	= &ethnl_preempt_request_ops,
>>  };
>>  
>>  /* default notification handler */
>> @@ -654,6 +656,7 @@ static const ethnl_notify_handler_t ethnl_notify_handlers[] = {
>>  	[ETHTOOL_MSG_PAUSE_NTF]		= ethnl_default_notify,
>>  	[ETHTOOL_MSG_EEE_NTF]		= ethnl_default_notify,
>>  	[ETHTOOL_MSG_FEC_NTF]		= ethnl_default_notify,
>> +	[ETHTOOL_MSG_PREEMPT_NTF]	= ethnl_default_notify,
>>  };
>>  
>>  void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data)
>> @@ -958,6 +961,22 @@ static const struct genl_ops ethtool_genl_ops[] = {
>>  		.policy = ethnl_stats_get_policy,
>>  		.maxattr = ARRAY_SIZE(ethnl_stats_get_policy) - 1,
>>  	},
>> +	{
>> +		.cmd	= ETHTOOL_MSG_PREEMPT_GET,
>> +		.doit	= ethnl_default_doit,
>> +		.start	= ethnl_default_start,
>> +		.dumpit	= ethnl_default_dumpit,
>> +		.done	= ethnl_default_done,
>> +		.policy = ethnl_preempt_get_policy,
>> +		.maxattr = ARRAY_SIZE(ethnl_preempt_get_policy) - 1,
>> +	},
>> +	{
>> +		.cmd	= ETHTOOL_MSG_PREEMPT_SET,
>> +		.flags	= GENL_UNS_ADMIN_PERM,
>> +		.doit	= ethnl_set_preempt,
>> +		.policy = ethnl_preempt_set_policy,
>> +		.maxattr = ARRAY_SIZE(ethnl_preempt_set_policy) - 1,
>> +	},
>>  };
>>  
>>  static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
>> diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
>> index 3e25a47fd482..cc90a463a81c 100644
>> --- a/net/ethtool/netlink.h
>> +++ b/net/ethtool/netlink.h
>> @@ -345,6 +345,7 @@ extern const struct ethnl_request_ops ethnl_pause_request_ops;
>>  extern const struct ethnl_request_ops ethnl_eee_request_ops;
>>  extern const struct ethnl_request_ops ethnl_tsinfo_request_ops;
>>  extern const struct ethnl_request_ops ethnl_fec_request_ops;
>> +extern const struct ethnl_request_ops ethnl_preempt_request_ops;
>>  extern const struct ethnl_request_ops ethnl_module_eeprom_request_ops;
>>  extern const struct ethnl_request_ops ethnl_stats_request_ops;
>>  
>> @@ -381,6 +382,8 @@ extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNNEL_INF
>>  extern const struct nla_policy ethnl_fec_get_policy[ETHTOOL_A_FEC_HEADER + 1];
>>  extern const struct nla_policy ethnl_fec_set_policy[ETHTOOL_A_FEC_AUTO + 1];
>>  extern const struct nla_policy ethnl_module_eeprom_get_policy[ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS + 1];
>> +extern const struct nla_policy ethnl_preempt_get_policy[ETHTOOL_A_PREEMPT_HEADER + 1];
>> +extern const struct nla_policy ethnl_preempt_set_policy[ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE + 1];
>>  extern const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_GROUPS + 1];
>>  
>>  int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
>> @@ -400,6 +403,7 @@ int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info);
>>  int ethnl_tunnel_info_start(struct netlink_callback *cb);
>>  int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
>>  int ethnl_set_fec(struct sk_buff *skb, struct genl_info *info);
>> +int ethnl_set_preempt(struct sk_buff *skb, struct genl_info *info);
>>  
>>  extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];
>>  extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];
>> diff --git a/net/ethtool/preempt.c b/net/ethtool/preempt.c
>> new file mode 100644
>> index 000000000000..4f96d3c2b1d5
>> --- /dev/null
>> +++ b/net/ethtool/preempt.c
>> @@ -0,0 +1,146 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +
>> +#include "netlink.h"
>> +#include "common.h"
>> +
>> +struct preempt_req_info {
>> +	struct ethnl_req_info		base;
>> +};
>> +
>> +struct preempt_reply_data {
>> +	struct ethnl_reply_data		base;
>> +	struct ethtool_fp		fp;
>> +};
>> +
>> +#define PREEMPT_REPDATA(__reply_base) \
>> +	container_of(__reply_base, struct preempt_reply_data, base)
>> +
>> +const struct nla_policy
>> +ethnl_preempt_get_policy[] = {
>> +	[ETHTOOL_A_PREEMPT_HEADER]		= NLA_POLICY_NESTED(ethnl_header_policy),
>> +};
>> +
>> +static int preempt_prepare_data(const struct ethnl_req_info *req_base,
>> +				struct ethnl_reply_data *reply_base,
>> +				struct genl_info *info)
>> +{
>> +	struct preempt_reply_data *data = PREEMPT_REPDATA(reply_base);
>> +	struct net_device *dev = reply_base->dev;
>> +	int ret;
>> +
>> +	if (!dev->ethtool_ops->get_preempt)
>> +		return -EOPNOTSUPP;
>> +
>> +	ret = ethnl_ops_begin(dev);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = dev->ethtool_ops->get_preempt(dev, &data->fp);
>> +	ethnl_ops_complete(dev);
>> +
>> +	return ret;
>> +}
>> +
>> +static int preempt_reply_size(const struct ethnl_req_info *req_base,
>> +			      const struct ethnl_reply_data *reply_base)
>> +{
>> +	int len = 0;
>> +
>> +	len += nla_total_size(sizeof(u8)); /* _PREEMPT_ENABLED */
>> +	len += nla_total_size(sizeof(u32)); /* _PREEMPT_ADD_FRAG_SIZE */
>> +
>> +	return len;
>> +}
>> +
>> +static int preempt_fill_reply(struct sk_buff *skb,
>> +			      const struct ethnl_req_info *req_base,
>> +			      const struct ethnl_reply_data *reply_base)
>> +{
>> +	const struct preempt_reply_data *data = PREEMPT_REPDATA(reply_base);
>> +	const struct ethtool_fp *preempt = &data->fp;
>> +
>> +	if (nla_put_u8(skb, ETHTOOL_A_PREEMPT_ENABLED, preempt->enabled))
>> +		return -EMSGSIZE;
>> +
>> +	if (nla_put_u32(skb, ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE,
>> +			preempt->add_frag_size))
>> +		return -EMSGSIZE;
>> +
>> +	return 0;
>> +}
>> +
>> +const struct ethnl_request_ops ethnl_preempt_request_ops = {
>> +	.request_cmd		= ETHTOOL_MSG_PREEMPT_GET,
>> +	.reply_cmd		= ETHTOOL_MSG_PREEMPT_GET_REPLY,
>> +	.hdr_attr		= ETHTOOL_A_PREEMPT_HEADER,
>> +	.req_info_size		= sizeof(struct preempt_req_info),
>> +	.reply_data_size	= sizeof(struct preempt_reply_data),
>> +
>> +	.prepare_data		= preempt_prepare_data,
>> +	.reply_size		= preempt_reply_size,
>> +	.fill_reply		= preempt_fill_reply,
>> +};
>> +
>> +const struct nla_policy
>> +ethnl_preempt_set_policy[ETHTOOL_A_PREEMPT_MAX + 1] = {
>> +	[ETHTOOL_A_PREEMPT_HEADER]			= NLA_POLICY_NESTED(ethnl_header_policy),
>> +	[ETHTOOL_A_PREEMPT_ENABLED]			= NLA_POLICY_RANGE(NLA_U8, 0, 1),
>> +	[ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE]		= { .type = NLA_U32 },
>> +};
>> +
>> +int ethnl_set_preempt(struct sk_buff *skb, struct genl_info *info)
>> +{
>> +	struct ethnl_req_info req_info = {};
>> +	struct nlattr **tb = info->attrs;
>> +	struct ethtool_fp preempt = {};
>> +	struct net_device *dev;
>> +	bool mod = false;
>> +	int ret;
>> +
>> +	ret = ethnl_parse_header_dev_get(&req_info,
>> +					 tb[ETHTOOL_A_PREEMPT_HEADER],
>> +					 genl_info_net(info), info->extack,
>> +					 true);
>> +	if (ret < 0)
>> +		return ret;
>> +	dev = req_info.dev;
>> +	ret = -EOPNOTSUPP;
>
> Some new lines around here please? And maybe it would look a bit cleaner
> if you could assign "ret = -EOPNOTSUPP" in the "preempt ops not present"
> if condition body?
>

I will add more vertical spaces. About the error returning idioms, even
if they are not my preferred style, they are consistent with the other
files in net/ethtool, so will keep that as it is.

>> +	if (!dev->ethtool_ops->get_preempt ||
>> +	    !dev->ethtool_ops->set_preempt)
>> +		goto out_dev;
>> +
>> +	rtnl_lock();
>> +	ret = ethnl_ops_begin(dev);
>> +	if (ret < 0)
>> +		goto out_rtnl;
>> +
>> +	ret = dev->ethtool_ops->get_preempt(dev, &preempt);
>
> I don't know much about the background of ethtool netlink, but why does
> the .doit of ETHTOOL_MSG_*_SET go through a getter first? Is it because
> all the netlink attributes from the message are optional, and we need to
> default to the current state?
>

Yes, and there's the "optimization" that the setter will only be called
if there's any modification, so we need to know the current state.

>> +	if (ret < 0) {
>> +		GENL_SET_ERR_MSG(info, "failed to retrieve frame preemption settings");
>> +		goto out_ops;
>> +	}
>> +
>> +	ethnl_update_u8(&preempt.enabled,
>> +			tb[ETHTOOL_A_PREEMPT_ENABLED], &mod);
>> +	ethnl_update_u32(&preempt.add_frag_size,
>> +			 tb[ETHTOOL_A_PREEMPT_ADD_FRAG_SIZE], &mod);
>> +	ret = 0;
>
> This reinitialization of ret to zero is interesting. It implies
> ->get_preempt() is allowed to return > 0 as a success error code.
> However ->set_preempt() below isn't? (its return value is directly
> propagated to callers of ethnl_set_preempt().
>

It also applies to other "commands" in net/ethtool. My feeling is that
this is more like a undocumented convention than a bug (following what
the first command did). Will leave as it is, unless there are strong
feelings.


>> +	if (!mod)
>> +		goto out_ops;
>> +
>> +	ret = dev->ethtool_ops->set_preempt(dev, &preempt, info->extack);
>> +	if (ret < 0) {
>> +		GENL_SET_ERR_MSG(info, "frame preemption settings update failed");
>> +		goto out_ops;
>> +	}
>> +
>> +	ethtool_notify(dev, ETHTOOL_MSG_PREEMPT_NTF, NULL);
>> +
>> +out_ops:
>> +	ethnl_ops_complete(dev);
>> +out_rtnl:
>> +	rtnl_unlock();
>> +out_dev:
>> +	dev_put(dev);
>> +	return ret;
>> +}
>> -- 
>> 2.32.0
>> 


Cheers,
-- 
Vinicius

  reply	other threads:[~2022-04-11 22:39 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-26  0:33 [PATCH net-next v4 00/12] ethtool: Add support for frame preemption Vinicius Costa Gomes
2021-06-26  0:33 ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 01/12] ethtool: Add support for configuring " Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-27 19:43   ` Vladimir Oltean
2021-06-27 19:43     ` [Intel-wired-lan] " Vladimir Oltean
2022-04-11 22:39     ` Vinicius Costa Gomes [this message]
2022-04-11 22:39       ` Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 02/12] taprio: Add support for frame preemption offload Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-27 19:58   ` Vladimir Oltean
2021-06-27 19:58     ` [Intel-wired-lan] " Vladimir Oltean
2022-04-11 23:31     ` Vinicius Costa Gomes
2022-04-11 23:31       ` [Intel-wired-lan] " Vinicius Costa Gomes
2022-04-12  0:08       ` Vladimir Oltean
2022-04-12  0:08         ` [Intel-wired-lan] " Vladimir Oltean
2022-04-12  0:38         ` Vinicius Costa Gomes
2022-04-12  0:38           ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 03/12] core: Introduce netdev_tc_map_to_queue_mask() Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 04/12] taprio: Replace tc_map_to_queue_mask() Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-27 20:02   ` Vladimir Oltean
2021-06-27 20:02     ` [Intel-wired-lan] " Vladimir Oltean
2021-06-26  0:33 ` [PATCH net-next v4 05/12] mqprio: Add support for frame preemption offload Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 06/12] igc: Add support for enabling frame preemption via ethtool Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 07/12] igc: Add support for TC_SETUP_PREEMPT Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 08/12] igc: Simplify TSN flags handling Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 09/12] igc: Add support for setting frame preemption configuration Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 10/12] ethtool: Add support for Frame Preemption verification Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-28  9:17   ` Vladimir Oltean
2021-06-28  9:17     ` [Intel-wired-lan] " Vladimir Oltean
2021-06-26  0:33 ` [PATCH net-next v4 11/12] igc: Check incompatible configs for Frame Preemption Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-28  9:20   ` Vladimir Oltean
2021-06-28  9:20     ` [Intel-wired-lan] " Vladimir Oltean
2022-04-11 23:36     ` Vinicius Costa Gomes
2022-04-11 23:36       ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  0:33 ` [PATCH net-next v4 12/12] igc: Add support for Frame Preemption verification Vinicius Costa Gomes
2021-06-26  0:33   ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-28  9:59   ` Vladimir Oltean
2021-06-28  9:59     ` [Intel-wired-lan] " Vladimir Oltean
2022-04-12  0:13     ` Vinicius Costa Gomes
2022-04-12  0:13       ` [Intel-wired-lan] " Vinicius Costa Gomes
2021-06-26  7:15 [PATCH net-next v4 01/12] ethtool: Add support for configuring frame preemption kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=878rsbdz3b.fsf@intel.com \
    --to=vinicius.gomes@intel.com \
    --cc=anthony.l.nguyen@intel.com \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=jhs@mojatatu.com \
    --cc=jiri@resnulli.us \
    --cc=kuba@kernel.org \
    --cc=mkubecek@suse.cz \
    --cc=netdev@vger.kernel.org \
    --cc=po.liu@nxp.com \
    --cc=vladimir.oltean@nxp.com \
    --cc=xiyou.wangcong@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.