With rtnl socket we can track link status per port(except UDS port).

We can make sure we get the correct interface and latest status with function
port_link_status().

At the same time we need to set clock sde after link down. But we return
EV_FAULT_DETECTED in port_event(), which will not set clock sde. So we need
to set it in port_link_status().

Signed-off-by: Hangbin Liu <liuhang...@gmail.com>
---
 clock.c |  5 +++++
 clock.h |  7 +++++++
 fd.h    |  1 +
 port.c  | 44 +++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/clock.c b/clock.c
index b6afba9..4c5c4e3 100644
--- a/clock.c
+++ b/clock.c
@@ -1469,6 +1469,11 @@ struct PortIdentity clock_parent_identity(struct clock 
*c)
        return c->dad.pds.parentPortIdentity;
 }
 
+void clock_set_sde(struct clock *c, int sde)
+{
+       c->sde = sde;
+}
+
 int clock_poll(struct clock *c)
 {
        int cnt, i;
diff --git a/clock.h b/clock.h
index fcd9328..49ecb76 100644
--- a/clock.h
+++ b/clock.h
@@ -205,6 +205,13 @@ void clock_peer_delay(struct clock *c, tmv_t ppd, tmv_t 
req, tmv_t rx,
                      double nrr);
 
 /**
+ * Set clock sde
+ * @param c     A pointer to a clock instance obtained with clock_create().
+ * @param sde   Pass one (1) if need a decision event and zero if not.
+ */
+void clock_set_sde(struct clock *c, int sde);
+
+/**
  * Poll for events and dispatch them.
  * @param c A pointer to a clock instance obtained with clock_create().
  * @return  Zero on success, non-zero otherwise.
diff --git a/fd.h b/fd.h
index e328e98..23401f4 100644
--- a/fd.h
+++ b/fd.h
@@ -31,6 +31,7 @@ enum {
        FD_QUALIFICATION_TIMER,
        FD_MANNO_TIMER,
        FD_SYNC_TX_TIMER,
+       FD_RTNL,
        N_POLLFD,
 };
 
diff --git a/port.c b/port.c
index ec02825..37d9f81 100644
--- a/port.c
+++ b/port.c
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/queue.h>
+#include <net/if.h>
 
 #include "bmc.h"
 #include "clock.h"
@@ -32,6 +33,7 @@
 #include "phc.h"
 #include "port.h"
 #include "print.h"
+#include "rtnl.h"
 #include "sk.h"
 #include "tlv.h"
 #include "tmv.h"
@@ -1458,7 +1460,9 @@ static void port_disable(struct port *p)
        for (i = 0; i < N_TIMER_FDS; i++) {
                close(p->fda.fd[FD_ANNOUNCE_TIMER + i]);
        }
-       port_clear_fda(p, N_POLLFD);
+
+       /* Keep rtnl socket to get link status info. */
+       port_clear_fda(p, FD_RTNL);
        clock_fda_changed(p->clock);
 }
 
@@ -1502,11 +1506,22 @@ static int port_initialize(struct port *p)
        if (port_set_announce_tmo(p))
                goto no_tmo;
 
+       /* No need to open rtnl socket on UDS port. */
+       if (p->announce_span) {
+               if (p->fda.fd[FD_RTNL] == -1)
+                       p->fda.fd[FD_RTNL] = rtnl_open();
+               if (p->fda.fd[FD_RTNL] == -1)
+                       goto no_rtnl;
+       } else {
+               p->fda.fd[FD_RTNL] = -1;
+       }
+
        port_nrate_initialize(p);
 
        clock_fda_changed(p->clock);
        return 0;
 
+no_rtnl:
 no_tmo:
        transport_close(p->trp, &p->fda);
 no_tropen:
@@ -2025,6 +2040,10 @@ void port_close(struct port *p)
        if (port_is_enabled(p)) {
                port_disable(p);
        }
+
+       if (p->fda.fd[FD_RTNL] >= 0)
+               rtnl_close(p->fda.fd[FD_RTNL]);
+
        transport_destroy(p->trp);
        tsproc_destroy(p->tsproc);
        if (p->fault_fd >= 0)
@@ -2204,6 +2223,24 @@ void port_dispatch(struct port *p, enum fsm_event event, 
int mdiff)
        }
 }
 
+static void port_link_status(void *ctx, int index, int linkup)
+{
+       struct port *p = ctx;
+
+       if (index != if_nametoindex(p->name) || p->link_status == linkup)
+               return;
+
+       p->link_status = linkup;
+       pr_notice("port %hu: link %s", portnum(p), linkup ? "up" : "down");
+
+       /*
+        * A port going down can affect the BMCA result.
+        * Force a state decision event.
+        */
+       if (!p->link_status)
+               clock_set_sde(p->clock, 1);
+}
+
 enum fsm_event port_event(struct port *p, int fd_index)
 {
        enum fsm_event event = EV_NONE;
@@ -2242,6 +2279,11 @@ enum fsm_event port_event(struct port *p, int fd_index)
                pr_debug("port %hu: master sync timeout", portnum(p));
                port_set_sync_tx_tmo(p);
                return port_tx_sync(p) ? EV_FAULT_DETECTED : EV_NONE;
+
+       case FD_RTNL:
+               pr_debug("port %hu: link status changed", portnum(p));
+               rtnl_link_status(fd, port_link_status, p);
+               return port_link_status_get(p) ? EV_FAULT_CLEARED : 
EV_FAULT_DETECTED;
        }
 
        msg = msg_allocate();
-- 
2.5.5


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to