All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
@ 2023-04-05  6:33 Maxim Georgiev
  2023-04-05 12:26 ` Vladimir Oltean
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: Maxim Georgiev @ 2023-04-05  6:33 UTC (permalink / raw)
  To: kory.maincent
  Cc: kuba, netdev, glipus, maxime.chevallier, vladimir.oltean,
	vadim.fedorenko, richardcochran, gerhard

This patch makes VLAN subsystem to use the newly introduced
ndo_hwtstamp_get/set API to pass hw timestamp requests to
underlying NIC drivers in case if these drivers implement
ndo_hwtstamp_get/set functions. Otherwise VLAN·subsystem
falls back to calling ndo_eth_ioctl.

Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Maxim Georgiev <glipus@gmail.com>
---
 net/8021q/vlan_dev.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 5920544e93e8..66d54c610aa5 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -353,6 +353,44 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p)
 	return 0;
 }
 
+static int vlan_dev_hwtstamp(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+	struct kernel_hwtstamp_config kernel_config = {};
+	struct hwtstamp_config config;
+	int err;
+
+	if (!netif_device_present(dev))
+		return -ENODEV;
+
+	if ((cmd == SIOCSHWTSTAMP && !ops->ndo_hwtstamp_set) ||
+	    (cmd == SIOCGHWTSTAMP && !ops->ndo_hwtstamp_get)) {
+		if (ops->ndo_eth_ioctl) {
+			return ops->ndo_eth_ioctl(real_dev, &ifr, cmd);
+		else
+			return -EOPNOTSUPP;
+	}
+
+	kernel_config.ifr = ifr;
+	if (cmd == SIOCSHWTSTAMP) {
+		if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+			return -EFAULT;
+
+		hwtstamp_config_to_kernel(&kernel_config, &config);
+		err = ops->ndo_hwtstamp_set(dev, &kernel_config, NULL);
+	} else if (cmd == SIOCGHWTSTAMP) {
+		err = ops->ndo_hwtstamp_get(dev, &kernel_config, NULL);
+	}
+
+	if (err)
+		return err;
+
+	hwtstamp_kernel_to_config(&config, &kernel_config);
+	if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
+		return -EFAULT;
+	return 0;
+}
+
 static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
@@ -368,10 +406,12 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 		if (!net_eq(dev_net(dev), dev_net(real_dev)))
 			break;
 		fallthrough;
+	case SIOCGHWTSTAMP:
+		err = vlan_dev_hwtstamp(real_dev, &ifrr, cmd);
+		break;
 	case SIOCGMIIPHY:
 	case SIOCGMIIREG:
 	case SIOCSMIIREG:
-	case SIOCGHWTSTAMP:
 		if (netif_device_present(real_dev) && ops->ndo_eth_ioctl)
 			err = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd);
 		break;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05  6:33 [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path Maxim Georgiev
@ 2023-04-05 12:26 ` Vladimir Oltean
  2023-04-05 16:19   ` Max Georgiev
  2023-04-05 15:50 ` kernel test robot
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 19+ messages in thread
From: Vladimir Oltean @ 2023-04-05 12:26 UTC (permalink / raw)
  To: Maxim Georgiev
  Cc: kory.maincent, kuba, netdev, maxime.chevallier, vadim.fedorenko,
	richardcochran, gerhard

On Wed, Apr 05, 2023 at 12:33:23AM -0600, Maxim Georgiev wrote:
> This patch makes VLAN subsystem to use the newly introduced
> ndo_hwtstamp_get/set API to pass hw timestamp requests to
> underlying NIC drivers in case if these drivers implement
> ndo_hwtstamp_get/set functions. Otherwise VLAN┬Ěsubsystem

Strange symbols (┬Ě).

