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(&current_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

Reply via email to