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