> falls back to calling ndo_eth_ioctl.
> 
> Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> Signed-off-by: Maxim Georgiev <glipus@gmail.com>
> ---
>  net/8021q/vlan_dev.c | 42 +++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 41 insertions(+), 1 deletion(-)
> 
> diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
> index 5920544e93e8..66d54c610aa5 100644
> --- a/net/8021q/vlan_dev.c
> +++ b/net/8021q/vlan_dev.c
> @@ -353,6 +353,44 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p)
>  	return 0;
>  }
>  
> +static int vlan_dev_hwtstamp(struct net_device *dev, struct ifreq *ifr, int cmd)
> +{
> +	const struct net_device_ops *ops = dev->netdev_ops;
> +	struct kernel_hwtstamp_config kernel_config = {};
> +	struct hwtstamp_config config;
> +	int err;
> +
> +	if (!netif_device_present(dev))
> +		return -ENODEV;
> +
> +	if ((cmd == SIOCSHWTSTAMP && !ops->ndo_hwtstamp_set) ||
> +	    (cmd == SIOCGHWTSTAMP && !ops->ndo_hwtstamp_get)) {
> +		if (ops->ndo_eth_ioctl) {
> +			return ops->ndo_eth_ioctl(real_dev, &ifr, cmd);
> +		else
> +			return -EOPNOTSUPP;
> +	}
> +
> +	kernel_config.ifr = ifr;
> +	if (cmd == SIOCSHWTSTAMP) {
> +		if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
> +			return -EFAULT;
> +
> +		hwtstamp_config_to_kernel(&kernel_config, &config);
> +		err = ops->ndo_hwtstamp_set(dev, &kernel_config, NULL);
> +	} else if (cmd == SIOCGHWTSTAMP) {
> +		err = ops->ndo_hwtstamp_get(dev, &kernel_config, NULL);
> +	}
> +
> +	if (err)
> +		return err;
> +
> +	hwtstamp_kernel_to_config(&config, &kernel_config);
> +	if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
> +		return -EFAULT;
> +	return 0;
> +}
> +
>  static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
>  {
>  	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
> @@ -368,10 +406,12 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
>  		if (!net_eq(dev_net(dev), dev_net(real_dev)))
>  			break;
>  		fallthrough;
> +	case SIOCGHWTSTAMP:
> +		err = vlan_dev_hwtstamp(real_dev, &ifrr, cmd);
> +		break;
>  	case SIOCGMIIPHY:
>  	case SIOCGMIIREG:
>  	case SIOCSMIIREG:
> -	case SIOCGHWTSTAMP:

I would recommend also making vlan_dev_hwtstamp() be called from the
VLAN driver's ndo_hwtstamp_set() rather than from ndo_eth_ioctl().

My understanding of Jakub's suggestion to (temporarily) stuff ifr
inside kernel_config was to do that from top-level net/core/dev_ioctl.c,
not from the VLAN driver.

>  		if (netif_device_present(real_dev) && ops->ndo_eth_ioctl)
>  			err = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd);
>  		break;
> -- 
> 2.39.2
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05  6:33 [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path Maxim Georgiev
  2023-04-05 12:26 ` Vladimir Oltean
@ 2023-04-05 15:50 ` kernel test robot
  2023-04-05 16:42 ` Jakub Kicinski
  2023-04-05 18:33 ` kernel test robot
  3 siblings, 0 replies; 19+ messages in thread
From: kernel test robot @ 2023-04-05 15:50 UTC (permalink / raw)
  To: Maxim Georgiev; +Cc: llvm, oe-kbuild-all

Hi Maxim,

[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:

[auto build test ERROR on tnguy-next-queue/dev-queue]
[also build test ERROR on next-20230405]
[cannot apply to horms-ipvs/master linus/master v6.3-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Maxim-Georgiev/Add-ifreq-pointer-field-to-kernel_hwtstamp_config-structure/20230405-143518
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue.git dev-queue
patch link:    https://lore.kernel.org/r/20230405063323.36270-1-glipus%40gmail.com
patch subject: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
config: hexagon-randconfig-r041-20230403 (https://download.01.org/0day-ci/archive/20230405/202304052343.Nwvcrk03-lkp@intel.com/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project 67409911353323ca5edf2049ef0df54132fa1ca7)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/e48fe7f9909e9c0768e866c43b1cc880c0eb329f
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Maxim-Georgiev/Add-ifreq-pointer-field-to-kernel_hwtstamp_config-structure/20230405-143518
        git checkout e48fe7f9909e9c0768e866c43b1cc880c0eb329f
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash net/8021q/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304052343.Nwvcrk03-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from net/8021q/vlan_dev.c:22:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __raw_readb(PCI_IOBASE + addr);
                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from net/8021q/vlan_dev.c:22:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from net/8021q/vlan_dev.c:22:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/hexagon/include/asm/io.h:334:
   include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writeb(value, PCI_IOBASE + addr);
                               ~~~~~~~~~~ ^
   include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
>> net/8021q/vlan_dev.c:369:30: error: use of undeclared identifier 'real_dev'
                           return ops->ndo_eth_ioctl(real_dev, &ifr, cmd);
                                                     ^
>> net/8021q/vlan_dev.c:370:3: error: expected expression
                   else
                   ^
>> net/8021q/vlan_dev.c:395:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:427:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:514:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:526:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:542:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:547:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:554:1: error: function definition is not allowed here
   {
   ^
>> net/8021q/vlan_dev.c:563:20: error: use of undeclared identifier 'vlan_parse_protocol'; did you mean 'vlan_get_protocol'?
           .parse_protocol = vlan_parse_protocol,
                             ^~~~~~~~~~~~~~~~~~~
                             vlan_get_protocol
   include/linux/if_vlan.h:626:22: note: 'vlan_get_protocol' declared here
   static inline __be16 vlan_get_protocol(const struct sk_buff *skb)
                        ^
   net/8021q/vlan_dev.c:570:1: error: function definition is not allowed here
   {
   ^
>> net/8021q/vlan_dev.c:581:13: error: use of undeclared identifier 'vlan_passthru_hard_header'; did you mean 'vlan_dev_hard_header'?
           .create  = vlan_passthru_hard_header,
                      ^~~~~~~~~~~~~~~~~~~~~~~~~
                      vlan_dev_hard_header
   net/8021q/vlan_dev.c:44:12: note: 'vlan_dev_hard_header' declared here
   static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
              ^
   net/8021q/vlan_dev.c:583:20: error: use of undeclared identifier 'vlan_parse_protocol'; did you mean 'vlan_get_protocol'?
           .parse_protocol = vlan_parse_protocol,
                             ^~~~~~~~~~~~~~~~~~~
                             vlan_get_protocol
   include/linux/if_vlan.h:626:22: note: 'vlan_get_protocol' declared here
   static inline __be16 vlan_get_protocol(const struct sk_buff *skb)
                        ^
   net/8021q/vlan_dev.c:593:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:665:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:679:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:685:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:708:1: error: function definition is not allowed here
   {
   ^
   net/8021q/vlan_dev.c:716:1: error: function definition is not allowed here
   {
   ^
   fatal error: too many errors emitted, stopping now [-ferror-limit=]
   6 warnings and 20 errors generated.


vim +/real_dev +369 net/8021q/vlan_dev.c

   355	
   356	static int vlan_dev_hwtstamp(struct net_device *dev, struct ifreq *ifr, int cmd)
   357	{
   358		const struct net_device_ops *ops = dev->netdev_ops;
   359		struct kernel_hwtstamp_config kernel_config = {};
   360		struct hwtstamp_config config;
   361		int err;
   362	
   363		if (!netif_device_present(dev))
   364			return -ENODEV;
   365	
   366		if ((cmd == SIOCSHWTSTAMP && !ops->ndo_hwtstamp_set) ||
   367		    (cmd == SIOCGHWTSTAMP && !ops->ndo_hwtstamp_get)) {
   368			if (ops->ndo_eth_ioctl) {
 > 369				return ops->ndo_eth_ioctl(real_dev, &ifr, cmd);
 > 370			else
   371				return -EOPNOTSUPP;
   372		}
   373	
   374		kernel_config.ifr = ifr;
   375		if (cmd == SIOCSHWTSTAMP) {
   376			if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
   377				return -EFAULT;
   378	
   379			hwtstamp_config_to_kernel(&kernel_config, &config);
   380			err = ops->ndo_hwtstamp_set(dev, &kernel_config, NULL);
   381		} else if (cmd == SIOCGHWTSTAMP) {
   382			err = ops->ndo_hwtstamp_get(dev, &kernel_config, NULL);
   383		}
   384	
   385		if (err)
   386			return err;
   387	
   388		hwtstamp_kernel_to_config(&config, &kernel_config);
   389		if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
   390			return -EFAULT;
   391		return 0;
   392	}
   393	
   394	static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 > 395	{
   396		struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
   397		const struct net_device_ops *ops = real_dev->netdev_ops;
   398		struct ifreq ifrr;
   399		int err = -EOPNOTSUPP;
   400	
   401		strscpy_pad(ifrr.ifr_name, real_dev->name, IFNAMSIZ);
   402		ifrr.ifr_ifru = ifr->ifr_ifru;
   403	
   404		switch (cmd) {
   405		case SIOCSHWTSTAMP:
   406			if (!net_eq(dev_net(dev), dev_net(real_dev)))
   407				break;
   408			fallthrough;
   409		case SIOCGHWTSTAMP:
   410			err = vlan_dev_hwtstamp(real_dev, &ifrr, cmd);
   411			break;
   412		case SIOCGMIIPHY:
   413		case SIOCGMIIREG:
   414		case SIOCSMIIREG:
   415			if (netif_device_present(real_dev) && ops->ndo_eth_ioctl)
   416				err = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd);
   417			break;
   418		}
   419	
   420		if (!err)
   421			ifr->ifr_ifru = ifrr.ifr_ifru;
   422	
   423		return err;
   424	}
   425	
   426	static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa)
   427	{
   428		struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
   429		const struct net_device_ops *ops = real_dev->netdev_ops;
   430		int err = 0;
   431	
   432		if (netif_device_present(real_dev) && ops->ndo_neigh_setup)
   433			err = ops->ndo_neigh_setup(real_dev, pa);
   434	
   435		return err;
   436	}
   437	
   438	#if IS_ENABLED(CONFIG_FCOE)
   439	static int vlan_dev_fcoe_ddp_setup(struct net_device *dev, u16 xid,
   440					   struct scatterlist *sgl, unsigned int sgc)
   441	{
   442		struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
   443		const struct net_device_ops *ops = real_dev->netdev_ops;
   444		int rc = 0;
   445	
   446		if (ops->ndo_fcoe_ddp_setup)
   447			rc = ops->ndo_fcoe_ddp_setup(real_dev, xid, sgl, sgc);
   448	
   449		return rc;
   450	}
   451	
   452	static int vlan_dev_fcoe_ddp_done(struct net_device *dev, u16 xid)
   453	{
   454		struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
   455		const struct net_device_ops *ops = real_dev->netdev_ops;
   456		int len = 0;
   457	
   458		if (ops->ndo_fcoe_ddp_done)
   459			len = ops->ndo_fcoe_ddp_done(real_dev, xid);
   460	
   461		return len;
   462	}
   463	
   464	static int vlan_dev_fcoe_enable(struct net_device *dev)
   465	{
   466		struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
   467		const struct net_device_ops *ops = real_dev->netdev_ops;
   468		int rc = -EINVAL;
   469	
   470		if (ops->ndo_fcoe_enable)
   471			rc = ops->ndo_fcoe_enable(real_dev);
   472		return rc;
   473	}
   474	
   475	static int vlan_dev_fcoe_disable(struct net_device *dev)
   476	{
   477		struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
   478		const struct net_device_ops *ops = real_dev->netdev_ops;
   479		int rc = -EINVAL;
   480	
   481		if (ops->ndo_fcoe_disable)
   482			rc = ops->ndo_fcoe_disable(real_dev);
   483		return rc;
   484	}
   485	
   486	static int vlan_dev_fcoe_ddp_target(struct net_device *dev, u16 xid,
   487					    struct scatterlist *sgl, unsigned int sgc)
   488	{
   489		struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
   490		const struct net_device_ops *ops = real_dev->netdev_ops;
   491		int rc = 0;
   492	
   493		if (ops->ndo_fcoe_ddp_target)
   494			rc = ops->ndo_fcoe_ddp_target(real_dev, xid, sgl, sgc);
   495	
   496		return rc;
   497	}
   498	#endif
   499	
   500	#ifdef NETDEV_FCOE_WWNN
   501	static int vlan_dev_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
   502	{
   503		struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
   504		const struct net_device_ops *ops = real_dev->netdev_ops;
   505		int rc = -EINVAL;
   506	
   507		if (ops->ndo_fcoe_get_wwn)
   508			rc = ops->ndo_fcoe_get_wwn(real_dev, wwn, type);
   509		return rc;
   510	}
   511	#endif
   512	
   513	static void vlan_dev_change_rx_flags(struct net_device *dev, int change)
   514	{
   515		struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
   516	
   517		if (dev->flags & IFF_UP) {
   518			if (change & IFF_ALLMULTI)
   519				dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1);
   520			if (change & IFF_PROMISC)
   521				dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1);
   522		}
   523	}
   524	
   525	static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
   526	{
   527		dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
   528		dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
   529	}
   530	
   531	/*
   532	 * vlan network devices have devices nesting below it, and are a special
   533	 * "super class" of normal network devices; split their locks off into a
   534	 * separate class since they always nest.
   535	 */
   536	static struct lock_class_key vlan_netdev_xmit_lock_key;
   537	static struct lock_class_key vlan_netdev_addr_lock_key;
   538	
   539	static void vlan_dev_set_lockdep_one(struct net_device *dev,
   540					     struct netdev_queue *txq,
   541					     void *unused)
   542	{
   543		lockdep_set_class(&txq->_xmit_lock, &vlan_netdev_xmit_lock_key);
   544	}
   545	
   546	static void vlan_dev_set_lockdep_class(struct net_device *dev)
   547	{
   548		lockdep_set_class(&dev->addr_list_lock,
   549				  &vlan_netdev_addr_lock_key);
   550		netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, NULL);
   551	}
   552	
   553	static __be16 vlan_parse_protocol(const struct sk_buff *skb)
   554	{
   555		struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data);
   556	
   557		return __vlan_get_protocol(skb, veth->h_vlan_proto, NULL);
   558	}
   559	
   560	static const struct header_ops vlan_header_ops = {
   561		.create	 = vlan_dev_hard_header,
   562		.parse	 = eth_header_parse,
 > 563		.parse_protocol = vlan_parse_protocol,
   564	};
   565	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05 12:26 ` Vladimir Oltean
@ 2023-04-05 16:19   ` Max Georgiev
  2023-04-05 16:28     ` Vladimir Oltean
  0 siblings, 1 reply; 19+ messages in thread
From: Max Georgiev @ 2023-04-05 16:19 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: kory.maincent, kuba, netdev, maxime.chevallier, vadim.fedorenko,
	richardcochran, gerhard

On Wed, Apr 5, 2023 at 6:26 AM Vladimir Oltean <vladimir.oltean@nxp.com> wrote:
>
> On Wed, Apr 05, 2023 at 12:33:23AM -0600, Maxim Georgiev wrote:
> > This patch makes VLAN subsystem to use the newly introduced
> > ndo_hwtstamp_get/set API to pass hw timestamp requests to
> > underlying NIC drivers in case if these drivers implement
> > ndo_hwtstamp_get/set functions. Otherwise VLAN┬Ěsubsystem
>
> Strange symbols (┬Ě).

Bad copy-paste, sorry. Fixed.

>
> > falls back to calling ndo_eth_ioctl.
> >
> > Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > Signed-off-by: Maxim Georgiev <glipus@gmail.com>
> > ---
> >  net/8021q/vlan_dev.c | 42 +++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 41 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
> > index 5920544e93e8..66d54c610aa5 100644
> > --- a/net/8021q/vlan_dev.c
> > +++ b/net/8021q/vlan_dev.c
> > @@ -353,6 +353,44 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p)
> >       return 0;
> >  }
> >
> > +static int vlan_dev_hwtstamp(struct net_device *dev, struct ifreq *ifr, int cmd)
> > +{
> > +     const struct net_device_ops *ops = dev->netdev_ops;
> > +     struct kernel_hwtstamp_config kernel_config = {};
> > +     struct hwtstamp_config config;
> > +     int err;
> > +
> > +     if (!netif_device_present(dev))
> > +             return -ENODEV;
> > +
> > +     if ((cmd == SIOCSHWTSTAMP && !ops->ndo_hwtstamp_set) ||
> > +         (cmd == SIOCGHWTSTAMP && !ops->ndo_hwtstamp_get)) {
> > +             if (ops->ndo_eth_ioctl) {
> > +                     return ops->ndo_eth_ioctl(real_dev, &ifr, cmd);
> > +             else
> > +                     return -EOPNOTSUPP;
> > +     }
> > +
> > +     kernel_config.ifr = ifr;
> > +     if (cmd == SIOCSHWTSTAMP) {
> > +             if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
> > +                     return -EFAULT;
> > +
> > +             hwtstamp_config_to_kernel(&kernel_config, &config);
> > +             err = ops->ndo_hwtstamp_set(dev, &kernel_config, NULL);
> > +     } else if (cmd == SIOCGHWTSTAMP) {
> > +             err = ops->ndo_hwtstamp_get(dev, &kernel_config, NULL);
> > +     }
> > +
> > +     if (err)
> > +             return err;
> > +
> > +     hwtstamp_kernel_to_config(&config, &kernel_config);
> > +     if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
> > +             return -EFAULT;
> > +     return 0;
> > +}
> > +
> >  static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
> >  {
> >       struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
> > @@ -368,10 +406,12 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
> >               if (!net_eq(dev_net(dev), dev_net(real_dev)))
> >                       break;
> >               fallthrough;
> > +     case SIOCGHWTSTAMP:
> > +             err = vlan_dev_hwtstamp(real_dev, &ifrr, cmd);
> > +             break;
> >       case SIOCGMIIPHY:
> >       case SIOCGMIIREG:
> >       case SIOCSMIIREG:
> > -     case SIOCGHWTSTAMP:
>
> I would recommend also making vlan_dev_hwtstamp() be called from the
> VLAN driver's ndo_hwtstamp_set() rather than from ndo_eth_ioctl().

Vladimir, could you please elaborate here a bit?
Are you saying that I should go all the way with vlan NDO conversion,
implement ndo_hwtstamp_get/set() for vlan, and stop handling
SIOCGHWTSTAMP/SIOCSHWTSTAMP in vlan_dev_ioctl()?

>
> My understanding of Jakub's suggestion to (temporarily) stuff ifr
> inside kernel_config was to do that from top-level net/core/dev_ioctl.c,
> not from the VLAN driver.

[RFC PATCH v3 2/5] in this patch stack changes net/core/dev_ioctl.c
to insert ifr inside kernel_config. I assumed that I should do it here too
so underlying drivers could rely on ifr pointer in kernel_config being
always initialized.
If the plan is to stop supporting SIOCGHWTSTAMP/SIOCSHWTSTAMP
in vlan_dev_ioctl() all together and move the hw timestamp handling
logic to vlan_get/set_hwtstamp() functions, then this ifr initialization
code will be removed from net/8021q/vlan_dev.c anyway.

>
> >               if (netif_device_present(real_dev) && ops->ndo_eth_ioctl)
> >                       err = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd);
> >               break;
> > --
> > 2.39.2
> >

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05 16:19   ` Max Georgiev
@ 2023-04-05 16:28     ` Vladimir Oltean
  0 siblings, 0 replies; 19+ messages in thread
From: Vladimir Oltean @ 2023-04-05 16:28 UTC (permalink / raw)
  To: Max Georgiev
  Cc: kory.maincent, kuba, netdev, maxime.chevallier, vadim.fedorenko,
	richardcochran, gerhard

On Wed, Apr 05, 2023 at 10:19:11AM -0600, Max Georgiev wrote:
> > I would recommend also making vlan_dev_hwtstamp() be called from the
> > VLAN driver's ndo_hwtstamp_set() rather than from ndo_eth_ioctl().
> 
> Vladimir, could you please elaborate here a bit?
> Are you saying that I should go all the way with vlan NDO conversion,
> implement ndo_hwtstamp_get/set() for vlan, and stop handling
> SIOCGHWTSTAMP/SIOCSHWTSTAMP in vlan_dev_ioctl()?

Yes, sorry for being unclear.

> > My understanding of Jakub's suggestion to (temporarily) stuff ifr
> > inside kernel_config was to do that from top-level net/core/dev_ioctl.c,
> > not from the VLAN driver.
> 
> [RFC PATCH v3 2/5] in this patch stack changes net/core/dev_ioctl.c
> to insert ifr inside kernel_config. I assumed that I should do it here too
> so underlying drivers could rely on ifr pointer in kernel_config being
> always initialized.
> If the plan is to stop supporting SIOCGHWTSTAMP/SIOCSHWTSTAMP
> in vlan_dev_ioctl() all together and move the hw timestamp handling
> logic to vlan_get/set_hwtstamp() functions, then this ifr initialization
> code will be removed from net/8021q/vlan_dev.c anyway.

Yes, correct, dev_set_hwtstamp() should provide it.

There's a small thing I don't like about stuffing "ifr" inside struct
kernel_hwtstamp_config, and that's that some drivers keep the last
configuration privately using memcpy(). If we put "ifr" there, they will
practically have access to a stale pointer, because "ifr" loses meaning
once the ioctl syscall is over.

Since we don't know how long it will take until the ndo_hwtstamp_set()
conversion is complete (experience says: possibly indefinitely), it
would be good if this wasn't possible, because who knows what ideas
people might get to do with it.

Options to avoid it are:
- keep doing what you're doing - let drivers memcpy() the struct
  hwtstamp_config and not the struct kernel_hwtstamp_config.
- pass the ifr as yet another argument to ndo_hwtstamp_set(), and don't
  stuff it inside struct kernel_hwtstamp_config.

Neither of these is particularly great, because at the end of the
conversion, some extra cleanup will be required to fix up the API again
(either to stop all drivers from using struct hwtstamp_config, or to
stop passing the argument which is no longer used by anybody).

I think, personally, I'd opt for the first bullet, keep doing what
you're doing. It should require a bit less cleanup, since not all
drivers do the memcpy() thing.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05  6:33 [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path Maxim Georgiev
  2023-04-05 12:26 ` Vladimir Oltean
  2023-04-05 15:50 ` kernel test robot
@ 2023-04-05 16:42 ` Jakub Kicinski
  2023-04-05 17:03   ` Vladimir Oltean
  2023-04-05 18:33 ` kernel test robot
  3 siblings, 1 reply; 19+ messages in thread
From: Jakub Kicinski @ 2023-04-05 16:42 UTC (permalink / raw)
  To: Maxim Georgiev
  Cc: kory.maincent, netdev, maxime.chevallier, vladimir.oltean,
	vadim.fedorenko, richardcochran, gerhard

On Wed,  5 Apr 2023 00:33:23 -0600 Maxim Georgiev wrote:
> +static int vlan_dev_hwtstamp(struct net_device *dev, struct ifreq *ifr, int cmd)
> +{
> +	const struct net_device_ops *ops = dev->netdev_ops;
> +	struct kernel_hwtstamp_config kernel_config = {};
> +	struct hwtstamp_config config;
> +	int err;
> +
> +	if (!netif_device_present(dev))
> +		return -ENODEV;
> +
> +	if ((cmd == SIOCSHWTSTAMP && !ops->ndo_hwtstamp_set) ||
> +	    (cmd == SIOCGHWTSTAMP && !ops->ndo_hwtstamp_get)) {
> +		if (ops->ndo_eth_ioctl) {
> +			return ops->ndo_eth_ioctl(real_dev, &ifr, cmd);
> +		else
> +			return -EOPNOTSUPP;
> +	}
> +
> +	kernel_config.ifr = ifr;
> +	if (cmd == SIOCSHWTSTAMP) {
> +		if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
> +			return -EFAULT;
> +
> +		hwtstamp_config_to_kernel(&kernel_config, &config);
> +		err = ops->ndo_hwtstamp_set(dev, &kernel_config, NULL);
> +	} else if (cmd == SIOCGHWTSTAMP) {
> +		err = ops->ndo_hwtstamp_get(dev, &kernel_config, NULL);
> +	}
> +
> +	if (err)
> +		return err;
> +
> +	hwtstamp_kernel_to_config(&config, &kernel_config);
> +	if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
> +		return -EFAULT;
> +	return 0;
> +}

This needs to live in the core. I think the real_dev is a lower of the
vlan device? All the vlan driver should do is attach the generic helper:

	.ndo_hwtstamp_get = generic_hwtstamp_get_lower,

and the same for set. No?

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05 16:42 ` Jakub Kicinski
@ 2023-04-05 17:03   ` Vladimir Oltean
  2023-04-05 17:13     ` Jakub Kicinski
  0 siblings, 1 reply; 19+ messages in thread
From: Vladimir Oltean @ 2023-04-05 17:03 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Maxim Georgiev, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Wed, Apr 05, 2023 at 09:42:10AM -0700, Jakub Kicinski wrote:
> This needs to live in the core. I think the real_dev is a lower of the
> vlan device? All the vlan driver should do is attach the generic helper:
> 
> 	.ndo_hwtstamp_get = generic_hwtstamp_get_lower,
> 
> and the same for set. No?

The goal would be for macvlan and bonding to use the same generic_hwtstamp_get_lower()?
How would the generic helper get to bond_option_active_slave_get_rcu(),
vlan_dev_priv(dev)->real_dev, macvlan_dev_real_dev(dev)?

Perhaps a generic_hwtstamp_get_lower() that takes the lower as argument,
and 3 small wrappers in vlan, macvlan, bonding which identify that lower?

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05 17:03   ` Vladimir Oltean
@ 2023-04-05 17:13     ` Jakub Kicinski
  2023-04-05 17:28       ` Vladimir Oltean
  0 siblings, 1 reply; 19+ messages in thread
From: Jakub Kicinski @ 2023-04-05 17:13 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Maxim Georgiev, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Wed, 5 Apr 2023 20:03:22 +0300 Vladimir Oltean wrote:
> The goal would be for macvlan and bonding to use the same generic_hwtstamp_get_lower()?
> How would the generic helper get to bond_option_active_slave_get_rcu(),
> vlan_dev_priv(dev)->real_dev, macvlan_dev_real_dev(dev)?
> 
> Perhaps a generic_hwtstamp_get_lower() that takes the lower as argument,
> and 3 small wrappers in vlan, macvlan, bonding which identify that lower?

The bonding situation is probably more complex, I haven't looked,
but for *vlans we can just get the lower from netdev linkage, no?
Sure the drivers have their own pointers for convenience and with
their own lifetime rules but under rtnl lock lower/upper should work...

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05 17:13     ` Jakub Kicinski
@ 2023-04-05 17:28       ` Vladimir Oltean
  2023-04-05 17:34         ` Vladimir Oltean
  2023-04-05 17:42         ` Jakub Kicinski
  0 siblings, 2 replies; 19+ messages in thread
From: Vladimir Oltean @ 2023-04-05 17:28 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Maxim Georgiev, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Wed, Apr 05, 2023 at 10:13:23AM -0700, Jakub Kicinski wrote:
> On Wed, 5 Apr 2023 20:03:22 +0300 Vladimir Oltean wrote:
> > The goal would be for macvlan and bonding to use the same generic_hwtstamp_get_lower()?
> > How would the generic helper get to bond_option_active_slave_get_rcu(),
> > vlan_dev_priv(dev)->real_dev, macvlan_dev_real_dev(dev)?
> > 
> > Perhaps a generic_hwtstamp_get_lower() that takes the lower as argument,
> > and 3 small wrappers in vlan, macvlan, bonding which identify that lower?
> 
> The bonding situation is probably more complex, I haven't looked,
> but for *vlans we can just get the lower from netdev linkage, no?
> Sure the drivers have their own pointers for convenience and with
> their own lifetime rules but under rtnl lock lower/upper should work...

So what do you suggest doing with bonding, then? Not use the generic
helper at all? It's not that more complex, btw. Here are the differences:

- it changes ifrr.ifr_name with real_dev->name for a reason I can't
  really determine or find in commit 94dd016ae538 ("bond: pass
  get_ts_info and SIOC[SG]HWTSTAMP ioctl to active device"). Since vlan
  and macvlan don't do it, and operate with lower drivers from the same
  pool as bonding, I'd imagine it's not needed.

- it requires cfg.flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX to be set in
  SET requests

- it sets cfg.flags | HWTSTAMP_FLAG_BONDED_PHC_INDEX in GET responses

Notably, something I would have expected it does but it doesn't do is it
doesn't apply the same hwtstamping config to the lower interface that
isn't active, when the switchover happens. Presumably user space does that.

So it's not that much different.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05 17:28       ` Vladimir Oltean
@ 2023-04-05 17:34         ` Vladimir Oltean
  2023-04-05 17:42         ` Jakub Kicinski
  1 sibling, 0 replies; 19+ messages in thread
From: Vladimir Oltean @ 2023-04-05 17:34 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Maxim Georgiev, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Wed, Apr 05, 2023 at 08:28:40PM +0300, Vladimir Oltean wrote:
> - it changes ifrr.ifr_name with real_dev->name for a reason I can't
>   really determine or find in commit 94dd016ae538 ("bond: pass
>   get_ts_info and SIOC[SG]HWTSTAMP ioctl to active device"). Since vlan
>   and macvlan don't do it, and operate with lower drivers from the same
>   pool as bonding, I'd imagine it's not needed.

Ah, they do, they do, my bad. So it's down to 2 differences, which can
be handled easily with the wrapper function model - the bonding wrapper
checks, or sets, the HWTSTAMP_FLAG_BONDED_PHC_INDEX flag.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05 17:28       ` Vladimir Oltean
  2023-04-05 17:34         ` Vladimir Oltean
@ 2023-04-05 17:42         ` Jakub Kicinski
  2023-04-05 18:01           ` Vladimir Oltean
  1 sibling, 1 reply; 19+ messages in thread
From: Jakub Kicinski @ 2023-04-05 17:42 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Maxim Georgiev, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Wed, 5 Apr 2023 20:28:40 +0300 Vladimir Oltean wrote:
> So what do you suggest doing with bonding, then? Not use the generic
> helper at all?

It'd seem most natural to me to split the generic "descend" helper into
two functions, one which retrieves the lower and one which does the
appropriate calling dance (ndo vs ioctl, and DSA, which I guess is now
gone?). The latter could be used for the first descend as well I'd
presume. And it can be exported for the use of more complex drivers
like bonding which want to walk the lowers themselves.

> - it requires cfg.flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX to be set in
>   SET requests
> 
> - it sets cfg.flags | HWTSTAMP_FLAG_BONDED_PHC_INDEX in GET responses

IIRC that was to indicate to user space that the real PHC may change
for this netdev so it needs to pay attention to netlink notifications.
Shouldn't apply to *vlans?

> Notably, something I would have expected it does but it doesn't do is it
> doesn't apply the same hwtstamping config to the lower interface that
> isn't active, when the switchover happens. Presumably user space does that.

Yes, user space must be involved anyway, because the entire clock will
change. IMHO implementing the pass thru for timestamping requests on
bonding is checkbox engineering, kernel can't make it work
transparently. But nobody else spoke up when it was proposed so...

> So it's not that much different.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05 17:42         ` Jakub Kicinski
@ 2023-04-05 18:01           ` Vladimir Oltean
  2023-04-06  0:00             ` Jakub Kicinski
  0 siblings, 1 reply; 19+ messages in thread
From: Vladimir Oltean @ 2023-04-05 18:01 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Maxim Georgiev, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Wed, Apr 05, 2023 at 10:42:53AM -0700, Jakub Kicinski wrote:
> On Wed, 5 Apr 2023 20:28:40 +0300 Vladimir Oltean wrote:
> > So what do you suggest doing with bonding, then? Not use the generic
> > helper at all?
> 
> It'd seem most natural to me to split the generic "descend" helper into
> two functions, one which retrieves the lower and one which does the
> appropriate calling dance (ndo vs ioctl, and DSA, which I guess is now
> gone?).

There's nothing DSA-related to be done. DSA masters can't be lowers of
any other virtual interface kinds except bridge or bonding/team, and:
- bridge doesn't support hwtstamping
- bonding is also DSA master when it has a DSA master as lower, so the
  DSA master restriction has already run once - on the bonding device
  itself

> The latter could be used for the first descend as well I'd presume.
> And it can be exported for the use of more complex drivers like
> bonding which want to walk the lowers themselves.
> 
> > - it requires cfg.flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX to be set in
> >   SET requests
> > 
> > - it sets cfg.flags | HWTSTAMP_FLAG_BONDED_PHC_INDEX in GET responses
> 
> IIRC that was to indicate to user space that the real PHC may change
> for this netdev so it needs to pay attention to netlink notifications.
> Shouldn't apply to *vlans?

No, this shouldn't apply to *vlans, but I didn't suggest that it should.
I don't think my proposal was clear enough, so here's some code
(untested, written in email client).

static int macvlan_hwtstamp_get(struct net_device *dev,
				struct kernel_hwtstamp_config *cfg,
				struct netlink_ext_ack *extack)
{
	struct net_device *real_dev = macvlan_dev_real_dev(dev);

	return generic_hwtstamp_get_lower(real_dev, cfg, extack);
}

static int macvlan_hwtstamp_set(struct net_device *dev,
				struct kernel_hwtstamp_config *cfg,
				struct netlink_ext_ack *extack)
{
	struct net_device *real_dev = macvlan_dev_real_dev(dev);

	return generic_hwtstamp_set_lower(real_dev, cfg, extack);
}

static int vlan_hwtstamp_get(struct net_device *dev,
			     struct kernel_hwtstamp_config *cfg,
			     struct netlink_ext_ack *extack)
{
	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;

	return generic_hwtstamp_get_lower(real_dev, cfg, extack);
}

static int vlan_hwtstamp_set(struct net_device *dev,
			     struct kernel_hwtstamp_config *cfg,
			     struct netlink_ext_ack *extack)
{
	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;

	return generic_hwtstamp_set_lower(real_dev, cfg, extack);
}

static int bond_hwtstamp_get(struct net_device *bond_dev,
			     struct kernel_hwtstamp_config *cfg,
			     struct netlink_ext_ack *extack)
{
	struct bonding *bond = netdev_priv(bond_dev);
	struct net_device *real_dev = bond_option_active_slave_get_rcu(bond);
	int err;

	if (!real_dev)
		return -EOPNOTSUPP;

	err = generic_hwtstamp_get_lower(real_dev, cfg, extack);
	if (err)
		return err;

	/* Set the BOND_PHC_INDEX flag to notify user space */
	cfg->flags |= HWTSTAMP_FLAG_BONDED_PHC_INDEX;

	return 0;
}

static int bond_hwtstamp_set(struct net_device *bond_dev,
			     struct kernel_hwtstamp_config *cfg,
			     struct netlink_ext_ack *extack)
{
	struct bonding *bond = netdev_priv(bond_dev);
	struct net_device *real_dev = bond_option_active_slave_get_rcu(bond);
	int err;

	if (!real_dev)
		return -EOPNOTSUPP;

	if (!(cfg->flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX))
		return -EOPNOTSUPP;

	return generic_hwtstamp_set_lower(real_dev, cfg, extack);
}

Doesn't seem in any way necessary to complicate things with the netdev
adjacence lists?

> Yes, user space must be involved anyway, because the entire clock will
> change. IMHO implementing the pass thru for timestamping requests on
> bonding is checkbox engineering, kernel can't make it work
> transparently. But nobody else spoke up when it was proposed so...

ok, but that's a bit beside the point here.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05  6:33 [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path Maxim Georgiev
                   ` (2 preceding siblings ...)
  2023-04-05 16:42 ` Jakub Kicinski
@ 2023-04-05 18:33 ` kernel test robot
  3 siblings, 0 replies; 19+ messages in thread
From: kernel test robot @ 2023-04-05 18:33 UTC (permalink / raw)
  To: Maxim Georgiev; +Cc: oe-kbuild-all

Hi Maxim,

[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:

[auto build test ERROR on tnguy-next-queue/dev-queue]
[also build test ERROR on next-20230405]
[cannot apply to horms-ipvs/master linus/master v6.3-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Maxim-Georgiev/Add-ifreq-pointer-field-to-kernel_hwtstamp_config-structure/20230405-143518
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue.git dev-queue
patch link:    https://lore.kernel.org/r/20230405063323.36270-1-glipus%40gmail.com
patch subject: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
config: arc-randconfig-r034-20230404 (https://download.01.org/0day-ci/archive/20230406/202304060246.Vxhd7U2x-lkp@intel.com/config)
compiler: arc-elf-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/e48fe7f9909e9c0768e866c43b1cc880c0eb329f
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Maxim-Georgiev/Add-ifreq-pointer-field-to-kernel_hwtstamp_config-structure/20230405-143518
        git checkout e48fe7f9909e9c0768e866c43b1cc880c0eb329f
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arc olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arc SHELL=/bin/bash net/8021q/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304060246.Vxhd7U2x-lkp@intel.com/

All errors (new ones prefixed by >>):

   net/8021q/vlan_dev.c: In function 'vlan_dev_hwtstamp':
>> net/8021q/vlan_dev.c:369:51: error: 'real_dev' undeclared (first use in this function)
     369 |                         return ops->ndo_eth_ioctl(real_dev, &ifr, cmd);
         |                                                   ^~~~~~~~
   net/8021q/vlan_dev.c:369:51: note: each undeclared identifier is reported only once for each function it appears in
>> net/8021q/vlan_dev.c:369:61: error: passing argument 2 of 'ops->ndo_eth_ioctl' from incompatible pointer type [-Werror=incompatible-pointer-types]
     369 |                         return ops->ndo_eth_ioctl(real_dev, &ifr, cmd);
         |                                                             ^~~~
         |                                                             |
         |                                                             struct ifreq **
   net/8021q/vlan_dev.c:369:61: note: expected 'struct ifreq *' but argument is of type 'struct ifreq **'
>> net/8021q/vlan_dev.c:370:17: error: expected '}' before 'else'
     370 |                 else
         |                 ^~~~
   cc1: some warnings being treated as errors


vim +/real_dev +369 net/8021q/vlan_dev.c

   355	
   356	static int vlan_dev_hwtstamp(struct net_device *dev, struct ifreq *ifr, int cmd)
   357	{
   358		const struct net_device_ops *ops = dev->netdev_ops;
   359		struct kernel_hwtstamp_config kernel_config = {};
   360		struct hwtstamp_config config;
   361		int err;
   362	
   363		if (!netif_device_present(dev))
   364			return -ENODEV;
   365	
   366		if ((cmd == SIOCSHWTSTAMP && !ops->ndo_hwtstamp_set) ||
   367		    (cmd == SIOCGHWTSTAMP && !ops->ndo_hwtstamp_get)) {
   368			if (ops->ndo_eth_ioctl) {
 > 369				return ops->ndo_eth_ioctl(real_dev, &ifr, cmd);
 > 370			else
   371				return -EOPNOTSUPP;
   372		}
   373	
   374		kernel_config.ifr = ifr;
   375		if (cmd == SIOCSHWTSTAMP) {
   376			if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
   377				return -EFAULT;
   378	
   379			hwtstamp_config_to_kernel(&kernel_config, &config);
   380			err = ops->ndo_hwtstamp_set(dev, &kernel_config, NULL);
   381		} else if (cmd == SIOCGHWTSTAMP) {
   382			err = ops->ndo_hwtstamp_get(dev, &kernel_config, NULL);
   383		}
   384	
   385		if (err)
   386			return err;
   387	
   388		hwtstamp_kernel_to_config(&config, &kernel_config);
   389		if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
   390			return -EFAULT;
   391		return 0;
   392	}
   393	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-05 18:01           ` Vladimir Oltean
@ 2023-04-06  0:00             ` Jakub Kicinski
  2023-04-06  6:21               ` Max Georgiev
  0 siblings, 1 reply; 19+ messages in thread
From: Jakub Kicinski @ 2023-04-06  0:00 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Maxim Georgiev, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Wed, 5 Apr 2023 21:01:21 +0300 Vladimir Oltean wrote:
> - bonding is also DSA master when it has a DSA master as lower, so the
>   DSA master restriction has already run once - on the bonding device
>   itself

Huh, didn't know that.

> > The latter could be used for the first descend as well I'd presume.
> > And it can be exported for the use of more complex drivers like
> > bonding which want to walk the lowers themselves.
> >   
> > > - it requires cfg.flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX to be set in
> > >   SET requests
> > > 
> > > - it sets cfg.flags | HWTSTAMP_FLAG_BONDED_PHC_INDEX in GET responses  
> > 
> > IIRC that was to indicate to user space that the real PHC may change
> > for this netdev so it needs to pay attention to netlink notifications.
> > Shouldn't apply to *vlans?  
> 
> No, this shouldn't apply to *vlans, but I didn't suggest that it should.

Good, so if we just target *vlans we don't have to worry.

> I don't think my proposal was clear enough, so here's some code
> (untested, written in email client).
> 
> static int macvlan_hwtstamp_get(struct net_device *dev,
> 				struct kernel_hwtstamp_config *cfg,
> 				struct netlink_ext_ack *extack)
> {
> 	struct net_device *real_dev = macvlan_dev_real_dev(dev);
> 
> 	return generic_hwtstamp_get_lower(real_dev, cfg, extack);
> }
> 
> static int macvlan_hwtstamp_set(struct net_device *dev,
> 				struct kernel_hwtstamp_config *cfg,
> 				struct netlink_ext_ack *extack)
> {
> 	struct net_device *real_dev = macvlan_dev_real_dev(dev);
> 
> 	return generic_hwtstamp_set_lower(real_dev, cfg, extack);
> }
> 
> static int vlan_hwtstamp_get(struct net_device *dev,
> 			     struct kernel_hwtstamp_config *cfg,
> 			     struct netlink_ext_ack *extack)
> {
> 	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
> 
> 	return generic_hwtstamp_get_lower(real_dev, cfg, extack);
> }
> 
> static int vlan_hwtstamp_set(struct net_device *dev,
> 			     struct kernel_hwtstamp_config *cfg,
> 			     struct netlink_ext_ack *extack)
> {
> 	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
> 
> 	return generic_hwtstamp_set_lower(real_dev, cfg, extack);
> }

I got that, but why wouldn't this not be better, as it avoids 
the 3 driver stubs? (also written in the MUA)

int net_lower_hwtstamp_set(struct net_device *dev,
			   struct kernel_hwtstamp_config *cfg,
			   struct netlink_ext_ack *extack)
{
	struct list_head *iter = dev->adj_list.lower.next;
	struct net_device *lower;
	
	lower = netdev_lower_get_next(dev, &iter);
	return generic_hwtstamp_set_lower(lower, cfg, extack);
}

> static int bond_hwtstamp_get(struct net_device *bond_dev,
> 			     struct kernel_hwtstamp_config *cfg,
> 			     struct netlink_ext_ack *extack)
> {
> 	struct bonding *bond = netdev_priv(bond_dev);
> 	struct net_device *real_dev = bond_option_active_slave_get_rcu(bond);
> 	int err;
> 
> 	if (!real_dev)
> 		return -EOPNOTSUPP;
> 
> 	err = generic_hwtstamp_get_lower(real_dev, cfg, extack);
> 	if (err)
> 		return err;
> 
> 	/* Set the BOND_PHC_INDEX flag to notify user space */
> 	cfg->flags |= HWTSTAMP_FLAG_BONDED_PHC_INDEX;
> 
> 	return 0;
> }
> 
> static int bond_hwtstamp_set(struct net_device *bond_dev,
> 			     struct kernel_hwtstamp_config *cfg,
> 			     struct netlink_ext_ack *extack)
> {
> 	struct bonding *bond = netdev_priv(bond_dev);
> 	struct net_device *real_dev = bond_option_active_slave_get_rcu(bond);
> 	int err;
> 
> 	if (!real_dev)
> 		return -EOPNOTSUPP;
> 
> 	if (!(cfg->flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX))
> 		return -EOPNOTSUPP;
> 
> 	return generic_hwtstamp_set_lower(real_dev, cfg, extack);
> }
> 
> Doesn't seem in any way necessary to complicate things with the netdev
> adjacence lists?

What is the complication? We can add a "get first" helper maybe to hide
the oddities of the linking.

> > Yes, user space must be involved anyway, because the entire clock will
> > change. IMHO implementing the pass thru for timestamping requests on
> > bonding is checkbox engineering, kernel can't make it work
> > transparently. But nobody else spoke up when it was proposed so...  
> 
> ok, but that's a bit beside the point here.

You cut off the quote it was responding to so IDK if it is.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-06  0:00             ` Jakub Kicinski
@ 2023-04-06  6:21               ` Max Georgiev
  2023-04-06 15:01                 ` Vladimir Oltean
  2023-04-08 13:56                 ` Richard Cochran
  0 siblings, 2 replies; 19+ messages in thread
From: Max Georgiev @ 2023-04-06  6:21 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Vladimir Oltean, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Wed, Apr 5, 2023 at 6:00 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Wed, 5 Apr 2023 21:01:21 +0300 Vladimir Oltean wrote:
> > - bonding is also DSA master when it has a DSA master as lower, so the
> >   DSA master restriction has already run once - on the bonding device
> >   itself
>
> Huh, didn't know that.
>
> > > The latter could be used for the first descend as well I'd presume.
> > > And it can be exported for the use of more complex drivers like
> > > bonding which want to walk the lowers themselves.
> > >
> > > > - it requires cfg.flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX to be set in
> > > >   SET requests
> > > >
> > > > - it sets cfg.flags | HWTSTAMP_FLAG_BONDED_PHC_INDEX in GET responses
> > >
> > > IIRC that was to indicate to user space that the real PHC may change
> > > for this netdev so it needs to pay attention to netlink notifications.
> > > Shouldn't apply to *vlans?
> >
> > No, this shouldn't apply to *vlans, but I didn't suggest that it should.
>
> Good, so if we just target *vlans we don't have to worry.
>
> > I don't think my proposal was clear enough, so here's some code
> > (untested, written in email client).
> >
> > static int macvlan_hwtstamp_get(struct net_device *dev,
> >                               struct kernel_hwtstamp_config *cfg,
> >                               struct netlink_ext_ack *extack)
> > {
> >       struct net_device *real_dev = macvlan_dev_real_dev(dev);
> >
> >       return generic_hwtstamp_get_lower(real_dev, cfg, extack);
> > }
> >
> > static int macvlan_hwtstamp_set(struct net_device *dev,
> >                               struct kernel_hwtstamp_config *cfg,
> >                               struct netlink_ext_ack *extack)
> > {
> >       struct net_device *real_dev = macvlan_dev_real_dev(dev);
> >
> >       return generic_hwtstamp_set_lower(real_dev, cfg, extack);
> > }
> >
> > static int vlan_hwtstamp_get(struct net_device *dev,
> >                            struct kernel_hwtstamp_config *cfg,
> >                            struct netlink_ext_ack *extack)
> > {
> >       struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
> >
> >       return generic_hwtstamp_get_lower(real_dev, cfg, extack);
> > }
> >
> > static int vlan_hwtstamp_set(struct net_device *dev,
> >                            struct kernel_hwtstamp_config *cfg,
> >                            struct netlink_ext_ack *extack)
> > {
> >       struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
> >
> >       return generic_hwtstamp_set_lower(real_dev, cfg, extack);
> > }
>
> I got that, but why wouldn't this not be better, as it avoids
> the 3 driver stubs? (also written in the MUA)
>
> int net_lower_hwtstamp_set(struct net_device *dev,
>                            struct kernel_hwtstamp_config *cfg,
>                            struct netlink_ext_ack *extack)
> {
>         struct list_head *iter = dev->adj_list.lower.next;
>         struct net_device *lower;
>
>         lower = netdev_lower_get_next(dev, &iter);
>         return generic_hwtstamp_set_lower(lower, cfg, extack);
> }
>
> > static int bond_hwtstamp_get(struct net_device *bond_dev,
> >                            struct kernel_hwtstamp_config *cfg,
> >                            struct netlink_ext_ack *extack)
> > {
> >       struct bonding *bond = netdev_priv(bond_dev);
> >       struct net_device *real_dev = bond_option_active_slave_get_rcu(bond);
> >       int err;
> >
> >       if (!real_dev)
> >               return -EOPNOTSUPP;
> >
> >       err = generic_hwtstamp_get_lower(real_dev, cfg, extack);
> >       if (err)
> >               return err;
> >
> >       /* Set the BOND_PHC_INDEX flag to notify user space */
> >       cfg->flags |= HWTSTAMP_FLAG_BONDED_PHC_INDEX;
> >
> >       return 0;
> > }
> >
> > static int bond_hwtstamp_set(struct net_device *bond_dev,
> >                            struct kernel_hwtstamp_config *cfg,
> >                            struct netlink_ext_ack *extack)
> > {
> >       struct bonding *bond = netdev_priv(bond_dev);
> >       struct net_device *real_dev = bond_option_active_slave_get_rcu(bond);
> >       int err;
> >
> >       if (!real_dev)
> >               return -EOPNOTSUPP;
> >
> >       if (!(cfg->flags & HWTSTAMP_FLAG_BONDED_PHC_INDEX))
> >               return -EOPNOTSUPP;
> >
> >       return generic_hwtstamp_set_lower(real_dev, cfg, extack);
> > }
> >
> > Doesn't seem in any way necessary to complicate things with the netdev
> > adjacence lists?
>
> What is the complication? We can add a "get first" helper maybe to hide
> the oddities of the linking.
>
> > > Yes, user space must be involved anyway, because the entire clock will
> > > change. IMHO implementing the pass thru for timestamping requests on
> > > bonding is checkbox engineering, kernel can't make it work
> > > transparently. But nobody else spoke up when it was proposed so...
> >
> > ok, but that's a bit beside the point here.
>
> You cut off the quote it was responding to so IDK if it is.

I tried my best to follow the discussion, and convert it to compilable code.
Here is what I have in mind for generic_hwtstamp_get_lower():

int generic_hwtstamp_get_lower(struct net_dev *dev,
                           struct kernel_hwtstamp_config *kernel_cfg,
                           struct netlink_ext_ack *extack)
{
        const struct net_device_ops *ops = dev->netdev_ops;
        struct hwtstamp_config cfg;
        int err;

        if (!netif_device_present(dev))
                return -ENODEV;

        if (ops->ndo_hwtstamp_get)
                return ops->ndo_hwtstamp_get(dev, cfg, extack);

        if (!cfg->ifr)
                return -EOPNOTSUPP;

        err = dev_eth_ioctl(dev, cfg->ifr, SIOCGHWTSTAMP);
        if (err)
            return err;

        if (copy_from_user(&cfg, cfg->ifr->ifr_data, sizeof(cfg)))
                return -EFAULT;

        hwtstamp_config_to_kernel(kernel_cfg, &cfg);

        return 0;
}

It looks like there is a possibility that the returned hwtstamp_config structure
will be copied twice to ifr and copied once from ifr on the return path
in case if the underlying driver does not implement ndo_hwtstamp_get():
- the underlying driver calls copy_to_user() inside its ndo_eth_ioctl()
  implementation to return the data to generic_hwtstamp_get_lower();
- then generic_hwtstamp_get_lower() calls copy_from_user() to copy it
  back out of the ifr to kernel_hwtstamp_config structure;
- then dev_get_hwtstamp() calls copy_to_user() again to update
  the same ifr with the same data the ifr already contains.

Should we consider this acceptable?

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-06  6:21               ` Max Georgiev
@ 2023-04-06 15:01                 ` Vladimir Oltean
  2023-04-06 16:18                   ` Max Georgiev
  2023-04-08 13:56                 ` Richard Cochran
  1 sibling, 1 reply; 19+ messages in thread
From: Vladimir Oltean @ 2023-04-06 15:01 UTC (permalink / raw)
  To: Max Georgiev
  Cc: Jakub Kicinski, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Thu, Apr 06, 2023 at 12:21:37AM -0600, Max Georgiev wrote:
> I tried my best to follow the discussion, and convert it to compilable code.
> Here is what I have in mind for generic_hwtstamp_get_lower():
> 
> int generic_hwtstamp_get_lower(struct net_dev *dev,
>                            struct kernel_hwtstamp_config *kernel_cfg,
>                            struct netlink_ext_ack *extack)
> {
>         const struct net_device_ops *ops = dev->netdev_ops;
>         struct hwtstamp_config cfg;
>         int err;
> 
>         if (!netif_device_present(dev))
>                 return -ENODEV;
> 
>         if (ops->ndo_hwtstamp_get)
>                 return ops->ndo_hwtstamp_get(dev, cfg, extack);
> 
>         if (!cfg->ifr)
>                 return -EOPNOTSUPP;
> 
>         err = dev_eth_ioctl(dev, cfg->ifr, SIOCGHWTSTAMP);
>         if (err)
>             return err;
> 
>         if (copy_from_user(&cfg, cfg->ifr->ifr_data, sizeof(cfg)))
>                 return -EFAULT;
> 
>         hwtstamp_config_to_kernel(kernel_cfg, &cfg);
> 
>         return 0;
> }

Side note, it doesn't look like this code is particularly compilable
either - "cfg" is used in some places instead of "kernel_cfg".

> 
> It looks like there is a possibility that the returned hwtstamp_config structure
> will be copied twice to ifr and copied once from ifr on the return path
> in case if the underlying driver does not implement ndo_hwtstamp_get():
> - the underlying driver calls copy_to_user() inside its ndo_eth_ioctl()
>   implementation to return the data to generic_hwtstamp_get_lower();
> - then generic_hwtstamp_get_lower() calls copy_from_user() to copy it
>   back out of the ifr to kernel_hwtstamp_config structure;
> - then dev_get_hwtstamp() calls copy_to_user() again to update
>   the same ifr with the same data the ifr already contains.
> 
> Should we consider this acceptable?

Thanks for laying this out. I guess with a table it's going to be
clearer, so to summarize, I believe this is the status:

Assuming we convert *vlan to ndo_hwtstamp_set():

===================

If the vlan driver is converted to ndo_hwtstamp_set() and the real_dev
driver uses ndo_eth_ioctl(), we have:
- one copy_from_user() in dev_set_hwtstamp()
- one copy_from_user() in the real_dev's ndo_eth_ioctl()
- one copy_to_user() in the real_dev's ndo_eth_ioctl()
- one copy_from_user() in generic_hwtstamp_get_lower()
- one copy_to_user() in dev_set_hwtstamp()

If the vlan driver is converted to ndo_hwtstamp_set() and the real_dev
is converted too, we have:
- one copy_from_user() in dev_set_hwtstamp()
- one copy_to_user() in dev_set_hwtstamp()

===================

Assuming we don't convert *vlan to ndo_hwtstamp_set():

===================

If the vlan driver isn't converted to ndo_hwtstamp_set() and the
real_dev driver isn't converted either, we have:
- one copy_from_user() in dev_set_hwtstamp()
- one copy_from_user() in the real_dev's ndo_eth_ioctl()
- one copy_to_user() in the real_dev's ndo_eth_ioctl()

If the vlan driver isn't converted to ndo_hwtstamp_set(), but the
real_dev driver is, we have:
- one copy_from_user() in dev_set_hwtstamp()
- one copy_from_user() in the vlan's ndo_eth_ioctl()
- one copy_to_user() in the vlan's ndo_eth_ioctl()

===================

So between converting and not converting the *vlans to ndo_hwtstamp_set(),
the worst case is going to be worse (with a mix of new API in *vlan and
old API in real_dev) and the best case is going to be better (with new
API in both *vlan and real_dev). OTOH, with old API in *vlan, the number
of copies to/from the user buffer is going to be constant at 3, which is
not the best, not the worst.

I guess the data indicates that we should convert the *vlans to
ndo_hwtstamp_set() at the very end of the process, and for now, just
make them compatible with a real_dev that uses the new API?

Note that I haven't done the math for the "get" operation yet, but I
believe it to be similar.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-06 15:01                 ` Vladimir Oltean
@ 2023-04-06 16:18                   ` Max Georgiev
  2023-04-06 16:50                     ` Vladimir Oltean
  0 siblings, 1 reply; 19+ messages in thread
From: Max Georgiev @ 2023-04-06 16:18 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Jakub Kicinski, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Thu, Apr 6, 2023 at 9:02 AM Vladimir Oltean <vladimir.oltean@nxp.com> wrote:
>
> On Thu, Apr 06, 2023 at 12:21:37AM -0600, Max Georgiev wrote:
> > I tried my best to follow the discussion, and convert it to compilable code.
> > Here is what I have in mind for generic_hwtstamp_get_lower():
> >
> > int generic_hwtstamp_get_lower(struct net_dev *dev,
> >                            struct kernel_hwtstamp_config *kernel_cfg,
> >                            struct netlink_ext_ack *extack)
> > {
> >         const struct net_device_ops *ops = dev->netdev_ops;
> >         struct hwtstamp_config cfg;
> >         int err;
> >
> >         if (!netif_device_present(dev))
> >                 return -ENODEV;
> >
> >         if (ops->ndo_hwtstamp_get)
> >                 return ops->ndo_hwtstamp_get(dev, cfg, extack);
> >
> >         if (!cfg->ifr)
> >                 return -EOPNOTSUPP;
> >
> >         err = dev_eth_ioctl(dev, cfg->ifr, SIOCGHWTSTAMP);
> >         if (err)
> >             return err;
> >
> >         if (copy_from_user(&cfg, cfg->ifr->ifr_data, sizeof(cfg)))
> >                 return -EFAULT;
> >
> >         hwtstamp_config_to_kernel(kernel_cfg, &cfg);
> >
> >         return 0;
> > }
>
> Side note, it doesn't look like this code is particularly compilable
> either - "cfg" is used in some places instead of "kernel_cfg".

That's true, this code wouldn't compile. I copied it here to
illustrate the potentially concerning logic.
Thank you for pointing this out though!

>
> >
> > It looks like there is a possibility that the returned hwtstamp_config structure
> > will be copied twice to ifr and copied once from ifr on the return path
> > in case if the underlying driver does not implement ndo_hwtstamp_get():
> > - the underlying driver calls copy_to_user() inside its ndo_eth_ioctl()
> >   implementation to return the data to generic_hwtstamp_get_lower();
> > - then generic_hwtstamp_get_lower() calls copy_from_user() to copy it
> >   back out of the ifr to kernel_hwtstamp_config structure;
> > - then dev_get_hwtstamp() calls copy_to_user() again to update
> >   the same ifr with the same data the ifr already contains.
> >
> > Should we consider this acceptable?
>
> Thanks for laying this out. I guess with a table it's going to be
> clearer, so to summarize, I believe this is the status:
>
> Assuming we convert *vlan to ndo_hwtstamp_set():
>
> ===================
>
> If the vlan driver is converted to ndo_hwtstamp_set() and the real_dev
> driver uses ndo_eth_ioctl(), we have:
> - one copy_from_user() in dev_set_hwtstamp()
> - one copy_from_user() in the real_dev's ndo_eth_ioctl()
> - one copy_to_user() in the real_dev's ndo_eth_ioctl()
> - one copy_from_user() in generic_hwtstamp_get_lower()
> - one copy_to_user() in dev_set_hwtstamp()
>
> If the vlan driver is converted to ndo_hwtstamp_set() and the real_dev
> is converted too, we have:
> - one copy_from_user() in dev_set_hwtstamp()
> - one copy_to_user() in dev_set_hwtstamp()
>
> ===================
>
> Assuming we don't convert *vlan to ndo_hwtstamp_set():
>
> ===================
>
> If the vlan driver isn't converted to ndo_hwtstamp_set() and the
> real_dev driver isn't converted either, we have:
> - one copy_from_user() in dev_set_hwtstamp()
> - one copy_from_user() in the real_dev's ndo_eth_ioctl()
> - one copy_to_user() in the real_dev's ndo_eth_ioctl()
>
> If the vlan driver isn't converted to ndo_hwtstamp_set(), but the
> real_dev driver is, we have:
> - one copy_from_user() in dev_set_hwtstamp()
> - one copy_from_user() in the vlan's ndo_eth_ioctl()
> - one copy_to_user() in the vlan's ndo_eth_ioctl()
>
> ===================
>
> So between converting and not converting the *vlans to ndo_hwtstamp_set(),
> the worst case is going to be worse (with a mix of new API in *vlan and
> old API in real_dev) and the best case is going to be better (with new
> API in both *vlan and real_dev). OTOH, with old API in *vlan, the number
> of copies to/from the user buffer is going to be constant at 3, which is
> not the best, not the worst.
>
> I guess the data indicates that we should convert the *vlans to
> ndo_hwtstamp_set() at the very end of the process, and for now, just
> make them compatible with a real_dev that uses the new API?
>
> Note that I haven't done the math for the "get" operation yet, but I
> believe it to be similar.

Thank you for putting this overhead tracking table together!

Here is my guess on how this accounting would look like
for the "get" codepath:

Assuming we convert *vlan to ndo_hwtstamp_set():

===================

If the vlan driver is converted to ndo_hwtstamp_get() and the real_dev
driver uses ndo_eth_ioctl(), we have:
- one copy_to_user() in the real_dev's ndo_eth_ioctl()
- one copy_from_user() in generic_hwtstamp_get_lower()
- one copy_to_user() in dev_get_hwtstamp()

If the vlan driver is converted to ndo_hwtstamp_get() and the real_dev
is converted too, we have:
- one copy_to_user() in dev_get_hwtstamp()

===================

Assuming we don't convert *vlan to ndo_hwtstamp_get():

===================

If the vlan driver isn't converted to ndo_hwtstamp_get() and the
real_dev driver isn't converted either, we have:
- one copy_to_user() in the real_dev's ndo_eth_ioctl()

If the vlan driver isn't converted to ndo_hwtstamp_get(), but the
real_dev driver is, we have:
- one copy_to_user() in the vlan's ndo_eth_ioctl()

===================

Adding real_dev->ndo_hwtstamp_get/set() support to vlan_eth_ioctl()
and holding back with ndo_hwtstamp_get/set() implementation in vlan
code looks like a winner again.

If I may, there are other ways to work around this inefficiency.
Since kernel_hwtstamp_config was meant to be easily extendable,
we can abuse it and add a flag field there. One of the flag values
can indicate that the operation result structure was already copied
to kernel_config->ifr by the function that received this kernel_config
instance as a parameter, and that the content of the
hwtstamp_config-related fields in kernel_config structure must
be ignored when the function returns. It would complicate the
implementation logic, but we'd avoid some unnecessary copy
operations while converting *vlan components to the newer interface.
Would it be a completely unreasonable approach?

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-06 16:18                   ` Max Georgiev
@ 2023-04-06 16:50                     ` Vladimir Oltean
  0 siblings, 0 replies; 19+ messages in thread
From: Vladimir Oltean @ 2023-04-06 16:50 UTC (permalink / raw)
  To: Max Georgiev
  Cc: Jakub Kicinski, kory.maincent, netdev, maxime.chevallier,
	vadim.fedorenko, richardcochran, gerhard

On Thu, Apr 06, 2023 at 10:18:36AM -0600, Max Georgiev wrote:
> If I may, there are other ways to work around this inefficiency.
> Since kernel_hwtstamp_config was meant to be easily extendable,
> we can abuse it and add a flag field there. One of the flag values
> can indicate that the operation result structure was already copied
> to kernel_config->ifr by the function that received this kernel_config
> instance as a parameter, and that the content of the
> hwtstamp_config-related fields in kernel_config structure must
> be ignored when the function returns. It would complicate the
> implementation logic, but we'd avoid some unnecessary copy
> operations while converting *vlan components to the newer interface.
> Would it be a completely unreasonable approach?

No, I think that's fair game and a good idea. It would make the best
case better (SET request on a converted real_dev drops from 3 copies to 2),
while keeping the worst case the same (SET request on an unconverted
real_dev remains at 3 copies).

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path
  2023-04-06  6:21               ` Max Georgiev
  2023-04-06 15:01                 ` Vladimir Oltean
@ 2023-04-08 13:56                 ` Richard Cochran
  1 sibling, 0 replies; 19+ messages in thread
From: Richard Cochran @ 2023-04-08 13:56 UTC (permalink / raw)
  To: Max Georgiev
  Cc: Jakub Kicinski, Vladimir Oltean, kory.maincent, netdev,
	maxime.chevallier, vadim.fedorenko, gerhard

On Thu, Apr 06, 2023 at 12:21:37AM -0600, Max Georgiev wrote:

> It looks like there is a possibility that the returned hwtstamp_config structure
> will be copied twice to ifr and copied once from ifr on the return path
> in case if the underlying driver does not implement ndo_hwtstamp_get():
> - the underlying driver calls copy_to_user() inside its ndo_eth_ioctl()
>   implementation to return the data to generic_hwtstamp_get_lower();
> - then generic_hwtstamp_get_lower() calls copy_from_user() to copy it
>   back out of the ifr to kernel_hwtstamp_config structure;
> - then dev_get_hwtstamp() calls copy_to_user() again to update
>   the same ifr with the same data the ifr already contains.
> 
> Should we consider this acceptable?

This is a slow path so copying a small structure is not a concern.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2023-04-08 14:00 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-05  6:33 [RFC PATCH v3 3/5] Add ndo_hwtstamp_get/set support to vlan code path Maxim Georgiev
2023-04-05 12:26 ` Vladimir Oltean
2023-04-05 16:19   ` Max Georgiev
2023-04-05 16:28     ` Vladimir Oltean
2023-04-05 15:50 ` kernel test robot
2023-04-05 16:42 ` Jakub Kicinski
2023-04-05 17:03   ` Vladimir Oltean
2023-04-05 17:13     ` Jakub Kicinski
2023-04-05 17:28       ` Vladimir Oltean
2023-04-05 17:34         ` Vladimir Oltean
2023-04-05 17:42         ` Jakub Kicinski
2023-04-05 18:01           ` Vladimir Oltean
2023-04-06  0:00             ` Jakub Kicinski
2023-04-06  6:21               ` Max Georgiev
2023-04-06 15:01                 ` Vladimir Oltean
2023-04-06 16:18                   ` Max Georgiev
2023-04-06 16:50                     ` Vladimir Oltean
2023-04-08 13:56                 ` Richard Cochran
2023-04-05 18:33 ` kernel test robot

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.