Latest Linux kernel has supported getting PHC from bond directly. This
would help topology like VLAN over bond to get PHC natively. To achieve
this, the new hwtstamp flag is needed when passing hwtstamp_config to
kernel. Let's supply the flag first, and fall back without flag if user
run on old kernel.

Split port_change_phc() from function port_link_status() so the event
functions could call it directly when find the phc changed.

Signed-off-by: Hangbin Liu <liuhang...@gmail.com>

v6: revert changes in clock_create(). Update ts_label by force and do
    interface_get_tsinfo() only once.
v5: no update
v4: define HWTSTAMP_FLAG_BONDED_PHC_INDEX in missing.h
    remove unneeded net_tstamp header files
v3: remove ifdef in clock_create() and FD_RTNL event.
v2: remove link state PHC_INDEX_CHANGED and use TS_LABEL_CHANGED only.
---
 clock.c        |  3 ++
 e2e_tc.c       |  7 ++++-
 missing.h      |  6 ++++
 p2p_tc.c       |  7 ++++-
 port.c         | 74 +++++++++++++++++++++++++++++++-------------------
 port_private.h |  1 +
 sk.c           |  5 ++++
 7 files changed, 73 insertions(+), 30 deletions(-)

diff --git a/clock.c b/clock.c
index 7be021f..16ca6ed 100644
--- a/clock.c
+++ b/clock.c
@@ -1767,6 +1767,9 @@ int clock_switch_phc(struct clock *c, int phc_index)
        c->clkid = clkid;
        c->servo = servo;
        c->servo_state = SERVO_UNLOCKED;
+
+       pr_info("Switched to /dev/ptp%d as PTP clock", phc_index);
+
        return 0;
 }
 
diff --git a/e2e_tc.c b/e2e_tc.c
index 2f8e821..42baea3 100644
--- a/e2e_tc.c
+++ b/e2e_tc.c
@@ -123,7 +123,12 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
 
        case FD_RTNL:
                pr_debug("%s: received link status notification", p->log_name);
-               rtnl_link_status(fd, p->name, port_link_status, p);
+               if (!interface_get_tsinfo(p->iface) &&
+                   (p->phc_index != interface_phc_index(p->iface)))
+                       port_change_phc(p);
+               else
+                       rtnl_link_status(fd, p->name, port_link_status, p);
+
                if (p->link_status == (LINK_UP|LINK_STATE_CHANGED)) {
                        return EV_FAULT_CLEARED;
                } else if ((p->link_status == (LINK_DOWN|LINK_STATE_CHANGED)) ||
diff --git a/missing.h b/missing.h
index 20f7193..4c7ac57 100644
--- a/missing.h
+++ b/missing.h
@@ -73,6 +73,12 @@ struct so_timestamping {
 };
 #endif
 
+#ifndef HWTSTAMP_FLAG_BONDED_PHC_INDEX
+enum {
+       HWTSTAMP_FLAG_BONDED_PHC_INDEX = (1<<0),
+};
+#endif
+
 #ifdef PTP_EXTTS_REQUEST2
 #define PTP_EXTTS_REQUEST_FAILED "PTP_EXTTS_REQUEST2 failed: %m"
 #else
diff --git a/p2p_tc.c b/p2p_tc.c
index 75cb3b9..1164c9a 100644
--- a/p2p_tc.c
+++ b/p2p_tc.c
@@ -126,7 +126,12 @@ enum fsm_event p2p_event(struct port *p, int fd_index)
 
        case FD_RTNL:
                pr_debug("%s: received link status notification", p->log_name);
-               rtnl_link_status(fd, p->name, port_link_status, p);
+               if (!interface_get_tsinfo(p->iface) &&
+                   (p->phc_index != interface_phc_index(p->iface)))
+                       port_change_phc(p);
+               else
+                       rtnl_link_status(fd, p->name, port_link_status, p);
+
                if (p->link_status == (LINK_UP|LINK_STATE_CHANGED)) {
                        return EV_FAULT_CLEARED;
                } else if ((p->link_status == (LINK_DOWN|LINK_STATE_CHANGED)) ||
diff --git a/port.c b/port.c
index f2b666c..76e323f 100644
--- a/port.c
+++ b/port.c
@@ -2636,10 +2636,48 @@ static void bc_dispatch(struct port *p, enum fsm_event 
event, int mdiff)
        }
 }
 
