public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Haoze Xie <royenheart@gmail.com>
To: Felix Maurer <fmaurer@redhat.com>, Ao Zhou <n05ec@lzu.edu.cn>
Cc: netdev@vger.kernel.org,
	Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
	"David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>,
	Murali Karicheri <m-karicheri2@ti.com>,
	Shaurya Rane <ssrane_b23@ee.vjti.ac.in>,
	Ingo Molnar <mingo@kernel.org>, Kees Cook <kees@kernel.org>,
	Yifan Wu <yifanwucs@gmail.com>,
	Juefei Pu <tomapufckgml@gmail.com>,
	Yuan Tan <yuantan098@gmail.com>, Xin Liu <bird@lzu.edu.cn>,
	Yuqi Xu <xuyuqiabc@gmail.com>,
	royenheart@gmail.com
Subject: Re: [PATCH net v2 1/1] net: hsr: avoid learning unknown senders for local delivery
Date: Tue, 21 Apr 2026 22:39:03 +0800	[thread overview]
Message-ID: <60c9218e-33fe-441e-ac25-1a42fecb29a5@gmail.com> (raw)
In-Reply-To: <adYwjxLBBaLY52Wb@thinkpad>

On 4/8/2026 6:40 PM, Felix Maurer wrote:
> On Sat, Apr 04, 2026 at 07:30:47PM +0800, Ao Zhou wrote:
>> From: Haoze Xie <royenheart@gmail.com>
>>
>> Traffic that is directly addressed to the local HSR/PRP master can be
>> delivered locally without creating a persistent node entry. Learning one
>> node per previously unseen source MAC lets forged sender floods grow
>> node_db until the prune timer catches up.
>>
>> Determine whether a frame is locally exclusive before node lookup and
>> skip learning for unknown senders in that case. When no node state
>> exists, also skip duplicate discard checks that depend on it.
>>
>> This keeps locally-destined traffic reachable while avoiding node table
>> growth from source-MAC floods in both the PRP SAN path and the HSR/PRP
>> tagged sender paths.
> 
> I see the problem you are trying to solve here, but I don't think this
> patch provides a significant improvement over the current situation.
> Yes, this will disable learning of new nodes from regular traffic (and
> thereby completely prevent the duplicate discard algorithm from
> working). New nodes would only be learned from supervision frames. But
> nothing prevents a malicious host in the network from spoofing tons of
> supervision frames.
> 
> HSR and PRP are supposed to be used in pretty restricted network
> environments, so the whole protocol design doesn't really expect
> malicious actors in the network and doesn't provide good options to
> safeguard against misuse.
> 
> IMHO, the only real way to prevent excessive resource use on our side is
> to put a limit on these resources. In this case, limit the size of the
> node table (bonus: make that limit configurable as Paolo suggested).
> 
> Thanks,
>    Felix
> 

I agree and therefore dropped the v2 learning-suppression approach and
reworked the fix toward directly bounding node-table growth in v3 patch.

If the node-table-limit approach in v3 looks acceptable, I can also follow
up later with refinements such as per-device configurability and better
visibility when the table is saturated.

Best regards,
Haoze Xie

