Now the ts label will be either the bond active slave or the interface name, which is the exactly interface we need to get ts info.
If there is a fail over and ts_label changed, we need to check the clock_required_modes. We will set the link to LINK_DOWN by force if the new ts_label's timestamp do not support required mode. If all good, then we will switch phc index to new one. Signed-off-by: Hangbin Liu <liuhang...@gmail.com> --- clock.c | 14 ++++++++++++++ config.c | 1 - port.c | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/clock.c b/clock.c index bd2b91b..a9da8c6 100644 --- a/clock.c +++ b/clock.c @@ -38,6 +38,7 @@ #include "servo.h" #include "stats.h" #include "print.h" +#include "rtnl.h" #include "tlv.h" #include "tsproc.h" #include "uds.h" @@ -834,6 +835,16 @@ int clock_required_modes(struct clock *c) return required_modes; } +/* + * If we do not have a slave or the rtnl query failed, then use our + * own interface name as the time stamping interface name. + */ +static void ensure_ts_label(struct interface *iface) +{ + if (iface->ts_label[0] == '\0') + strncpy(iface->ts_label, iface->name, MAX_IFNAME_SIZE); +} + struct clock *clock_create(enum clock_type type, struct config *config, const char *phc_device) { @@ -945,6 +956,9 @@ struct clock *clock_create(enum clock_type type, struct config *config, c->timestamping = timestamping; required_modes = clock_required_modes(c); STAILQ_FOREACH(iface, &config->interfaces, list) { + rtnl_get_ts_label(iface); + ensure_ts_label(iface); + sk_get_ts_info(iface->ts_label, &iface->ts_info); if (iface->ts_info.valid && ((iface->ts_info.so_timestamping & required_modes) != required_modes)) { pr_err("interface '%s' does not support " diff --git a/config.c b/config.c index e6fe676..bbaf36e 100644 --- a/config.c +++ b/config.c @@ -633,7 +633,6 @@ struct interface *config_create_interface(char *name, struct config *cfg) } strncpy(iface->name, name, MAX_IFNAME_SIZE); - sk_get_ts_info(iface->name, &iface->ts_info); STAILQ_INSERT_TAIL(&cfg->interfaces, iface, list); cfg->n_interfaces++; diff --git a/port.c b/port.c index 81d52ff..5f638c0 100644 --- a/port.c +++ b/port.c @@ -60,6 +60,7 @@ enum link_state { LINK_DOWN = (1<<0), LINK_UP = (1<<1), LINK_STATE_CHANGED = (1<<3), + TS_LABEL_CHANGED = (1<<4), }; struct nrate_estimator { @@ -2231,6 +2232,8 @@ static void port_link_status(void *ctx, int linkup, int ts_index) { struct port *p = ctx; int link_state; + char ts_label[MAX_IFNAME_SIZE + 1]; + int required_modes; link_state = linkup ? LINK_UP : LINK_DOWN; if (p->link_status & link_state) { @@ -2240,6 +2243,35 @@ static void port_link_status(void *ctx, int linkup, int ts_index) pr_notice("port %hu: link %s", portnum(p), linkup ? "up" : "down"); } + /* ts_label changed */ + if (if_indextoname(ts_index, ts_label) && strcmp(p->iface->ts_label, ts_label)) { + strncpy(p->iface->ts_label, ts_label, MAX_IFNAME_SIZE); + sk_get_ts_info(p->iface->ts_label, &p->iface->ts_info); + + p->link_status |= TS_LABEL_CHANGED; + pr_notice("port %hu: ts label changed to %s", portnum(p), ts_label); + } + + /* We set the link status to down by force if its timestamp not + * support required mode. But the link's status is actually up. + * + * So the next time we receive this link's rtnl message, we need + * to check the required_modes again. If still not support + * required_modes, then keep the link status down. + */ + if (p->iface->ts_info.valid) { + required_modes = clock_required_modes(p->clock); + if ((p->iface->ts_info.so_timestamping & required_modes) != required_modes) { + pr_err("interface '%s' does not support requested " + "timestamping mode, set link status down by force.", + p->iface->ts_label); + p->link_status = LINK_DOWN | LINK_STATE_CHANGED; + } else if (p->link_status & TS_LABEL_CHANGED) { + p->phc_index = p->iface->ts_info.phc_index; + clock_switch_phc(p->clock, p->phc_index); + } + } + /* * A port going down can affect the BMCA result. * Force a state decision event. @@ -2292,7 +2324,8 @@ enum fsm_event port_event(struct port *p, int fd_index) 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)) + else if ((p->link_status == (LINK_DOWN | LINK_STATE_CHANGED)) || + (p->link_status & TS_LABEL_CHANGED)) return EV_FAULT_DETECTED; else return EV_NONE; -- 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