+void port_change_phc(struct port *p)
+{
+       int required_modes;
+
+       /* Only switch phc with HW time stamping mode */
+       if (!interface_tsinfo_valid(p->iface) ||
+           interface_phc_index(p->iface) < 0)
+               return;
+
+       required_modes = clock_required_modes(p->clock);
+       if (!interface_tsmodes_supported(p->iface, required_modes)) {
+               pr_err("interface '%s' does not support requested "
+                      "timestamping mode, set link status down by force.",
+                      interface_label(p->iface));
+               p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
+       } else if (p->phc_from_cmdline) {
+               pr_warning("%s: taking /dev/ptp%d from the "
+                          "command line, not the attached ptp%d",
+                          p->log_name, p->phc_index,
+                          interface_phc_index(p->iface));
+       } else if (p->phc_index != interface_phc_index(p->iface)) {
+               p->phc_index = interface_phc_index(p->iface);
+
+               if (clock_switch_phc(p->clock, p->phc_index)) {
+                       p->last_fault_type = FT_SWITCH_PHC;
+                       port_dispatch(p, EV_FAULT_DETECTED, 0);
+                       return;
+               }
+               clock_sync_interval(p->clock, p->log_sync_interval);
+
+               /* Ensure TS_LABEL_CHANGED is set for failover when
+                * PHC changed as we may not call port_change_phc()
+                * from port_link_status().
+                */
+               p->link_status |= TS_LABEL_CHANGED;
+       }
+}
+
 void port_link_status(void *ctx, int linkup, int ts_index)
 {
        char ts_label[MAX_IFNAME_SIZE + 1] = {0};
-       int link_state, required_modes;
+       int link_state;
        const char *old_ts_label;
        struct port *p = ctx;
 
@@ -2663,32 +2701,7 @@ void port_link_status(void *ctx, int linkup, int 
ts_index)
        if (p->link_status & LINK_UP &&
            (p->link_status & LINK_STATE_CHANGED || p->link_status & 
TS_LABEL_CHANGED)) {
                interface_get_tsinfo(p->iface);
-
-               /* Only switch phc with HW time stamping mode */
-               if (interface_tsinfo_valid(p->iface) &&
-                   interface_phc_index(p->iface) >= 0) {
-                       required_modes = clock_required_modes(p->clock);
-                       if (!interface_tsmodes_supported(p->iface, 
required_modes)) {
-                               pr_err("interface '%s' does not support 
requested "
-                                      "timestamping mode, set link status down 
by force.",
-                                      interface_label(p->iface));
-                               p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
-                       } else if (p->phc_from_cmdline) {
-                               pr_warning("%s: taking /dev/ptp%d from the "
-                                          "command line, not the attached 
ptp%d",
-                                          p->log_name, p->phc_index,
-                                          interface_phc_index(p->iface));
-                       } else if (p->phc_index != 
interface_phc_index(p->iface)) {
-                               p->phc_index = interface_phc_index(p->iface);
-
-                               if (clock_switch_phc(p->clock, p->phc_index)) {
-                                       p->last_fault_type = FT_SWITCH_PHC;
-                                       port_dispatch(p, EV_FAULT_DETECTED, 0);
-                                       return;
-                               }
-                               clock_sync_interval(p->clock, 
p->log_sync_interval);
-                       }
-               }
+               port_change_phc(p);
        }
 
        /*
@@ -2802,7 +2815,12 @@ static enum fsm_event bc_event(struct port *p, int 
fd_index)
 
        case FD_RTNL:
                pr_debug("%s: received link status notification", p->log_name);
-               rtnl_link_status(fd, p->name, port_link_status, p);
+               if (!interface_get_tsinfo(p->iface) &&
+                   (p->phc_index != interface_phc_index(p->iface)))
+                       port_change_phc(p);
+               else
+                       rtnl_link_status(fd, p->name, port_link_status, p);
+
                if (p->link_status == (LINK_UP | LINK_STATE_CHANGED))
                        return EV_FAULT_CLEARED;
                else if ((p->link_status == (LINK_DOWN | LINK_STATE_CHANGED)) ||
diff --git a/port_private.h b/port_private.h
index d27dceb..2a800a9 100644
--- a/port_private.h
+++ b/port_private.h
@@ -179,6 +179,7 @@ int port_delay_request(struct port *p);
 void port_disable(struct port *p);
 int port_initialize(struct port *p);
 int port_is_enabled(struct port *p);
+void port_change_phc(struct port *p);
 void port_link_status(void *ctx, int index, int linkup);
 int port_set_announce_tmo(struct port *p);
 int port_set_delay_tmo(struct port *p);
diff --git a/sk.c b/sk.c
index b55d6b5..80075be 100644
--- a/sk.c
+++ b/sk.c
@@ -66,6 +66,11 @@ static int hwts_init(int fd, const char *device, int 
rx_filter,
 
        init_ifreq(&ifreq, &cfg, device);
 
+       cfg.flags = HWTSTAMP_FLAG_BONDED_PHC_INDEX;
+       /* Fall back without flag if user run new build on old kernel */
+       if (ioctl(fd, SIOCGHWTSTAMP, &ifreq) == -EINVAL)
+               init_ifreq(&ifreq, &cfg, device);
+
        switch (sk_hwts_filter_mode) {
        case HWTS_FILTER_CHECK:
                err = ioctl(fd, SIOCGHWTSTAMP, &ifreq);
-- 
2.35.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to