public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
@ 2026-02-04 11:24 Sebastian Andrzej Siewior
  2026-02-04 11:24 ` [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header Sebastian Andrzej Siewior
                   ` (2 more replies)
  0 siblings, 3 replies; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-04 11:24 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn, Sebastian Andrzej Siewior

I am trying to extend linuxptp to support PTP over a HSR network. The
user space for linuxptp are still under discussion, the thread starts at
	https://lists.nwtime.org/sympa/arc/linuxptp-devel/2025-11/msg00013.html

the posted patches are also available at git repository for convenience
	https://git.kernel.org/pub/scm/linux/kernel/git/bigeasy/linuxptp-hsr.git hsr_v2

This is the kernel side of the changes. In short PTP over HSR sends its
packets to multicast address and every node needs to forward the PTP
packet (SYNC and FOLLOW-UP for instance) within the HSR ring.
In order to achieve this, the HSR stack must not duplicate and forward
the PTP packets as it would with other packets. The delay caused by the
duplication and forwarding adds overhead which in turn makes the timing
information within the PTP packet inaccurate.

My current approach is to open the hsr0 device from userland and send
and receive the PTP packets individually on both slave interfaces. I
added additional hints to the af_packet interface, which is used by
linuxptp, to be able send a packet on a specific interface (A or B) and
also to have the information recorded for received packets.
Additionally, the PTP-timestamps which arrive on the slave interface are
forwarded to the hsr interface.

This solves the following:
- Forwarding a SYNC and a FOLLOW_UP packet.
  Userland receives a SYNC, FOLLOW_UP and timestamp packet from port A.
  The received port is known and recorded. The SYNC sync packet and the
  updated FOLLOW_UP packet can then be forwarded on port B. The update
  is based on the time spent during the forward so the forwarding delay
  is accounted for.
  In this scenario the HSR header is used from the original sender of
  the SYNC and FOLLOW_UP header and the stack must not prepand the
  system's HSR header nor replace the provided header.

- Sending PDELAY_REQ and PDELAY_RESP*
  These packets are only exchanged between the two nodes directly
  connected and they must not be forwarded within the HSR ring.
  These packets are sent as PTP packets and the HSR stack must prepand
  system's HSR header including a sequence number.
  This logic is also used for SYNC packet if the node acts as a GM.

This has been tested in a pure software environment and in an HW-assited
environment where the HW is able to duplicate and deduplicate packets
but does not do it for PTP packets.
It has not been tested within an enviroment where the HW is able to
forward the PTP packet and correctly update the timming information.

This series will clash with Felix's sequence number/ deduplication
rework.

---
Sebastian Andrzej Siewior (2):
      hsr: Allow to send a specific port and with HSR header
      af_packet: Add port specific handling for HSR

 include/linux/if_hsr.h         |   2 +
 include/linux/skbuff.h         |   1 +
 include/uapi/linux/if_packet.h |   9 ++++
 net/hsr/hsr_device.c           |   7 +++
 net/hsr/hsr_forward.c          | 114 ++++++++++++++++++++++++++++++++++++++---
 net/hsr/hsr_slave.c            |  16 ++++++
 net/packet/af_packet.c         | 103 +++++++++++++++++++++++++++++++++++++
 net/packet/internal.h          |   1 +
 8 files changed, 246 insertions(+), 7 deletions(-)
---
base-commit: 4ff7d63728ef2315d402a608cef1376248aa5c56
change-id: 20260204-hsr_ptp-1f6380f1d35f

