On Mon, 13 Nov 2023 at 18:49, IlorDash <ilordas...@gmail.com> wrote:

> 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.
>

This is by design, not a mistake.
Most controllers allow timestamp all RX packets.
Users usually limit, to save resources.

You can set the values using the 'hwstamp_ctl' tool.

The reason to add this functionality to ptp4l is to allow dynamic change
from
master to slave.

Please update the description to explain properly.



> Device driver can only get info about the current PTP port state
> from ptp4l, because it doesn’t have direct access to it.
>

And this helps?


> I assumed, if these filters are defined in Kernel, they might be used in
>

No need to fix the kernel.


> 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.
>

This new feature does make sense.
But no need to talk on "Unfortunately" or "fix the kernel".
Just add explanation on why you can *NOT* use RX timestamp on all PTP
packets.
And explanation on the new feature.


>
> 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.
>

Do you suggest using HWTSTAMP_FILTER_PTP_V1?
Or only HWTSTAMP_FILTER_PTP_V2?



> +
>  .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
>
_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to