From: Ilya Orazov <ilordas...@gmail.com>

Added adv_rx_filter config that allows to send SIOCSHWTSTAMP ioctl with
HWTSTAMP_FILTER_PTP_XXX_SYNC or HWTSTAMP_FILTER_PTP_XXX_DELAY_REQ
rx filters based on whether the Device is Slave or Master respectively.
This Feature is added for all transport levels.

I’m using Ethernet controller with PTP support, which requires to
determine which PTP packet on Rx it must timestamp: SYNC or DELAY_REQ
packets based on whether the device is Slave or Masterrespectively.
Unfortunately, I’ve found out that ptp4l can’t send SIOCSHWTSTAMP ioctl
with HWTSTAMP_FILTER_PTP_XXX_SYNC or HWTSTAMP_FILTER_PTP_XXX_DELAY_REQ
rx filters, and sends only EVENT rx filters to device driver.

Device driver can only get info about the current PTP port state
from ptp4l, because it doesn’t have direct access to it.
I assumed, if these filters are defined in Kernel, they might be used in
ptp4l utility to fix this. So I added adv_rx_filter config that allows
to send SIOCSHWTSTAMP ioctl with HWTSTAMP_FILTER_PTP_XXX_SYNC or
HWTSTAMP_FILTER_PTP_XXX_DELAY_REQ rx filters for all transport levels.

Signed-off-by: Ilya Orazov <ilordas...@gmail.com>
---
 config.c            |  1 +
 port.c              | 17 ++++++++++++++
 ptp4l.8             |  8 +++++++
 ptp4l.c             |  1 +
 raw.c               | 13 +++++++++++
 sk.c                | 56 ++++++++++++++++++++++++++++++++++++++++-----
 sk.h                | 15 ++++++++++++
 transport.c         |  7 ++++++
 transport.h         |  5 ++++
 transport_private.h |  3 +++
 udp.c               | 14 ++++++++++++
 udp6.c              | 14 ++++++++++++
 12 files changed, 148 insertions(+), 6 deletions(-)

