Signed-off-by: Erez Geva <erez.geva....@siemens.com>
---
 config.c            |  9 +++++++++
 ptp4l.8             |  8 ++++++++
 raw.c               |  6 ++++--
 sk.c                | 38 ++++++++++++++++++++++++++++----------
 sk.h                | 14 +++++++++++++-
 transport.c         | 11 ++++++++++-
 transport_private.h |  4 +++-
 udp.c               |  6 ++++--
 udp6.c              |  6 ++++--
 uds.c               |  2 +-
 10 files changed, 84 insertions(+), 20 deletions(-)

diff --git a/config.c b/config.c
index 98e8f1c..269f249 100644
--- a/config.c
+++ b/config.c
@@ -187,6 +187,14 @@ static struct config_enum tsproc_enu[] = {
        { NULL, 0 },
 };
 
+static struct config_enum hwts_filter_enu[] = {
+       { "default", HWTS_FILTER_DEF     },
+       { "ignore",  HWTS_FILTER_IGNORE  },
+       { "upgrade", HWTS_FILTER_UPGRADE },
+       { "check",   HWTS_FILTER_CHECK   },
+       { NULL, 0 },
+};
+
 struct config_item config_tab[] = {
        PORT_ITEM_INT("announceReceiptTimeout", 3, 2, UINT8_MAX),
        GLOB_ITEM_INT("assume_two_step", 0, 0, 1),
@@ -268,6 +276,7 @@ struct config_item config_tab[] = {
        GLOB_ITEM_STR("userDescription", ""),
        GLOB_ITEM_INT("utc_offset", CURRENT_UTC_OFFSET, 0, INT_MAX),
        GLOB_ITEM_INT("verbose", 0, 0, 1),
+       PORT_ITEM_ENU("hwts_filter", HWTS_FILTER_DEF, hwts_filter_enu),
 };
 
 static enum parser_result
diff --git a/ptp4l.8 b/ptp4l.8
index ae6e491..4e2e87e 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -624,6 +624,14 @@ The time source is a single byte code that gives an idea 
of the kind
 of local clock in use. The value is purely informational, having no
 effect on the outcome of the Best Master Clock algorithm, and is
 advertised when the clock becomes grand master.
+.TP
+.B hwts_filter
+Select the hardware time stamp filter setting mode;
+Possible values are ignore, upgrade, check.
+Some AVB/TSN applications may need the receiving hardware time stamp.
+Upgrade mode prevent downgrading the RX filter.
+Check mode only check but do not set.
+The default is ignore.
 
 .SH TIME SCALE USAGE
 
diff --git a/raw.c b/raw.c
index 8dc50bc..ff60fea 100644
--- a/raw.c
+++ b/raw.c
@@ -200,7 +200,8 @@ static void addr_to_mac(void *mac, struct address *addr)
 }
 
 static int raw_open(struct transport *t, struct interface *iface,
-                   struct fdarray *fda, enum timestamp_type ts_type)
+                   struct fdarray *fda, enum timestamp_type ts_type,
+                   enum hwts_filter_mode ftm)
 {
        struct raw *raw = container_of(t, struct raw, t);
        unsigned char ptp_dst_mac[MAC_LEN];
@@ -233,7 +234,8 @@ static int raw_open(struct transport *t, struct interface 
*iface,
        if (gfd < 0)
                goto no_general;
 
-       if (sk_timestamping_init(efd, name, ts_type, TRANS_IEEE_802_3))
+       if (sk_timestamping_init(efd, name, ts_type, TRANS_IEEE_802_3,
+                              ftm))
                goto no_timestamping;
 
        if (sk_general_init(gfd))
diff --git a/sk.c b/sk.c
index f18b2bf..9dda532 100644
--- a/sk.c
+++ b/sk.c
@@ -43,7 +43,8 @@ int sk_check_fupsync;
 
 /* private methods */
 
-static int hwts_init(int fd, const char *device, int rx_filter, int tx_type)
+static int hwts_init(int fd, const char *device, int rx_filter, int tx_type,
+       enum hwts_filter_mode ftm)
 {
        struct ifreq ifreq;
        struct hwtstamp_config cfg, req;
@@ -55,12 +56,27 @@ static int hwts_init(int fd, const char *device, int 
rx_filter, int tx_type)
        strncpy(ifreq.ifr_name, device, sizeof(ifreq.ifr_name) - 1);
 
        ifreq.ifr_data = (void *) &cfg;
-       cfg.tx_type    = tx_type;
-       cfg.rx_filter  = rx_filter;
-       req = cfg;
-       err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
-       if (err < 0)
-               return err;
+
+       if (ftm != HWTS_FILTER_IGNORE) {
+               if (ioctl(fd, SIOCGHWTSTAMP, &ifreq) < 0) {
+                       pr_err("ioctl SIOCGHWTSTAMP failed: %m");
+                       return -1;
+               }
+       }
+
+       if (ftm == HWTS_FILTER_CHECK) {
+               req.tx_type   = tx_type;
+               req.rx_filter = rx_filter;
+       } else {
+               cfg.tx_type    = tx_type;
+               if (ftm == HWTS_FILTER_IGNORE ||
+                   cfg.rx_filter != HWTSTAMP_FILTER_ALL)
+                       cfg.rx_filter = rx_filter;
+               req = cfg;
+               err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
+               if (err < 0)
+                       return err;
+       }
 
        if (memcmp(&cfg, &req, sizeof(cfg))) {
 
@@ -393,7 +409,8 @@ int sk_set_priority(int fd, uint8_t dscp)
 }
 
 int sk_timestamping_init(int fd, const char *device, enum timestamp_type type,
-                        enum transport_type transport)
+                        enum transport_type transport,
+                        enum hwts_filter_mode ftm)
 {
        int err, filter1, filter2 = 0, flags, tx_type = HWTSTAMP_TX_ON;
 
@@ -450,10 +467,11 @@ int sk_timestamping_init(int fd, const char *device, enum 
timestamp_type type,
                case TRANS_UDS:
                        return -1;
                }
-               err = hwts_init(fd, device, filter1, tx_type);
+               err = hwts_init(fd, device, filter1, tx_type, ftm);
                if (err) {
                        pr_info("driver rejected most general HWTSTAMP filter");
-                       err = hwts_init(fd, device, filter2, tx_type);
+                       err = hwts_init(fd, device, filter2, tx_type,
+                               ftm);
                        if (err) {
                                pr_err("ioctl SIOCSHWTSTAMP failed: %m");
                                return err;
diff --git a/sk.h b/sk.h
index d91d5d8..1b5b39d 100644
--- a/sk.h
+++ b/sk.h
@@ -23,6 +23,17 @@
 #include "address.h"
 #include "transport.h"
 
+/**
+ * Defines the available modes.
+ */
+
+enum hwts_filter_mode {
+       HWTS_FILTER_DEF,       /* default value for real value detection */
+       HWTS_FILTER_IGNORE,    /* ignore previous mode and set new mode */
+       HWTS_FILTER_UPGRADE,   /* upgrade rx filter */
+       HWTS_FILTER_CHECK,     /* check filters but do not change them */
+};
+
 /**
  * Contains timestamping information returned by the GET_TS_INFO ioctl.
  * @valid:            set to non-zero when the info struct contains valid data.
@@ -116,7 +127,8 @@ int sk_set_priority(int fd, uint8_t dscp);
  * @return            Zero on success, non-zero otherwise.
  */
 int sk_timestamping_init(int fd, const char *device, enum timestamp_type type,
-                        enum transport_type transport);
+                        enum transport_type transport,
+                        enum hwts_filter_mode ftm);
 
 /**
  * Limits the time that RECVMSG(2) will poll while waiting for the tx timestamp
diff --git a/transport.c b/transport.c
index 8fb94de..4dd4c2d 100644
--- a/transport.c
+++ b/transport.c
@@ -25,6 +25,7 @@
 #include "udp.h"
 #include "udp6.h"
 #include "uds.h"
+#include "sk.h"
 
 int transport_close(struct transport *t, struct fdarray *fda)
 {
@@ -34,7 +35,15 @@ 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)
 {
-       return t->open(t, iface, fda, tt);
+       /* try interface section else use global */
+       enum hwts_filter_mode ftm = config_get_int(t->cfg, iface->name,
+               "hwts_filter");
+       if (ftm == HWTS_FILTER_DEF) {
+               ftm = config_get_int(t->cfg, NULL, "hwts_filter");
+               if (ftm == HWTS_FILTER_DEF)
+                       ftm = HWTS_FILTER_IGNORE;
+       }
+       return t->open(t, iface, fda, tt, ftm);
 }
 
 int transport_recv(struct transport *t, int fd, struct ptp_message *msg)
diff --git a/transport_private.h b/transport_private.h
index ec28e47..0562f19 100644
--- a/transport_private.h
+++ b/transport_private.h
@@ -25,6 +25,7 @@
 #include "address.h"
 #include "fd.h"
 #include "transport.h"
+#include "sk.h"
 
 struct transport {
        enum transport_type type;
@@ -33,7 +34,8 @@ struct transport {
        int (*close)(struct transport *t, struct fdarray *fda);
 
        int (*open)(struct transport *t, struct interface *iface,
-                   struct fdarray *fda, enum timestamp_type tt);
+                   struct fdarray *fda, enum timestamp_type tt,
+                   enum hwts_filter_mode ftm);
 
        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 6ebec3e..aae83c1 100644
--- a/udp.c
+++ b/udp.c
@@ -153,7 +153,8 @@ enum { MC_PRIMARY, MC_PDELAY };
 static struct in_addr mcast_addr[2];
 
 static int udp_open(struct transport *t, struct interface *iface,
-                   struct fdarray *fda, enum timestamp_type ts_type)
+                   struct fdarray *fda, enum timestamp_type ts_type,
+                   enum hwts_filter_mode ftm)
 {
        struct udp *udp = container_of(t, struct udp, t);
        uint8_t event_dscp, general_dscp;
@@ -181,7 +182,8 @@ static int udp_open(struct transport *t, struct interface 
*iface,
        if (gfd < 0)
                goto no_general;
 
-       if (sk_timestamping_init(efd, iface->ts_label, ts_type, TRANS_UDP_IPV4))
+       if (sk_timestamping_init(efd, iface->ts_label, ts_type, TRANS_UDP_IPV4,
+               ftm))
                goto no_timestamping;
 
        if (sk_general_init(gfd))
diff --git a/udp6.c b/udp6.c
index 9978844..d550129 100644
--- a/udp6.c
+++ b/udp6.c
@@ -161,7 +161,8 @@ enum { MC_PRIMARY, MC_PDELAY };
 static struct in6_addr mc6_addr[2];
 
 static int udp6_open(struct transport *t, struct interface *iface,
-                    struct fdarray *fda, enum timestamp_type ts_type)
+                    struct fdarray *fda, enum timestamp_type ts_type,
+                    enum hwts_filter_mode ftm)
 {
        struct udp6 *udp6 = container_of(t, struct udp6, t);
        uint8_t event_dscp, general_dscp;
@@ -191,7 +192,8 @@ static int udp6_open(struct transport *t, struct interface 
*iface,
        if (gfd < 0)
                goto no_general;
 
-       if (sk_timestamping_init(efd, iface->ts_label, ts_type, TRANS_UDP_IPV6))
+       if (sk_timestamping_init(efd, iface->ts_label, ts_type, TRANS_UDP_IPV6,
+               ftm))
                goto no_timestamping;
 
        if (sk_general_init(gfd))
diff --git a/uds.c b/uds.c
index 44d135f..fe300da 100644
--- a/uds.c
+++ b/uds.c
@@ -53,7 +53,7 @@ static int uds_close(struct transport *t, struct fdarray *fda)
 }
 
 static int uds_open(struct transport *t, struct interface *iface, struct 
fdarray *fda,
-                   enum timestamp_type tt)
+                   enum timestamp_type tt, enum hwts_filter_mode ftm)
 {
        int fd, err;
        struct sockaddr_un sa;
-- 
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
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to