e6f414
commit 399907db7f9dc3f57c3f9831b3b4da705a2c51a3
e6f414
Author: Erez Geva <erezgeva2@gmail.com>
e6f414
Date:   Tue Aug 28 22:05:28 2018 +0200
e6f414
e6f414
    config: Add hardware time stamp filter setting mode
e6f414
    
e6f414
    Add global option for the hardware time stamp setting.
e6f414
    The function could:
e6f414
    Normally set the filters as the PTP daemon require.
e6f414
    Check that the filters are proper but do not change them.
e6f414
    Full, set the RX filter to all and the TX filter as the PTP daemon require.
e6f414
    
e6f414
    [ RC: added missing extern keyword and fixed indentation. ]
e6f414
    
e6f414
    Signed-off-by: Erez Geva <erez.geva.ext@siemens.com>
e6f414
    Signed-off-by: Erez Geva <ErezGeva2@gmail.com>
e6f414
e6f414
diff --git a/config.c b/config.c
e6f414
index 7914ba4..3530ce6 100644
e6f414
--- a/config.c
e6f414
+++ b/config.c
e6f414
@@ -164,6 +164,13 @@ static struct config_enum delay_mech_enu[] = {
e6f414
 	{ NULL, 0 },
e6f414
 };
e6f414
 
