port: add FD_RTNL event to track per-port status
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 <liuhangbin@gmail.com>master
parent
17aa750a49
commit
c149a3dbc1
5
clock.c
5
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;
|
||||
|
|
7
clock.h
7
clock.h
|
@ -204,6 +204,13 @@ void clock_path_delay(struct clock *c, tmv_t req, tmv_t rx);
|
|||
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().
|
||||
|
|
1
fd.h
1
fd.h
|
@ -31,6 +31,7 @@ enum {
|
|||
FD_QUALIFICATION_TIMER,
|
||||
FD_MANNO_TIMER,
|
||||
FD_SYNC_TX_TIMER,
|
||||
FD_RTNL,
|
||||
N_POLLFD,
|
||||
};
|
||||
|
||||
|
|
41
port.c
41
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,6 +1506,14 @@ 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 (transport_type(p->trp) != TRANS_UDS) {
|
||||
if (p->fda.fd[FD_RTNL] == -1)
|
||||
p->fda.fd[FD_RTNL] = rtnl_open();
|
||||
if (p->fda.fd[FD_RTNL] >= 0)
|
||||
rtnl_link_query(p->fda.fd[FD_RTNL]);
|
||||
}
|
||||
|
||||
port_nrate_initialize(p);
|
||||
|
||||
clock_fda_changed(p->clock);
|
||||
|
@ -2025,6 +2037,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 +2220,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 +2276,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: received link status notification", 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();
|
||||
|
|
Loading…
Reference in New Issue