> 
>> Fixes: f421436a591d ("net/hsr: Add support for the High-availability Seamless Redundancy protocol (HSRv0)")
>> Fixes: 451d8123f897 ("net: prp: add packet handling support")
>> Reported-by: Yifan Wu <yifanwucs@gmail.com>
>> Reported-by: Juefei Pu <tomapufckgml@gmail.com>
>> Co-developed-by: Yuan Tan <yuantan098@gmail.com>
>> Signed-off-by: Yuan Tan <yuantan098@gmail.com>
>> Suggested-by: Xin Liu <bird@lzu.edu.cn>
>> Tested-by: Yuqi Xu <xuyuqiabc@gmail.com>
>> Signed-off-by: Haoze Xie <royenheart@gmail.com>
>> Signed-off-by: Ao Zhou <n05ec@lzu.edu.cn>
>> ---
>> changes in v2:
>> - generalize the fix beyond PRP SAN traffic and cover HSR/PRP tagged sender floods
>> - decide whether learning is needed from local-exclusive delivery instead of protocol-specific SAN checks
>> - use the normal NULL return semantics from hsr_get_node() instead of ERR_PTR-based error plumbing
>> - skip duplicate-discard state checks when no node state exists
>>
>>  net/hsr/hsr_forward.c  | 23 +++++++++++++----------
>>  net/hsr/hsr_framereg.c |  5 ++++-
>>  net/hsr/hsr_framereg.h |  2 +-
>>  3 files changed, 18 insertions(+), 12 deletions(-)
>>
>> diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
>> index aefc9b6936ba..15bd17b4ee17 100644
>> --- a/net/hsr/hsr_forward.c
>> +++ b/net/hsr/hsr_forward.c
>> @@ -403,7 +403,8 @@ static void hsr_deliver_master(struct sk_buff *skb, struct net_device *dev,
>>  	int res, recv_len;
>>
>>  	was_multicast_frame = (skb->pkt_type == PACKET_MULTICAST);
>> -	hsr_addr_subst_source(node_src, skb);
>> +	if (node_src)
>> +		hsr_addr_subst_source(node_src, skb);
>>  	skb_pull(skb, ETH_HLEN);
>>  	recv_len = skb->len;
>>  	res = netif_rx(skb);
>> @@ -545,7 +546,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
>>  		/* Don't send frame over port where it has been sent before.
>>  		 * Also for SAN, this shouldn't be done.
>>  		 */
>> -		if (!frame->is_from_san &&
>> +		if (frame->node_src && !frame->is_from_san &&
>>  		    hsr->proto_ops->register_frame_out &&
>>  		    hsr->proto_ops->register_frame_out(port, frame))
>>  			continue;
>> @@ -688,21 +689,25 @@ static int fill_frame_info(struct hsr_frame_info *frame,
>>  		return -EINVAL;
>>
>>  	memset(frame, 0, sizeof(*frame));
>> +	frame->port_rcv = port;
>>  	frame->is_supervision = is_supervision_frame(port->hsr, skb);
>>  	if (frame->is_supervision && hsr->redbox)
>>  		frame->is_proxy_supervision =
>>  			is_proxy_supervision_frame(port->hsr, skb);
>>
>> +	ethhdr = (struct ethhdr *)skb_mac_header(skb);
>> +	check_local_dest(port->hsr, skb, frame);
>> +
>>  	n_db = &hsr->node_db;
>>  	if (port->type == HSR_PT_INTERLINK)
>>  		n_db = &hsr->proxy_node_db;
>>
>>  	frame->node_src = hsr_get_node(port, n_db, skb,
>> -				       frame->is_supervision, port->type);
>> -	if (!frame->node_src)
>> -		return -1; /* Unknown node and !is_supervision, or no mem */
>> +				       frame->is_supervision, port->type,
>> +				       !frame->is_local_exclusive);
>> +	if (!frame->node_src && !frame->is_local_exclusive)
>> +		return -1;
>>
>> -	ethhdr = (struct ethhdr *)skb_mac_header(skb);
>>  	frame->is_vlan = false;
>>  	proto = ethhdr->h_proto;
>>
>> @@ -720,13 +725,10 @@ static int fill_frame_info(struct hsr_frame_info *frame,
>>  	}
>>
>>  	frame->is_from_san = false;
>> -	frame->port_rcv = port;
>>  	ret = hsr->proto_ops->fill_frame_info(proto, skb, frame);
>>  	if (ret)
>>  		return ret;
>>
>> -	check_local_dest(port->hsr, skb, frame);
>> -
>>  	return 0;
>>  }
>>
>> @@ -739,7 +741,8 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port)
>>  	if (fill_frame_info(&frame, skb, port) < 0)
>>  		goto out_drop;
>>
>> -	hsr_register_frame_in(frame.node_src, port, frame.sequence_nr);
>> +	if (frame.node_src)
>> +		hsr_register_frame_in(frame.node_src, port, frame.sequence_nr);
>>  	hsr_forward_do(&frame);
>>  	rcu_read_unlock();
>>  	/* Gets called for ingress frames as well as egress from master port.
>> diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
>> index 50996f4de7f9..2bc6f8f154c2 100644
>> --- a/net/hsr/hsr_framereg.c
>> +++ b/net/hsr/hsr_framereg.c
>> @@ -221,7 +221,7 @@ void prp_update_san_info(struct hsr_node *node, bool is_sup)
>>   */
>>  struct hsr_node *hsr_get_node(struct hsr_port *port, struct list_head *node_db,
>>  			      struct sk_buff *skb, bool is_sup,
>> -			      enum hsr_port_type rx_port)
>> +			      enum hsr_port_type rx_port, bool learn)
>>  {
>>  	struct hsr_priv *hsr = port->hsr;
>>  	struct hsr_node *node;
>> @@ -270,6 +270,9 @@ struct hsr_node *hsr_get_node(struct hsr_port *port, struct list_head *node_db,
>>  			san = true;
>>  	}
>>
>> +	if (!learn)
>> +		return NULL;
>> +
>>  	return hsr_add_node(hsr, node_db, ethhdr->h_source, san, rx_port);
>>  }
>>
>> diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h
>> index c65ecb925734..3d9c88e83090 100644
>> --- a/net/hsr/hsr_framereg.h
>> +++ b/net/hsr/hsr_framereg.h
>> @@ -33,7 +33,7 @@ void hsr_del_self_node(struct hsr_priv *hsr);
>>  void hsr_del_nodes(struct list_head *node_db);
>>  struct hsr_node *hsr_get_node(struct hsr_port *port, struct list_head *node_db,
>>  			      struct sk_buff *skb, bool is_sup,
>> -			      enum hsr_port_type rx_port);
>> +			      enum hsr_port_type rx_port, bool learn);
>>  void hsr_handle_sup_frame(struct hsr_frame_info *frame);
>>  bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr);
>>  bool hsr_addr_is_redbox(struct hsr_priv *hsr, unsigned char *addr);
>> --
>> 2.53.0
>>
> 


      parent reply	other threads:[~2026-04-21 14:39 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <cover.1775056603.git.royenheart@outlook.com>
2026-04-02 14:18 ` [PATCH 1/1] net: hsr: avoid learning nodes from ordinary PRP SAN traffic Ao Zhou
2026-04-07  8:40   ` Paolo Abeni
2026-04-04 11:30 ` [PATCH net v2 1/1] net: hsr: avoid learning unknown senders for local delivery Ao Zhou
2026-04-08 10:40   ` Felix Maurer
2026-04-14 14:59     ` Sebastian Andrzej Siewior
2026-04-14 23:05       ` Yuan Tan
2026-04-21 14:39     ` Haoze Xie [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=60c9218e-33fe-441e-ac25-1a42fecb29a5@gmail.com \
    --to=royenheart@gmail.com \
    --cc=bigeasy@linutronix.de \
    --cc=bird@lzu.edu.cn \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=fmaurer@redhat.com \
    --cc=horms@kernel.org \
    --cc=kees@kernel.org \
    --cc=kuba@kernel.org \
    --cc=m-karicheri2@ti.com \
    --cc=mingo@kernel.org \
    --cc=n05ec@lzu.edu.cn \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=ssrane_b23@ee.vjti.ac.in \
    --cc=tomapufckgml@gmail.com \
    --cc=xuyuqiabc@gmail.com \
    --cc=yifanwucs@gmail.com \
    --cc=yuantan098@gmail.com \
    /path/to/YOUR_REPLY

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

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