e6f414
+static struct config_enum hwts_filter_enu[] = {
e6f414
+	{ "normal",  HWTS_FILTER_NORMAL  },
e6f414
+	{ "check",   HWTS_FILTER_CHECK   },
e6f414
+	{ "full",    HWTS_FILTER_FULL    },
e6f414
+	{ NULL, 0 },
e6f414
+};
e6f414
+
e6f414
 static struct config_enum nw_trans_enu[] = {
e6f414
 	{ "L2",    TRANS_IEEE_802_3 },
e6f414
 	{ "UDPv4", TRANS_UDP_IPV4   },
e6f414
@@ -215,6 +222,7 @@ struct config_item config_tab[] = {
e6f414
 	GLOB_ITEM_INT("G.8275.defaultDS.localPriority", 128, 1, UINT8_MAX),
e6f414
 	PORT_ITEM_INT("G.8275.portDS.localPriority", 128, 1, UINT8_MAX),
e6f414
 	GLOB_ITEM_INT("gmCapable", 1, 0, 1),
e6f414
+	GLOB_ITEM_ENU("hwts_filter", HWTS_FILTER_NORMAL, hwts_filter_enu),
e6f414
 	PORT_ITEM_INT("hybrid_e2e", 0, 0, 1),
e6f414
 	PORT_ITEM_INT("ignore_transport_specific", 0, 0, 1),
e6f414
 	PORT_ITEM_INT("ingressLatency", 0, INT_MIN, INT_MAX),
e6f414
diff --git a/ptp4l.8 b/ptp4l.8
e6f414
index 10c5c2f..39bf36e 100644
e6f414
--- a/ptp4l.8
e6f414
+++ b/ptp4l.8
e6f414
@@ -661,6 +661,15 @@ The time source is a single byte code that gives an idea of the kind
e6f414
 of local clock in use. The value is purely informational, having no
e6f414
 effect on the outcome of the Best Master Clock algorithm, and is
e6f414
 advertised when the clock becomes grand master.
e6f414
+.TP
e6f414
+.B hwts_filter
e6f414
+Select the hardware time stamp filter setting mode.
e6f414
+Possible values are normal, check, full.
e6f414
+Normal mode set the filters as needed.
e6f414
+Check mode only check but do not set.
e6f414
+Full mode set the receive filter to mark all packets with hardware time stamp,
e6f414
+ so all applications can get them.
e6f414
+The default is normal.
e6f414
 
e6f414
 .SH UNICAST DISCOVERY OPTIONS
e6f414
 
e6f414
diff --git a/ptp4l.c b/ptp4l.c
e6f414
index 9ef8169..3a9f084 100644
e6f414
--- a/ptp4l.c
e6f414
+++ b/ptp4l.c
e6f414
@@ -191,6 +191,7 @@ int main(int argc, char *argv[])
e6f414
 	assume_two_step = config_get_int(cfg, NULL, "assume_two_step");
e6f414
 	sk_check_fupsync = config_get_int(cfg, NULL, "check_fup_sync");
e6f414
 	sk_tx_timeout = config_get_int(cfg, NULL, "tx_timestamp_timeout");
e6f414
+	sk_hwts_filter_mode = config_get_int(cfg, NULL, "hwts_filter");
e6f414
 
e6f414
 	if (config_get_int(cfg, NULL, "clock_servo") == CLOCK_SERVO_NTPSHM) {
e6f414
 		config_set_int(cfg, "kernel_leap", 0);
e6f414
diff --git a/sk.c b/sk.c
e6f414
index f18b2bf..43f1800 100644
e6f414
--- a/sk.c
e6f414
+++ b/sk.c
e6f414
@@ -40,39 +40,76 @@
e6f414
 
e6f414
 int sk_tx_timeout = 1;
e6f414
 int sk_check_fupsync;
e6f414
+enum hwts_filter_mode sk_hwts_filter_mode = HWTS_FILTER_NORMAL;
e6f414
 
e6f414
 /* private methods */
e6f414
 
e6f414
-static int hwts_init(int fd, const char *device, int rx_filter, int tx_type)
e6f414
+static void init_ifreq(struct ifreq *ifreq, struct hwtstamp_config *cfg,
e6f414
+	const char *device)
e6f414
 {
e6f414
-	struct ifreq ifreq;
e6f414
-	struct hwtstamp_config cfg, req;
e6f414
-	int err;
e6f414
+	memset(ifreq, 0, sizeof(*ifreq));
e6f414
+	memset(cfg, 0, sizeof(*cfg));
e6f414
 
e6f414
-	memset(&ifreq, 0, sizeof(ifreq));
e6f414
-	memset(&cfg, 0, sizeof(cfg));
e6f414
+	strncpy(ifreq->ifr_name, device, sizeof(ifreq->ifr_name) - 1);
e6f414
 
e6f414
-	strncpy(ifreq.ifr_name, device, sizeof(ifreq.ifr_name) - 1);
e6f414
+	ifreq->ifr_data = (void *) cfg;
e6f414
+}
e6f414
 
e6f414
-	ifreq.ifr_data = (void *) &cfg;
e6f414
-	cfg.tx_type    = tx_type;
e6f414
-	cfg.rx_filter  = rx_filter;
e6f414
-	req = cfg;
e6f414
-	err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
e6f414
-	if (err < 0)
e6f414
-		return err;
e6f414
+static int hwts_init(int fd, const char *device, int rx_filter,
e6f414
+	int rx_filter2, int tx_type)
e6f414
+{
e6f414
+	struct ifreq ifreq;
e6f414
+	struct hwtstamp_config cfg;
e6f414
+	int err;
e6f414
 
e6f414
-	if (memcmp(&cfg, &req, sizeof(cfg))) {
e6f414
+	init_ifreq(&ifreq, &cfg, device);
e6f414
 
e6f414
-		pr_debug("driver changed our HWTSTAMP options");
e6f414
-		pr_debug("tx_type   %d not %d", cfg.tx_type, req.tx_type);
e6f414
-		pr_debug("rx_filter %d not %d", cfg.rx_filter, req.rx_filter);
e6f414
+	switch (sk_hwts_filter_mode) {
e6f414
+	case HWTS_FILTER_CHECK:
e6f414
+		err = ioctl(fd, SIOCGHWTSTAMP, &ifreq);
e6f414
+		if (err < 0) {
e6f414
+			pr_err("ioctl SIOCGHWTSTAMP failed: %m");
e6f414
+			return err;
e6f414
+		}
e6f414
+		break;
e6f414
+	case HWTS_FILTER_FULL:
e6f414
+		cfg.tx_type   = tx_type;
e6f414
+		cfg.rx_filter = HWTSTAMP_FILTER_ALL;
e6f414
+		err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
e6f414
+		if (err < 0) {
e6f414
+			pr_err("ioctl SIOCSHWTSTAMP failed: %m");
e6f414
+			return err;
e6f414
+		}
e6f414
+		break;
e6f414
+	case HWTS_FILTER_NORMAL:
e6f414
+		cfg.tx_type   = tx_type;
e6f414
+		cfg.rx_filter = rx_filter;
e6f414
+		err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
e6f414
+		if (err < 0) {
e6f414
+			pr_info("driver rejected most general HWTSTAMP filter");
e6f414
 
e6f414
-		if (cfg.tx_type != req.tx_type ||
e6f414
-		    (cfg.rx_filter != HWTSTAMP_FILTER_ALL &&
e6f414
-		     cfg.rx_filter != HWTSTAMP_FILTER_PTP_V2_EVENT)) {
e6f414
-			return -1;
e6f414
+			init_ifreq(&ifreq, &cfg, device);
e6f414
+			cfg.tx_type   = tx_type;
e6f414
+			cfg.rx_filter = rx_filter2;
e6f414
+
e6f414
+			err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
e6f414
+			if (err < 0) {
e6f414
+				pr_err("ioctl SIOCSHWTSTAMP failed: %m");
e6f414
+				return err;
e6f414
+			}
e6f414
 		}
e6f414
+		break;
e6f414
+	}
e6f414
+
e6f414
+	if (cfg.tx_type != tx_type ||
e6f414
+	    (cfg.rx_filter != rx_filter &&
e6f414
+	     cfg.rx_filter != rx_filter2 &&
e6f414
+	     cfg.rx_filter != HWTSTAMP_FILTER_ALL)) {
e6f414
+		pr_debug("tx_type   %d not %d", cfg.tx_type, tx_type);
e6f414
+		pr_debug("rx_filter %d not %d or %d", cfg.rx_filter, rx_filter,
e6f414
+			 rx_filter2);
e6f414
+		pr_err("The current filter does not match the required");
e6f414
+		return -1;
e6f414
 	}
e6f414
 
e6f414
 	return 0;
e6f414
@@ -450,15 +487,9 @@ int sk_timestamping_init(int fd, const char *device, enum timestamp_type type,
e6f414
 		case TRANS_UDS:
e6f414
 			return -1;
e6f414
 		}
e6f414
-		err = hwts_init(fd, device, filter1, tx_type);
e6f414
-		if (err) {
e6f414
-			pr_info("driver rejected most general HWTSTAMP filter");
e6f414
-			err = hwts_init(fd, device, filter2, tx_type);
e6f414
-			if (err) {
e6f414
-				pr_err("ioctl SIOCSHWTSTAMP failed: %m");
e6f414
-				return err;
e6f414
-			}
e6f414
-		}
e6f414
+		err = hwts_init(fd, device, filter1, filter2, tx_type);
e6f414
+		if (err)
e6f414
+			return err;
e6f414
 	}
e6f414
 
e6f414
 	if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
e6f414
diff --git a/sk.h b/sk.h
e6f414
index d91d5d8..fd4d820 100644
e6f414
--- a/sk.h
e6f414
+++ b/sk.h
e6f414
@@ -23,6 +23,16 @@
e6f414
 #include "address.h"
e6f414
 #include "transport.h"
e6f414
 
e6f414
+/**
e6f414
+ * Defines the available Hardware time-stamp setting modes.
e6f414
+ */
e6f414
+
e6f414
+enum hwts_filter_mode {
e6f414
+	HWTS_FILTER_NORMAL,    /* set hardware filters in normal way */
e6f414
+	HWTS_FILTER_CHECK,     /* check filters but do not change them */
e6f414
+	HWTS_FILTER_FULL,      /* Use time-stamp on all received packets */
e6f414
+};
e6f414
+
e6f414
 /**
e6f414
  * Contains timestamping information returned by the GET_TS_INFO ioctl.
e6f414
  * @valid:            set to non-zero when the info struct contains valid data.
e6f414
@@ -131,4 +141,9 @@ extern int sk_tx_timeout;
e6f414
  */
e6f414
 extern int sk_check_fupsync;
e6f414
 
e6f414
+/**
e6f414
+ * Hardware time-stamp setting mode
e6f414
+ */
e6f414
+extern enum hwts_filter_mode sk_hwts_filter_mode;
e6f414
+
e6f414
 #endif