The latest proposal for DC PTP Profile[1] provides logic to make load balancing of unicast clients when running multiple GMs in active-active mode. This patch adds this logic to ptp4l using already existing localPriority field for telecom profile. Together with telecom BMCA algorithm it implements sharding based on provided GM priority.
[1] https://www.opencompute.org/documents/ocp-dc-ptp-profile-v1r1-pdf-2 Signed-off-by: Vadim Fedorenko <vad...@meta.com> --- v1 -> v2: Removed warning of absence of local priority to not consufe current users config.c | 21 +++++++++++++++------ mtab.h | 1 + port.c | 4 +++- unicast_client.c | 11 +++++++++++ unicast_client.h | 10 +++++++++- 5 files changed, 39 insertions(+), 8 deletions(-) diff --git a/config.c b/config.c index 08e3346..836af8e 100644 --- a/config.c +++ b/config.c @@ -454,8 +454,8 @@ static int config_switch_unicast_mtab(struct config *cfg, int idx, int line_num) return 0; } -static int config_unicast_mtab_address(enum transport_type type, char *address, - int line_num) +static int config_unicast_mtab_address_prio(enum transport_type type, char *address, + int line_num, unsigned char prio) { struct unicast_master_address *item; @@ -475,6 +475,7 @@ static int config_unicast_mtab_address(enum transport_type type, char *address, } memset(&item->portIdentity, 0xff, sizeof(item->portIdentity)); item->type = type; + item->localPriority = prio; STAILQ_INSERT_TAIL(¤t_uc_mtab->addrs, item, list); current_uc_mtab->count++; @@ -665,7 +666,7 @@ static int parse_unicast_mtab_line(struct config *cfg, char *line, int line_num) char address[64 + 1] = {0}, transport[16 + 1] = {0}; enum transport_type type = TRANS_UDS; struct config_enum *cte; - int cnt, lqi, table_id; + int cnt, lqi, table_id, prio; cnt = sscanf(line, " table_id %d", &table_id); if (cnt == 1) { @@ -679,18 +680,26 @@ static int parse_unicast_mtab_line(struct config *cfg, char *line, int line_num) if (cnt == 1) { return config_unicast_mtab_peer(address, line_num); } - cnt = sscanf(line, " %16s %64s", transport, address); - if (cnt != 2) { + cnt = sscanf(line, " %16s %64s %d", transport, address, &prio); + if (cnt < 2) { fprintf(stderr, "bad master table at line %d\n", line_num); return -1; } + if (cnt == 3 && (prio < 0 || prio > 255)) { + fprintf(stderr, "bad address priority(%d) at line %d\n", prio, line_num); + prio = 0; + } + if (cnt == 2) { + prio = 0; + } + for (cte = nw_trans_enu; cte->label; cte++) { if (!strcasecmp(cte->label, transport)) { type = cte->value; break; } } - return config_unicast_mtab_address(type, address, line_num); + return config_unicast_mtab_address_prio(type, address, line_num, prio); } static enum parser_result parse_setting_line(char *line, diff --git a/mtab.h b/mtab.h index 949929f..412bcc9 100644 --- a/mtab.h +++ b/mtab.h @@ -37,6 +37,7 @@ struct unicast_master_address { unsigned int granted; unsigned int sydymsk; time_t renewal_tmo; + unsigned char localPriority; }; struct unicast_master_table { diff --git a/port.c b/port.c index 6baf5c8..36b73f5 100644 --- a/port.c +++ b/port.c @@ -80,7 +80,8 @@ static void announce_to_dataset(struct ptp_message *m, struct port *p, out->identity = a->grandmasterIdentity; out->quality = a->grandmasterClockQuality; out->priority2 = a->grandmasterPriority2; - out->localPriority = p->localPriority; + if (!out->localPriority) + out->localPriority = p->localPriority; out->stepsRemoved = a->stepsRemoved; out->sender = m->header.sourcePortIdentity; out->receiver = p->portIdentity; @@ -405,6 +406,7 @@ static int add_foreign_master(struct port *p, struct ptp_message *m) LIST_INSERT_HEAD(&p->foreign_masters, fc, list); fc->port = p; fc->dataset.sender = m->header.sourcePortIdentity; + fc->dataset.localPriority = unicast_client_get_priority(p, m); /* We do not count this first message, see 9.5.3(b) */ return 0; } diff --git a/unicast_client.c b/unicast_client.c index 039967f..81113ae 100644 --- a/unicast_client.c +++ b/unicast_client.c @@ -624,3 +624,14 @@ out: msg_put(msg); return err; } + +unsigned char unicast_client_get_priority(struct port *p, struct ptp_message *m) +{ + struct unicast_master_address *ucma; + + ucma = unicast_client_ok(p, m); + if (!ucma) { + return 0; + } + return p->localPriority + ucma->localPriority; +} diff --git a/unicast_client.h b/unicast_client.h index 18a12c8..9d21a8a 100644 --- a/unicast_client.h +++ b/unicast_client.h @@ -90,7 +90,7 @@ int unicast_client_timer(struct port *p); * @return One (1) if the message is from an entry in the unicast * master table, or zero otherwise. */ -int unicast_client_msg_is_from_master_table_entry(struct port *p, +int unicast_client_msg_is_from_master_table_entry(struct port *p, struct ptp_message *m); /** @@ -101,4 +101,12 @@ int unicast_client_msg_is_from_master_table_entry(struct port *p, */ int unicast_client_tx_cancel(struct port *p, struct unicast_master_address *dst); + +/** + * Return local priority configured for unicast client + * @param p The port on which the signaling message was received. + * @param m The signaling message containing the announce. + * @return Unicast client local priority if configured otherwise zero. + */ +unsigned char unicast_client_get_priority(struct port *p, struct ptp_message *m); #endif -- 2.30.2 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel