diff mbox series

[PATCHv2,net-next,1/3] bonding: add common function to check ipsec device

Message ID 20240819075334.236334-2-liuhangbin@gmail.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series Bonding: support new xfrm state offload functions | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 16 this patch: 18
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 2 maintainers not CCed: jv@jvosburgh.net andy@greyhouse.net
netdev/build_clang fail Errors and warnings before: 18 this patch: 19
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 240 this patch: 18
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 59 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc fail Errors and warnings before: 13 this patch: 14
netdev/source_inline success Was 0 now: 0

Commit Message

Hangbin Liu Aug. 19, 2024, 7:53 a.m. UTC
This patch adds a common function to check the status of IPSec devices.
This function will be useful for future implementations, such as IPSec ESN
and state offload callbacks.

Suggested-by: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 drivers/net/bonding/bond_main.c | 43 +++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 13 deletions(-)

Comments

Nikolay Aleksandrov Aug. 19, 2024, 8:02 a.m. UTC | #1
On 19/08/2024 10:53, Hangbin Liu wrote:
> This patch adds a common function to check the status of IPSec devices.
> This function will be useful for future implementations, such as IPSec ESN
> and state offload callbacks.
> 
> Suggested-by: Nikolay Aleksandrov <razor@blackwall.org>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
> ---
>  drivers/net/bonding/bond_main.c | 43 +++++++++++++++++++++++----------
>  1 file changed, 30 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index f9633a6f8571..250a2717b4e9 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -418,6 +418,34 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
>  /*---------------------------------- XFRM -----------------------------------*/
>  
>  #ifdef CONFIG_XFRM_OFFLOAD
> +/**
> + * bond_ipsec_dev - return the device for ipsec offload, or NULL if not exist
> + *                  caller must hold rcu_read_lock.
> + * @xs: pointer to transformer state struct
> + **/
> +static struct net_device bond_ipsec_dev(struct xfrm_state *xs)
> +{
> +	struct net_device *bond_dev = xs->xso.dev;
> +	struct net_device *real_dev;
> +	struct bonding *bond;
> +	struct slave *slave;
> +
> +	if (!bond_dev)
> +		return NULL;
> +
> +	bond = netdev_priv(bond_dev);
> +	slave = rcu_dereference(bond->curr_active_slave);
> +	real_dev = slave ? slave->dev : NULL;
> +
> +	if ((BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) ||
> +	    !slave || !real_dev || !xs->xso.real_dev)
> +		return NULL;

No need to check !slave again here.  !real_dev implies !slave and
vice-versa, if it is set then we must have had a slave.
I prefer the more obvious way - check slave after deref and
bail out, similar to my fix, I think it is easier to follow the
code and more obvious. Although I don't feel strong about that
it's just a preference. :)

> +
> +	WARN_ON(xs->xso.real_dev != slave->dev);
> +
> +	return real_dev;
> +}
> +
>  /**
>   * bond_ipsec_add_sa - program device with a security association
>   * @xs: pointer to transformer state struct
> @@ -595,23 +623,12 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
>   **/
>  static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
>  {
> -	struct net_device *bond_dev = xs->xso.dev;
>  	struct net_device *real_dev;
> -	struct slave *curr_active;
> -	struct bonding *bond;
>  	int err;
>  
> -	bond = netdev_priv(bond_dev);
>  	rcu_read_lock();
> -	curr_active = rcu_dereference(bond->curr_active_slave);
> -	real_dev = curr_active->dev;
> -
> -	if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
> -		err = false;
> -		goto out;
> -	}
> -
> -	if (!xs->xso.real_dev) {
> +	real_dev = bond_ipsec_dev(xs);
> +	if (!real_dev) {
>  		err = false;
>  		goto out;
>  	}
Hangbin Liu Aug. 19, 2024, 8:43 a.m. UTC | #2
On Mon, Aug 19, 2024 at 11:02:14AM +0300, Nikolay Aleksandrov wrote:
> > +static struct net_device bond_ipsec_dev(struct xfrm_state *xs)
> > +{
> > +	struct net_device *bond_dev = xs->xso.dev;
> > +	struct net_device *real_dev;
> > +	struct bonding *bond;
> > +	struct slave *slave;
> > +
> > +	if (!bond_dev)
> > +		return NULL;
> > +
> > +	bond = netdev_priv(bond_dev);
> > +	slave = rcu_dereference(bond->curr_active_slave);
> > +	real_dev = slave ? slave->dev : NULL;
> > +
> > +	if ((BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) ||
> > +	    !slave || !real_dev || !xs->xso.real_dev)
> > +		return NULL;
> 
> No need to check !slave again here.  !real_dev implies !slave and
> vice-versa, if it is set then we must have had a slave.

Ah yes, I missed this.

> I prefer the more obvious way - check slave after deref and
> bail out, similar to my fix, I think it is easier to follow the
> code and more obvious. Although I don't feel strong about that
> it's just a preference. :)

I don't have a inclination, I just want to check all the error and fail out.
If we check each one separately, do you think if I should do like

	if (!bond_dev)
		return NULL;

	bond = netdev_priv(bond_dev);
	if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)
		return NULL;

	slave = rcu_dereference(bond->curr_active_slave);
	if (!slave)
		return NULL;

> > +	WARN_ON(xs->xso.real_dev != slave->dev);

Here as you said, the WARN_ON would be triggered easily, do you think if I
should change to pr_warn or salve_warn?

Thanks
Hangbin
Nikolay Aleksandrov Aug. 19, 2024, 8:48 a.m. UTC | #3
On 19/08/2024 11:43, Hangbin Liu wrote:
> On Mon, Aug 19, 2024 at 11:02:14AM +0300, Nikolay Aleksandrov wrote:
>>> +static struct net_device bond_ipsec_dev(struct xfrm_state *xs)
>>> +{
>>> +	struct net_device *bond_dev = xs->xso.dev;
>>> +	struct net_device *real_dev;
>>> +	struct bonding *bond;
>>> +	struct slave *slave;
>>> +
>>> +	if (!bond_dev)
>>> +		return NULL;
>>> +
>>> +	bond = netdev_priv(bond_dev);
>>> +	slave = rcu_dereference(bond->curr_active_slave);
>>> +	real_dev = slave ? slave->dev : NULL;
>>> +
>>> +	if ((BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) ||
>>> +	    !slave || !real_dev || !xs->xso.real_dev)
>>> +		return NULL;
>>
>> No need to check !slave again here.  !real_dev implies !slave and
>> vice-versa, if it is set then we must have had a slave.
> 
> Ah yes, I missed this.
> 

This is exactly my point about it being easier to follow if it's not all
combined in this way.

>> I prefer the more obvious way - check slave after deref and
>> bail out, similar to my fix, I think it is easier to follow the
>> code and more obvious. Although I don't feel strong about that
>> it's just a preference. :)
> 
> I don't have a inclination, I just want to check all the error and fail out.
> If we check each one separately, do you think if I should do like
> 
> 	if (!bond_dev)
> 		return NULL;
> 
> 	bond = netdev_priv(bond_dev);
> 	if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)
> 		return NULL;
> 
> 	slave = rcu_dereference(bond->curr_active_slave);
> 	if (!slave)
> 		return NULL;
> 

I like this, even though it's more verbose, it's also easier to follow.
The alternative I have to track all code above and then verify the
combined check below. Depending on how complex it is, might be ok.
As I said it's a preference, if you prefer the other way - I don't mind.

>>> +	WARN_ON(xs->xso.real_dev != slave->dev);
> 
> Here as you said, the WARN_ON would be triggered easily, do you think if I
> should change to pr_warn or salve_warn?
> 

I haven't verified it, but yeah. Given how these are synced, it should be something
that's limited (we're talking about packets here, we shouldn't flood the logs) and
not a WARN_ON(). We can see any mid-state while changing.

> Thanks
> Hangbin

Cheers,
 Nik
Simon Horman Aug. 19, 2024, 2:37 p.m. UTC | #4
On Mon, Aug 19, 2024 at 03:53:31PM +0800, Hangbin Liu wrote:
> This patch adds a common function to check the status of IPSec devices.
> This function will be useful for future implementations, such as IPSec ESN
> and state offload callbacks.
> 
> Suggested-by: Nikolay Aleksandrov <razor@blackwall.org>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
> ---
>  drivers/net/bonding/bond_main.c | 43 +++++++++++++++++++++++----------
>  1 file changed, 30 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index f9633a6f8571..250a2717b4e9 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -418,6 +418,34 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
>  /*---------------------------------- XFRM -----------------------------------*/
>  
>  #ifdef CONFIG_XFRM_OFFLOAD
> +/**
> + * bond_ipsec_dev - return the device for ipsec offload, or NULL if not exist
> + *                  caller must hold rcu_read_lock.
> + * @xs: pointer to transformer state struct
> + **/
> +static struct net_device bond_ipsec_dev(struct xfrm_state *xs)

Hi Hangbin,

Based on the implementation of the function, it looks like it should return
'struct net_device *' rather than 'struct net_device' (a '*' is missing).

> +{
> +	struct net_device *bond_dev = xs->xso.dev;
> +	struct net_device *real_dev;
> +	struct bonding *bond;
> +	struct slave *slave;
> +
> +	if (!bond_dev)
> +		return NULL;
> +
> +	bond = netdev_priv(bond_dev);
> +	slave = rcu_dereference(bond->curr_active_slave);
> +	real_dev = slave ? slave->dev : NULL;
> +
> +	if ((BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) ||
> +	    !slave || !real_dev || !xs->xso.real_dev)
> +		return NULL;
> +
> +	WARN_ON(xs->xso.real_dev != slave->dev);
> +
> +	return real_dev;
> +}
> +
>  /**
>   * bond_ipsec_add_sa - program device with a security association
>   * @xs: pointer to transformer state struct
kernel test robot Aug. 19, 2024, 7:24 p.m. UTC | #5
Hi Hangbin,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Hangbin-Liu/bonding-add-common-function-to-check-ipsec-device/20240819-195504
base:   net-next/main
patch link:    https://lore.kernel.org/r/20240819075334.236334-2-liuhangbin%40gmail.com
patch subject: [PATCHv2 net-next 1/3] bonding: add common function to check ipsec device
config: x86_64-buildonly-randconfig-001-20240820 (https://download.01.org/0day-ci/archive/20240820/202408200327.ab8Ea0y8-lkp@intel.com/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240820/202408200327.ab8Ea0y8-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202408200327.ab8Ea0y8-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/net/bonding/bond_main.c:434:10: error: returning 'void *' from a function with incompatible result type 'struct net_device'
     434 |                 return NULL;
         |                        ^~~~
   include/linux/stddef.h:8:14: note: expanded from macro 'NULL'
       8 | #define NULL ((void *)0)
         |              ^~~~~~~~~~~
   drivers/net/bonding/bond_main.c:442:10: error: returning 'void *' from a function with incompatible result type 'struct net_device'
     442 |                 return NULL;
         |                        ^~~~
   include/linux/stddef.h:8:14: note: expanded from macro 'NULL'
       8 | #define NULL ((void *)0)
         |              ^~~~~~~~~~~
>> drivers/net/bonding/bond_main.c:446:9: error: returning 'struct net_device *' from a function with incompatible result type 'struct net_device'; dereference with *
     446 |         return real_dev;
         |                ^~~~~~~~
         |                *
>> drivers/net/bonding/bond_main.c:630:11: error: assigning to 'struct net_device *' from incompatible type 'struct net_device'
     630 |         real_dev = bond_ipsec_dev(xs);
         |                  ^ ~~~~~~~~~~~~~~~~~~
   4 errors generated.


vim +434 drivers/net/bonding/bond_main.c

   419	
   420	#ifdef CONFIG_XFRM_OFFLOAD
   421	/**
   422	 * bond_ipsec_dev - return the device for ipsec offload, or NULL if not exist
   423	 *                  caller must hold rcu_read_lock.
   424	 * @xs: pointer to transformer state struct
   425	 **/
   426	static struct net_device bond_ipsec_dev(struct xfrm_state *xs)
   427	{
   428		struct net_device *bond_dev = xs->xso.dev;
   429		struct net_device *real_dev;
   430		struct bonding *bond;
   431		struct slave *slave;
   432	
   433		if (!bond_dev)
 > 434			return NULL;
   435	
   436		bond = netdev_priv(bond_dev);
   437		slave = rcu_dereference(bond->curr_active_slave);
   438		real_dev = slave ? slave->dev : NULL;
   439	
   440		if ((BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) ||
   441		    !slave || !real_dev || !xs->xso.real_dev)
   442			return NULL;
   443	
   444		WARN_ON(xs->xso.real_dev != slave->dev);
   445	
 > 446		return real_dev;
   447	}
   448	
   449	/**
   450	 * bond_ipsec_add_sa - program device with a security association
   451	 * @xs: pointer to transformer state struct
   452	 * @extack: extack point to fill failure reason
   453	 **/
   454	static int bond_ipsec_add_sa(struct xfrm_state *xs,
   455				     struct netlink_ext_ack *extack)
   456	{
   457		struct net_device *bond_dev = xs->xso.dev;
   458		struct bond_ipsec *ipsec;
   459		struct bonding *bond;
   460		struct slave *slave;
   461		int err;
   462	
   463		if (!bond_dev)
   464			return -EINVAL;
   465	
   466		rcu_read_lock();
   467		bond = netdev_priv(bond_dev);
   468		slave = rcu_dereference(bond->curr_active_slave);
   469		if (!slave) {
   470			rcu_read_unlock();
   471			return -ENODEV;
   472		}
   473	
   474		if (!slave->dev->xfrmdev_ops ||
   475		    !slave->dev->xfrmdev_ops->xdo_dev_state_add ||
   476		    netif_is_bond_master(slave->dev)) {
   477			NL_SET_ERR_MSG_MOD(extack, "Slave does not support ipsec offload");
   478			rcu_read_unlock();
   479			return -EINVAL;
   480		}
   481	
   482		ipsec = kmalloc(sizeof(*ipsec), GFP_ATOMIC);
   483		if (!ipsec) {
   484			rcu_read_unlock();
   485			return -ENOMEM;
   486		}
   487		xs->xso.real_dev = slave->dev;
   488	
   489		err = slave->dev->xfrmdev_ops->xdo_dev_state_add(xs, extack);
   490		if (!err) {
   491			ipsec->xs = xs;
   492			INIT_LIST_HEAD(&ipsec->list);
   493			spin_lock_bh(&bond->ipsec_lock);
   494			list_add(&ipsec->list, &bond->ipsec_list);
   495			spin_unlock_bh(&bond->ipsec_lock);
   496		} else {
   497			kfree(ipsec);
   498		}
   499		rcu_read_unlock();
   500		return err;
   501	}
   502	
   503	static void bond_ipsec_add_sa_all(struct bonding *bond)
   504	{
   505		struct net_device *bond_dev = bond->dev;
   506		struct bond_ipsec *ipsec;
   507		struct slave *slave;
   508	
   509		rcu_read_lock();
   510		slave = rcu_dereference(bond->curr_active_slave);
   511		if (!slave)
   512			goto out;
   513	
   514		if (!slave->dev->xfrmdev_ops ||
   515		    !slave->dev->xfrmdev_ops->xdo_dev_state_add ||
   516		    netif_is_bond_master(slave->dev)) {
   517			spin_lock_bh(&bond->ipsec_lock);
   518			if (!list_empty(&bond->ipsec_list))
   519				slave_warn(bond_dev, slave->dev,
   520					   "%s: no slave xdo_dev_state_add\n",
   521					   __func__);
   522			spin_unlock_bh(&bond->ipsec_lock);
   523			goto out;
   524		}
   525	
   526		spin_lock_bh(&bond->ipsec_lock);
   527		list_for_each_entry(ipsec, &bond->ipsec_list, list) {
   528			ipsec->xs->xso.real_dev = slave->dev;
   529			if (slave->dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
   530				slave_warn(bond_dev, slave->dev, "%s: failed to add SA\n", __func__);
   531				ipsec->xs->xso.real_dev = NULL;
   532			}
   533		}
   534		spin_unlock_bh(&bond->ipsec_lock);
   535	out:
   536		rcu_read_unlock();
   537	}
   538	
   539	/**
   540	 * bond_ipsec_del_sa - clear out this specific SA
   541	 * @xs: pointer to transformer state struct
   542	 **/
   543	static void bond_ipsec_del_sa(struct xfrm_state *xs)
   544	{
   545		struct net_device *bond_dev = xs->xso.dev;
   546		struct bond_ipsec *ipsec;
   547		struct bonding *bond;
   548		struct slave *slave;
   549	
   550		if (!bond_dev)
   551			return;
   552	
   553		rcu_read_lock();
   554		bond = netdev_priv(bond_dev);
   555		slave = rcu_dereference(bond->curr_active_slave);
   556	
   557		if (!slave)
   558			goto out;
   559	
   560		if (!xs->xso.real_dev)
   561			goto out;
   562	
   563		WARN_ON(xs->xso.real_dev != slave->dev);
   564	
   565		if (!slave->dev->xfrmdev_ops ||
   566		    !slave->dev->xfrmdev_ops->xdo_dev_state_delete ||
   567		    netif_is_bond_master(slave->dev)) {
   568			slave_warn(bond_dev, slave->dev, "%s: no slave xdo_dev_state_delete\n", __func__);
   569			goto out;
   570		}
   571	
   572		slave->dev->xfrmdev_ops->xdo_dev_state_delete(xs);
   573	out:
   574		spin_lock_bh(&bond->ipsec_lock);
   575		list_for_each_entry(ipsec, &bond->ipsec_list, list) {
   576			if (ipsec->xs == xs) {
   577				list_del(&ipsec->list);
   578				kfree(ipsec);
   579				break;
   580			}
   581		}
   582		spin_unlock_bh(&bond->ipsec_lock);
   583		rcu_read_unlock();
   584	}
   585	
   586	static void bond_ipsec_del_sa_all(struct bonding *bond)
   587	{
   588		struct net_device *bond_dev = bond->dev;
   589		struct bond_ipsec *ipsec;
   590		struct slave *slave;
   591	
   592		rcu_read_lock();
   593		slave = rcu_dereference(bond->curr_active_slave);
   594		if (!slave) {
   595			rcu_read_unlock();
   596			return;
   597		}
   598	
   599		spin_lock_bh(&bond->ipsec_lock);
   600		list_for_each_entry(ipsec, &bond->ipsec_list, list) {
   601			if (!ipsec->xs->xso.real_dev)
   602				continue;
   603	
   604			if (!slave->dev->xfrmdev_ops ||
   605			    !slave->dev->xfrmdev_ops->xdo_dev_state_delete ||
   606			    netif_is_bond_master(slave->dev)) {
   607				slave_warn(bond_dev, slave->dev,
   608					   "%s: no slave xdo_dev_state_delete\n",
   609					   __func__);
   610			} else {
   611				slave->dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
   612			}
   613			ipsec->xs->xso.real_dev = NULL;
   614		}
   615		spin_unlock_bh(&bond->ipsec_lock);
   616		rcu_read_unlock();
   617	}
   618	
   619	/**
   620	 * bond_ipsec_offload_ok - can this packet use the xfrm hw offload
   621	 * @skb: current data packet
   622	 * @xs: pointer to transformer state struct
   623	 **/
   624	static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
   625	{
   626		struct net_device *real_dev;
   627		int err;
   628	
   629		rcu_read_lock();
 > 630		real_dev = bond_ipsec_dev(xs);
   631		if (!real_dev) {
   632			err = false;
   633			goto out;
   634		}
   635	
   636		if (!real_dev->xfrmdev_ops ||
   637		    !real_dev->xfrmdev_ops->xdo_dev_offload_ok ||
   638		    netif_is_bond_master(real_dev)) {
   639			err = false;
   640			goto out;
   641		}
   642	
   643		err = real_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs);
   644	out:
   645		rcu_read_unlock();
   646		return err;
   647	}
   648