Best regards,
-- 
Sebastian Andrzej Siewior <bigeasy@linutronix.de>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-02-04 11:24 [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Sebastian Andrzej Siewior
@ 2026-02-04 11:24 ` Sebastian Andrzej Siewior
  2026-02-04 17:30   ` Willem de Bruijn
  2026-02-04 11:24 ` [PATCH RFC net-next 2/2] af_packet: Add port specific handling for HSR Sebastian Andrzej Siewior
  2026-02-16 16:10 ` [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Felix Maurer
  2 siblings, 1 reply; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-04 11:24 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn, Sebastian Andrzej Siewior

HSR forwards all packets it received on slave port A to slave port B and
one of the possible two copies to the user (master) interface.
In terms of PTP this is not good because the latency introduced by
forwarding makes the timestamp in the PTP packet inaccurate.

Introduce a hsr_ptp field to struct skb_shared_info which can be used to
store HSR specific information for sending and receiving skbs.

Receive (slave ports):
- HSR_PT_SLAVE_A/ HSR_PT_SLAVE_B to denote the port which received the
  packet. This information is only added to PTP packets.

Send (master port):
- HSR_PT_SLAVE_A/ HSR_PT_SLAVE_B to denote the port on which the packet
  has to be sent.
- HSR_SKB_INCLUDES_HEADER to denote that the packet already contains a
  HSR header and the stack must not add the system's header to it.

HSR_SKB_INCLUDES_HEADER is used to allow forwarding a PTP packet and
preserving the HSR header by the sender.
Cloning skbs requires to preserve the socket information so that a PTP
timestamp can be associated with the socket.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 include/linux/if_hsr.h |   2 +
 include/linux/skbuff.h |   1 +
 net/hsr/hsr_device.c   |   7 +++
 net/hsr/hsr_forward.c  | 114 ++++++++++++++++++++++++++++++++++++++++++++++---
 net/hsr/hsr_slave.c    |  16 +++++++
 5 files changed, 133 insertions(+), 7 deletions(-)

diff --git a/include/linux/if_hsr.h b/include/linux/if_hsr.h
index f4cf2dd36d193..1463ddbc8cddf 100644
--- a/include/linux/if_hsr.h
+++ b/include/linux/if_hsr.h
@@ -22,6 +22,8 @@ enum hsr_port_type {
 	HSR_PT_PORTS,	/* This must be the last item in the enum */
 };
 
+#define HSR_SKB_INCLUDES_HEADER		(1 << 4)
+
 /* HSR Tag.
  * As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB,
  * path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest,
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 86737076101d4..52c847e490ee8 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -605,6 +605,7 @@ struct skb_shared_info {
 	};
 	unsigned int	gso_type;
 	u32		tskey;
+	u32		hsr_ptp;
 
 	/*
 	 * Warning : all fields before dataref are cleared in __alloc_skb()
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index d1bfc49b5f017..a06ef7c88792c 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -230,6 +230,13 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 	master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
 	if (master) {
 		skb->dev = master->dev;
+
+		/* skb includes HSR header but the network header is only set to
+		 * the ethernet header.
+		 */
+		if (skb_shinfo(skb)->hsr_ptp & HSR_SKB_INCLUDES_HEADER)
+			skb_set_network_header(skb, ETH_HLEN + HSR_HLEN);
+
 		skb_reset_mac_header(skb);
 		skb_reset_mac_len(skb);
 		spin_lock_bh(&hsr->seqnr_lock);
diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
index aefc9b6936ba0..c4040e61bd914 100644
--- a/net/hsr/hsr_forward.c
+++ b/net/hsr/hsr_forward.c
@@ -17,6 +17,16 @@
 
 struct hsr_node;
 
+static unsigned int hsr_get_ptp_flags(struct sk_buff *skb)
+{
+	return skb_shinfo(skb)->hsr_ptp;
+}
+
+static unsigned int hsr_keep_header(struct sk_buff *skb)
+{
+	return (hsr_get_ptp_flags(skb) & 0xf0) == HSR_SKB_INCLUDES_HEADER;
+}
+
 /* The uses I can see for these HSR supervision frames are:
  * 1) Use the frames that are sent after node initialization ("HSR_TLV.Type =
  *    22") to reset any sequence_nr counters belonging to that node. Useful if
@@ -343,7 +353,10 @@ struct sk_buff *hsr_create_tagged_frame(struct hsr_frame_info *frame,
 		hsr_set_path_id(frame, hsr_ethhdr, port);
 		return skb_clone(frame->skb_hsr, GFP_ATOMIC);
 	} else if (port->dev->features & NETIF_F_HW_HSR_TAG_INS) {
-		return skb_clone(frame->skb_std, GFP_ATOMIC);
+		skb = skb_clone(frame->skb_std, GFP_ATOMIC);
+		if (skb_shinfo(frame->skb_std)->hsr_ptp && skb)
+			skb->sk = frame->skb_std->sk;
+		return skb;
 	}
 
 	/* Create the new skb with enough headroom to fit the HSR tag */
@@ -365,6 +378,16 @@ struct sk_buff *hsr_create_tagged_frame(struct hsr_frame_info *frame,
 	memmove(dst, src, movelen);
 	skb_reset_mac_header(skb);
 
+	if (skb_shinfo(frame->skb_std)->hsr_ptp) {
+		/* Packets are bound to a port and the sender may expect time
+		 * information.
+		 */
+		skb_shinfo(skb)->hsr_ptp = skb_shinfo(frame->skb_std)->hsr_ptp;
+		skb_shinfo(skb)->tx_flags = skb_shinfo(frame->skb_std)->tx_flags;
+		skb_shinfo(skb)->tskey = skb_shinfo(frame->skb_std)->tskey;
+		skb->sk = frame->skb_std->sk;
+	}
+
 	/* skb_put_padto free skb on error and hsr_fill_tag returns NULL in
 	 * that case
 	 */
@@ -420,7 +443,7 @@ static void hsr_deliver_master(struct sk_buff *skb, struct net_device *dev,
 static int hsr_xmit(struct sk_buff *skb, struct hsr_port *port,
 		    struct hsr_frame_info *frame)
 {
-	if (frame->port_rcv->type == HSR_PT_MASTER) {
+	if (frame->port_rcv->type == HSR_PT_MASTER && !hsr_keep_header(skb)) {
 		hsr_addr_subst_dest(frame->node_src, skb, port);
 
 		/* Address substitution (IEC62439-3 pp 26, 50): replace mac
@@ -504,6 +527,32 @@ bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port)
 	return false;
 }
 
+static void hsr_parse_req_master(struct hsr_frame_info *frame,
+				 unsigned int *req_port,
+				 bool *req_keep_header)
+{
+	struct skb_shared_info *si;
+	unsigned int val;
+
+	*req_port = HSR_PT_NONE;
+	*req_keep_header = false;
+
+	if (!frame->skb_std)
+		return;
+
+	si = skb_shinfo(frame->skb_std);
+	if (!si->hsr_ptp)
+		return;
+
+	val = si->hsr_ptp & 0xf;
+	if (val == HSR_PT_SLAVE_A || val == HSR_PT_SLAVE_B)
+		*req_port = val;
+
+	val = si->hsr_ptp & 0xf0;
+	if (val == HSR_SKB_INCLUDES_HEADER)
+		*req_keep_header = true;
+}
+
 /* Forward the frame through all devices except:
  * - Back through the receiving device
  * - If it's a HSR frame: through a device where it has passed before
@@ -521,6 +570,10 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
 	struct hsr_port *port;
 	struct sk_buff *skb;
 	bool sent = false;
+	unsigned int req_port;
+	bool req_keep_header;
+
+	hsr_parse_req_master(frame, &req_port, &req_keep_header);
 
 	hsr_for_each_port(frame->port_rcv->hsr, port) {
 		struct hsr_priv *hsr = port->hsr;
@@ -542,6 +595,42 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
 		if ((port->dev->features & NETIF_F_HW_HSR_DUP) && sent)
 			continue;
 
+		{
+			struct skb_shared_info *si = NULL;
+
+			if (frame->skb_hsr)
+				si = skb_shinfo(frame->skb_hsr);
+
+			/* Received over a slave interface */
+			if (si && si->hsr_ptp) {
+				/* No PTP forwarding */
+				if (port->type == HSR_PT_SLAVE_A ||
+				    port->type == HSR_PT_SLAVE_B)
+					continue;
+
+				if (port->type != HSR_PT_MASTER)
+					continue;
+
+				skb = skb_clone(frame->skb_hsr, GFP_ATOMIC);
+				/* Inject the PTP frame into the master
+				 * interface including HSR headers.
+				 */
+				goto inject_into_stack;
+			}
+
+			/* Outgoing port has been specified */
+			if ((req_port != HSR_PT_NONE) && (req_port != port->type))
+				continue;
+			if (req_keep_header) {
+				skb = skb_clone(frame->skb_std, GFP_ATOMIC);
+				/* Send the frame on the specific port without
+				 * addign HSR headers.
+				 */
+				if (skb)
+					skb->sk = frame->skb_std->sk;
+				goto inject_into_stack;
+			}
+		}
 		/* Don't send frame over port where it has been sent before.
 		 * Also for SAN, this shouldn't be done.
 		 */
@@ -569,6 +658,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
 		else
 			skb = hsr->proto_ops->get_untagged_frame(frame, port);
 
+inject_into_stack:
 		if (!skb) {
 			frame->port_rcv->dev->stats.rx_dropped++;
 			continue;
@@ -633,6 +723,13 @@ int hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
 	struct hsr_port *port = frame->port_rcv;
 	struct hsr_priv *hsr = port->hsr;
 
+	if (hsr_keep_header(skb)) {
+		frame->skb_std = skb;
+
+		WARN_ON_ONCE(port->type != HSR_PT_MASTER);
+		WARN_ON_ONCE(skb->mac_len < sizeof(struct hsr_ethhdr));
+		return 0;
+	}
 	/* HSRv0 supervisory frames double as a tag so treat them as tagged. */
 	if ((!hsr->prot_version && proto == htons(ETH_P_PRP)) ||
 	    proto == htons(ETH_P_HSR)) {
@@ -697,10 +794,12 @@ static int fill_frame_info(struct hsr_frame_info *frame,
 	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 */
+	if (!hsr_keep_header(skb)) {
+		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 */
+	}
 
 	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 	frame->is_vlan = false;
@@ -739,7 +838,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 (!hsr_keep_header(skb))
+		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_slave.c b/net/hsr/hsr_slave.c
index afe06ba00ea44..8329d01eee287 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -81,6 +81,22 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
 		hsr_forward_skb(skb, port);
 		spin_unlock_bh(&hsr->seqnr_lock);
 	} else {
+		struct hsr_ethhdr *hsr_ethhdr;
+		struct skb_shared_info *si;
+
+		hsr_ethhdr = (struct hsr_ethhdr *)skb_mac_header(skb);
+		if (hsr_ethhdr->hsr_tag.encap_proto == htons(ETH_P_1588)) {
+			/* PTP packages are not supposed to be forwarded via HSR
+			 * as-is. The latency introduced by forwarding renders
+			 * the time information useless.
+			 * Instead attach the port information on which it was
+			 * received, forward both copies to userland only and
+			 * let it deal with it.
+			 */
+			si = skb_shinfo(skb);
+			si->hsr_ptp = port->type;
+		}
+
 		hsr_forward_skb(skb, port);
 	}
 

-- 
2.51.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH RFC net-next 2/2] af_packet: Add port specific handling for HSR
  2026-02-04 11:24 [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Sebastian Andrzej Siewior
  2026-02-04 11:24 ` [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header Sebastian Andrzej Siewior
@ 2026-02-04 11:24 ` Sebastian Andrzej Siewior
  2026-02-04 17:36   ` Willem de Bruijn
  2026-02-16 16:10 ` [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Felix Maurer
  2 siblings, 1 reply; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-04 11:24 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn, Sebastian Andrzej Siewior

linuxptp/ ptp4l uses a AF_PACKET with a RAW socket to send and receive
PTP packets. Extend the interface with the ability to bind the socket to
one of the two HSR ports and add a flag for sendmsg() to indicate that
the packet already contains a HSR header.

Once PACKET_HSR_BIND_PORT is set, the socket will be bound to requested
slave port. All incoming packets without a set port will be discarded.
This limits receiving packet to PTP only packets. The packet will be
forwarded to userland with the HSR header.

For control messages used by sendmsg(), PACKET_HSR_INFO is added with
PACKET_HSR_INFO_HAS_HDR as the only option. This option sets
HSR_SKB_INCLUDES_HEADER on the outgoing skb to indicate that the packet
already contains a HSR header. This requires that the socket is bound to
a specific HSR port so that the packet is sent only on one of the two
ports.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 include/uapi/linux/if_packet.h |   9 ++++
 net/packet/af_packet.c         | 103 +++++++++++++++++++++++++++++++++++++++++
 net/packet/internal.h          |   1 +
 3 files changed, 113 insertions(+)

diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
index 6cd1d7a41dfb7..3443eeac8470e 100644
--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -60,6 +60,7 @@ struct sockaddr_ll {
 #define PACKET_FANOUT_DATA		22
 #define PACKET_IGNORE_OUTGOING		23
 #define PACKET_VNET_HDR_SZ		24
+#define PACKET_HSR_BIND_PORT		25
 
 #define PACKET_FANOUT_HASH		0
 #define PACKET_FANOUT_LB		1
@@ -74,6 +75,14 @@ struct sockaddr_ll {
 #define PACKET_FANOUT_FLAG_IGNORE_OUTGOING     0x4000
 #define PACKET_FANOUT_FLAG_DEFRAG	0x8000
 
+/* For HSR, bind port */
+#define PACKET_HSR_BIND_PORT_AB		0
+#define PACKET_HSR_BIND_PORT_A		1
+#define PACKET_HSR_BIND_PORT_B		2
+/* HSR, CMSG */
+#define PACKET_HSR_INFO			1
+#define PACKET_HSR_INFO_HAS_HDR		1
+
 struct tpacket_stats {
 	unsigned int	tp_packets;
 	unsigned int	tp_drops;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 494d628d10a51..cd7c4ad034bc5 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -82,6 +82,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
+#include <linux/if_hsr.h>
 #include <linux/if_vlan.h>
 #include <linux/virtio_net.h>
 #include <linux/errqueue.h>
@@ -1938,6 +1939,36 @@ static void packet_parse_headers(struct sk_buff *skb, struct socket *sock)
 	skb_probe_transport_header(skb);
 }
 
+static int packet_cmsg_send(struct msghdr *msg, struct packet_sock *po,
+			    unsigned int *hsr_setting)
+{
+	struct cmsghdr *cmsg;
+	int ret = -EINVAL;
+	u32 val;
+
+	for_each_cmsghdr(cmsg, msg) {
+		if (!CMSG_OK(msg, cmsg))
+			goto out;
+		if (cmsg->cmsg_level != SOL_PACKET)
+			continue;
+		if (cmsg->cmsg_type != PACKET_HSR_INFO)
+			continue;
+		if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
+			goto out;
+
+		val = *(u32 *)CMSG_DATA(cmsg);
+		if (val != PACKET_HSR_INFO_HAS_HDR)
+			goto out;
+		if (!po->hsr_bound_port)
+			goto out;
+
+		*hsr_setting = HSR_SKB_INCLUDES_HEADER;
+	}
+	ret = 0;
+out:
+	return ret;
+}
+
 /*
  *	Output a raw packet to a device layer. This bypasses all the other
  *	protocol layers and you must therefore supply it with a complete frame
@@ -1947,6 +1978,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
 			       size_t len)
 {
 	struct sock *sk = sock->sk;
+	struct packet_sock *po = pkt_sk(sk);
 	DECLARE_SOCKADDR(struct sockaddr_pkt *, saddr, msg->msg_name);
 	struct sk_buff *skb = NULL;
 	struct net_device *dev;
@@ -1954,6 +1986,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
 	__be16 proto = 0;
 	int err;
 	int extra_len = 0;
+	u32 hsr_setting = 0;
 
 	/*
 	 *	Get and verify the address.
@@ -2044,6 +2077,9 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
 		err = sock_cmsg_send(sk, msg, &sockc);
 		if (unlikely(err))
 			goto out_unlock;
+		err = packet_cmsg_send(msg, po, &hsr_setting);
+		if (unlikely(err))
+			goto out_unlock;
 	}
 
 	skb->protocol = proto;
@@ -2052,6 +2088,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
 	skb->mark = sockc.mark;
 	skb_set_delivery_type_by_clockid(skb, sockc.transmit_time, sk->sk_clockid);
 	skb_setup_tx_timestamp(skb, &sockc);
+	skb_shinfo(skb)->hsr_ptp = hsr_setting | po->hsr_bound_port;
 
 	if (unlikely(extra_len == 4))
 		skb->no_fcs = 1;
@@ -2131,6 +2168,13 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (!net_eq(dev_net(dev), sock_net(sk)))
 		goto drop;
 
+	if (po->hsr_bound_port) {
+		struct skb_shared_info *si = skb_shinfo(skb);
+
+		if (po->hsr_bound_port != si->hsr_ptp)
+			goto drop;
+	}
+
 	skb->dev = dev;
 
 	if (dev_has_header(dev)) {
@@ -2260,6 +2304,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (!net_eq(dev_net(dev), sock_net(sk)))
 		goto drop;
 
+	if (po->hsr_bound_port) {
+		struct skb_shared_info *si = skb_shinfo(skb);
+
+		if (po->hsr_bound_port != si->hsr_ptp)
+			goto drop;
+	}
+
 	if (dev_has_header(dev)) {
 		if (sk->sk_type != SOCK_DGRAM)
 			skb_push(skb, skb->data - skb_mac_header(skb));
@@ -2731,6 +2782,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 	int len_sum = 0;
 	int status = TP_STATUS_AVAILABLE;
 	int hlen, tlen, copylen = 0;
+	u32 hsr_setting = 0;
 	long timeo;
 
 	mutex_lock(&po->pg_vec_lock);
@@ -2775,6 +2827,10 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 		err = sock_cmsg_send(&po->sk, msg, &sockc);
 		if (unlikely(err))
 			goto out_put;
+
+		err = packet_cmsg_send(msg, po, &hsr_setting);
+		if (unlikely(err))
+			goto out_put;
 	}
 
 	if (po->sk.sk_socket->type == SOCK_RAW)
@@ -2863,6 +2919,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 				goto out_status;
 			}
 		}
+		skb_shinfo(skb)->hsr_ptp = hsr_setting | po->hsr_bound_port;
 
 		if (vnet_hdr_sz) {
 			if (virtio_net_hdr_to_skb(skb, vnet_hdr, vio_le())) {
@@ -2952,6 +3009,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 	int vnet_hdr_sz = READ_ONCE(po->vnet_hdr_sz);
 	int hlen, tlen, linear;
 	int extra_len = 0;
+	u32 hsr_setting = 0;
 
 	/*
 	 *	Get and verify the address.
@@ -2988,6 +3046,10 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 		err = sock_cmsg_send(sk, msg, &sockc);
 		if (unlikely(err))
 			goto out_unlock;
+
+		err = packet_cmsg_send(msg, po, &hsr_setting);
+		if (unlikely(err))
+			goto out_unlock;
 	}
 
 	if (sock->type == SOCK_RAW)
@@ -3047,6 +3109,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 	}
 
 	skb_setup_tx_timestamp(skb, &sockc);
+	skb_shinfo(skb)->hsr_ptp = hsr_setting | po->hsr_bound_port;
 
 	if (!vnet_hdr.gso_type && (len > dev->mtu + reserve + extra_len) &&
 	    !packet_extra_vlan_len_allowed(dev, skb)) {
@@ -4044,6 +4107,31 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,
 		packet_sock_flag_set(po, PACKET_SOCK_QDISC_BYPASS, val);
 		return 0;
 	}
+	case PACKET_HSR_BIND_PORT:
+	{
+		int val;
+
+		if (optlen != sizeof(val))
+			return -EINVAL;
+		if (copy_from_sockptr(&val, optval, sizeof(val)))
+			return -EFAULT;
+
+		switch (val) {
+		case 0:
+			po->hsr_bound_port = 0;
+			break;
+		case PACKET_HSR_BIND_PORT_A:
+			po->hsr_bound_port = HSR_PT_SLAVE_A;
+			break;
+		case PACKET_HSR_BIND_PORT_B:
+			po->hsr_bound_port = HSR_PT_SLAVE_B;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		return 0;
+	}
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -4164,6 +4252,21 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 	case PACKET_QDISC_BYPASS:
 		val = packet_sock_flag(po, PACKET_SOCK_QDISC_BYPASS);
 		break;
+	case PACKET_HSR_BIND_PORT:
+		switch (po->hsr_bound_port) {
+		case 0:
+			val = 0;
+			break;
+		case HSR_PT_SLAVE_A:
+			val = PACKET_HSR_BIND_PORT_A;
+			break;
+		case HSR_PT_SLAVE_B:
+			val = PACKET_HSR_BIND_PORT_B;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
 	default:
 		return -ENOPROTOOPT;
 	}
diff --git a/net/packet/internal.h b/net/packet/internal.h
index b76e645cd78d1..24d63275d432f 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -114,6 +114,7 @@ struct packet_sock {
 	unsigned long		flags;
 	int			ifindex;	/* bound device		*/
 	u8			vnet_hdr_sz;
+	u8			hsr_bound_port;
 	__be16			num;
 	struct packet_rollover	*rollover;
 	struct packet_mclist	*mclist;

-- 
2.51.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-02-04 11:24 ` [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header Sebastian Andrzej Siewior
@ 2026-02-04 17:30   ` Willem de Bruijn
  2026-02-17 15:36     ` Sebastian Andrzej Siewior
  2026-03-04 14:58     ` Sebastian Andrzej Siewior
  0 siblings, 2 replies; 23+ messages in thread
From: Willem de Bruijn @ 2026-02-04 17:30 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, netdev
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn, Sebastian Andrzej Siewior

Sebastian Andrzej Siewior wrote:
> HSR forwards all packets it received on slave port A to slave port B and
> one of the possible two copies to the user (master) interface.
> In terms of PTP this is not good because the latency introduced by
> forwarding makes the timestamp in the PTP packet inaccurate.
> 
> Introduce a hsr_ptp field to struct skb_shared_info which can be used to
> store HSR specific information for sending and receiving skbs.
> 
> Receive (slave ports):
> - HSR_PT_SLAVE_A/ HSR_PT_SLAVE_B to denote the port which received the
>   packet. This information is only added to PTP packets.
> 
> Send (master port):
> - HSR_PT_SLAVE_A/ HSR_PT_SLAVE_B to denote the port on which the packet
>   has to be sent.
> - HSR_SKB_INCLUDES_HEADER to denote that the packet already contains a
>   HSR header and the stack must not add the system's header to it.
> 
> HSR_SKB_INCLUDES_HEADER is used to allow forwarding a PTP packet and
> preserving the HSR header by the sender.
> Cloning skbs requires to preserve the socket information so that a PTP
> timestamp can be associated with the socket.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  include/linux/if_hsr.h |   2 +
>  include/linux/skbuff.h |   1 +
>  net/hsr/hsr_device.c   |   7 +++
>  net/hsr/hsr_forward.c  | 114 ++++++++++++++++++++++++++++++++++++++++++++++---
>  net/hsr/hsr_slave.c    |  16 +++++++
>  5 files changed, 133 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/if_hsr.h b/include/linux/if_hsr.h
> index f4cf2dd36d193..1463ddbc8cddf 100644
> --- a/include/linux/if_hsr.h
> +++ b/include/linux/if_hsr.h
> @@ -22,6 +22,8 @@ enum hsr_port_type {
>  	HSR_PT_PORTS,	/* This must be the last item in the enum */
>  };
>  
> +#define HSR_SKB_INCLUDES_HEADER		(1 << 4)
> +
>  /* HSR Tag.
>   * As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB,
>   * path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest,
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 86737076101d4..52c847e490ee8 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -605,6 +605,7 @@ struct skb_shared_info {
>  	};
>  	unsigned int	gso_type;
>  	u32		tskey;
> +	u32		hsr_ptp;

skb_shared_info cannot easily be expanded.

This is too specific a use-case to warrant fields in every packet.

I'm not super familiar with High-availability Seamless Redundancy
(HSR). Perhaps you can use either an skb_extension. Or the skb->cb[]
field if this data is only needed within the HSR protocol logic, so
can be assured to not be overwritten by other users of the control
block.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 2/2] af_packet: Add port specific handling for HSR
  2026-02-04 11:24 ` [PATCH RFC net-next 2/2] af_packet: Add port specific handling for HSR Sebastian Andrzej Siewior
@ 2026-02-04 17:36   ` Willem de Bruijn
  2026-02-17 15:51     ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 23+ messages in thread
From: Willem de Bruijn @ 2026-02-04 17:36 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, netdev
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn, Sebastian Andrzej Siewior

Sebastian Andrzej Siewior wrote:
> linuxptp/ ptp4l uses a AF_PACKET with a RAW socket to send and receive
> PTP packets. Extend the interface with the ability to bind the socket to
> one of the two HSR ports and add a flag for sendmsg() to indicate that
> the packet already contains a HSR header.
> 
> Once PACKET_HSR_BIND_PORT is set, the socket will be bound to requested
> slave port. All incoming packets without a set port will be discarded.
> This limits receiving packet to PTP only packets. The packet will be
> forwarded to userland with the HSR header.
> 
> For control messages used by sendmsg(), PACKET_HSR_INFO is added with
> PACKET_HSR_INFO_HAS_HDR as the only option. This option sets
> HSR_SKB_INCLUDES_HEADER on the outgoing skb to indicate that the packet
> already contains a HSR header. This requires that the socket is bound to
> a specific HSR port so that the packet is sent only on one of the two
> ports.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  include/uapi/linux/if_packet.h |   9 ++++
>  net/packet/af_packet.c         | 103 +++++++++++++++++++++++++++++++++++++++++
>  net/packet/internal.h          |   1 +
>  3 files changed, 113 insertions(+)
> 
> diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
> index 6cd1d7a41dfb7..3443eeac8470e 100644
> --- a/include/uapi/linux/if_packet.h
> +++ b/include/uapi/linux/if_packet.h
> @@ -60,6 +60,7 @@ struct sockaddr_ll {
>  #define PACKET_FANOUT_DATA		22
>  #define PACKET_IGNORE_OUTGOING		23
>  #define PACKET_VNET_HDR_SZ		24
> +#define PACKET_HSR_BIND_PORT		25
>  
>  #define PACKET_FANOUT_HASH		0
>  #define PACKET_FANOUT_LB		1
> @@ -74,6 +75,14 @@ struct sockaddr_ll {
>  #define PACKET_FANOUT_FLAG_IGNORE_OUTGOING     0x4000
>  #define PACKET_FANOUT_FLAG_DEFRAG	0x8000
>  
> +/* For HSR, bind port */
> +#define PACKET_HSR_BIND_PORT_AB		0
> +#define PACKET_HSR_BIND_PORT_A		1
> +#define PACKET_HSR_BIND_PORT_B		2
> +/* HSR, CMSG */
> +#define PACKET_HSR_INFO			1
> +#define PACKET_HSR_INFO_HAS_HDR		1
> +
>  struct tpacket_stats {
>  	unsigned int	tp_packets;
>  	unsigned int	tp_drops;
> diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> index 494d628d10a51..cd7c4ad034bc5 100644
> --- a/net/packet/af_packet.c
> +++ b/net/packet/af_packet.c
> @@ -82,6 +82,7 @@
>  #include <linux/module.h>
>  #include <linux/init.h>
>  #include <linux/mutex.h>
> +#include <linux/if_hsr.h>
>  #include <linux/if_vlan.h>
>  #include <linux/virtio_net.h>
>  #include <linux/errqueue.h>
> @@ -1938,6 +1939,36 @@ static void packet_parse_headers(struct sk_buff *skb, struct socket *sock)
>  	skb_probe_transport_header(skb);
>  }
>  
> +static int packet_cmsg_send(struct msghdr *msg, struct packet_sock *po,
> +			    unsigned int *hsr_setting)
> +{
> +	struct cmsghdr *cmsg;
> +	int ret = -EINVAL;
> +	u32 val;
> +
> +	for_each_cmsghdr(cmsg, msg) {
> +		if (!CMSG_OK(msg, cmsg))
> +			goto out;
> +		if (cmsg->cmsg_level != SOL_PACKET)
> +			continue;
> +		if (cmsg->cmsg_type != PACKET_HSR_INFO)
> +			continue;
> +		if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
> +			goto out;
> +
> +		val = *(u32 *)CMSG_DATA(cmsg);
> +		if (val != PACKET_HSR_INFO_HAS_HDR)
> +			goto out;
> +		if (!po->hsr_bound_port)
> +			goto out;
> +
> +		*hsr_setting = HSR_SKB_INCLUDES_HEADER;
> +	}
> +	ret = 0;
> +out:
> +	return ret;
> +}
> +
>  /*
>   *	Output a raw packet to a device layer. This bypasses all the other
>   *	protocol layers and you must therefore supply it with a complete frame
> @@ -1947,6 +1978,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
>  			       size_t len)
>  {
>  	struct sock *sk = sock->sk;
> +	struct packet_sock *po = pkt_sk(sk);
>  	DECLARE_SOCKADDR(struct sockaddr_pkt *, saddr, msg->msg_name);
>  	struct sk_buff *skb = NULL;
>  	struct net_device *dev;
> @@ -1954,6 +1986,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
>  	__be16 proto = 0;
>  	int err;
>  	int extra_len = 0;
> +	u32 hsr_setting = 0;
>  
>  	/*
>  	 *	Get and verify the address.
> @@ -2044,6 +2077,9 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
>  		err = sock_cmsg_send(sk, msg, &sockc);
>  		if (unlikely(err))
>  			goto out_unlock;
> +		err = packet_cmsg_send(msg, po, &hsr_setting);
> +		if (unlikely(err))
> +			goto out_unlock;

packet_sendmsg_spkt is legacy. No need to extend that.

>  	}
>  
>  	skb->protocol = proto;
> @@ -2052,6 +2088,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
>  	skb->mark = sockc.mark;
>  	skb_set_delivery_type_by_clockid(skb, sockc.transmit_time, sk->sk_clockid);
>  	skb_setup_tx_timestamp(skb, &sockc);
> +	skb_shinfo(skb)->hsr_ptp = hsr_setting | po->hsr_bound_port;
>  
>  	if (unlikely(extra_len == 4))
>  		skb->no_fcs = 1;
> @@ -2131,6 +2168,13 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
>  	if (!net_eq(dev_net(dev), sock_net(sk)))
>  		goto drop;
>  
> +	if (po->hsr_bound_port) {
> +		struct skb_shared_info *si = skb_shinfo(skb);
> +
> +		if (po->hsr_bound_port != si->hsr_ptp)
> +			goto drop;
> +	}
> +

Similar to the high level comment to patch 1/2: this is quite a rare
use case, but this implementation imposes cost on every user. By
adding branches in the hot path, among others.

It is simply not scalable to extend core infra in this way for every
use case. The cross product of features is too great. We'll have to
find a way that is less HSR specific.

There are existing mechanisms for binding to a specific interface or
port, such as SO_BINDTOIFINDEX and packet bind().

>  	skb->dev = dev;
>  
>  	if (dev_has_header(dev)) {
> @@ -2260,6 +2304,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
>  	if (!net_eq(dev_net(dev), sock_net(sk)))
>  		goto drop;
>  
> +	if (po->hsr_bound_port) {
> +		struct skb_shared_info *si = skb_shinfo(skb);
> +
> +		if (po->hsr_bound_port != si->hsr_ptp)
> +			goto drop;
> +	}
> +
>  	if (dev_has_header(dev)) {
>  		if (sk->sk_type != SOCK_DGRAM)
>  			skb_push(skb, skb->data - skb_mac_header(skb));
> @@ -2731,6 +2782,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
>  	int len_sum = 0;
>  	int status = TP_STATUS_AVAILABLE;
>  	int hlen, tlen, copylen = 0;
> +	u32 hsr_setting = 0;
>  	long timeo;
>  
>  	mutex_lock(&po->pg_vec_lock);
> @@ -2775,6 +2827,10 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
>  		err = sock_cmsg_send(&po->sk, msg, &sockc);
>  		if (unlikely(err))
>  			goto out_put;
> +
> +		err = packet_cmsg_send(msg, po, &hsr_setting);
> +		if (unlikely(err))
> +			goto out_put;
>  	}
>  
>  	if (po->sk.sk_socket->type == SOCK_RAW)



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
  2026-02-04 11:24 [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Sebastian Andrzej Siewior
  2026-02-04 11:24 ` [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header Sebastian Andrzej Siewior
  2026-02-04 11:24 ` [PATCH RFC net-next 2/2] af_packet: Add port specific handling for HSR Sebastian Andrzej Siewior
@ 2026-02-16 16:10 ` Felix Maurer
  2026-02-16 16:19   ` Sebastian Andrzej Siewior
                     ` (2 more replies)
  2 siblings, 3 replies; 23+ messages in thread
From: Felix Maurer @ 2026-02-16 16:10 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn

Hi Sebastian,

I had to read quite a bit about PTP and how it's supposed to be handled
in HSR rings. I've got no experience with PTP in the real world, but
here we go.

On Wed, Feb 04, 2026 at 12:24:02PM +0100, Sebastian Andrzej Siewior wrote:
> I am trying to extend linuxptp to support PTP over a HSR network. The
> user space for linuxptp are still under discussion, the thread starts at
> 	https://lists.nwtime.org/sympa/arc/linuxptp-devel/2025-11/msg00013.html
>
> the posted patches are also available at git repository for convenience
> 	https://git.kernel.org/pub/scm/linux/kernel/git/bigeasy/linuxptp-hsr.git hsr_v2
>
> This is the kernel side of the changes. In short PTP over HSR sends its
> packets to multicast address and every node needs to forward the PTP
> packet (SYNC and FOLLOW-UP for instance) within the HSR ring.
> In order to achieve this, the HSR stack must not duplicate and forward
> the PTP packets as it would with other packets. The delay caused by the
> duplication and forwarding adds overhead which in turn makes the timing
> information within the PTP packet inaccurate.
>
> My current approach is to open the hsr0 device from userland and send
> and receive the PTP packets individually on both slave interfaces. I
> added additional hints to the af_packet interface, which is used by
> linuxptp, to be able send a packet on a specific interface (A or B) and
> also to have the information recorded for received packets.
> Additionally, the PTP-timestamps which arrive on the slave interface are
> forwarded to the hsr interface.

I agree with Willem that the changes are pretty invasive in core parts
of the stack for a pretty narrow use case. It got me thinking what would
already be supported at the moment without any changes in the kernel or
pretty small changes. For that, I see three parts:

1. Userspace needs to get the full HSR+PTP frames including the headers
   and including the rx port information.
     a) Userspace should have a way to _only_ receive HSR+PTP frames
        instead of all traffic on one of the ports.
2. We should not forward HSR+PTP frames in HSR interface to prevent
   creating inaccurate timing information.
3. Userspace needs a way to send packets a) over just port A or B of an
   HSR interface, that b) already include an HSR header and should
   therefore go mostly unmodified.

Is that about a correct summary?

If I understand your patch 2 correctly, you will be maintaining two
sockets in userspace (one bound to each of the ports A and B through the
HSR interface using PACKET_HSR_BIND_PORT). Binding through the HSR
interface to port A/B has the very special meaning of making a socket
only receive a very small subset of the packets, that is PTP traffic at
the moment. This seems like a somewhat hidden property of the bound
sockets and should at least be very explicit.

Is there a reason not to create and bind one socket directly to each of
the underlying slave interfaces, with a socket filter attached to only
receive the HSR+PTP packets you want? The rx port information is
inherent to the socket this way. I'm not sure if sending over the
sockets works out of the box, but if something is needed for that, I'd
assume it's less invasive and more generally usable.

We'd still need to address 2. for this to work, but blocking forwarding
for PTP could be done in hsr_forward and friends with a much simpler
patch.

The other thing that came to my mind: this sounds like XDP with AF_XDP
could be a solution that could be used already today; not so much
because of their speed but because you can program what goes to the
stack and what ends up in userspace. It fulfills 1) + a) directly, 2)
implicitly by not letting these frames enter the stack, and 3) directly.
But I also see that handling AF_XDP sockets in userspace is quite some
work to do if all you really need is to separate out some traffic.

Thanks,
   Felix


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
  2026-02-16 16:10 ` [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Felix Maurer
@ 2026-02-16 16:19   ` Sebastian Andrzej Siewior
  2026-02-16 16:25   ` Andrew Lunn
  2026-02-17 16:10   ` Sebastian Andrzej Siewior
  2 siblings, 0 replies; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-16 16:19 UTC (permalink / raw)
  To: Felix Maurer
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn

On 2026-02-16 17:10:38 [+0100], Felix Maurer wrote:
> Hi Sebastian,
Hi Felix,

> I had to read quite a bit about PTP and how it's supposed to be handled
> in HSR rings. I've got no experience with PTP in the real world, but
> here we go.

Thank you two. I will re-read the thread tomorrow and get back to both
of you.

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
  2026-02-16 16:10 ` [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Felix Maurer
  2026-02-16 16:19   ` Sebastian Andrzej Siewior
@ 2026-02-16 16:25   ` Andrew Lunn
  2026-02-17 16:14     ` Sebastian Andrzej Siewior
  2026-02-17 16:10   ` Sebastian Andrzej Siewior
  2 siblings, 1 reply; 23+ messages in thread
From: Andrew Lunn @ 2026-02-16 16:25 UTC (permalink / raw)
  To: Felix Maurer
  Cc: Sebastian Andrzej Siewior, netdev, Andrew Lunn, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran,
	Simon Horman, Willem de Bruijn

> Is there a reason not to create and bind one socket directly to each of
> the underlying slave interfaces, with a socket filter attached to only
> receive the HSR+PTP packets you want?

I don't know HSR too well. But what you are suggesting is what is used
when you have an 802.1 bridge on top of two or more
interfaces. ptp4linux is configured to open the lower interfaces of
the bridge and sends/receives frames out the ports as required. I
_think_ it only works in L2 mode, since the ports don't have IP
addresses of their own.

If HSR can be made to work in the same way, you might be able to avoid
all the invasive changes.

    Andrew

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-02-04 17:30   ` Willem de Bruijn
@ 2026-02-17 15:36     ` Sebastian Andrzej Siewior
  2026-03-04 14:58     ` Sebastian Andrzej Siewior
  1 sibling, 0 replies; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-17 15:36 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman

On 2026-02-04 12:30:47 [-0500], Willem de Bruijn wrote:
> > --- a/include/linux/skbuff.h
> > +++ b/include/linux/skbuff.h
> > @@ -605,6 +605,7 @@ struct skb_shared_info {
> >  	};
> >  	unsigned int	gso_type;
> >  	u32		tskey;
> > +	u32		hsr_ptp;
> 
> skb_shared_info cannot easily be expanded.
> 
> This is too specific a use-case to warrant fields in every packet.
> 
> I'm not super familiar with High-availability Seamless Redundancy
> (HSR). Perhaps you can use either an skb_extension. Or the skb->cb[]
> field if this data is only needed within the HSR protocol logic, so
> can be assured to not be overwritten by other users of the control
> block.

Okay, will look into this.

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 2/2] af_packet: Add port specific handling for HSR
  2026-02-04 17:36   ` Willem de Bruijn
@ 2026-02-17 15:51     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-17 15:51 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman

On 2026-02-04 12:36:36 [-0500], Willem de Bruijn wrote:
> > --- a/net/packet/af_packet.c
> > +++ b/net/packet/af_packet.c
> > @@ -2131,6 +2168,13 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
> >  	if (!net_eq(dev_net(dev), sock_net(sk)))
> >  		goto drop;
> >  
> > +	if (po->hsr_bound_port) {
> > +		struct skb_shared_info *si = skb_shinfo(skb);
> > +
> > +		if (po->hsr_bound_port != si->hsr_ptp)
> > +			goto drop;
> > +	}
> > +
> 
> Similar to the high level comment to patch 1/2: this is quite a rare
> use case, but this implementation imposes cost on every user. By
> adding branches in the hot path, among others.
> 
> It is simply not scalable to extend core infra in this way for every
> use case. The cross product of features is too great. We'll have to
> find a way that is less HSR specific.
> 
> There are existing mechanisms for binding to a specific interface or
> port, such as SO_BINDTOIFINDEX and packet bind().

Would a static_branch_unlikely() be okay to have it off by default and
only enable once there is at least one user doing it?

I do
   setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name))

which is probably the same thing. With this I get to the "hsr0" device.
The hsr device has two slave ports which are hidden from the user in
general and only copy gets passed. For PTP I need to know which (PTP)
packet was received on the individual port. This is purpose of it. So I
have one fd for port A and one fd port B. (+ timestamps).

For the RX side I could simply use that device directly instead of the
hsr device.
But for TX I need to send a PTP packet with system's HSR header
(including the HSR-sequence number). I don't know how to achieve this
without using the hsr device. And the packet must not be sent on both
ports (like it is usually the case) but only on one of the ports (either
A or B).

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
  2026-02-16 16:10 ` [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Felix Maurer
  2026-02-16 16:19   ` Sebastian Andrzej Siewior
  2026-02-16 16:25   ` Andrew Lunn
@ 2026-02-17 16:10   ` Sebastian Andrzej Siewior
  2026-02-18 19:28     ` Felix Maurer
  2 siblings, 1 reply; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-17 16:10 UTC (permalink / raw)
  To: Felix Maurer
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn

On 2026-02-16 17:10:38 [+0100], Felix Maurer wrote:
> Hi Sebastian,
Hi,

> I agree with Willem that the changes are pretty invasive in core parts
> of the stack for a pretty narrow use case. It got me thinking what would
> already be supported at the moment without any changes in the kernel or
> pretty small changes. For that, I see three parts:
> 
> 1. Userspace needs to get the full HSR+PTP frames including the headers
>    and including the rx port information.
>      a) Userspace should have a way to _only_ receive HSR+PTP frames
>         instead of all traffic on one of the ports.
> 2. We should not forward HSR+PTP frames in HSR interface to prevent
>    creating inaccurate timing information.
> 3. Userspace needs a way to send packets a) over just port A or B of an
>    HSR interface, that b) already include an HSR header and should
>    therefore go mostly unmodified.
> 
> Is that about a correct summary?

Yes. Point 3b needs to be extended by
  " + or does not contain a HSR/PRP header and requires one by the
  system."

> If I understand your patch 2 correctly, you will be maintaining two
> sockets in userspace (one bound to each of the ports A and B through the
> HSR interface using PACKET_HSR_BIND_PORT). Binding through the HSR
> interface to port A/B has the very special meaning of making a socket
> only receive a very small subset of the packets, that is PTP traffic at
> the moment. This seems like a somewhat hidden property of the bound
> sockets and should at least be very explicit.

Technically four sockets (two for A and two for B) but in general yes.
What you mean by hidden property/ very explicit? Document
PACKET_HSR_BIND_PORT in packet(7) or something else?

> Is there a reason not to create and bind one socket directly to each of
> the underlying slave interfaces, with a socket filter attached to only
> receive the HSR+PTP packets you want? The rx port information is
> inherent to the socket this way. I'm not sure if sending over the
> sockets works out of the box, but if something is needed for that, I'd
> assume it's less invasive and more generally usable.

This was v1. The missing part is sending a new packet and not forwarding
one. The specification mandates to use system's sequence number.

> We'd still need to address 2. for this to work, but blocking forwarding
> for PTP could be done in hsr_forward and friends with a much simpler
> patch.

Blocking forwarding is simple as it needs just to look at the ethernet
protocol and drop it if it is PTP. Here I additionally add some
hints to get the port right and the time stamp.

> The other thing that came to my mind: this sounds like XDP with AF_XDP
> could be a solution that could be used already today; not so much
> because of their speed but because you can program what goes to the
> stack and what ends up in userspace. It fulfills 1) + a) directly, 2)
> implicitly by not letting these frames enter the stack, and 3) directly.
> But I also see that handling AF_XDP sockets in userspace is quite some
> work to do if all you really need is to separate out some traffic.

Not forwarding PTP traffic needs to happen unconditionally and not to
wait until the system is up and has the software running. However if we
ignore this detail and can receive on interface A and send on interface
B over XDP and get timestamps right then we have the same as the packet
interface on the two eth devices. What is missing is sending with HSR/
PRP header.

> Thanks,
>    Felix

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
  2026-02-16 16:25   ` Andrew Lunn
@ 2026-02-17 16:14     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-17 16:14 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Felix Maurer, netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn

On 2026-02-16 17:25:33 [+0100], Andrew Lunn wrote:
> > Is there a reason not to create and bind one socket directly to each of
> > the underlying slave interfaces, with a socket filter attached to only
> > receive the HSR+PTP packets you want?
> 
> I don't know HSR too well. But what you are suggesting is what is used
> when you have an 802.1 bridge on top of two or more
> interfaces. ptp4linux is configured to open the lower interfaces of
> the bridge and sends/receives frames out the ports as required. I
> _think_ it only works in L2 mode, since the ports don't have IP
> addresses of their own.
> 
> If HSR can be made to work in the same way, you might be able to avoid
> all the invasive changes.

The missing point is that I need occasionally to send packet with system
HSR/ PRP header on a specific slave interface. Otherwise this is what I
had in my initial PoC version (this and dropping PTP packets early in the
HSR stack before they get forwarded).

>     Andrew

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
  2026-02-17 16:10   ` Sebastian Andrzej Siewior
@ 2026-02-18 19:28     ` Felix Maurer
  2026-02-18 21:53       ` Willem de Bruijn
  2026-02-24 11:24       ` Sebastian Andrzej Siewior
  0 siblings, 2 replies; 23+ messages in thread
From: Felix Maurer @ 2026-02-18 19:28 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn

On Tue, Feb 17, 2026 at 05:10:53PM +0100, Sebastian Andrzej Siewior wrote:
> On 2026-02-16 17:10:38 [+0100], Felix Maurer wrote:
> > I agree with Willem that the changes are pretty invasive in core parts
> > of the stack for a pretty narrow use case. It got me thinking what would
> > already be supported at the moment without any changes in the kernel or
> > pretty small changes. For that, I see three parts:
> >
> > 1. Userspace needs to get the full HSR+PTP frames including the headers
> >    and including the rx port information.
> >      a) Userspace should have a way to _only_ receive HSR+PTP frames
> >         instead of all traffic on one of the ports.
> > 2. We should not forward HSR+PTP frames in HSR interface to prevent
> >    creating inaccurate timing information.
> > 3. Userspace needs a way to send packets a) over just port A or B of an
> >    HSR interface, that b) already include an HSR header and should
> >    therefore go mostly unmodified.
> >
> > Is that about a correct summary?
>
> Yes. Point 3b needs to be extended by
>   " + or does not contain a HSR/PRP header and requires one by the
>   system."

Ah, I missed that! Thanks for pointing it out, that seems to be the
tricky part to me. Just be sure, you refer to the Pdelay_{Req,Resp}
messages? Or are there any other messages?

> > If I understand your patch 2 correctly, you will be maintaining two
> > sockets in userspace (one bound to each of the ports A and B through the
> > HSR interface using PACKET_HSR_BIND_PORT). Binding through the HSR
> > interface to port A/B has the very special meaning of making a socket
> > only receive a very small subset of the packets, that is PTP traffic at
> > the moment. This seems like a somewhat hidden property of the bound
> > sockets and should at least be very explicit.
>
> Technically four sockets (two for A and two for B) but in general yes.
> What you mean by hidden property/ very explicit? Document
> PACKET_HSR_BIND_PORT in packet(7) or something else?

Yes, at least that. Maybe also make it more clear in the name that this
kind of binding means that you will not receive all packets from this
port but just some (atm, PTP).

[...]
> > The other thing that came to my mind: this sounds like XDP with AF_XDP
> > could be a solution that could be used already today; not so much
> > because of their speed but because you can program what goes to the
> > stack and what ends up in userspace. It fulfills 1) + a) directly, 2)
> > implicitly by not letting these frames enter the stack, and 3) directly.
> > But I also see that handling AF_XDP sockets in userspace is quite some
> > work to do if all you really need is to separate out some traffic.
>
> Not forwarding PTP traffic needs to happen unconditionally and not to
> wait until the system is up and has the software running.

I agree that we should just do that in the kernel, no matter what else
we do to support PTP.

> However if we
> ignore this detail and can receive on interface A and send on interface
> B over XDP and get timestamps right then we have the same as the packet
> interface on the two eth devices. What is missing is sending with HSR/
> PRP header.

You wrote in another reply, and I agree with it, that sending with the
system HSR header and sequence number must go through the hsr device.
Frames that already have a header, such as Sync an FollowUp that are
forwarded, could just directly go through the slave interfaces.

I think the cases should be handled independently: to send a frame with
a full header (i.e., the forward case), we already have the AF_PACKET
socket on the slave interfaces as an option. For sending a frame just in
one direction in the HSR ring through the hsr interface, we have to come
up with something, but IMHO just for that.

I like the idea of putting the port hint in the ancillary data of the
message, but I'm not sure where to put in the skb then / how to pass it
to the hsr interface. Willem's suggestions are worth exploring I think.

Thanks,
   Felix


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
  2026-02-18 19:28     ` Felix Maurer
@ 2026-02-18 21:53       ` Willem de Bruijn
  2026-02-24 11:48         ` Sebastian Andrzej Siewior
  2026-02-24 11:24       ` Sebastian Andrzej Siewior
  1 sibling, 1 reply; 23+ messages in thread
From: Willem de Bruijn @ 2026-02-18 21:53 UTC (permalink / raw)
  To: Felix Maurer, Sebastian Andrzej Siewior
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn

Felix Maurer wrote:
> On Tue, Feb 17, 2026 at 05:10:53PM +0100, Sebastian Andrzej Siewior wrote:
> > On 2026-02-16 17:10:38 [+0100], Felix Maurer wrote:
> > > I agree with Willem that the changes are pretty invasive in core parts
> > > of the stack for a pretty narrow use case. It got me thinking what would
> > > already be supported at the moment without any changes in the kernel or
> > > pretty small changes. For that, I see three parts:
> > >
> > > 1. Userspace needs to get the full HSR+PTP frames including the headers
> > >    and including the rx port information.
> > >      a) Userspace should have a way to _only_ receive HSR+PTP frames
> > >         instead of all traffic on one of the ports.
> > > 2. We should not forward HSR+PTP frames in HSR interface to prevent
> > >    creating inaccurate timing information.
> > > 3. Userspace needs a way to send packets a) over just port A or B of an
> > >    HSR interface, that b) already include an HSR header and should
> > >    therefore go mostly unmodified.
> > >
> > > Is that about a correct summary?
> >
> > Yes. Point 3b needs to be extended by
> >   " + or does not contain a HSR/PRP header and requires one by the
> >   system."
> 
> Ah, I missed that! Thanks for pointing it out, that seems to be the
> tricky part to me. Just be sure, you refer to the Pdelay_{Req,Resp}
> messages? Or are there any other messages?
> 
> > > If I understand your patch 2 correctly, you will be maintaining two
> > > sockets in userspace (one bound to each of the ports A and B through the
> > > HSR interface using PACKET_HSR_BIND_PORT). Binding through the HSR
> > > interface to port A/B has the very special meaning of making a socket
> > > only receive a very small subset of the packets, that is PTP traffic at
> > > the moment. This seems like a somewhat hidden property of the bound
> > > sockets and should at least be very explicit.
> >
> > Technically four sockets (two for A and two for B) but in general yes.
> > What you mean by hidden property/ very explicit? Document
> > PACKET_HSR_BIND_PORT in packet(7) or something else?
> 
> Yes, at least that. Maybe also make it more clear in the name that this
> kind of binding means that you will not receive all packets from this
> port but just some (atm, PTP).
> 
> [...]
> > > The other thing that came to my mind: this sounds like XDP with AF_XDP
> > > could be a solution that could be used already today; not so much
> > > because of their speed but because you can program what goes to the
> > > stack and what ends up in userspace. It fulfills 1) + a) directly, 2)
> > > implicitly by not letting these frames enter the stack, and 3) directly.
> > > But I also see that handling AF_XDP sockets in userspace is quite some
> > > work to do if all you really need is to separate out some traffic.
> >
> > Not forwarding PTP traffic needs to happen unconditionally and not to
> > wait until the system is up and has the software running.
> 
> I agree that we should just do that in the kernel, no matter what else
> we do to support PTP.
> 
> > However if we
> > ignore this detail and can receive on interface A and send on interface
> > B over XDP and get timestamps right then we have the same as the packet
> > interface on the two eth devices. What is missing is sending with HSR/
> > PRP header.
> 
> You wrote in another reply, and I agree with it, that sending with the
> system HSR header and sequence number must go through the hsr device.
> Frames that already have a header, such as Sync an FollowUp that are
> forwarded, could just directly go through the slave interfaces.
> 
> I think the cases should be handled independently: to send a frame with
> a full header (i.e., the forward case), we already have the AF_PACKET
> socket on the slave interfaces as an option. For sending a frame just in
> one direction in the HSR ring through the hsr interface, we have to come
> up with something, but IMHO just for that.
> 
> I like the idea of putting the port hint in the ancillary data of the
> message, but I'm not sure where to put in the skb then / how to pass it
> to the hsr interface. Willem's suggestions are worth exploring I think.

Could you use existing SO_MARK? Optionally per packet with
sock_cmsg_send. And use that in hsr_forward_do if set.

Or perhaps skb->queue_mapping. For instance with tc BPF, see commit
74e31ca850c1 ("bpf: add skb->queue_mapping write access from tc
clsact").


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
  2026-02-18 19:28     ` Felix Maurer
  2026-02-18 21:53       ` Willem de Bruijn
@ 2026-02-24 11:24       ` Sebastian Andrzej Siewior
  1 sibling, 0 replies; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-24 11:24 UTC (permalink / raw)
  To: Felix Maurer
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman,
	Willem de Bruijn

On 2026-02-18 20:28:36 [+0100], Felix Maurer wrote:
> > Yes. Point 3b needs to be extended by
> >   " + or does not contain a HSR/PRP header and requires one by the
> >   system."
> 
> Ah, I missed that! Thanks for pointing it out, that seems to be the
> tricky part to me. Just be sure, you refer to the Pdelay_{Req,Resp}
> messages? Or are there any other messages?

These and the SYNC+FOLLOW_UP if the node is master.

> > > If I understand your patch 2 correctly, you will be maintaining two
> > > sockets in userspace (one bound to each of the ports A and B through the
> > > HSR interface using PACKET_HSR_BIND_PORT). Binding through the HSR
> > > interface to port A/B has the very special meaning of making a socket
> > > only receive a very small subset of the packets, that is PTP traffic at
> > > the moment. This seems like a somewhat hidden property of the bound
> > > sockets and should at least be very explicit.
> >
> > Technically four sockets (two for A and two for B) but in general yes.
> > What you mean by hidden property/ very explicit? Document
> > PACKET_HSR_BIND_PORT in packet(7) or something else?
> 
> Yes, at least that. Maybe also make it more clear in the name that this
> kind of binding means that you will not receive all packets from this
> port but just some (atm, PTP).

Right. That happens implicit because they are not tagged. Extending the
present documentation would be something I consider once we do align on
something.

> > However if we
> > ignore this detail and can receive on interface A and send on interface
> > B over XDP and get timestamps right then we have the same as the packet
> > interface on the two eth devices. What is missing is sending with HSR/
> > PRP header.
> 
> You wrote in another reply, and I agree with it, that sending with the
> system HSR header and sequence number must go through the hsr device.
> Frames that already have a header, such as Sync an FollowUp that are
> forwarded, could just directly go through the slave interfaces.
> 
> I think the cases should be handled independently: to send a frame with
> a full header (i.e., the forward case), we already have the AF_PACKET
> socket on the slave interfaces as an option. For sending a frame just in
> one direction in the HSR ring through the hsr interface, we have to come
> up with something, but IMHO just for that.
> 
> I like the idea of putting the port hint in the ancillary data of the
> message, but I'm not sure where to put in the skb then / how to pass it
> to the hsr interface. Willem's suggestions are worth exploring I think.

Good. I will try to come up with something. Willem had something, I will
look into this.

> Thanks,
>    Felix

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs
  2026-02-18 21:53       ` Willem de Bruijn
@ 2026-02-24 11:48         ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-02-24 11:48 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: Felix Maurer, netdev, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman

On 2026-02-18 16:53:23 [-0500], Willem de Bruijn wrote:
> > I like the idea of putting the port hint in the ancillary data of the
> > message, but I'm not sure where to put in the skb then / how to pass it
> > to the hsr interface. Willem's suggestions are worth exploring I think.
> 
> Could you use existing SO_MARK? Optionally per packet with
> sock_cmsg_send. And use that in hsr_forward_do if set.
> 
> Or perhaps skb->queue_mapping. For instance with tc BPF, see commit
> 74e31ca850c1 ("bpf: add skb->queue_mapping write access from tc
> clsact").

So the idea is to replace the custom marking from userland with SO_MARK.
If SO_MARK is not conflicting with a possible classifier/ firewall rule
then I shouldn't have a problem switching to it. The content would be
fix however for the PORT_A/ PORT_B setting.

Thanks.

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-02-04 17:30   ` Willem de Bruijn
  2026-02-17 15:36     ` Sebastian Andrzej Siewior
@ 2026-03-04 14:58     ` Sebastian Andrzej Siewior
  2026-03-04 15:56       ` Willem de Bruijn
  1 sibling, 1 reply; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-03-04 14:58 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman

On 2026-02-04 12:30:47 [-0500], Willem de Bruijn wrote:
> > --- a/include/linux/skbuff.h
> > +++ b/include/linux/skbuff.h
> > @@ -605,6 +605,7 @@ struct skb_shared_info {
> >  	};
> >  	unsigned int	gso_type;
> >  	u32		tskey;
> > +	u32		hsr_ptp;
> 
> skb_shared_info cannot easily be expanded.
> 
> This is too specific a use-case to warrant fields in every packet.
> 
> I'm not super familiar with High-availability Seamless Redundancy
> (HSR). Perhaps you can use either an skb_extension. Or the skb->cb[]
> field if this data is only needed within the HSR protocol logic, so
> can be assured to not be overwritten by other users of the control
> block.

skb->cb does not work because I need share it between the HSR stack
and AF_PACKET so it gets overwritten (as it is no meant to be shared
between layers).
I need actually three bits: HAVE_HEADER and PORT_NUMBER which 0-2.
Would it work if I add a :1 and :2 member to struct sk_buff into the
header group after unreadable? In my config there is a 6bit + 1 byte
hole. Worst case (all ifdefs enabled) it sums to 30 bits so I would have
just 2 left. Exceeding it by one bit in this case would extend create a
7bit + 1 byte hole and shift shifts tc_index + alloc_cpu. However there
is a two byte hole between alloc_cpu before csum which is removed then.

Would it be okay if I occupy three bits in sk_buff which look unused?

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-03-04 14:58     ` Sebastian Andrzej Siewior
@ 2026-03-04 15:56       ` Willem de Bruijn
  2026-03-04 16:12         ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 23+ messages in thread
From: Willem de Bruijn @ 2026-03-04 15:56 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, Willem de Bruijn
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman

Sebastian Andrzej Siewior wrote:
> On 2026-02-04 12:30:47 [-0500], Willem de Bruijn wrote:
> > > --- a/include/linux/skbuff.h
> > > +++ b/include/linux/skbuff.h
> > > @@ -605,6 +605,7 @@ struct skb_shared_info {
> > >  	};
> > >  	unsigned int	gso_type;
> > >  	u32		tskey;
> > > +	u32		hsr_ptp;
> > 
> > skb_shared_info cannot easily be expanded.
> > 
> > This is too specific a use-case to warrant fields in every packet.
> > 
> > I'm not super familiar with High-availability Seamless Redundancy
> > (HSR). Perhaps you can use either an skb_extension. Or the skb->cb[]
> > field if this data is only needed within the HSR protocol logic, so
> > can be assured to not be overwritten by other users of the control
> > block.
> 
> skb->cb does not work because I need share it between the HSR stack
> and AF_PACKET so it gets overwritten (as it is no meant to be shared
> between layers).
> I need actually three bits: HAVE_HEADER and PORT_NUMBER which 0-2.
> Would it work if I add a :1 and :2 member to struct sk_buff into the
> header group after unreadable? In my config there is a 6bit + 1 byte
> hole. Worst case (all ifdefs enabled) it sums to 30 bits so I would have
> just 2 left. Exceeding it by one bit in this case would extend create a
> 7bit + 1 byte hole and shift shifts tc_index + alloc_cpu. However there
> is a two byte hole between alloc_cpu before csum which is removed then.
> 
> Would it be okay if I occupy three bits in sk_buff which look unused?

Have you looked into using skb_extensions?

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-03-04 15:56       ` Willem de Bruijn
@ 2026-03-04 16:12         ` Sebastian Andrzej Siewior
  2026-03-04 23:48           ` Willem de Bruijn
  0 siblings, 1 reply; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-03-04 16:12 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman

On 2026-03-04 10:56:16 [-0500], Willem de Bruijn wrote:
> Sebastian Andrzej Siewior wrote:
> > Would it be okay if I occupy three bits in sk_buff which look unused?
> 
> Have you looked into using skb_extensions?

Yes. I would have allocate memory via __skb_ext_alloc() and attach it to
the skb via __skb_ext_set(). That would on receive and while sending
(via af_packet).
Looking at the current allocations as of skb_ext_type_len, they all need
a bit of memory, the smallest is mctp_flow with just a pointer the other
are a fair amount larger. For the three bits, I was hoping to avoid it.

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-03-04 16:12         ` Sebastian Andrzej Siewior
@ 2026-03-04 23:48           ` Willem de Bruijn
  2026-03-05  8:07             ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 23+ messages in thread
From: Willem de Bruijn @ 2026-03-04 23:48 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, Willem de Bruijn
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman

Sebastian Andrzej Siewior wrote:
> On 2026-03-04 10:56:16 [-0500], Willem de Bruijn wrote:
> > Sebastian Andrzej Siewior wrote:
> > > Would it be okay if I occupy three bits in sk_buff which look unused?
> > 
> > Have you looked into using skb_extensions?
> 
> Yes. I would have allocate memory via __skb_ext_alloc() and attach it to
> the skb via __skb_ext_set(). That would on receive and while sending
> (via af_packet).
> Looking at the current allocations as of skb_ext_type_len, they all need
> a bit of memory, the smallest is mctp_flow with just a pointer the other
> are a fair amount larger. For the three bits, I was hoping to avoid it.

But this is not a performance sensitive path, right? Nor is it very
complicated to add?

I understand your preference. It's just that if every protocol and
feature, let alone their cross-product, adds a few bits to struct
sk_buff, it grows to become unmangeable. A classic tragedy of the
commons. For this reason pushback is common.

Devil's advocate, an alternative would be to add a few bits, then
maybe union them so that other users can use the same bits as long
as their code does not overlaps. This quickly becomes hard to analyze
for correctness. In a sense skb extensions resolved some of this.

That said, happy to hear other opinions or implementation concerns
that I may have underappreciated, e.g., it may not address the HSR
specific needs for AF_PACKET.



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-03-04 23:48           ` Willem de Bruijn
@ 2026-03-05  8:07             ` Sebastian Andrzej Siewior
  2026-03-05 14:41               ` Jakub Kicinski
  0 siblings, 1 reply; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-03-05  8:07 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: netdev, Andrew Lunn, David S . Miller, Eric Dumazet, Felix Maurer,
	Jakub Kicinski, Paolo Abeni, Richard Cochran, Simon Horman

On 2026-03-04 18:48:19 [-0500], Willem de Bruijn wrote:
> Sebastian Andrzej Siewior wrote:
> > On 2026-03-04 10:56:16 [-0500], Willem de Bruijn wrote:
> > > Sebastian Andrzej Siewior wrote:
> > > > Would it be okay if I occupy three bits in sk_buff which look unused?
> > > 
> > > Have you looked into using skb_extensions?
> > 
> > Yes. I would have allocate memory via __skb_ext_alloc() and attach it to
> > the skb via __skb_ext_set(). That would on receive and while sending
> > (via af_packet).
> > Looking at the current allocations as of skb_ext_type_len, they all need
> > a bit of memory, the smallest is mctp_flow with just a pointer the other
> > are a fair amount larger. For the three bits, I was hoping to avoid it.
> 
> But this is not a performance sensitive path, right? Nor is it very
> complicated to add?

The non-PTP packets are not affected by this and the PTP packets need to
processed in userland before they can be forwarded. So probably not.

> I understand your preference. It's just that if every protocol and
> feature, let alone their cross-product, adds a few bits to struct
> sk_buff, it grows to become unmangeable. A classic tragedy of the
> commons. For this reason pushback is common.
> 
> Devil's advocate, an alternative would be to add a few bits, then
> maybe union them so that other users can use the same bits as long
> as their code does not overlaps. This quickly becomes hard to analyze
> for correctness. In a sense skb extensions resolved some of this.
> 
> That said, happy to hear other opinions or implementation concerns
> that I may have underappreciated, e.g., it may not address the HSR
> specific needs for AF_PACKET.

Let me redo this with the skb-extension variant. If this somehow becomes
later a concern we could have a talk with new arguments. Now given what
I wrote above all I have is that it is simpler.

Thank you for your comments.

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-03-05  8:07             ` Sebastian Andrzej Siewior
@ 2026-03-05 14:41               ` Jakub Kicinski
  2026-03-05 15:05                 ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 23+ messages in thread
From: Jakub Kicinski @ 2026-03-05 14:41 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Willem de Bruijn, netdev, Andrew Lunn, David S . Miller,
	Eric Dumazet, Felix Maurer, Paolo Abeni, Richard Cochran,
	Simon Horman

On Thu, 5 Mar 2026 09:07:31 +0100 Sebastian Andrzej Siewior wrote:
> Let me redo this with the skb-extension variant. 

Expect opposition. HSR is an Orphan full of trouble already and what
you're trying to do very much feels like a one off hack to me.
Can't the Tx path be done with an egress redirect on the HSR upper?

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header
  2026-03-05 14:41               ` Jakub Kicinski
@ 2026-03-05 15:05                 ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 23+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-03-05 15:05 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Willem de Bruijn, netdev, Andrew Lunn, David S . Miller,
	Eric Dumazet, Felix Maurer, Paolo Abeni, Richard Cochran,
	Simon Horman

On 2026-03-05 06:41:11 [-0800], Jakub Kicinski wrote:
> On Thu, 5 Mar 2026 09:07:31 +0100 Sebastian Andrzej Siewior wrote:
> > Let me redo this with the skb-extension variant. 
> 
> Expect opposition. HSR is an Orphan full of trouble already and what

it might be an orphan but the handling of sequence numbers reworked
recently.

> you're trying to do very much feels like a one off hack to me.

It specific support for PTP support over HSR/PRP, yes. So nothing else
benefits from it.

> Can't the Tx path be done with an egress redirect on the HSR upper?

For the RX side I need to know which port received the PTP packet and
forward this information to userland along with a possible PTP
timestamp and ensure the HSR stack does not forward the packet on the
other port.

For the TX side I need to be able to send the packet on one of the two
ports, be able to let the HSR stack create a HSR header or use the
provided header which should not be used for any checks (de-duplication
and so on) while sending it. Here is also the possible PTP timestamp.

If it wouldn't be for the HSR frame header on the TX side where the
packets originate from the node (sending PTP SYNC, PDELAY_* and so on)
then I could directly attach to the two slave devices.

Sebastian

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2026-03-05 15:06 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-04 11:24 [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Sebastian Andrzej Siewior
2026-02-04 11:24 ` [PATCH RFC net-next 1/2] hsr: Allow to send a specific port and with HSR header Sebastian Andrzej Siewior
2026-02-04 17:30   ` Willem de Bruijn
2026-02-17 15:36     ` Sebastian Andrzej Siewior
2026-03-04 14:58     ` Sebastian Andrzej Siewior
2026-03-04 15:56       ` Willem de Bruijn
2026-03-04 16:12         ` Sebastian Andrzej Siewior
2026-03-04 23:48           ` Willem de Bruijn
2026-03-05  8:07             ` Sebastian Andrzej Siewior
2026-03-05 14:41               ` Jakub Kicinski
2026-03-05 15:05                 ` Sebastian Andrzej Siewior
2026-02-04 11:24 ` [PATCH RFC net-next 2/2] af_packet: Add port specific handling for HSR Sebastian Andrzej Siewior
2026-02-04 17:36   ` Willem de Bruijn
2026-02-17 15:51     ` Sebastian Andrzej Siewior
2026-02-16 16:10 ` [PATCH RFC net-next 0/2] hsr: Add additional info to send/ receive skbs Felix Maurer
2026-02-16 16:19   ` Sebastian Andrzej Siewior
2026-02-16 16:25   ` Andrew Lunn
2026-02-17 16:14     ` Sebastian Andrzej Siewior
2026-02-17 16:10   ` Sebastian Andrzej Siewior
2026-02-18 19:28     ` Felix Maurer
2026-02-18 21:53       ` Willem de Bruijn
2026-02-24 11:48         ` Sebastian Andrzej Siewior
2026-02-24 11:24       ` Sebastian Andrzej Siewior

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox