---
This patch implements a primitive way to recognize a PTP ports operational link 
status. If a link on a network interface goes down, it will create an 
EV_DESIGNATED_DISABLED transition for the appropriate PTP port (setting it into 
PS_DISABLED state). If a link on a network interface goes up, it will create a 
EV_DESIGNATED_ENABLED transition to return the related PTP port into 
PS_LISTENING 
state.

The most important advantage of this patch is its massive reduction of log noise
if a PTP port loses its link for some reason.

Signed-off-by: Henry Jesuiter <henry.jesui...@alcnetworx.de>
---
diff -rwbBu -p a/clock.c b/clock.c
--- a/clock.c   2016-07-21 16:49:14.000000000 +0200
+++ b/clock.c   2016-07-28 11:01:08.949982556 +0200
@@ -1422,6 +1422,13 @@ int clock_poll(struct clock *c)
        cur = c->pollfd;
        LIST_FOREACH(p, &c->ports, list) {
                /* Let the ports handle their events. */
+               event = port_link_state(p);
+               if ((EV_DESIGNATED_DISABLED == event) 
+                   || (EV_DESIGNATED_ENABLED == event)) {
+                       sde = 1;
+                       port_dispatch(p, event, 0);
+               }
+
                for (i = err = 0; i < N_POLLFD && !err; i++) {
                        if (cur[i].revents & (POLLIN|POLLPRI)) {
                                event = port_event(p, i);
diff -rwbBu -p a/port.c b/port.c
--- a/port.c    2016-07-21 16:49:14.000000000 +0200
+++ b/port.c    2016-07-28 10:59:56.377398582 +0200
@@ -2194,6 +2194,24 @@ int port_dispatch(struct port *p, enum f
        return 0;
 }
 
+enum fsm_event port_link_state(struct port* p)
+{
+       int link_status = sk_interface_link_state(p->name);
+
+       if((link_status <= 0) && (port_state(p) != PS_DISABLED)) {
+               /* either link down, or failure on getting link status */
+               pr_debug("port %hu: link down on %s", portnum(p), p->name);
+               return EV_DESIGNATED_DISABLED;
+       }
+
+       if((link_status > 0) && (port_state(p) == PS_DISABLED)) {
+               pr_debug("port %hu: link up on %s", portnum(p), p->name);
+               return EV_DESIGNATED_ENABLED;
+       }
+
+       return EV_NONE;
+}
+
 enum fsm_event port_event(struct port *p, int fd_index)
 {
        enum fsm_event event = EV_NONE;
diff -rwbBu -p a/port.h b/port.h
--- a/port.h    2016-07-21 16:49:14.000000000 +0200
+++ b/port.h    2016-07-28 11:00:22.021614463 +0200
@@ -120,6 +120,14 @@ int port_prepare_and_send(struct port *p
 struct PortIdentity port_identity(struct port *p);
 
 /**
+ * Check for port link state changes.
+ * @param port A pointer previously obtained via port_open().
+ * @return EV_NONE if nothing happened, EV_DESIGNATED_DISABLED on
+ *         link down and EV_DESIGNATED_ENABLED on link up
+ */
+enum fsm_event port_link_state(struct port *p);
+
+/**
  * Obtain a port number.
  * @param p        A port instance.
  * @return         The port number of 'p'.
diff -rwbBu -p a/sk.c b/sk.c
--- a/sk.c      2016-07-21 16:49:14.000000000 +0200
+++ b/sk.c      2016-07-28 11:01:31.870150427 +0200
@@ -211,6 +211,27 @@ int sk_interface_addr(const char *name,
        return result;
 }
 
+int sk_interface_link_state(const char *name) {
+       int sock;
+       struct ifreq if_req;
+
+       sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+       if(sock < 0) {
+               return -1;
+       }
+
+       strncpy(if_req.ifr_name, name, sizeof(if_req.ifr_name));
+       if(ioctl(sock, SIOCGIFFLAGS, &if_req) < 0) {
+               close(sock);
+               return -1;
+       }
+       close(sock);
+
+       /* IFF_RUNNING => operational status, e.g. actual link status        */
+       /* IFF_UP      => administrative status, interface up/down in system */
+       return if_req.ifr_flags & IFF_RUNNING ? 1 : 0;
+}
+
 static short sk_events = POLLPRI;
 static short sk_revents = POLLPRI;
 
diff -rwbBu -p a/sk.h b/sk.h
--- a/sk.h      2016-07-21 16:49:14.000000000 +0200
+++ b/sk.h      2016-07-28 10:57:41.944071527 +0200
@@ -80,6 +80,13 @@ int sk_interface_macaddr(const char *nam
 int sk_interface_addr(const char *name, int family, struct address *addr);
 
 /**
+ * Check operational link status of an interface
+ * @param name  The name of the interface
+ * @return 0 on link down, 1 on link up, -1 on failure
+ */
+int sk_interface_link_state(const char *name);
+
+/**
  * Read a message from a socket.
  * @param fd      An open socket.
  * @param buf     Buffer to receive the message.

---

Please note: as the commit message tells, that is a primitive method to 
recognize the link status,
since it will poll for this information each time clock_poll() will be called. 
Another (better) 
solution could use the linux netlink socket infrastructure. If you prefer such 
implementation
I could provide it as well.

Best regards
Henry Jesuiter



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

Reply via email to