6c691d
commit afd709924edcea26fec24a6253d1b85fc94c88e6
6c691d
Author: Hangbin Liu <liuhangbin@gmail.com>
6c691d
Date:   Wed May 25 14:46:14 2022 +0800
6c691d
6c691d
    ptp4l: init iface->ts_label when interface created
6c691d
    
6c691d
    It's redundant to ensure tslabel if we could get ts_info directly from
6c691d
    the interface. By init iface->ts_label when interface created, there is
6c691d
    no need to take care of ts_label on other places.
6c691d
    
6c691d
    It will also make the later vlan over bonding support patch more clear
6c691d
    after removing function interface_ensure_tslabel().
6c691d
    
6c691d
    Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
6c691d
6c691d
diff --git a/clock.c b/clock.c
6c691d
index 7ffbd6a..d4f273f 100644
6c691d
--- a/clock.c
6c691d
+++ b/clock.c
6c691d
@@ -1006,9 +1006,8 @@ struct clock *clock_create(enum clock_type type, struct config *config,
6c691d
 	required_modes = clock_required_modes(c);
6c691d
 	STAILQ_FOREACH(iface, &config->interfaces, list) {
6c691d
 		memset(ts_label, 0, sizeof(ts_label));
6c691d
-		rtnl_get_ts_device(interface_name(iface), ts_label);
6c691d
-		interface_set_label(iface, ts_label);
6c691d
-		interface_ensure_tslabel(iface);
6c691d
+		if (!rtnl_get_ts_device(interface_name(iface), ts_label))
6c691d
+			interface_set_label(iface, ts_label);
6c691d
 		interface_get_tsinfo(iface);
6c691d
 		if (interface_tsinfo_valid(iface) &&
6c691d
 		    !interface_tsmodes_supported(iface, required_modes)) {
6c691d
diff --git a/interface.c b/interface.c
6c691d
index 445a270..6c2630c 100644
6c691d
--- a/interface.c
6c691d
+++ b/interface.c
6c691d
@@ -24,6 +24,7 @@ struct interface *interface_create(const char *name)
6c691d
 		return NULL;
6c691d
 	}
6c691d
 	strncpy(iface->name, name, MAX_IFNAME_SIZE);
6c691d
+	strncpy(iface->ts_label, name, MAX_IFNAME_SIZE);
6c691d
 	iface->vclock = -1;
6c691d
 
6c691d
 	return iface;
6c691d
@@ -34,13 +35,6 @@ void interface_destroy(struct interface *iface)
6c691d
 	free(iface);
6c691d
 }
6c691d
 
6c691d
-void interface_ensure_tslabel(struct interface *iface)
6c691d
-{
6c691d
-	if (!iface->ts_label[0]) {
6c691d
-		memcpy(iface->ts_label, iface->name, MAX_IFNAME_SIZE);
6c691d
-	}
6c691d
-}
6c691d
-
6c691d
 int interface_get_tsinfo(struct interface *iface)
6c691d
 {
6c691d
 	return sk_get_ts_info(iface->ts_label, &iface->ts_info);
6c691d
diff --git a/interface.h b/interface.h
6c691d
index 752f4f1..5fc7836 100644
6c691d
--- a/interface.h
6c691d
+++ b/interface.h
6c691d
@@ -33,12 +33,6 @@ struct interface *interface_create(const char *name);
6c691d
  */
6c691d
 void interface_destroy(struct interface *iface);
6c691d
 
6c691d
-/**
6c691d
- * Ensures that an interface has a proper time stamping label.
6c691d
- * @param iface  The interface of interest.
6c691d
- */
6c691d
-void interface_ensure_tslabel(struct interface *iface);
6c691d
-
6c691d
 /**
6c691d
  * Populate the time stamping information of a given interface.
6c691d
  * @param iface  The interface of interest.
6c691d
diff --git a/nsm.c b/nsm.c
6c691d
index 5aa925b..8d4a362 100644
6c691d
--- a/nsm.c
6c691d
+++ b/nsm.c
6c691d
@@ -274,9 +274,8 @@ static int nsm_open(struct nsm *nsm, struct config *cfg)
6c691d
 	STAILQ_FOREACH(iface, &cfg->interfaces, list) {
6c691d
 		ifname = interface_name(iface);
6c691d
 		memset(ts_label, 0, sizeof(ts_label));
6c691d
-		rtnl_get_ts_device(ifname, ts_label);
6c691d
-		interface_set_label(iface, ts_label);
6c691d
-		interface_ensure_tslabel(iface);
6c691d
+		if (!rtnl_get_ts_device(ifname, ts_label))
6c691d
+			interface_set_label(iface, ts_label);
6c691d
 		count++;
6c691d
 	}
6c691d
 	if (count != 1) {
6c691d
diff --git a/pmc_common.c b/pmc_common.c
6c691d
index 756edf5..ee2ece6 100644
6c691d
--- a/pmc_common.c
6c691d
+++ b/pmc_common.c
6c691d
@@ -405,7 +405,6 @@ struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type,
6c691d
 		pr_err("failed to create interface");
6c691d
 		goto failed;
6c691d
 	}
6c691d
-	interface_ensure_tslabel(pmc->iface);
6c691d
 
6c691d
 	if (transport_open(pmc->transport, pmc->iface,
6c691d
 			   &pmc->fdarray, TS_SOFTWARE)) {
6c691d
6c691d
commit 6aab466eb0563c1025c78ab496b22a8833b02d20
6c691d
Author: Vincent Cheng <vincent.cheng.xh@renesas.com>
6c691d
Date:   Fri Jan 8 10:21:14 2021 -0500
6c691d
6c691d
    port: Fix link down/up to continue using phc_index set from command line -p option.
6c691d
    
6c691d
    In the scenario where a port link goes down and up, current code checks
6c691d
    the port's phc_index against the interface's phc_index and if they are
6c691d
    different will set the port phc_index to the interface phc_index.
6c691d
    
6c691d
    If the phc_index was initially set by the command line -p option, then we
6c691d
    end up using the wrong phc_index.
6c691d
    
6c691d
    Fix is to skip updating the port phc_index with the interface phc_index
6c691d
    when port link is back up if it was initialy set from the command line.
6c691d
    
6c691d
    Signed-off-by: Vincent Cheng <vincent.cheng.xh@renesas.com>
6c691d
6c691d
diff --git a/port.c b/port.c
6c691d
index 70b6e60..d22f30f 100644
6c691d
--- a/port.c
6c691d
+++ b/port.c
6c691d
@@ -2601,6 +2601,11 @@ void port_link_status(void *ctx, int linkup, int ts_index)
6c691d
 				       "timestamping mode, set link status down by force.",
6c691d
 				       interface_label(p->iface));
6c691d
 				p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
6c691d
+			} else if (p->phc_from_cmdline) {
6c691d
+				pr_warning("port %d: taking /dev/ptp%d from the "
6c691d
+					   "command line, not the attached ptp%d",
6c691d
+					   portnum(p), p->phc_index,
6c691d
+					   interface_phc_index(p->iface));
6c691d
 			} else if (p->phc_index != interface_phc_index(p->iface)) {
6c691d
 				p->phc_index = interface_phc_index(p->iface);
6c691d
 
6c691d
@@ -3107,6 +3112,7 @@ struct port *port_open(const char *phc_device,
6c691d
 				   "not the attached ptp%d", number, phc_device,
6c691d
 				   interface_phc_index(interface));
6c691d
 			p->phc_index = phc_index;
6c691d
+			p->phc_from_cmdline = 1;
6c691d
 		} else {
6c691d
 			pr_err("port %d: PHC device mismatch", number);
6c691d
 			pr_err("port %d: /dev/ptp%d requested, ptp%d attached",
6c691d
diff --git a/port_private.h b/port_private.h
6c691d
index fcabaa6..6e40e15 100644
6c691d
--- a/port_private.h
6c691d
+++ b/port_private.h
6c691d
@@ -69,6 +69,7 @@ struct port {
6c691d
 	struct fdarray fda;
6c691d
 	int fault_fd;
6c691d
 	int phc_index;
6c691d
+	int phc_from_cmdline;
6c691d
 
6c691d
 	void (*dispatch)(struct port *p, enum fsm_event event, int mdiff);
6c691d
 	enum fsm_event (*event)(struct port *p, int fd_index);
6c691d
6c691d
commit 45f20e824fdfb8748d73495ccc7578dc70866282
6c691d
Author: Hangbin Liu <liuhangbin@gmail.com>
6c691d
Date:   Wed May 25 14:46:15 2022 +0800
6c691d
6c691d
    port: refactor port_link_status
6c691d
    
6c691d
    Split port_change_phc() logic form port_link_status() to improve the
6c691d
    readability of the code
6c691d
    
6c691d
    (Rebased to 3.1.1)
6c691d
    
6c691d
    Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
6c691d
6c691d
diff --git a/port.c b/port.c
6c691d
index d22f30f..031b212 100644
6c691d
--- a/port.c
6c691d
+++ b/port.c
6c691d
@@ -2563,10 +2563,43 @@ static void bc_dispatch(struct port *p, enum fsm_event event, int mdiff)
6c691d
 	}
6c691d
 }
6c691d
 
6c691d
+static void port_change_phc(struct port *p)
6c691d
+{
6c691d
+	int required_modes;
6c691d
+
6c691d
+	/* Only switch a non-vclock PHC with HW time stamping. */
6c691d
+	if (!interface_tsinfo_valid(p->iface) ||
6c691d
+	    interface_get_vclock(p->iface) >= 0 ||
6c691d
+	    interface_phc_index(p->iface) < 0)
6c691d
+		return;
6c691d
+
6c691d
+	required_modes = clock_required_modes(p->clock);
6c691d
+	if (!interface_tsmodes_supported(p->iface, required_modes)) {
6c691d
+		pr_err("interface '%s' does not support requested "
6c691d
+		       "timestamping mode, set link status down by force.",
6c691d
+		       interface_label(p->iface));
6c691d
+		p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
6c691d
+	} else if (p->phc_from_cmdline) {
6c691d
+		pr_warning("port %d: taking /dev/ptp%d from the "
6c691d
+			   "command line, not the attached ptp%d",
6c691d
+			   portnum(p), p->phc_index,
6c691d
+			   interface_phc_index(p->iface));
6c691d
+	} else if (p->phc_index != interface_phc_index(p->iface)) {
6c691d
+		p->phc_index = interface_phc_index(p->iface);
6c691d
+
6c691d
+		if (clock_switch_phc(p->clock, p->phc_index)) {
6c691d
+			p->last_fault_type = FT_SWITCH_PHC;
6c691d
+			port_dispatch(p, EV_FAULT_DETECTED, 0);
6c691d
+			return;
6c691d
+		}
6c691d
+		clock_sync_interval(p->clock, p->log_sync_interval);
6c691d
+	}
6c691d
+}
6c691d
+
6c691d
 void port_link_status(void *ctx, int linkup, int ts_index)
6c691d
 {
6c691d
 	char ts_label[MAX_IFNAME_SIZE + 1] = {0};
6c691d
-	int link_state, required_modes;
6c691d
+	int link_state;
6c691d
 	const char *old_ts_label;
6c691d
 	struct port *p = ctx;
6c691d
 
6c691d
@@ -2590,33 +2623,7 @@ void port_link_status(void *ctx, int linkup, int ts_index)
6c691d
 	if (p->link_status & LINK_UP &&
6c691d
 	    (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED)) {
6c691d
 		interface_get_tsinfo(p->iface);
6c691d
-
6c691d
-		/* Only switch a non-vclock PHC with HW time stamping. */
6c691d
-		if (interface_tsinfo_valid(p->iface) &&
6c691d
-		    interface_get_vclock(p->iface) < 0 &&
6c691d
-		    interface_phc_index(p->iface) >= 0) {
6c691d
-			required_modes = clock_required_modes(p->clock);
6c691d
-			if (!interface_tsmodes_supported(p->iface, required_modes)) {
6c691d
-				pr_err("interface '%s' does not support requested "
6c691d
-				       "timestamping mode, set link status down by force.",
6c691d
-				       interface_label(p->iface));
6c691d
-				p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
6c691d
-			} else if (p->phc_from_cmdline) {
6c691d
-				pr_warning("port %d: taking /dev/ptp%d from the "
6c691d
-					   "command line, not the attached ptp%d",
6c691d
-					   portnum(p), p->phc_index,
6c691d
-					   interface_phc_index(p->iface));
6c691d
-			} else if (p->phc_index != interface_phc_index(p->iface)) {
6c691d
-				p->phc_index = interface_phc_index(p->iface);
6c691d
-
6c691d
-				if (clock_switch_phc(p->clock, p->phc_index)) {
6c691d
-					p->last_fault_type = FT_SWITCH_PHC;
6c691d
-					port_dispatch(p, EV_FAULT_DETECTED, 0);
6c691d
-					return;
6c691d
-				}
6c691d
-				clock_sync_interval(p->clock, p->log_sync_interval);
6c691d
-			}
6c691d
-		}
6c691d
+		port_change_phc(p);
6c691d
 	}
6c691d
 
6c691d
 	/*
6c691d
6c691d
commit 878c2eac77cc7abd1d86620a82ae9046545439ea
6c691d
Author: Hangbin Liu <liuhangbin@gmail.com>
6c691d
Date:   Wed May 25 14:46:16 2022 +0800
6c691d
6c691d
    ptp4l: add VLAN over bond support
6c691d
    
6c691d
    Latest Linux kernel has supported getting active port's PHC from bond
6c691d
    directly. This would help topology like VLAN over bond to get PHC natively,
6c691d
    as VLAN also albe to get downlink's PHC.
6c691d
    
6c691d
    To achieve this, the new hwtstamp flag is needed when passing hwtstamp_config
6c691d
    to kernel. Let's supply the flag first, and fall back without flag if user
6c691d
    run on old kernel.
6c691d
    
6c691d
    We also need to update the PHC index in port_link_status() when there is
6c691d
    a RTNL event. The PHC info will be update in later port_change_phc().
6c691d
    
6c691d
    Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
6c691d
6c691d
diff --git a/clock.c b/clock.c
6c691d
index d4f273f..f3df220 100644
6c691d
--- a/clock.c
6c691d
+++ b/clock.c
6c691d
@@ -1758,6 +1758,9 @@ int clock_switch_phc(struct clock *c, int phc_index)
6c691d
 	c->clkid = clkid;
6c691d
 	c->servo = servo;
6c691d
 	c->servo_state = SERVO_UNLOCKED;
6c691d
+
6c691d
+	pr_info("Switched to /dev/ptp%d as PTP clock", phc_index);
6c691d
+
6c691d
 	return 0;
6c691d
 }
6c691d
 
6c691d
diff --git a/missing.h b/missing.h
6c691d
index c5194f4..5f684dd 100644
6c691d
--- a/missing.h
6c691d
+++ b/missing.h
6c691d
@@ -73,6 +73,12 @@ struct so_timestamping {
6c691d
 };
6c691d
 #endif
6c691d
 
6c691d
+#ifndef HWTSTAMP_FLAG_BONDED_PHC_INDEX
6c691d
+enum {
6c691d
+	HWTSTAMP_FLAG_BONDED_PHC_INDEX = (1<<0),
6c691d
+};
6c691d
+#endif
6c691d
+
6c691d
 #ifdef PTP_EXTTS_REQUEST2
6c691d
 #define PTP_EXTTS_REQUEST_FAILED "PTP_EXTTS_REQUEST2 failed: %m"
6c691d
 #else
6c691d
diff --git a/port.c b/port.c
6c691d
index 031b212..ae9c4d3 100644
6c691d
--- a/port.c
6c691d
+++ b/port.c
6c691d
@@ -2619,12 +2619,18 @@ void port_link_status(void *ctx, int linkup, int ts_index)
6c691d
 		pr_notice("port %hu: ts label changed to %s", portnum(p), ts_label);
6c691d
 	}
6c691d
 
6c691d
+	/* phc index may changed while ts_label keeps the same after failover.
6c691d
+	 * e.g. vlan over bond. Since the lower link changed, we still set
6c691d
+	 * the TS_LABEL_CHANGED flag.
6c691d
+	 */
6c691d
+	interface_get_tsinfo(p->iface);
6c691d
+	if (p->phc_index != interface_phc_index(p->iface))
6c691d
+		p->link_status |= TS_LABEL_CHANGED;
6c691d
+
6c691d
 	/* Both link down/up and change ts_label may change phc index. */
6c691d
 	if (p->link_status & LINK_UP &&
6c691d
-	    (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED)) {
6c691d
-		interface_get_tsinfo(p->iface);
6c691d
+	    (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED))
6c691d
 		port_change_phc(p);
6c691d
-	}
6c691d
 
6c691d
 	/*
6c691d
 	 * A port going down can affect the BMCA result.
6c691d
diff --git a/sk.c b/sk.c
6c691d
index b55d6b5..80075be 100644
6c691d
--- a/sk.c
6c691d
+++ b/sk.c
6c691d
@@ -66,6 +66,11 @@ static int hwts_init(int fd, const char *device, int rx_filter,
6c691d
 
6c691d
 	init_ifreq(&ifreq, &cfg, device);
6c691d
 
6c691d
+	cfg.flags = HWTSTAMP_FLAG_BONDED_PHC_INDEX;
6c691d
+	/* Fall back without flag if user run new build on old kernel */
6c691d
+	if (ioctl(fd, SIOCGHWTSTAMP, &ifreq) == -EINVAL)
6c691d
+		init_ifreq(&ifreq, &cfg, device);
6c691d
+
6c691d
 	switch (sk_hwts_filter_mode) {
6c691d
 	case HWTS_FILTER_CHECK:
6c691d
 		err = ioctl(fd, SIOCGHWTSTAMP, &ifreq);
6c691d
6c691d
commit 98edb4d72b3d1d4e988f810b9a9cb1078212e5dc
6c691d
Author: Miroslav Lichvar <mlichvar@redhat.com>
6c691d
Date:   Tue Nov 22 17:07:16 2022 +0100
6c691d
6c691d
    port: Avoid faults with vclocks and PHC from command line.
6c691d
    
6c691d
    After commit afeabf3c90ed ("ptp4l: add VLAN over bond support") the
6c691d
    TS_LABEL_CHANGED flag was set on link status changes when the used
6c691d
    PHC index was different from the PHC index of the interface.
6c691d
    
6c691d
    This caused the port to be constantly switching to the faulty state when
6c691d
    using vclocks, or a different PHC device was forced with the -p option,
6c691d
    where it is expected the used PHC doesn't match the interface's PHC.
6c691d
    
6c691d
    Rework port_link_status() and port_change_phc() to avoid setting the
6c691d
    flag and switch the clock only in the cases where it is expected.
6c691d
    
6c691d
    Fixes: afeabf3c90ed ("ptp4l: add VLAN over bond support")
6c691d
    Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
6c691d
6c691d
diff --git a/port.c b/port.c
6c691d
index ae9c4d3..96e097a 100644
6c691d
--- a/port.c
6c691d
+++ b/port.c
6c691d
@@ -2567,10 +2567,13 @@ static void port_change_phc(struct port *p)
6c691d
 {
6c691d
 	int required_modes;
6c691d
 
6c691d
-	/* Only switch a non-vclock PHC with HW time stamping. */
6c691d
-	if (!interface_tsinfo_valid(p->iface) ||
6c691d
+	/* Try to switch only if the interface is up, it has HW time stamping
6c691d
+	   using a non-vclock PHC, and the PHC actually changed. */
6c691d
+	if (!(p->link_status & LINK_UP) ||
6c691d
+	    !interface_tsinfo_valid(p->iface) ||
6c691d
 	    interface_get_vclock(p->iface) >= 0 ||
6c691d
-	    interface_phc_index(p->iface) < 0)
6c691d
+	    interface_phc_index(p->iface) < 0 ||
6c691d
+	    p->phc_index == interface_phc_index(p->iface))
6c691d
 		return;
6c691d
 
6c691d
 	required_modes = clock_required_modes(p->clock);
6c691d
@@ -2584,7 +2587,7 @@ static void port_change_phc(struct port *p)
6c691d
 			   "command line, not the attached ptp%d",
6c691d
 			   portnum(p), p->phc_index,
6c691d
 			   interface_phc_index(p->iface));
6c691d
-	} else if (p->phc_index != interface_phc_index(p->iface)) {
6c691d
+	} else {
6c691d
 		p->phc_index = interface_phc_index(p->iface);
6c691d
 
6c691d
 		if (clock_switch_phc(p->clock, p->phc_index)) {
6c691d
@@ -2619,18 +2622,12 @@ void port_link_status(void *ctx, int linkup, int ts_index)
6c691d
 		pr_notice("port %hu: ts label changed to %s", portnum(p), ts_label);
6c691d
 	}
6c691d
 
6c691d
-	/* phc index may changed while ts_label keeps the same after failover.
6c691d
-	 * e.g. vlan over bond. Since the lower link changed, we still set
6c691d
-	 * the TS_LABEL_CHANGED flag.
6c691d
-	 */
6c691d
+	/* The PHC index may change even with the same ts_label, e.g. after
6c691d
+	   failover with VLAN over bond. */
6c691d
 	interface_get_tsinfo(p->iface);
6c691d
-	if (p->phc_index != interface_phc_index(p->iface))
6c691d
-		p->link_status |= TS_LABEL_CHANGED;
6c691d
 
6c691d
-	/* Both link down/up and change ts_label may change phc index. */
6c691d
-	if (p->link_status & LINK_UP &&
6c691d
-	    (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED))
6c691d
-		port_change_phc(p);
6c691d
+	/* Switch the clock if needed */
6c691d
+	port_change_phc(p);
6c691d
 
6c691d
 	/*
6c691d
 	 * A port going down can affect the BMCA result.