netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* RFC: PTP Boundary Clock over UDPv4/UDPv6 on Linux bridge
@ 2021-11-16 10:19 Kurt Kanzenbach
  2021-11-16 10:21 ` Vladimir Oltean
  0 siblings, 1 reply; 3+ messages in thread
From: Kurt Kanzenbach @ 2021-11-16 10:19 UTC (permalink / raw)
  To: netdev, bridge
  Cc: Richard Cochran, Vladimir Oltean, Roopa Prabhu, Nikolay Aleksandrov

[-- Attachment #1: Type: text/plain, Size: 3440 bytes --]

Hi all,

I'm currently trying to setup a PTP Boundary Clock over UDPv4 or UDPv6
on top of a switch using a Linux bridge. It works fine using PTP Layer 2
transport, but not for UDP. I'm wondering whether this is supported
using Linux or if I'm doing something wrong.

My setup looks like this:

Bridge (DSA):

|$ ip link set eth0 up
|$ ip link set lan0 up
|$ ip link set lan1 up
|$ ip link add name br0 type bridge
|$ ip link set dev lan0 master br0
|$ ip link set dev lan1 master br0
|$ ip link set br0 up
|$ dhclient br0

PTP:

|$ ptp4l -4 -i lan0 -i lan1 --tx_timestamp_timeout=40 -m

It seems like ptp4l cannot receive any PTP messages. Tx works fine.

The following hack solves the problem for me. However, I'm not sure
whether that's the correct approach or not. Any opinions, ideas,
comments?

Thanks,
Kurt

|From 2e8b429b3ebabda8e81693b9704dbe5e5205ab09 Mon Sep 17 00:00:00 2001
|From: Kurt Kanzenbach <kurt@linutronix.de>
|Date: Wed, 4 Aug 2021 09:33:12 +0200
|Subject: [PATCH] net: bridge: input: Handle PTP over UDPv4 and UDPv6
|
|PTP is considered management traffic. A time aware switch should intercept all
|PTP messages and handle them accordingly. The corresponding Linux setup is like
|this:
|
|         +-- br0 --+
|        / /   |     \
|       / /    |      \
|      /  |    |     / \
|     /   |    |    /   \
|   swp0 swp1 swp2 swp3 swp4
|
|ptp4l runs on all individual switch ports and needs full control over sending
|and receiving messages on these ports.
|
|However, the bridge code treats PTP messages over UDP transport as regular IP
|messages and forwards them to br0. This way, the running ptp4l instances cannot
|receive these frames on the individual switch port interfaces.
|
|Fix it by intercepting PTP UDP traffic in the bridge code and pass them to the
|regular network processing.
|
|Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
|---
| net/bridge/br_input.c | 13 +++++++++++++
| 1 file changed, 13 insertions(+)
|
|diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
|index b50382f957c1..4e12be70a003 100644
|--- a/net/bridge/br_input.c
|+++ b/net/bridge/br_input.c
|@@ -271,6 +271,13 @@ static int br_process_frame_type(struct net_bridge_port *p,
| 	return 0;
| }
| 
|+static const unsigned char ptp_ip_destinations[][ETH_ALEN] = {
|+	{ 0x01, 0x00, 0x5e, 0x00, 0x01, 0x81 }, /* IPv4 PTP */
|+	{ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x6b }, /* IPv4 P2P */
|+	{ 0x33, 0x33, 0x00, 0x00, 0x01, 0x81 }, /* IPv6 PTP */
|+	{ 0x33, 0x33, 0x00, 0x00, 0x00, 0x6b }, /* IPv6 P2P */
|+};
|+
| /*
|  * Return NULL if skb is handled
|  * note: already called with rcu_read_lock
|@@ -280,6 +287,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
| 	struct net_bridge_port *p;
| 	struct sk_buff *skb = *pskb;
| 	const unsigned char *dest = eth_hdr(skb)->h_dest;
|+	int i;
| 
| 	if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
| 		return RX_HANDLER_PASS;
|@@ -360,6 +368,11 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
| 	if (unlikely(br_process_frame_type(p, skb)))
| 		return RX_HANDLER_PASS;
| 
|+	/* Check for PTP over UDPv4 or UDPv6. */
|+	for (i = 0; i < ARRAY_SIZE(ptp_ip_destinations); ++i)
|+		if (ether_addr_equal(ptp_ip_destinations[i], dest))
|+			return RX_HANDLER_PASS;
|+
| forward:
| 	switch (p->state) {
| 	case BR_STATE_FORWARDING:
|-- 
|2.30.2


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 861 bytes --]

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

* Re: RFC: PTP Boundary Clock over UDPv4/UDPv6 on Linux bridge
  2021-11-16 10:19 RFC: PTP Boundary Clock over UDPv4/UDPv6 on Linux bridge Kurt Kanzenbach
@ 2021-11-16 10:21 ` Vladimir Oltean
  2021-11-16 11:02   ` Kurt Kanzenbach
  0 siblings, 1 reply; 3+ messages in thread
From: Vladimir Oltean @ 2021-11-16 10:21 UTC (permalink / raw)
  To: Kurt Kanzenbach
  Cc: netdev, bridge, Richard Cochran, Roopa Prabhu, Nikolay Aleksandrov

On Tue, Nov 16, 2021 at 11:19:24AM +0100, Kurt Kanzenbach wrote:
> Hi all,
> 
> I'm currently trying to setup a PTP Boundary Clock over UDPv4 or UDPv6
> on top of a switch using a Linux bridge. It works fine using PTP Layer 2
> transport, but not for UDP. I'm wondering whether this is supported
> using Linux or if I'm doing something wrong.
> 
> My setup looks like this:
> 
> Bridge (DSA):
> 
> |$ ip link set eth0 up
> |$ ip link set lan0 up
> |$ ip link set lan1 up
> |$ ip link add name br0 type bridge
> |$ ip link set dev lan0 master br0
> |$ ip link set dev lan1 master br0
> |$ ip link set br0 up
> |$ dhclient br0
> 
> PTP:
> 
> |$ ptp4l -4 -i lan0 -i lan1 --tx_timestamp_timeout=40 -m
> 
> It seems like ptp4l cannot receive any PTP messages. Tx works fine.
> 
> The following hack solves the problem for me. However, I'm not sure
> whether that's the correct approach or not. Any opinions, ideas,
> comments?
> 
> Thanks,
> Kurt
> 
> |From 2e8b429b3ebabda8e81693b9704dbe5e5205ab09 Mon Sep 17 00:00:00 2001
> |From: Kurt Kanzenbach <kurt@linutronix.de>
> |Date: Wed, 4 Aug 2021 09:33:12 +0200
> |Subject: [PATCH] net: bridge: input: Handle PTP over UDPv4 and UDPv6
> |
> |PTP is considered management traffic. A time aware switch should intercept all
> |PTP messages and handle them accordingly. The corresponding Linux setup is like
> |this:
> |
> |         +-- br0 --+
> |        / /   |     \
> |       / /    |      \
> |      /  |    |     / \
> |     /   |    |    /   \
> |   swp0 swp1 swp2 swp3 swp4
> |
> |ptp4l runs on all individual switch ports and needs full control over sending
> |and receiving messages on these ports.
> |
> |However, the bridge code treats PTP messages over UDP transport as regular IP
> |messages and forwards them to br0. This way, the running ptp4l instances cannot
> |receive these frames on the individual switch port interfaces.
> |
> |Fix it by intercepting PTP UDP traffic in the bridge code and pass them to the
> |regular network processing.
> |
> |Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
> |---
> | net/bridge/br_input.c | 13 +++++++++++++
> | 1 file changed, 13 insertions(+)
> |
> |diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
> |index b50382f957c1..4e12be70a003 100644
> |--- a/net/bridge/br_input.c
> |+++ b/net/bridge/br_input.c
> |@@ -271,6 +271,13 @@ static int br_process_frame_type(struct net_bridge_port *p,
> | 	return 0;
> | }
> | 
> |+static const unsigned char ptp_ip_destinations[][ETH_ALEN] = {
> |+	{ 0x01, 0x00, 0x5e, 0x00, 0x01, 0x81 }, /* IPv4 PTP */
> |+	{ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x6b }, /* IPv4 P2P */
> |+	{ 0x33, 0x33, 0x00, 0x00, 0x01, 0x81 }, /* IPv6 PTP */
> |+	{ 0x33, 0x33, 0x00, 0x00, 0x00, 0x6b }, /* IPv6 P2P */
> |+};
> |+
> | /*
> |  * Return NULL if skb is handled
> |  * note: already called with rcu_read_lock
> |@@ -280,6 +287,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
> | 	struct net_bridge_port *p;
> | 	struct sk_buff *skb = *pskb;
> | 	const unsigned char *dest = eth_hdr(skb)->h_dest;
> |+	int i;
> | 
> | 	if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
> | 		return RX_HANDLER_PASS;
> |@@ -360,6 +368,11 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
> | 	if (unlikely(br_process_frame_type(p, skb)))
> | 		return RX_HANDLER_PASS;
> | 
> |+	/* Check for PTP over UDPv4 or UDPv6. */
> |+	for (i = 0; i < ARRAY_SIZE(ptp_ip_destinations); ++i)
> |+		if (ether_addr_equal(ptp_ip_destinations[i], dest))
> |+			return RX_HANDLER_PASS;
> |+
> | forward:
> | 	switch (p->state) {
> | 	case BR_STATE_FORWARDING:
> |-- 
> |2.30.2
>

This should do the trick as well?

/sbin/ebtables --table broute --append BROUTING --protocol 0x88F7 --jump DROP

/sbin/ebtables --table broute --append BROUTING --protocol 0x0800 --ip-protocol udp --ip-destination-port 320 --jump DROP
/sbin/ebtables --table broute --append BROUTING --protocol 0x0800 --ip-protocol udp --ip-destination-port 319 --jump DROP

/sbin/ebtables --table broute --append BROUTING --protocol 0x86DD --ip6-protocol udp --ip6-destination-port 320 --jump DROP
/sbin/ebtables --table broute --append BROUTING --protocol 0x86DD --ip6-protocol udp --ip6-destination-port 319 --jump DROP

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

* Re: RFC: PTP Boundary Clock over UDPv4/UDPv6 on Linux bridge
  2021-11-16 10:21 ` Vladimir Oltean