kernel test robot Aug. 19, 2024, 8:16 p.m. UTC | #6
Hi Hangbin,

kernel test robot noticed the following build errors:

[auto build test ERROR on net-next/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Hangbin-Liu/bonding-add-common-function-to-check-ipsec-device/20240819-195504
base:   net-next/main
patch link:    https://lore.kernel.org/r/20240819075334.236334-2-liuhangbin%40gmail.com
patch subject: [PATCHv2 net-next 1/3] bonding: add common function to check ipsec device
config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20240820/202408200345.a4DQ8ecT-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 14.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240820/202408200345.a4DQ8ecT-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202408200345.a4DQ8ecT-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from include/uapi/linux/posix_types.h:5,
                    from include/uapi/linux/types.h:14,
                    from include/linux/types.h:6,
                    from include/linux/kasan-checks.h:5,
                    from include/asm-generic/rwonce.h:26,
                    from ./arch/m68k/include/generated/asm/rwonce.h:1,
                    from include/linux/compiler.h:314,
                    from include/linux/array_size.h:5,
                    from include/linux/kernel.h:16,
                    from drivers/net/bonding/bond_main.c:35:
   drivers/net/bonding/bond_main.c: In function 'bond_ipsec_dev':
>> include/linux/stddef.h:8:14: error: incompatible types when returning type 'void *' but 'struct net_device' was expected
       8 | #define NULL ((void *)0)
         |              ^
   drivers/net/bonding/bond_main.c:434:24: note: in expansion of macro 'NULL'
     434 |                 return NULL;
         |                        ^~~~
>> include/linux/stddef.h:8:14: error: incompatible types when returning type 'void *' but 'struct net_device' was expected
       8 | #define NULL ((void *)0)
         |              ^
   drivers/net/bonding/bond_main.c:442:24: note: in expansion of macro 'NULL'
     442 |                 return NULL;
         |                        ^~~~
>> drivers/net/bonding/bond_main.c:446:16: error: incompatible types when returning type 'struct net_device *' but 'struct net_device' was expected
     446 |         return real_dev;
         |                ^~~~~~~~
   drivers/net/bonding/bond_main.c: In function 'bond_ipsec_offload_ok':
>> drivers/net/bonding/bond_main.c:630:20: error: incompatible types when assigning to type 'struct net_device *' from type 'struct net_device'
     630 |         real_dev = bond_ipsec_dev(xs);
         |                    ^~~~~~~~~~~~~~


vim +8 include/linux/stddef.h

^1da177e4c3f41 Linus Torvalds   2005-04-16  6  
^1da177e4c3f41 Linus Torvalds   2005-04-16  7  #undef NULL
^1da177e4c3f41 Linus Torvalds   2005-04-16 @8  #define NULL ((void *)0)
6e218287432472 Richard Knutsson 2006-09-30  9
Hangbin Liu Aug. 19, 2024, 11:07 p.m. UTC | #7
On Mon, Aug 19, 2024 at 03:37:53PM +0100, Simon Horman wrote:
> > +static struct net_device bond_ipsec_dev(struct xfrm_state *xs)
> 
> Hi Hangbin,
> 
> Based on the implementation of the function, it looks like it should return
> 'struct net_device *' rather than 'struct net_device' (a '*' is missing).

Sigh, I noticed this but forgot the update the patch.. The build also passed
due to missing CONFIG_XFRM_OFFLOAD=y, even I added CONFIG_XFRM_OFFLOAD=y to
config file. I need to check the reason.

Hangbin
diff mbox series

Patch

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f9633a6f8571..250a2717b4e9 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -418,6 +418,34 @@  static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
 /*---------------------------------- XFRM -----------------------------------*/
 
 #ifdef CONFIG_XFRM_OFFLOAD
+/**
+ * bond_ipsec_dev - return the device for ipsec offload, or NULL if not exist
+ *                  caller must hold rcu_read_lock.
+ * @xs: pointer to transformer state struct
+ **/
+static struct net_device bond_ipsec_dev(struct xfrm_state *xs)
+{
+	struct net_device *bond_dev = xs->xso.dev;
+	struct net_device *real_dev;
+	struct bonding *bond;
+	struct slave *slave;
+
+	if (!bond_dev)
+		return NULL;
+
+	bond = netdev_priv(bond_dev);
+	slave = rcu_dereference(bond->curr_active_slave);
+	real_dev = slave ? slave->dev : NULL;
+
+	if ((BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) ||
+	    !slave || !real_dev || !xs->xso.real_dev)
+		return NULL;
+
+	WARN_ON(xs->xso.real_dev != slave->dev);
+
+	return real_dev;
+}
+
 /**
  * bond_ipsec_add_sa - program device with a security association
  * @xs: pointer to transformer state struct
@@ -595,23 +623,12 @@  static void bond_ipsec_del_sa_all(struct bonding *bond)
  **/
 static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
 {
-	struct net_device *bond_dev = xs->xso.dev;
 	struct net_device *real_dev;
-	struct slave *curr_active;
-	struct bonding *bond;
 	int err;
 
-	bond = netdev_priv(bond_dev);
 	rcu_read_lock();
-	curr_active = rcu_dereference(bond->curr_active_slave);
-	real_dev = curr_active->dev;
-
-	if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
-		err = false;
-		goto out;
-	}
-
-	if (!xs->xso.real_dev) {
+	real_dev = bond_ipsec_dev(xs);
+	if (!real_dev) {
 		err = false;
 		goto out;
 	}