Jiri Benc
2012-10-18 10:33:34 UTC
With UDP, use L4 timestamping unless overriden by rx_timestamp_l2only. This
allows ptp4l to work with drivers that do not support L2 timestamping (like
sfc).
The sfc driver returns -ERANGE as a response to HWTSTAMP_FILTER_PTP_V2_EVENT
which causes ptp4l to output:
ioctl SIOCSHWTSTAMP failed: Numerical result out of range
and get stuck later.
Signed-off-by: Jiri Benc <***@redhat.com>
---
raw.c | 2 +-
sk.c | 16 +++++++++++-----
sk.h | 12 +++++++-----
udp.c | 2 +-
udp6.c | 2 +-
5 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/raw.c b/raw.c
index 3fe04c1..5511582 100644
--- a/raw.c
+++ b/raw.c
@@ -206,7 +206,7 @@ static int raw_open(struct transport *t, char *name,
if (gfd < 0)
goto no_general;
- if (sk_timestamping_init(efd, name, ts_type))
+ if (sk_timestamping_init(efd, name, ts_type, TRANS_IEEE_802_3))
goto no_timestamping;
fda->fd[FD_EVENT] = efd;
diff --git a/sk.c b/sk.c
index b006c57..aabee4b 100644
--- a/sk.c
+++ b/sk.c
@@ -29,6 +29,7 @@
#include "print.h"
#include "sk.h"
+#include "transport.h"
/* globals */
@@ -36,7 +37,7 @@ int sk_tx_retries = 2, sk_prefer_layer2 = 0;
/* private methods */
-static int hwts_init(int fd, char *device)
+static int hwts_init(int fd, char *device, enum transport_type transport)
{
struct ifreq ifreq;
struct hwtstamp_config cfg, req;
@@ -49,8 +50,12 @@ static int hwts_init(int fd, char *device)
ifreq.ifr_data = (void *) &cfg;
cfg.tx_type = HWTSTAMP_TX_ON;
- cfg.rx_filter = sk_prefer_layer2 ?
- HWTSTAMP_FILTER_PTP_V2_L2_EVENT : HWTSTAMP_FILTER_PTP_V2_EVENT;
+ if (sk_prefer_layer2)
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+ else if (transport == TRANS_UDP_IPV4 || transport == TRANS_UDP_IPV6)
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+ else
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
req = cfg;
err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
@@ -223,7 +228,8 @@ int sk_receive(int fd, void *buf, int buflen,
return cnt;
}
-int sk_timestamping_init(int fd, char *device, enum timestamp_type type)
+int sk_timestamping_init(int fd, char *device, enum timestamp_type type,
+ enum transport_type transport)
{
int flags;
@@ -247,7 +253,7 @@ int sk_timestamping_init(int fd, char *device, enum timestamp_type type)
return -1;
}
- if (type != TS_SOFTWARE && hwts_init(fd, device))
+ if (type != TS_SOFTWARE && hwts_init(fd, device, transport))
return -1;
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
diff --git a/sk.h b/sk.h
index b2787b2..b6ce88c 100644
--- a/sk.h
+++ b/sk.h
@@ -61,12 +61,14 @@ int sk_receive(int fd, void *buf, int buflen,
/**
* Enable time stamping on a given network interface.
- * @param fd An open socket.
- * @param device The name of the network interface to configure.
- * @param type The requested flavor of time stamping.
- * @return Zero on success, non-zero otherwise.
+ * @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.
+ * @return Zero on success, non-zero otherwise.
*/
-int sk_timestamping_init(int fd, char *device, enum timestamp_type type);
+int sk_timestamping_init(int fd, char *device, enum timestamp_type type,
+ enum transport_type transport);
/**
* Limits the number of RECVMSG(2) calls when attempting to obtain a
diff --git a/udp.c b/udp.c
index b361ff4..d0aab6f 100644
--- a/udp.c
+++ b/udp.c
@@ -155,7 +155,7 @@ static int udp_open(struct transport *t, char *name, struct fdarray *fda,
if (gfd < 0)
goto no_general;
- if (sk_timestamping_init(efd, name, ts_type))
+ if (sk_timestamping_init(efd, name, ts_type, TRANS_UDP_IPV4))
goto no_timestamping;
fda->fd[FD_EVENT] = efd;
diff --git a/udp6.c b/udp6.c
index 115cd83..e6023a6 100644
--- a/udp6.c
+++ b/udp6.c
@@ -154,7 +154,7 @@ static int udp6_open(struct transport *t, char *name, struct fdarray *fda,
if (gfd < 0)
goto no_general;
- if (sk_timestamping_init(efd, name, ts_type))
+ if (sk_timestamping_init(efd, name, ts_type, TRANS_UDP_IPV6))
goto no_timestamping;
fda->fd[FD_EVENT] = efd;
allows ptp4l to work with drivers that do not support L2 timestamping (like
sfc).
The sfc driver returns -ERANGE as a response to HWTSTAMP_FILTER_PTP_V2_EVENT
which causes ptp4l to output:
ioctl SIOCSHWTSTAMP failed: Numerical result out of range
and get stuck later.
Signed-off-by: Jiri Benc <***@redhat.com>
---
raw.c | 2 +-
sk.c | 16 +++++++++++-----
sk.h | 12 +++++++-----
udp.c | 2 +-
udp6.c | 2 +-
5 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/raw.c b/raw.c
index 3fe04c1..5511582 100644
--- a/raw.c
+++ b/raw.c
@@ -206,7 +206,7 @@ static int raw_open(struct transport *t, char *name,
if (gfd < 0)
goto no_general;
- if (sk_timestamping_init(efd, name, ts_type))
+ if (sk_timestamping_init(efd, name, ts_type, TRANS_IEEE_802_3))
goto no_timestamping;
fda->fd[FD_EVENT] = efd;
diff --git a/sk.c b/sk.c
index b006c57..aabee4b 100644
--- a/sk.c
+++ b/sk.c
@@ -29,6 +29,7 @@
#include "print.h"
#include "sk.h"
+#include "transport.h"
/* globals */
@@ -36,7 +37,7 @@ int sk_tx_retries = 2, sk_prefer_layer2 = 0;
/* private methods */
-static int hwts_init(int fd, char *device)
+static int hwts_init(int fd, char *device, enum transport_type transport)
{
struct ifreq ifreq;
struct hwtstamp_config cfg, req;
@@ -49,8 +50,12 @@ static int hwts_init(int fd, char *device)
ifreq.ifr_data = (void *) &cfg;
cfg.tx_type = HWTSTAMP_TX_ON;
- cfg.rx_filter = sk_prefer_layer2 ?
- HWTSTAMP_FILTER_PTP_V2_L2_EVENT : HWTSTAMP_FILTER_PTP_V2_EVENT;
+ if (sk_prefer_layer2)
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+ else if (transport == TRANS_UDP_IPV4 || transport == TRANS_UDP_IPV6)
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+ else
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
req = cfg;
err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
@@ -223,7 +228,8 @@ int sk_receive(int fd, void *buf, int buflen,
return cnt;
}
-int sk_timestamping_init(int fd, char *device, enum timestamp_type type)
+int sk_timestamping_init(int fd, char *device, enum timestamp_type type,
+ enum transport_type transport)
{
int flags;
@@ -247,7 +253,7 @@ int sk_timestamping_init(int fd, char *device, enum timestamp_type type)
return -1;
}
- if (type != TS_SOFTWARE && hwts_init(fd, device))
+ if (type != TS_SOFTWARE && hwts_init(fd, device, transport))
return -1;
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
diff --git a/sk.h b/sk.h
index b2787b2..b6ce88c 100644
--- a/sk.h
+++ b/sk.h
@@ -61,12 +61,14 @@ int sk_receive(int fd, void *buf, int buflen,
/**
* Enable time stamping on a given network interface.
- * @param fd An open socket.
- * @param device The name of the network interface to configure.
- * @param type The requested flavor of time stamping.
- * @return Zero on success, non-zero otherwise.
+ * @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.
+ * @return Zero on success, non-zero otherwise.
*/
-int sk_timestamping_init(int fd, char *device, enum timestamp_type type);
+int sk_timestamping_init(int fd, char *device, enum timestamp_type type,
+ enum transport_type transport);
/**
* Limits the number of RECVMSG(2) calls when attempting to obtain a
diff --git a/udp.c b/udp.c
index b361ff4..d0aab6f 100644
--- a/udp.c
+++ b/udp.c
@@ -155,7 +155,7 @@ static int udp_open(struct transport *t, char *name, struct fdarray *fda,
if (gfd < 0)
goto no_general;
- if (sk_timestamping_init(efd, name, ts_type))
+ if (sk_timestamping_init(efd, name, ts_type, TRANS_UDP_IPV4))
goto no_timestamping;
fda->fd[FD_EVENT] = efd;
diff --git a/udp6.c b/udp6.c
index 115cd83..e6023a6 100644
--- a/udp6.c
+++ b/udp6.c
@@ -154,7 +154,7 @@ static int udp6_open(struct transport *t, char *name, struct fdarray *fda,
if (gfd < 0)
goto no_general;
- if (sk_timestamping_init(efd, name, ts_type))
+ if (sk_timestamping_init(efd, name, ts_type, TRANS_UDP_IPV6))
goto no_timestamping;
fda->fd[FD_EVENT] = efd;
--
1.7.6.5
1.7.6.5