public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: "Łukasz Majewski" <lukma@nabladev.com>
To: "Luka Gejak" <luka.gejak@linux.dev>
Cc: "Fernando Fernandez Mancera" <fmancera@suse.de>,
	"Fernando Fernandez Mancera" <ffmancera@riseup.net>,
	<netdev@vger.kernel.org>, <edumazet@google.com>,
	<pabeni@redhat.com>, <shannon.nelson@amd.com>, <horms@kernel.org>,
	<kuba@kernel.org>
Subject: Re: [PATCH v3 net-next] net: hsr: sync hw addr of slave2 according to slave1 hw addr on PRP
Date: Mon, 30 Mar 2026 10:28:12 +0200	[thread overview]
Message-ID: <20260330102812.214f27f4@wsk> (raw)
In-Reply-To: <DHFG26KI6L23.1YCOVQ5SSYMO5@linux.dev>

Hi Luka,

> On Sun Mar 29, 2026 at 7:22 PM CEST, Fernando Fernandez Mancera wrote:
> > On 3/29/26 6:58 PM, Fernando Fernandez Mancera wrote:  
> >> On 3/29/26 5:07 PM, Luka Gejak wrote:  
> >>> On Wed Apr 9, 2025 at 12:19 PM CEST, Fernando Fernandez Mancera
> >>> wrote:  
> >>>> In order to work properly PRP requires slave1 and slave2 to
> >>>> share the same MAC address. To ease the configuration process on
> >>>> userspace tools, sync the slave2 MAC address with slave1. In
> >>>> addition, when deleting the port from the list, restore the
> >>>> original MAC address.
> >>>>
> >>>> Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
> >>>> ---
> >>>> v3: restore the original MAC address on slave removal.
> >>>> ---
> >>>>   net/hsr/hsr_device.c | 5 +++++
> >>>>   net/hsr/hsr_main.c   | 9 +++++++++
> >>>>   net/hsr/hsr_main.h   | 1 +
> >>>>   net/hsr/hsr_slave.c  | 2 ++
> >>>>   4 files changed, 17 insertions(+)
> >>>>
> >>>> diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
> >>>> index 439cfb7ad5d1..e8922e8d9398 100644
> >>>> --- a/net/hsr/hsr_device.c
> >>>> +++ b/net/hsr/hsr_device.c
> >>>> @@ -761,6 +761,11 @@ int hsr_dev_finalize(struct net_device
> >>>> *hsr_dev, struct net_device *slave[2],
> >>>>       if (res)
> >>>>           goto err_unregister;
> >>>> +    if (protocol_version == PRP_V1) {
> >>>> +        eth_hw_addr_set(slave[1], slave[0]->dev_addr);
> >>>> +        call_netdevice_notifiers(NETDEV_CHANGEADDR, slave[1]);
> >>>> +    }
> >>>> +
> >>>>       if (interlink) {
> >>>>           res = hsr_add_port(hsr, interlink, HSR_PT_INTERLINK,
> >>>> extack); if (res)
> >>>> diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c
> >>>> index d7ae32473c41..192893c3f2ec 100644
> >>>> --- a/net/hsr/hsr_main.c
> >>>> +++ b/net/hsr/hsr_main.c
> >>>> @@ -78,6 +78,15 @@ static int hsr_netdev_notify(struct
> >>>> notifier_block *nb, unsigned long event,
> >>>>               eth_hw_addr_set(master->dev, dev->dev_addr);
> >>>>               call_netdevice_notifiers(NETDEV_CHANGEADDR,
> >>>>                            master->dev);
> >>>> +
> >>>> +            if (hsr->prot_version == PRP_V1) {
> >>>> +                port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
> >>>> +                if (port) {
> >>>> +                    eth_hw_addr_set(port->dev, dev->dev_addr);
> >>>> +                    call_netdevice_notifiers(NETDEV_CHANGEADDR,
> >>>> +                                 port->dev);
> >>>> +                }
> >>>> +            }
> >>>>           }
> >>>>           /* Make sure we recognize frames from ourselves in 
> >>>> hsr_rcv() */
> >>>> diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h
> >>>> index 1bc47b17a296..135ec5fce019 100644
> >>>> --- a/net/hsr/hsr_main.h
> >>>> +++ b/net/hsr/hsr_main.h
> >>>> @@ -155,6 +155,7 @@ struct hsr_port {
> >>>>       struct hsr_priv        *hsr;
> >>>>       enum hsr_port_type    type;
> >>>>       struct rcu_head        rcu;
> >>>> +    unsigned char        original_macaddress[ETH_ALEN];
> >>>>   };
> >>>>   struct hsr_frame_info;
> >>>> diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
> >>>> index 2a802a5de2ac..b87b6a6fe070 100644
> >>>> --- a/net/hsr/hsr_slave.c
> >>>> +++ b/net/hsr/hsr_slave.c
> >>>> @@ -196,6 +196,7 @@ int hsr_add_port(struct hsr_priv *hsr,
> >>>> struct net_device *dev,
> >>>>       port->hsr = hsr;
> >>>>       port->dev = dev;
> >>>>       port->type = type;
> >>>> +    ether_addr_copy(port->original_macaddress, dev->dev_addr);
> >>>>       if (type != HSR_PT_MASTER) {
> >>>>           res = hsr_portdev_setup(hsr, dev, port, extack);
> >>>> @@ -232,6 +233,7 @@ void hsr_del_port(struct hsr_port *port)
> >>>>           if (!port->hsr->fwd_offloaded)
> >>>>               dev_set_promiscuity(port->dev, -1);
> >>>>           netdev_upper_dev_unlink(port->dev, master->dev);
> >>>> +        eth_hw_addr_set(port->dev, port->original_macaddress);
> >>>>       }
> >>>>       kfree_rcu(port, rcu);  
> >>>
> >>> Hi Fernando,
> >>>
> >>> Thanks for the patch. The logic to sync the slave2 MAC address
> >>> with slave1 for PRP is sound, but there are a few implementation
> >>> issues here that will cause hardware filtering problems and style
> >>> violations.
> >>>
> >>> 1. Hardware MAC Filtering
> >>> In your current implementation:
> >>>
> >>>    if (protocol_version == PRP_V1) {
> >>>
> >>>        eth_hw_addr_set(slave[1], slave[0]->dev_addr);
> >>>
> >>>        call_netdevice_notifiers(NETDEV_CHANGEADDR, slave[1]);
> >>>
> >>>    }
> >>>
> >>> eth_hw_addr_set() is appropriate for virtual devices (like the
> >>> hsr_dev itself), but slave[1] is a physical net_device. By using
> >>> this helper, you are bypassing
> >>> dev->netdev_ops->ndo_set_mac_address. This means the physical
> >>> NIC's hardware MAC filter will not be programmed, and it will
> >>> silently drop unicast traffic destined for the new PRP MAC
> >>> address unless the interface happens to be in promiscuous mode.
> >>> You should use dev_set_mac_address() here instead. Note that
> >>> unlike eth_hw_addr_set(), dev_set_mac_address() can fail and
> >>> returns an error code, so you will need to check its return value
> >>> and handle the error path accordingly.
> >>>
> >>> 2. Teardown Notifiers
> >>> In hsr_del_port():
> >>>
> >>>    netdev_upper_dev_unlink(port->dev, master->dev);
> >>>    eth_hw_addr_set(port->dev, port->original_macaddress);
> >>>
> >>> You have the same issue with eth_hw_addr_set() here. Additionally,
> >>> unlike the setup paths, this version omits
> >>> call_netdevice_notifiers (NETDEV_CHANGEADDR, port->dev).
> >>> Switching to dev_set_mac_address() for the restoration will
> >>> handle both the hardware programming and the notifier chain
> >>> automatically. 
> >> 
> >> These points makes sense. I guess I didn't notice the that 
> >> eth_hw_addr_set() due to my interface being set to promiscuous
> >> mode at hsr_slave.c.
> >> 
> >> Let me research a bit more about the impact here and will get back
> >> to you either with a new patch or an reply here.
> >>   
> >
> > Does this actually makes sense? I am not an expert on how hardware
> > is handling offloading here. But if I am not wrong, as the
> > interface is set on promiscuous or offload enabled. For promiscuous
> > this does not matter and for the offloaded scenario shouldn't the
> > decision be handled by hardware and not depend on
> > ndo_set_mac_address()?
> >
> > Let me know if I am missing something here.
> >
> >
> > Anyway, the missing notification makes sense and should be fixed
> > for SLAVE_B.
> >
> > Thanks,
> > Fernando.  
> 
> Hi Fernando,
> You raise a fair point, and I should have looked more carefully at
> the existing code paths.
> 
> You are correct that in the non-offloaded case, hsr_slave.c already 
> sets promiscuous mode via dev_set_promiscuity(dev, 1), so the
> hardware MAC filter is bypassed and eth_hw_addr_set() is sufficient
> for frame reception.
> 
> For the offloaded case, the comment in hsr_portdev_setup() notes that 
> "L2 frame forward happens at the offloaded hardware" — so the
> hardware is configured through its own HSR/PRP offload mechanisms,
> not through ndo_set_mac_address().
> 
> So the practical impact of my original concern is limited to edge
> cases where promiscuous mode might be disabled or fail. The more
> important issue, which you've already acknowledged, is the missing
> notifier in hsr_del_port(). That should definitely be fixed for
> correctness.
> 
> One additional consideration: even though promiscuous mode handles
> the receive path, dev->dev_addr is still used as the source MAC for 
> outgoing frames. Using dev_set_mac_address() would ensure the
> software state (dev->dev_addr) and any driver-level state remain
> consistent. But I agree this is less critical than I initially
> suggested. Thanks for pushing back on this — it's a good
> clarification.
> 

Thanks for your patches - as denx.de is not operational anymore (now I
do work for nabladev.com) I've just stumbled upon your patches.

I'm very happy that PRP now also gains support :-)

> Best regards,
> Luka


-- 
Best regards,

Lukasz Majewski

--
Nabla Software Engineering GmbH
HRB 40522 Augsburg
Phone: +49 821 45592596
E-Mail: office@nabladev.com
Managing Director : Stefano Babic

      parent reply	other threads:[~2026-03-30  8:28 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-09 10:19 [PATCH v3 net-next] net: hsr: sync hw addr of slave2 according to slave1 hw addr on PRP Fernando Fernandez Mancera
2025-04-14 11:51 ` patchwork-bot+netdevbpf
2026-03-29 15:07 ` Luka Gejak
2026-03-29 16:58   ` Fernando Fernandez Mancera
2026-03-29 17:19     ` Luka Gejak
2026-03-29 17:22     ` Fernando Fernandez Mancera
2026-03-29 17:32       ` Luka Gejak
2026-03-29 17:46         ` Fernando Fernandez Mancera
2026-03-30  8:28         ` Łukasz Majewski [this message]

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20260330102812.214f27f4@wsk \
    --to=lukma@nabladev.com \
    --cc=edumazet@google.com \
    --cc=ffmancera@riseup.net \
    --cc=fmancera@suse.de \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=luka.gejak@linux.dev \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=shannon.nelson@amd.com \
    /path/to/YOUR_REPLY

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

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