diff --git a/config.c b/config.c
index b104f1b..642b78c 100644
--- a/config.c
+++ b/config.c
@@ -268,6 +268,7 @@ struct config_item config_tab[] = {
        PORT_ITEM_INT("G.8275.portDS.localPriority", 128, 1, UINT8_MAX),
        GLOB_ITEM_INT("gmCapable", 1, 0, 1),
        GLOB_ITEM_ENU("hwts_filter", HWTS_FILTER_NORMAL, hwts_filter_enu),
+       GLOB_ITEM_INT("adv_rx_filter", 0, 0, 1),
        PORT_ITEM_INT("hybrid_e2e", 0, 0, 1),
        PORT_ITEM_INT("ignore_source_id", 0, 0, 1),
        PORT_ITEM_INT("ignore_transport_specific", 0, 0, 1),
diff --git a/port.c b/port.c
index 5803cd3..2376925 100644
--- a/port.c
+++ b/port.c
@@ -3526,6 +3526,23 @@ int port_state_update(struct port *p, enum fsm_event 
event, int mdiff)
                p->unicast_state_dirty = true;
        }
        if (next != p->state) {
+               if (sk_adv_rx_filter == 1) {
+                       pr_debug("port state update prev %d next %d", p->state,
+                                next);
+
+                       if ((next == PS_MASTER) || (next == PS_GRAND_MASTER))
+                               transport_update_rx_filter(p->trp, p->iface,
+                                                          &p->fda,
+                                                          p->timestamping,
+                                                          true);
+
+                       if (next == PS_UNCALIBRATED)
+                               transport_update_rx_filter(p->trp, p->iface,
+                                                          &p->fda,
+                                                          p->timestamping,
+                                                          false);
+               }
+
                port_show_transition(p, next, event);
                p->state = next;
                port_notify_event(p, NOTIFY_PORT_STATE);
diff --git a/ptp4l.8 b/ptp4l.8
index 40c66c2..9d838eb 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -142,6 +142,14 @@ See UNICAST DISCOVERY OPTIONS, below.
 
 .SH PORT OPTIONS
 
+.TP
+.B adv_rx_filter
+Enable support of HWTSTAMP_FILTER_PTP_XX_SYNC and 
HWTSTAMP_FILTER_PTP_XX_DELAY_REQ.
+Some Ethernet controllers doesn't support PTP event packets,
+thus they must be provided with correct rx_filter for timestamping required 
packets
+(SYNC or DELAY_REQ) depends on whether it's Slave or Master respectively.
+The default is 0 or disabled.
+
 .TP
 .B announceReceiptTimeout
 The number of missed Announce messages before the last Announce messages
diff --git a/ptp4l.c b/ptp4l.c
index c61175b..8f9531a 100644
--- a/ptp4l.c
+++ b/ptp4l.c
@@ -191,6 +191,7 @@ int main(int argc, char *argv[])
        sk_check_fupsync = config_get_int(cfg, NULL, "check_fup_sync");
        sk_tx_timeout = config_get_int(cfg, NULL, "tx_timestamp_timeout");
        sk_hwts_filter_mode = config_get_int(cfg, NULL, "hwts_filter");
+       sk_adv_rx_filter = config_get_int(cfg, NULL, "adv_rx_filter");
 
        if (config_get_int(cfg, NULL, "clock_servo") == CLOCK_SERVO_NTPSHM) {
                config_set_int(cfg, "kernel_leap", 0);
diff --git a/raw.c b/raw.c
index 1b978f0..7af3b2a 100644
--- a/raw.c
+++ b/raw.c
@@ -363,6 +363,18 @@ no_mac:
        return -1;
 }
 
+static int raw_update_rx_filter(struct interface *iface, struct fdarray *fda,
+                               enum timestamp_type ts_type, bool is_master)
+{
+       int err;
+       const char *name;
+
+       name = interface_label(iface);
+       err = sk_ts_update_rx_filter(fda->fd[FD_EVENT], name, ts_type,
+                                    TRANS_IEEE_802_3, is_master);
+       return err;
+}
+
 static int raw_recv(struct transport *t, int fd, void *buf, int buflen,
                    struct address *addr, struct hw_timestamp *hwts)
 {
@@ -476,6 +488,7 @@ struct transport *raw_transport_create(void)
                return NULL;
        raw->t.close   = raw_close;
        raw->t.open    = raw_open;
+       raw->t.update_rx_filter = raw_update_rx_filter;
        raw->t.recv    = raw_recv;
        raw->t.send    = raw_send;
        raw->t.release = raw_release;
diff --git a/sk.c b/sk.c
index 19395c9..a641e45 100644
--- a/sk.c
+++ b/sk.c
@@ -41,6 +41,8 @@
 
 int sk_tx_timeout = 1;
 int sk_check_fupsync;
+int sk_tx_type = -1;
+int sk_adv_rx_filter = -1;
 enum hwts_filter_mode sk_hwts_filter_mode = HWTS_FILTER_NORMAL;
 
 /* private methods */
@@ -56,7 +58,7 @@ static void init_ifreq(struct ifreq *ifreq, struct 
hwtstamp_config *cfg,
        ifreq->ifr_data = (void *) cfg;
 }
 
-static int hwts_init(int fd, const char *device, int rx_filter,
+static int hwts_set(int fd, const char *device, int rx_filter,
        int rx_filter2, int tx_type)
 {
        struct ifreq ifreq;
@@ -131,7 +133,7 @@ static int hwts_init(int fd, const char *device, int 
rx_filter,
                pr_err("The current filter does not match the required");
                return -1;
        }
-
+       sk_tx_type = cfg.tx_type;
        return 0;
 }
 
@@ -556,6 +558,36 @@ int sk_set_priority(int fd, int family, uint8_t dscp)
        return 0;
 }
 
+int sk_ts_update_rx_filter(int fd, const char *device, enum timestamp_type 
type,
+                          enum transport_type transport, bool is_master)
+{
+       int err, filter1, filter2 = 0;
+
+       if (type == TS_SOFTWARE)
+               return 0;
+
+       filter1 = (is_master) ? HWTSTAMP_FILTER_PTP_V2_DELAY_REQ :
+                               HWTSTAMP_FILTER_PTP_V2_SYNC;
+       switch (transport) {
+       case TRANS_UDP_IPV4:
+       case TRANS_UDP_IPV6:
+               filter2 = (is_master) ? HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ :
+                                       HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
+               break;
+       case TRANS_IEEE_802_3:
+               filter2 = (is_master) ? HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ :
+                                       HWTSTAMP_FILTER_PTP_V2_L2_SYNC;
+               break;
+       default:
+               return -1;
+       }
+       pr_debug("update rx filter1 %d, filter2 %d, sk_tx_type %d", filter1,
+                filter2, sk_tx_type);
+       err = hwts_set(fd, device, filter1, filter2, sk_tx_type);
+
+       return err;
+}
+
 int sk_timestamping_init(int fd, const char *device, enum timestamp_type type,
                         enum transport_type transport, int vclock)
 {
@@ -585,7 +617,11 @@ int sk_timestamping_init(int fd, const char *device, enum 
timestamp_type type,
        }
 
        if (type != TS_SOFTWARE) {
-               filter1 = HWTSTAMP_FILTER_PTP_V2_EVENT;
+               if (sk_adv_rx_filter == 1) {
+                       filter1 = HWTSTAMP_FILTER_PTP_V2_SYNC;
+               } else {
+                       filter1 = HWTSTAMP_FILTER_PTP_V2_EVENT;
+               }
                switch (type) {
                case TS_SOFTWARE:
                        tx_type = HWTSTAMP_TX_OFF;
@@ -604,10 +640,18 @@ int sk_timestamping_init(int fd, const char *device, enum 
timestamp_type type,
                switch (transport) {
                case TRANS_UDP_IPV4:
                case TRANS_UDP_IPV6:
-                       filter2 = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+                       if (sk_adv_rx_filter == 1) {
+                               filter2 = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
+                       } else {
+                               filter2 = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+                       }
                        break;
                case TRANS_IEEE_802_3:
-                       filter2 = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+                       if (sk_adv_rx_filter == 1) {
+                               filter2 = HWTSTAMP_FILTER_PTP_V2_L2_SYNC;
+                       } else {
+                               filter2 = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+                       }
                        break;
                case TRANS_DEVICENET:
                case TRANS_CONTROLNET:
@@ -615,7 +659,7 @@ int sk_timestamping_init(int fd, const char *device, enum 
timestamp_type type,
                case TRANS_UDS:
                        return -1;
                }
-               err = hwts_init(fd, device, filter1, filter2, tx_type);
+               err = hwts_set(fd, device, filter1, filter2, tx_type);
                if (err)
                        return err;
        }
diff --git a/sk.h b/sk.h
index 76062d0..88dc878 100644
--- a/sk.h
+++ b/sk.h
@@ -146,6 +146,19 @@ int sk_get_error(int fd);
  */
 int sk_set_priority(int fd, int family, uint8_t dscp);
 
+/**
+ * If sk_adv_rx_filter is set, then handle XXX_SYNC and
+ * XXX_DELAY_REQ hwtstamp_rx_filters.
+ * @param fd          An open socket.
+ * @param device      The name of the network interface to configure.
+ * @param type        The requested flavor of time stamping.
+ * @param transport   The type of transport used.
+ * @param is_master   Is current port state is Master.
+ * @return            Zero on success, non-zero otherwise.
+ */
+int sk_ts_update_rx_filter(int fd, const char *device, enum timestamp_type 
type,
+                          enum transport_type transport, bool is_master);
+
 /**
  * Enable time stamping on a given network interface.
  * @param fd          An open socket.
@@ -171,6 +184,8 @@ extern int sk_tx_timeout;
  */
 extern int sk_check_fupsync;
 
+extern int sk_adv_rx_filter;
+
 /**
  * Hardware time-stamp setting mode
  */
diff --git a/transport.c b/transport.c
index 9366fbf..c27137b 100644
--- a/transport.c
+++ b/transport.c
@@ -37,6 +37,13 @@ int transport_open(struct transport *t, struct interface 
*iface,
        return t->open(t, iface, fda, tt);
 }
 
+int transport_update_rx_filter(struct transport *t, struct interface *iface,
+                              struct fdarray *fda, enum timestamp_type tt,
+                              bool is_master)
+{
+       return t->update_rx_filter(iface, fda, tt, is_master);
+}
+
 int transport_recv(struct transport *t, int fd, struct ptp_message *msg)
 {
        return t->recv(t, fd, msg, sizeof(msg->data), &msg->address, 
&msg->hwts);
diff --git a/transport.h b/transport.h
index 7a7f87b..37ef0f1 100644
--- a/transport.h
+++ b/transport.h
@@ -22,6 +22,7 @@
 
 #include <time.h>
 #include <inttypes.h>
+#include <stdbool.h>
 
 #include "fd.h"
 #include "msg.h"
@@ -60,6 +61,10 @@ int transport_close(struct transport *t, struct fdarray 
*fda);
 int transport_open(struct transport *t, struct interface *iface,
                   struct fdarray *fda, enum timestamp_type tt);
 
+int transport_update_rx_filter(struct transport *t, struct interface *iface,
+                              struct fdarray *fda, enum timestamp_type tt,
+                              bool is_master);
+
 int transport_recv(struct transport *t, int fd, struct ptp_message *msg);
 
 /**
diff --git a/transport_private.h b/transport_private.h
index ec28e47..61d277f 100644
--- a/transport_private.h
+++ b/transport_private.h
@@ -35,6 +35,9 @@ struct transport {
        int (*open)(struct transport *t, struct interface *iface,
                    struct fdarray *fda, enum timestamp_type tt);
 
+       int (*update_rx_filter)(struct interface *iface, struct fdarray *fda,
+                               enum timestamp_type ts_type, bool is_master);
+
        int (*recv)(struct transport *t, int fd, void *buf, int buflen,
                    struct address *addr, struct hw_timestamp *hwts);
 
diff --git a/udp.c b/udp.c
index 7c9402e..b66ff7e 100644
--- a/udp.c
+++ b/udp.c
@@ -208,6 +208,19 @@ no_event:
        return -1;
 }
 
+static int udp_update_rx_filter(struct interface *iface, struct fdarray *fda,
+                               enum timestamp_type ts_type, bool is_master)
+{
+       int err;
+       const char *name;
+
+       name = interface_label(iface);
+       err = sk_ts_update_rx_filter(fda->fd[FD_EVENT], name, ts_type,
+                                    TRANS_UDP_IPV4, is_master);
+
+       return err;
+}
+
 static int udp_recv(struct transport *t, int fd, void *buf, int buflen,
                    struct address *addr, struct hw_timestamp *hwts)
 {
@@ -302,6 +315,7 @@ struct transport *udp_transport_create(void)
                return NULL;
        udp->t.close = udp_close;
        udp->t.open  = udp_open;
+       udp->t.update_rx_filter = udp_update_rx_filter;
        udp->t.recv  = udp_recv;
        udp->t.send  = udp_send;
        udp->t.release = udp_release;
diff --git a/udp6.c b/udp6.c
index bde1710..6a75962 100644
--- a/udp6.c
+++ b/udp6.c
@@ -225,6 +225,19 @@ no_event:
        return -1;
 }
 
+static int udp6_update_rx_filter(struct interface *iface, struct fdarray *fda,
+                                enum timestamp_type ts_type, bool is_master)
+{
+       int err;
+       const char *name;
+
+       name = interface_label(iface);
+       err = sk_ts_update_rx_filter(fda->fd[FD_EVENT], name, ts_type,
+                                    TRANS_UDP_IPV6, is_master);
+
+       return err;
+}
+
 static int udp6_recv(struct transport *t, int fd, void *buf, int buflen,
                     struct address *addr, struct hw_timestamp *hwts)
 {
@@ -318,6 +331,7 @@ struct transport *udp6_transport_create(void)
                return NULL;
        udp6->t.close   = udp6_close;
        udp6->t.open    = udp6_open;
+       udp6->t.update_rx_filter = udp6_update_rx_filter;
        udp6->t.recv    = udp6_recv;
        udp6->t.send    = udp6_send;
        udp6->t.release = udp6_release;
-- 
2.34.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to