when receiving the PTP message with timestamp inserted in
the PTP header, the udp checksum is zero, which is permitted
in IPv6 by enabling the socket option.

Signed-off-by: roger luo <[email protected]>
---
 config.c            |  1 +
 configs/default.cfg |  1 +
 ptp4l.8             |  5 +++++
 udp6.c              | 20 ++++++++++++++++----
 4 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/config.c b/config.c
index 7914ba4..e9477b4 100644
--- a/config.c
+++ b/config.c
@@ -257,6 +257,7 @@ struct config_item config_tab[] = {
        GLOB_ITEM_INT("summary_interval", 0, INT_MIN, INT_MAX),
        PORT_ITEM_INT("syncReceiptTimeout", 0, 0, UINT8_MAX),
        GLOB_ITEM_INT("tc_spanning_tree", 0, 0, 1),
+       GLOB_ITEM_INT("udp6_checksum_disabled", 0, 0, 1),
        GLOB_ITEM_INT("timeSource", INTERNAL_OSCILLATOR, 0x10, 0xfe),
        GLOB_ITEM_ENU("time_stamping", TS_HARDWARE, timestamping_enu),
        PORT_ITEM_INT("transportSpecific", 0, 0, 0x0F),
diff --git a/configs/default.cfg b/configs/default.cfg
index c5a8b57..e8908e6 100644
--- a/configs/default.cfg
+++ b/configs/default.cfg
@@ -42,6 +42,7 @@ hybrid_e2e            0
 inhibit_multicast_service      0
 net_sync_monitor       0
 tc_spanning_tree       0
+udp6_checksum_disabled 0
 tx_timestamp_timeout   1
 unicast_listen         0
 unicast_master_table   0
diff --git a/ptp4l.8 b/ptp4l.8
index 10c5c2f..66f02d4 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -442,6 +442,11 @@ field of Announce messages that pass through the switch.  
Enabling
 this option ensures that PTP message loops never form, provided the
 switches all implement this option together with the BMCA.
 .TP
+.B udp6_checksum_disabled
+When network_transport is UDPv6, the PTP message inserted by the
+timestamp is used with a zero UDP checksum, disabling udp6 checksum
+ensures that the PTP message can be received successfully.
+.TP
 .B tx_timestamp_timeout
 The number of milliseconds to poll waiting for the tx time stamp from the 
kernel
 when a message has recently been sent.
diff --git a/udp6.c b/udp6.c
index d3c9c86..a4c09db 100644
--- a/udp6.c
+++ b/udp6.c
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <linux/udp.h>
 #include <unistd.h>
 
 #include "address.h"
@@ -97,7 +98,7 @@ static int udp6_close(struct transport *t, struct fdarray 
*fda)
 }
 
 static int open_socket_ipv6(const char *name, struct in6_addr mc_addr[2], 
short port,
-                           int *interface_index, int hop_limit)
+                           int *interface_index, int hop_limit, int 
udp_no_check6)
 {
        struct sockaddr_in6 addr;
        int fd, index, on = 1;
@@ -122,6 +123,16 @@ static int open_socket_ipv6(const char *name, struct 
in6_addr mc_addr[2], short
                pr_err("setsockopt SO_REUSEADDR failed: %m");
                goto no_option;
        }
+       if (udp_no_check6 == 1) {
+               if (setsockopt(fd, IPPROTO_UDP, UDP_NO_CHECK6_RX, &on, 
sizeof(on))) {
+                       pr_err("setsockopt UDP_NO_CHECK6_RX failed: %m");
+                       goto no_option;
+               }
+               if (setsockopt(fd, IPPROTO_UDP, UDP_NO_CHECK6_TX, &on, 
sizeof(on))) {
+                       pr_err("setsockopt UDP_NO_CHECK6_TX failed: %m");
+                       goto no_option;
+               }
+       }
        if (bind(fd, (struct sockaddr *) &addr, sizeof(addr))) {
                pr_err("bind failed: %m");
                goto no_option;
@@ -164,9 +175,10 @@ static int udp6_open(struct transport *t, struct interface 
*iface,
 {
        struct udp6 *udp6 = container_of(t, struct udp6, t);
        uint8_t event_dscp, general_dscp;
-       int efd, gfd, hop_limit;
+       int efd, gfd, hop_limit, udp_no_check6;
        char *name = iface->name;
 
+       udp_no_check6 = config_get_int(t->cfg, name, "udp6_checksum_disabled");
        hop_limit = config_get_int(t->cfg, name, "udp_ttl");
        udp6->mac.len = 0;
        sk_interface_macaddr(name, &udp6->mac);
@@ -182,11 +194,11 @@ static int udp6_open(struct transport *t, struct 
interface *iface,
        if (1 != inet_pton(AF_INET6, PTP_PDELAY_MCAST_IP6ADDR, 
&mc6_addr[MC_PDELAY]))
                return -1;
 
-       efd = open_socket_ipv6(name, mc6_addr, EVENT_PORT, &udp6->index, 
hop_limit);
+       efd = open_socket_ipv6(name, mc6_addr, EVENT_PORT, &udp6->index, 
hop_limit, udp_no_check6);
        if (efd < 0)
                goto no_event;
 
-       gfd = open_socket_ipv6(name, mc6_addr, GENERAL_PORT, &udp6->index, 
hop_limit);
+       gfd = open_socket_ipv6(name, mc6_addr, GENERAL_PORT, &udp6->index, 
hop_limit, udp_no_check6);
        if (gfd < 0)
                goto no_general;
 
-- 
2.17.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linuxptp-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to