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;
|
return c->dad.pds.parentPortIdentity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clock_set_sde(struct clock *c, int sde)
|
||||||
|
{
|
||||||
|
c->sde = sde;
|
||||||
|
}
|
||||||
|
|
||||||
int clock_poll(struct clock *c)
|
int clock_poll(struct clock *c)
|
||||||
{
|
{
|
||||||
int cnt, i;
|
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,
|
void clock_peer_delay(struct clock *c, tmv_t ppd, tmv_t req, tmv_t rx,
|
||||||
double nrr);
|
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.
|
* Poll for events and dispatch them.
|
||||||
* @param c A pointer to a clock instance obtained with clock_create().
|
* @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_QUALIFICATION_TIMER,
|
||||||
FD_MANNO_TIMER,
|
FD_MANNO_TIMER,
|
||||||
FD_SYNC_TX_TIMER,
|
FD_SYNC_TX_TIMER,
|
||||||
|
FD_RTNL,
|
||||||
N_POLLFD,
|
N_POLLFD,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
41
port.c
41
port.c
|
@ -23,6 +23,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
#include "bmc.h"
|
#include "bmc.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
#include "phc.h"
|
#include "phc.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
#include "rtnl.h"
|
||||||
#include "sk.h"
|
#include "sk.h"
|
||||||
#include "tlv.h"
|
#include "tlv.h"
|
||||||
#include "tmv.h"
|
#include "tmv.h"
|
||||||
|
@ -1458,7 +1460,9 @@ static void port_disable(struct port *p)
|
||||||
for (i = 0; i < N_TIMER_FDS; i++) {
|
for (i = 0; i < N_TIMER_FDS; i++) {
|
||||||
close(p->fda.fd[FD_ANNOUNCE_TIMER + 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);
|
clock_fda_changed(p->clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1502,6 +1506,14 @@ static int port_initialize(struct port *p)
|
||||||
if (port_set_announce_tmo(p))
|
if (port_set_announce_tmo(p))
|
||||||
goto no_tmo;
|
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);
|
port_nrate_initialize(p);
|
||||||
|
|
||||||
clock_fda_changed(p->clock);
|
clock_fda_changed(p->clock);
|
||||||
|
@ -2025,6 +2037,10 @@ void port_close(struct port *p)
|
||||||
if (port_is_enabled(p)) {
|
if (port_is_enabled(p)) {
|
||||||
port_disable(p);
|
port_disable(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p->fda.fd[FD_RTNL] >= 0)
|
||||||
|
rtnl_close(p->fda.fd[FD_RTNL]);
|
||||||
|
|
||||||
transport_destroy(p->trp);
|
transport_destroy(p->trp);
|
||||||
tsproc_destroy(p->tsproc);
|
tsproc_destroy(p->tsproc);
|
||||||
if (p->fault_fd >= 0)
|
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 port_event(struct port *p, int fd_index)
|
||||||
{
|
{
|
||||||
enum fsm_event event = EV_NONE;
|
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));
|
pr_debug("port %hu: master sync timeout", portnum(p));
|
||||||
port_set_sync_tx_tmo(p);
|
port_set_sync_tx_tmo(p);
|
||||||
return port_tx_sync(p) ? EV_FAULT_DETECTED : EV_NONE;
|
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();
|
msg = msg_allocate();
|
||||||
|
|
Loading…
Reference in New Issue