Subject: Re: [net-next, v3 1/2] psp: Support for transmit on logical device when the underlying transport device supports PSP.

From: Jakub Kicinski <[email-masked]>
Date: Sat, 28 Feb 2026 10:04:49 -0800

On Thu, 26 Feb 2026 10:46:53 -0800 Kiran Kella wrote:
> This is achieved by propagating the psp_dev from the lower device
> to the upper devices in the device stack via a netdevice notifier.
> The lowest device owns the psp_dev pointer while the upper devices
> just borrow the pointer. When the lower device is unlinked, the
> borrowed pointer is cleared in the upper device.
> Assumption being that psp_dev is set on the lowest device before
> any upper devices are stacked on that lowest device.

As I mentioned in the other thread I'd like to establish some clear
expectation on where psd propagates automatically and where it doesn't.
I don't want to see a stream of patches that say "fix propagating PSP
onto X upper". And conversely report saying "PSP got propagated but
it doesn't actually work" (macvlan in bridge mode etc).

Hence my preference was to require the user who created the device
to propagate PSP. Willem, WDYT?

> +/**
> + * psp_clear_upper_dev_psp_dev() - Clear borrowed psp_dev pointer on upper
> + *				   device
> + * @upper_dev:	Upper device that may have borrowed psp_dev pointer
> + * @priv:	netdev_nested_priv containing the psp_dev being unregistered
> + *
> + * Callback for netdev_walk_all_upper_dev_rcu() to clear borrowed psp_dev
> + * pointers on upper devices when the underlying psp_dev is being unregistered.
> + *
> + * Return: 0 to continue walking, non-zero to stop.

Please (tell your LLM) to avoid adding kdoc which restates what the
code does. For static function really kdoc is only useful if there's
something not-obvious to say.

> +static int psp_clear_upper_dev_psp_dev(struct net_device *upper_dev,
> +				       struct netdev_nested_priv *priv)

Please (tell your LLM) that the action goes after the object / noun.
psp_upper_psp_dev_clear() or some such.

> +{
> +	struct psp_dev *psd = priv->data;
> +	struct psp_dev *upper_psd;
> +
> +	upper_psd = rcu_dereference(upper_dev->psp_dev);
> +	if (upper_psd == psd)
> +		rcu_assign_pointer(upper_dev->psp_dev, NULL);
> +
> +	return 0;
> +}
> +
>  /**
>   * psp_dev_unregister() - unregister PSP device
>   * @psd:	PSP device structure
> + *
> + * Unregisters a PSP device and clears all borrowed psp_dev pointers on
> + * upper devices (e.g., VLAN subinterfaces) that reference this device.
> + * This prevents use-after-free if upper devices still have borrowed
> + * pointers when the psp_dev structure is freed.
>   */
>  void psp_dev_unregister(struct psp_dev *psd)
>  {
>  	struct psp_assoc *pas, *next;
> +	struct netdev_nested_priv priv = {
> +		.data = psd,
> +	};

reverse xmas tree
-- 
pw-bot: cr