@ 2021-11-16 11:02   ` Kurt Kanzenbach
  0 siblings, 0 replies; 3+ messages in thread
From: Kurt Kanzenbach @ 2021-11-16 11:02 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, bridge, Richard Cochran, Roopa Prabhu, Nikolay Aleksandrov

[-- Attachment #1: Type: text/plain, Size: 738 bytes --]

On Tue Nov 16 2021, Vladimir Oltean wrote:
> This should do the trick as well?
>
> /sbin/ebtables --table broute --append BROUTING --protocol 0x88F7 --jump DROP
>
> /sbin/ebtables --table broute --append BROUTING --protocol 0x0800 --ip-protocol udp --ip-destination-port 320 --jump DROP
> /sbin/ebtables --table broute --append BROUTING --protocol 0x0800 --ip-protocol udp --ip-destination-port 319 --jump DROP
>
> /sbin/ebtables --table broute --append BROUTING --protocol 0x86DD --ip6-protocol udp --ip6-destination-port 320 --jump DROP
> /sbin/ebtables --table broute --append BROUTING --protocol 0x86DD --ip6-protocol udp --ip6-destination-port 319 --jump DROP

After quick test, indeed it does. Thanks, problem solved.

Thanks,
Kurt

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 861 bytes --]

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

end of thread, other threads:[~2021-11-16 11:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-16 10:19 RFC: PTP Boundary Clock over UDPv4/UDPv6 on Linux bridge Kurt Kanzenbach
2021-11-16 10:21 ` Vladimir Oltean
2021-11-16 11:02   ` Kurt Kanzenbach

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).