This patch introduces
- "enable" configuration flag at port level
- support for ENABLE_PORT and DISABLE_PORT TLV commands
---
clock.c | 6 +++-
config.c | 1 +
designated_fsm.c | 36 ++++++++++++++++++++---
e2e_tc.c | 11 +++++++
fd.h | 1 +
p2p_tc.c | 11 +++++++
pmc_common.c | 9 +++---
port.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++--
port.h | 19 +++++++++++++
port_private.h | 4 ++-
ptp4l.8 | 3 ++
11 files changed, 161 insertions(+), 14 deletions(-)
diff --git a/clock.c b/clock.c
index e545a9b..d1ab880 100644
--- a/clock.c
+++ b/clock.c
@@ -1250,7 +1250,11 @@ struct clock *clock_create(enum clock_type type, struct
config *config,
c->dds.numberPorts = c->nports;
LIST_FOREACH(p, &c->ports, list) {
- port_dispatch(p, EV_INITIALIZE, 0);
+ if (port_enable(p)) {
+ port_dispatch(p, EV_INITIALIZE, 0);
+ } else {
+ port_dispatch(p, EV_DESIGNATED_DISABLED, 0);
+ }
}
port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0);
port_dispatch(c->uds_ro_port, EV_INITIALIZE, 0);
diff --git a/config.c b/config.c
index 4472d3d..b32e0a3 100644
--- a/config.c
+++ b/config.c
@@ -242,6 +242,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_INT("dscp_event", 0, 0, 63),
GLOB_ITEM_INT("dscp_general", 0, 0, 63),
GLOB_ITEM_INT("domainNumber", 0, 0, 127),
+ PORT_ITEM_INT("enable", 1, 0, 1),
PORT_ITEM_INT("egressLatency", 0, INT_MIN, INT_MAX),
PORT_ITEM_INT("fault_badpeernet_interval", 16, INT32_MIN, INT32_MAX),
PORT_ITEM_INT("fault_reset_interval", 4, INT8_MIN, INT8_MAX),
diff --git a/designated_fsm.c b/designated_fsm.c
index d19158b..c6bb692 100644
--- a/designated_fsm.c
+++ b/designated_fsm.c
@@ -44,16 +44,34 @@ enum port_state designated_master_fsm(enum port_state state,
break;
case PS_FAULTY:
- if (event == EV_FAULT_CLEARED) {
+ switch (event) {
+ case EV_DESIGNATED_DISABLED:
+ next = PS_DISABLED;
+ break;
+ case EV_FAULT_CLEARED:
next = PS_INITIALIZING;
+ break;
+ default:
+ break;
}
break;
+ case PS_DISABLED:
+ if (EV_DESIGNATED_ENABLED == event)
+ next = PS_INITIALIZING;
+ break;
+
case PS_MASTER:
- if (event == EV_FAULT_DETECTED) {
+ switch (event) {
+ case EV_FAULT_DETECTED:
next = PS_FAULTY;
+ break;
+ case EV_DESIGNATED_DISABLED:
+ next = PS_DISABLED;
+ break;
+ default:
+ break;
}
- break;
default:
break;
@@ -85,13 +103,23 @@ enum port_state designated_slave_fsm(enum port_state state,
break;
case PS_FAULTY:
- if (event == EV_FAULT_CLEARED) {
+ switch (event) {
+ case EV_DESIGNATED_DISABLED:
+ next = PS_DISABLED;
+ break;
+ case EV_FAULT_CLEARED:
next = PS_INITIALIZING;
+ break;
+ default:
+ break;
}
break;
case PS_SLAVE:
switch (event) {
+ case EV_DESIGNATED_DISABLED:
+ next = PS_DISABLED;
+ break;
case EV_FAULT_DETECTED:
next = PS_FAULTY;
break;
diff --git a/e2e_tc.c b/e2e_tc.c
index 2f8e821..dea482f 100644
--- a/e2e_tc.c
+++ b/e2e_tc.c
@@ -124,6 +124,8 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
case FD_RTNL:
pr_debug("%s: received link status notification", p->log_name);
rtnl_link_status(fd, p->name, port_link_status, p);
+ if (!p->enable)
+ return EV_NONE;
if (p->link_status == (LINK_UP|LINK_STATE_CHANGED)) {
return EV_FAULT_CLEARED;
} else if ((p->link_status == (LINK_DOWN|LINK_STATE_CHANGED)) ||
@@ -132,6 +134,15 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
} else {
return EV_NONE;
}
+
+ case FD_PORT_ENABLE:
+ pr_debug("%s: received port enable/disable notification",
p->log_name);
+ if (!port_enable_changed(fd, p))
+ return EV_NONE;
+ else if (p->enable)
+ return EV_DESIGNATED_ENABLED;
+ else
+ return EV_DESIGNATED_DISABLED;
}
msg = msg_allocate();
diff --git a/fd.h b/fd.h
index 16420d7..f60e208 100644
--- a/fd.h
+++ b/fd.h
@@ -40,6 +40,7 @@ enum {
FD_UNICAST_REQ_TIMER,
FD_UNICAST_SRV_TIMER,
FD_RTNL,
+ FD_PORT_ENABLE,
N_POLLFD,
};
diff --git a/p2p_tc.c b/p2p_tc.c
index 75cb3b9..b2863d2 100644
--- a/p2p_tc.c
+++ b/p2p_tc.c
@@ -127,6 +127,8 @@ enum fsm_event p2p_event(struct port *p, int fd_index)
case FD_RTNL:
pr_debug("%s: received link status notification", p->log_name);
rtnl_link_status(fd, p->name, port_link_status, p);
+ if (!p->enable)
+ return EV_NONE;
if (p->link_status == (LINK_UP|LINK_STATE_CHANGED)) {
return EV_FAULT_CLEARED;
} else if ((p->link_status == (LINK_DOWN|LINK_STATE_CHANGED)) ||
@@ -135,6 +137,15 @@ enum fsm_event p2p_event(struct port *p, int fd_index)
} else {
return EV_NONE;
}
+
+ case FD_PORT_ENABLE:
+ pr_debug("%s: received port enable/disable notification",
p->log_name);
+ if (!port_enable_changed(fd, p))
+ return EV_NONE;
+ else if (p->enable)
+ return EV_DESIGNATED_ENABLED;
+ else
+ return EV_DESIGNATED_DISABLED;
}
msg = msg_allocate();
diff --git a/pmc_common.c b/pmc_common.c
index c7d8bed..af1de95 100644
--- a/pmc_common.c
+++ b/pmc_common.c
@@ -119,8 +119,8 @@ struct management_id idtab[] = {
{ "ANNOUNCE_RECEIPT_TIMEOUT", TLV_ANNOUNCE_RECEIPT_TIMEOUT,
do_get_action },
{ "LOG_SYNC_INTERVAL", TLV_LOG_SYNC_INTERVAL, do_get_action },
{ "VERSION_NUMBER", TLV_VERSION_NUMBER, do_get_action },
- { "ENABLE_PORT", TLV_ENABLE_PORT, not_supported },
- { "DISABLE_PORT", TLV_DISABLE_PORT, not_supported },
+ { "ENABLE_PORT", TLV_ENABLE_PORT, do_cmd_action },
+ { "DISABLE_PORT", TLV_DISABLE_PORT, do_cmd_action },
{ "UNICAST_NEGOTIATION_ENABLE", TLV_UNICAST_NEGOTIATION_ENABLE,
not_supported },
{ "UNICAST_MASTER_TABLE", TLV_UNICAST_MASTER_TABLE, not_supported },
{ "UNICAST_MASTER_MAX_TABLE_SIZE", TLV_UNICAST_MASTER_MAX_TABLE_SIZE,
not_supported },
@@ -297,13 +297,12 @@ static void do_cmd_action(struct pmc *pmc, int action,
int index, char *str)
idtab[index].name);
return;
}
-/*
switch (code) {
- case TLV_XXXX:
+ case TLV_ENABLE_PORT:
+ case TLV_DISABLE_PORT:
pmc_send_cmd_action(pmc, code);
break;
}
-*/
}
static void not_supported(struct pmc *pmc, int action, int index, char *str)
diff --git a/port.c b/port.c
index 10bb9e1..adbef50 100644
--- a/port.c
+++ b/port.c
@@ -18,6 +18,7 @@
*/
#include <arpa/inet.h>
#include <errno.h>
+#include <fcntl.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
@@ -2396,6 +2397,12 @@ void port_close(struct port *p)
if (p->fault_fd >= 0) {
close(p->fault_fd);
}
+ if (p->enable_ev_fd >=0) {
+ close(p->enable_ev_fd);
+ }
+ if (p->fda.fd[FD_PORT_ENABLE] >=0) {
+ close(p->fda.fd[FD_PORT_ENABLE]);
+ }
free(p->log_name);
free(p);
}
@@ -2619,6 +2626,30 @@ void port_link_status(void *ctx, int linkup, int
ts_index)
clock_set_sde(p->clock, 1);
}
+int port_enable_changed(int fd, struct port *p)
+{
+ int enable;
+
+ if (read(fd, &enable, sizeof(enable)) != sizeof(enable)) {
+ pr_err("%s: Unable to receince enable/disable event",
p->log_name);
+ return 0;
+ }
+
+ enable = !!enable; // normalize value;
+
+ if (enable == p->enable)
+ return 0;
+
+ p->enable = enable;
+
+ return 1;
+}
+
+int port_enable(struct port *p)
+{
+ return p->enable;
+}
+
enum fsm_event port_event(struct port *p, int fd_index)
{
return p->event(p, fd_index);
@@ -2696,6 +2727,8 @@ static enum fsm_event bc_event(struct port *p, int
fd_index)
case FD_RTNL:
pr_debug("%s: received link status notification", p->log_name);
rtnl_link_status(fd, p->name, port_link_status, p);
+ if (!p->enable)
+ return EV_NONE;
if (p->link_status == (LINK_UP | LINK_STATE_CHANGED))
return EV_FAULT_CLEARED;
else if ((p->link_status == (LINK_DOWN | LINK_STATE_CHANGED)) ||
@@ -2703,6 +2736,15 @@ static enum fsm_event bc_event(struct port *p, int
fd_index)
return EV_FAULT_DETECTED;
else
return EV_NONE;
+
+ case FD_PORT_ENABLE:
+ pr_debug("%s: received port enable/disable notification",
p->log_name);
+ if (!port_enable_changed(fd, p))
+ return EV_NONE;
+ else if (p->enable)
+ return EV_DESIGNATED_ENABLED;
+ else
+ return EV_DESIGNATED_DISABLED;
}
msg = msg_allocate();
@@ -2862,6 +2904,7 @@ int port_manage(struct port *p, struct port *ingress,
struct ptp_message *msg)
{
struct management_tlv *mgt;
UInteger16 target = msg->management.targetPortIdentity.portNumber;
+ int enable;
if (target != portnum(p) && target != 0xffff) {
return 0;
@@ -2884,6 +2927,15 @@ int port_manage(struct port *p, struct port *ingress,
struct ptp_message *msg)
}
switch (mgt->id) {
+ case TLV_ENABLE_PORT:
+ case TLV_DISABLE_PORT:
+ // raise port enable/disable change event
+ enable = (mgt->id == TLV_ENABLE_PORT);
+ if (write(p->enable_ev_fd, &enable, sizeof(enable)) !=
sizeof(enable)) {
+ pr_err("%s: Unable to forward port %s change envent",
p->log_name, enable ? "enable" : "disable");
+ }
+ break;
+
case TLV_NULL_MANAGEMENT:
case TLV_CLOCK_DESCRIPTION:
case TLV_PORT_DATA_SET:
@@ -2891,8 +2943,6 @@ int port_manage(struct port *p, struct port *ingress,
struct ptp_message *msg)
case TLV_ANNOUNCE_RECEIPT_TIMEOUT:
case TLV_LOG_SYNC_INTERVAL:
case TLV_VERSION_NUMBER:
- case TLV_ENABLE_PORT:
- case TLV_DISABLE_PORT:
case TLV_UNICAST_NEGOTIATION_ENABLE:
case TLV_UNICAST_MASTER_TABLE:
case TLV_UNICAST_MASTER_MAX_TABLE_SIZE:
@@ -3039,6 +3089,7 @@ struct port *port_open(const char *phc_device,
struct config *cfg = clock_config(clock);
struct port *p = malloc(sizeof(*p));
int i;
+ int enable_fds[2];
if (!p) {
return NULL;
@@ -3119,6 +3170,7 @@ struct port *port_open(const char *phc_device,
}
p->iface = interface;
+ p->enable = config_get_int(cfg, p->name, "enable");
p->asymmetry = config_get_int(cfg, p->name, "delayAsymmetry");
p->asymmetry <<= 16;
p->announce_span = port_is_uds(p) ? 0 : ANNOUNCE_SPAN;
@@ -3137,7 +3189,11 @@ struct port *port_open(const char *phc_device,
p->timestamping = timestamping;
p->portIdentity.clockIdentity = clock_identity(clock);
p->portIdentity.portNumber = number;
- p->state = PS_INITIALIZING;
+ if (p->enable) {
+ p->state = PS_INITIALIZING;
+ } else {
+ p->state = PS_DISABLED;
+ }
p->delayMechanism = config_get_int(cfg, p->name, "delay_mechanism");
p->versionNumber = PTP_MAJOR_VERSION;
p->slave_event_monitor = clock_slave_monitor(clock);
@@ -3201,8 +3257,16 @@ struct port *port_open(const char *phc_device,
goto err_tsproc;
}
}
+ if (pipe2(enable_fds, O_DIRECT | O_NONBLOCK) < 0) {
+ pr_err("unable to open event fd: %m");
+ goto err_fd_port_enable;
+ }
+ p->fda.fd[FD_PORT_ENABLE] = enable_fds[0];
+ p->enable_ev_fd = enable_fds[1];
+
return p;
+err_fd_port_enable:
err_tsproc:
tsproc_destroy(p->tsproc);
err_uc_service:
@@ -3227,6 +3291,10 @@ int port_state_update(struct port *p, enum fsm_event
event, int mdiff)
{
enum port_state next = p->state_machine(p->state, event, mdiff);
+ if (PS_DISABLED == next) {
+ port_disable(p);
+ }
+
if (PS_FAULTY == next) {
struct fault_interval i;
fault_interval(p, last_fault_type(p), &i);
diff --git a/port.h b/port.h
index 37a4e19..05f3bb1 100644
--- a/port.h
+++ b/port.h
@@ -75,6 +75,25 @@ struct foreign_clock *port_compute_best(struct port *port);
*/
void port_dispatch(struct port *p, enum fsm_event event, int mdiff);
+/**
+ * Return portEnable changes. This may cause a state transition on the
+ * port, with the associated side effect.
+ *
+ * @param fd, Event file descriptor.
+ * @param port A pointer previously obtained via port_open().
+ * @return true if the portEnable changed, false otherwise.
+ */
+int port_enable_changed(int fd, struct port *p);
+
+/**
+ * Return portEnable status. This may cause a state transition on the
+ * port, with the associated side effect.
+ *
+ * @param port A pointer previously obtained via port_open().
+ * @return true if the portEnable changed, false otherwise.
+ */
+int port_enable(struct port *p);
+
/**
* Generates state machine events based on activity on a port's file
* descriptors.
diff --git a/port_private.h b/port_private.h
index 2a98ef4..d62e795 100644
--- a/port_private.h
+++ b/port_private.h
@@ -69,6 +69,7 @@ struct port {
enum timestamp_type timestamping;
struct fdarray fda;
int fault_fd;
+ int enable_ev_fd;
int phc_index;
int phc_from_cmdline;
@@ -119,7 +120,7 @@ struct port {
UInteger8 transportSpecific;
UInteger8 localPriority;
Integer8 initialLogSyncInterval;
- Integer8 operLogSyncInterval;
+ Integer8 operLogSyncInterval;
Integer8 logSyncInterval;
Enumeration8 delayMechanism;
Integer8 logMinPdelayReqInterval;
@@ -129,6 +130,7 @@ struct port {
int follow_up_info;
int freq_est_interval;
int hybrid_e2e;
+ int enable;
int master_only;
int match_transport_specific;
int msg_interval_request;
diff --git a/ptp4l.8 b/ptp4l.8
index fe9e150..f9c3f65 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -143,6 +143,9 @@ See UNICAST DISCOVERY OPTIONS, below.
.SH PORT OPTIONS
.TP
+.B enable
+When 0 the port is kept disabled. When 1 the port activaly partecipate
+to protocol. The default is 1 (enabled).
.B delayAsymmetry
The time difference in nanoseconds of the transmit and receive
paths. This value should be positive when the server-to-client
--
2.31.1
_______________________________________________
Linuxptp-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel