diff --git a/clock.c b/clock.c index a2676e2..c1a7a83 100644 --- a/clock.c +++ b/clock.c @@ -32,6 +32,7 @@ #include "port.h" #include "servo.h" #include "print.h" +#include "tlv.h" #include "util.h" #define FAULT_RESET_SECONDS 15 @@ -67,6 +68,11 @@ struct clock the_clock; static void handle_state_decision_event(struct clock *c); +static int cid_eq(struct ClockIdentity *a, struct ClockIdentity *b) +{ + return 0 == memcmp(a, b, sizeof(*a)); +} + static void clock_destroy(struct clock *c) { int i; @@ -177,6 +183,22 @@ static void clock_update_slave(struct clock *c) c->tds.timeSource = msg->announce.timeSource; } +static int forwarding(struct port *p) +{ + enum port_state ps = port_state(p); + switch (ps) { + case PS_MASTER: + case PS_GRAND_MASTER: + case PS_SLAVE: + case PS_UNCALIBRATED: + case PS_PRE_MASTER: + return 1; + default: + break; + } + return 0; +} + /* public methods */ UInteger8 clock_class(struct clock *c) @@ -322,6 +344,80 @@ void clock_install_fda(struct clock *c, struct port *p, struct fdarray fda) } } +void clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) +{ + int i, pdulen; + struct port *fwd; + struct management_tlv *mgt; + struct ClockIdentity *tcid, wildcard = { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + }; + + /* Forward this message out all eligible ports. */ + if (forwarding(p) && msg->management.boundaryHops) { + pdulen = msg->header.messageLength; + msg->management.boundaryHops--; + msg_pre_send(msg); + for (i = 0; i < c->nports; i++) { + fwd = c->port[i]; + if (fwd != p && forwarding(fwd) && + port_forward(fwd, msg, pdulen)) + pr_err("port %d: management forward failed", i); + } + msg_post_recv(msg, pdulen); + msg->management.boundaryHops++; + } + + /* Apply this message to the local clock and ports. */ + tcid = &msg->management.targetPortIdentity.clockIdentity; + if (!cid_eq(tcid, &wildcard) && !cid_eq(tcid, &c->dds.clockIdentity)) { + return; + } + if (msg->tlv_count != 1) { + return; + } + mgt = (struct management_tlv *) msg->management.suffix; + switch (mgt->id) { + case USER_DESCRIPTION: + case SAVE_IN_NON_VOLATILE_STORAGE: + case RESET_NON_VOLATILE_STORAGE: + case INITIALIZE: + case FAULT_LOG: + case FAULT_LOG_RESET: + case DEFAULT_DATA_SET: + case CURRENT_DATA_SET: + case PARENT_DATA_SET: + case TIME_PROPERTIES_DATA_SET: + case PRIORITY1: + case PRIORITY2: + case DOMAIN: + case SLAVE_ONLY: + case TIME: + case CLOCK_ACCURACY: + case UTC_PROPERTIES: + case TRACEABILITY_PROPERTIES: + case TIMESCALE_PROPERTIES: + case PATH_TRACE_LIST: + case PATH_TRACE_ENABLE: + case GRANDMASTER_CLUSTER_TABLE: + case ACCEPTABLE_MASTER_TABLE: + case ACCEPTABLE_MASTER_MAX_TABLE_SIZE: + case ALTERNATE_TIME_OFFSET_ENABLE: + case ALTERNATE_TIME_OFFSET_NAME: + case ALTERNATE_TIME_OFFSET_MAX_KEY: + case ALTERNATE_TIME_OFFSET_PROPERTIES: + case TRANSPARENT_CLOCK_DEFAULT_DATA_SET: + case PRIMARY_DOMAIN: + break; + default: + for (i = 0; i < c->nports; i++) { + if (port_manage(c->port[i], p, msg)) + break; + } + break; + } +} + struct parentDS *clock_parent_ds(struct clock *c) { return &c->dad; diff --git a/clock.h b/clock.h index 86b72f0..e48aaeb 100644 --- a/clock.h +++ b/clock.h @@ -26,6 +26,8 @@ #include "tmv.h" #include "transport.h" +struct ptp_message; /*forward declaration*/ + #define MAX_PORTS 8 /** Defines a network interface, with PTP options. */ @@ -106,6 +108,14 @@ struct ClockIdentity clock_identity(struct clock *c); */ void clock_install_fda(struct clock *c, struct port *p, struct fdarray fda); +/** + * Manage the clock according to a given message. + * @param c The clock instance. + * @param p The port on which the message arrived. + * @param msg A management message. + */ +void clock_manage(struct clock *c, struct port *p, struct ptp_message *msg); + /** * Obtain a clock's parent data set. * @param c The clock instance. diff --git a/port.c b/port.c index bf65384..4a8af3b 100644 --- a/port.c +++ b/port.c @@ -1338,7 +1338,9 @@ enum fsm_event port_event(struct port *p, int fd_index) event = EV_STATE_DECISION_EVENT; break; case SIGNALING: + break; case MANAGEMENT: + clock_manage(p->clock, p, msg); break; } @@ -1346,6 +1348,18 @@ enum fsm_event port_event(struct port *p, int fd_index) return event; } +int port_forward(struct port *p, struct ptp_message *msg, int msglen) +{ + int cnt; + cnt = transport_send(p->trp, &p->fda, 0, msg, msglen, &msg->hwts); + return cnt <= 0 ? -1 : 0; +} + +int port_manage(struct port *p, struct port *ingress, struct ptp_message *msg) +{ + return 0; +} + struct port *port_open(struct port_defaults *pod, int phc_index, char *name, diff --git a/port.h b/port.h index fc08e0a..c64723a 100644 --- a/port.h +++ b/port.h @@ -77,6 +77,24 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff); */ enum fsm_event port_event(struct port *port, int fd_index); +/** + * Forward a message on a given port. + * @param port A pointer previously obtained via port_open(). + * @param msg The message to send. Must be in network byte order. + * @param msglen The length of the message in bytes. + * @return Zero on success, non-zero otherwise. + */ +int port_forward(struct port *p, struct ptp_message *msg, int msglen); + +/** + * Manage a port according to a given message. + * @param p A pointer previously obtained via port_open(). + * @param ingress The port on which 'msg' was received. + * @param msg A management message. + * @return Zero if the message is valid, non-zero otherwise. + */ +int port_manage(struct port *p, struct port *ingress, struct ptp_message *msg); + /** * Open a network port. * @param pod A pointer to a default port data set for this port.