From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 76969299A87 for ; Sat, 4 Jul 2026 23:47:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783208830; cv=none; b=QOh933UNlcORO+wXjVfaxMi63CXtGC8fxJZEwKhrdi7UMnqWskdKMp+WbMMqz5I1BAIIEqNIVufHx/obr8YKwj0aHWce8rHOhQ2JoDHDBEe9QzsX74cHcilB1OBYd7NWEKNmFFSmLxEh1bUNvQRKH13or/8TQ+IwcjnhIDNhMYE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783208830; c=relaxed/simple; bh=WmdVxG1qjyumTLg0dAYkqMTScBrx63gA3nVyRq5XgG4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tpLHwuDbd91n+Mfkyvw/YOPcNT7PyyVOAiMIQWwkbzBIlhuVQ4zPuIJZIJk7Et6CiECNcYtimfo5x5hCkqsYTl5E9R9qD4mwtWkLHgVudzd/RoS6LWqLngt6YFQ8bgABMBT526SKyf97b/DlqIubUPCY/yXNWy9m7xT5k/Y/tiw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=XLPwZYb4; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XLPwZYb4" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-493a6258788so591835e9.3 for ; Sat, 04 Jul 2026 16:47:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783208827; x=1783813627; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=u2AK/8mBVRm/uASU3oq6CXiRGB/9zBaQ2taBmIKBqgA=; b=XLPwZYb41pfPaC0ovv/karFQTLFAp2SmbTk8rr5dI8DrZp72Rg/iXc0JEPsGyi1dtr /VJeETSB+GHfAZ3+htxi+kX9npUCJJACKmUChGbYhocbGsqxmUpYbA1BPKs6knjw63G/ LQ/VDJAf0sj2dT5zfiW3llo1MngL6Dg85Y0BH+YJhdtEYxrlXvb9wg0FOWQZ645fXJdC MVV4g0vCja8KwRecPY4O168utBPrlqC7x05p/iVzOHQ1hJ6BIARlnHWfy97v8EhIQ90r e3IVpz2R+1bLmQ4gLl0kTbS1I7BPjNDsgV9FNS3V+LNqRcxteTwIIykhz8MK1POwCg9d nfMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783208827; x=1783813627; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=u2AK/8mBVRm/uASU3oq6CXiRGB/9zBaQ2taBmIKBqgA=; b=rDIXcJ2Gru3G5ML+CcnXdl4I0h3nPJmWF/1RwcgLPfGG+fqilHsq3CgXpFri3DOFX2 qoqJ7smozIqpmA3qaOAi1+TioORGNtKr8tMArrKAO+DtB0B8jsEOSbBtjOjvCdm6bdK3 d3DFLEEbzPuEpV49XwtcX50xG9QwyTNhO0+oJTtxOhTEaL8I0vfYRDRDeEteS83FBUtT y5Re9za0oKsh5gFF8p6BPHjixSd8JdHMBMnSUgX3PoH2+UOWA21Fv9w/4U0Ygp6NHRKg NZO721pUbhUS14V8r6KjKytVd/O5dFaLK63AYGQaAEF9Bhm3GPcvs9q3WzB4QqKO71c8 ySSw== X-Forwarded-Encrypted: i=1; AFNElJ871RitbxfOGOxtkqSsuV640HqOMLzBParJDExjpuvyjyK7kv+RdE7t7tZFiMO1uxpYqkP8g5X7Hi4HaIg=@vger.kernel.org X-Gm-Message-State: AOJu0Yw1WkEoFhyeorcalbQ5ultNaBsPFxViYxligQbdPn1uCBpiJC7F gFQDztBzhd3LE4VF4EEaLPweMYouzxiYzHiF+DLL+/StygoYU3CUBoOF X-Gm-Gg: AfdE7cmZ2KrT1Z1/mxwwPpcul3nm9JcqUkEErzk9vSYPx4nTPZFj6zInVaYqOthD6/I ItSDwtN3mXwrhYGu+Exp1wFxYhOHPVHPoCQymHGx1QglCPtFJAtmbsre/YqPnH0Yk/cqUrc9q4k nxodv2PKBx8ISU2ZaZOOD5rBHa6G1Xn6q+DrPsi122dkvvn3/1NKXXoJwWEs8m+9fR+9/ByTu2B w8QwA08MnVeMQ7M/3wYYywRhcfO7ih3yfRZR7dEXzvn7ICcbkcaIDgu4qspF8yE6Ea1yhVm/i9B qwoDKslmxs5VVJGX8us6n3888nvNORGL9BgdIcvy0GlkASTqNRdCdG865mckSPOKBLlIgUI3gAD sBy6gE9y5VhxQyLRDvLD85jlWbkepZwd14azysPscVvwst2HDzO35cFRpap4vzszT6NZUuuPkDr aqNvOkN6X3u544QpJGf5Ppymj/0z09MLDNrXGbK/+4z+incrfM84PlPaawvDM/vnBAslKmDF0xb j44nxhL0cLvEJXfRRcGBd6FCqVitwBaBYJ/fWfEsTU/q/Dehy8= X-Received: by 2002:a05:600c:83c6:b0:493:cc01:8067 with SMTP id 5b1f17b1804b1-493d0f48594mr30891745e9.8.1783208826853; Sat, 04 Jul 2026 16:47:06 -0700 (PDT) Received: from hpubt (dynamic-2a02-3100-5cf8-ddfc-6651-06ff-fed8-72a4.310.pool.telefonica.de. [2a02:3100:5cf8:ddfc:6651:6ff:fed8:72a4]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-493cce040b4sm216014125e9.10.2026.07.04.16.47.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 04 Jul 2026 16:47:06 -0700 (PDT) From: Xin Xie To: netdev@vger.kernel.org Cc: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Shuah Khan , linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Xin Xie Subject: [PATCH net-next 1/4] net: hsr: add PRP interlink (RedBox) datapath and duplicate discard Date: Sat, 4 Jul 2026 23:47:01 +0000 Message-ID: <20260704234704.4297-2-xiexinet@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260704234704.4297-1-xiexinet@gmail.com> References: <20260704234704.4297-1-xiexinet@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit A PRP RedBox proxies SANs that sit behind an interlink port: their frames must reach the PRP network with the SAN source MAC preserved, and PRP unicast must be steered between the LAN and the SAN segment correctly. Add the PRP interlink forwarding rules to prp_drop_frame() and give RedBox nodes a second duplicate-discard slot so the two LAN copies of a frame destined to a SAN collapse to a single delivery out the interlink. The destination classification (is the unicast DA a PRP-network node or a proxied SAN) is resolved once per frame in fill_frame_info(), gated to PRP RedBox devices, and cached in struct hsr_frame_info, so prp_drop_frame() stays O(1) and does not walk the node tables for every candidate egress port in the softIRQ path. HSR RedBox frame classification is untouched. Factor the LAN A/B duplicate test into prp_is_lan_dup() so the new PRP interlink rules do not change hsr_drop_frame() behaviour, including the NETIF_F_HW_HSR_FWD path which keeps using the LAN-duplicate test only. Signed-off-by: Xin Xie --- net/hsr/hsr_forward.c | 49 ++++++++++++++++++++++++++++++++++++------ net/hsr/hsr_framereg.c | 10 ++++++--- net/hsr/hsr_framereg.h | 2 ++ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index 0774981a6..efcd0acef 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -440,12 +440,37 @@ static int hsr_xmit(struct sk_buff *skb, struct hsr_port *port, return dev_queue_xmit(skb); } +static bool prp_is_lan_dup(struct hsr_frame_info *frame, + struct hsr_port *port) +{ + enum hsr_port_type rx = frame->port_rcv->type; + + return (rx == HSR_PT_SLAVE_A && port->type == HSR_PT_SLAVE_B) || + (rx == HSR_PT_SLAVE_B && port->type == HSR_PT_SLAVE_A); +} + bool prp_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port) { - return ((frame->port_rcv->type == HSR_PT_SLAVE_A && - port->type == HSR_PT_SLAVE_B) || - (frame->port_rcv->type == HSR_PT_SLAVE_B && - port->type == HSR_PT_SLAVE_A)); + enum hsr_port_type rx = frame->port_rcv->type; + + /* Supervision frames are not delivered to a SAN on the interlink. */ + if (frame->is_supervision && port->type == HSR_PT_INTERLINK) + return true; + + if (prp_is_lan_dup(frame, port)) + return true; + + /* LAN to interlink: keep PRP-network unicast off the SAN segment. */ + if ((rx == HSR_PT_SLAVE_A || rx == HSR_PT_SLAVE_B) && + port->type == HSR_PT_INTERLINK) + return frame->dst_in_node_db; + + /* Interlink to LAN: keep SAN-to-SAN unicast local. */ + if ((port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B) && + rx == HSR_PT_INTERLINK) + return frame->dst_in_proxy_node_db; + + return false; } bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port) @@ -453,7 +478,7 @@ bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port) struct sk_buff *skb; if (port->dev->features & NETIF_F_HW_HSR_FWD) - return prp_drop_frame(frame, port); + return prp_is_lan_dup(frame, port); /* RedBox specific frames dropping policies * @@ -466,7 +491,7 @@ bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port) * are addressed to interlink port (and are in the ProxyNodeTable). */ skb = frame->skb_hsr; - if (skb && prp_drop_frame(frame, port) && + if (skb && prp_is_lan_dup(frame, port) && is_unicast_ether_addr(eth_hdr(skb)->h_dest) && hsr_is_node_in_db(&port->hsr->proxy_node_db, eth_hdr(skb)->h_dest)) { @@ -706,6 +731,18 @@ static int fill_frame_info(struct hsr_frame_info *frame, frame->is_vlan = false; proto = ethhdr->h_proto; + /* PRP RedBox only: classify the unicast destination once so the + * per-egress-port decision in prp_drop_frame() stays O(1). HSR RedBox + * does its own classification and must not pay these node-table walks. + */ + if (hsr->prot_version == PRP_V1 && hsr->redbox && + is_unicast_ether_addr(ethhdr->h_dest)) { + frame->dst_in_node_db = + hsr_is_node_in_db(&hsr->node_db, ethhdr->h_dest); + frame->dst_in_proxy_node_db = + hsr_is_node_in_db(&hsr->proxy_node_db, ethhdr->h_dest); + } + if (proto == htons(ETH_P_8021Q)) frame->is_vlan = true; diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index e44929871..7a7c52a95 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -199,7 +199,7 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr, spin_lock_init(&new_node->seq_out_lock); if (hsr->prot_version == PRP_V1) - new_node->seq_port_cnt = 1; + new_node->seq_port_cnt = hsr->redbox ? 2 : 1; else new_node->seq_port_cnt = HSR_PT_PORTS - 1; @@ -649,9 +649,13 @@ int prp_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame) if (frame->port_rcv->type == HSR_PT_MASTER) return 0; - /* for PRP we should only forward frames from the slave ports - * to the master port + /* RedBox: forward LAN frames out the interlink to a SAN, deduping the + * two LAN copies on a dedicated slot. */ + if (port->type == HSR_PT_INTERLINK) + return hsr_check_duplicate(frame, 1); + + /* For PRP only slave-to-master frames are forwarded. */ if (port->type != HSR_PT_MASTER) return 1; diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h index c65ecb925..127a3fb64 100644 --- a/net/hsr/hsr_framereg.h +++ b/net/hsr/hsr_framereg.h @@ -27,6 +27,8 @@ struct hsr_frame_info { bool is_local_dest; bool is_local_exclusive; bool is_from_san; + bool dst_in_node_db; + bool dst_in_proxy_node_db; }; void hsr_del_self_node(struct hsr_priv *hsr); -- 2.53.0