Add option unicast_max_message_rate to limit the rate of messages
generated by the unicast service for all contracts of the port.
When a request is received and the current rate of messages is so large
that granting the service would exceed the maximum, deny the request.

The default value is 1024 messages per second, which corresponds to
about 680 clients using the default announce and sync intervals, or 4
clients using the maximum rate of 128 messages per second.

Signed-off-by: Miroslav Lichvar <mlich...@redhat.com>
---
 config.c            |  1 +
 configs/default.cfg |  1 +
 ptp4l.8             |  9 ++++++++-
 unicast_service.c   | 32 +++++++++++++++++++++++++++++++-
 4 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/config.c b/config.c
index 2321310..24aac3b 100644
--- a/config.c
+++ b/config.c
@@ -295,6 +295,7 @@ struct config_item config_tab[] = {
        GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"),
        PORT_ITEM_INT("unicast_listen", 0, 0, 1),
        PORT_ITEM_INT("unicast_master_table", 0, 0, INT_MAX),
+       PORT_ITEM_INT("unicast_max_message_rate", 1024, 1, INT_MAX),
        PORT_ITEM_INT("unicast_req_duration", 3600, 10, INT_MAX),
        GLOB_ITEM_INT("use_syslog", 1, 0, 1),
        GLOB_ITEM_STR("userDescription", ""),
diff --git a/configs/default.cfg b/configs/default.cfg
index 3ee3a9b..bc6b230 100644
--- a/configs/default.cfg
+++ b/configs/default.cfg
@@ -49,6 +49,7 @@ net_sync_monitor      0
 tc_spanning_tree       0
 tx_timestamp_timeout   1
 unicast_listen         0
+unicast_max_message_rate       1024
 unicast_master_table   0
 unicast_req_duration   3600
 use_syslog             1
diff --git a/ptp4l.8 b/ptp4l.8
index 99b085c..15430a6 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -249,9 +249,16 @@ The default is 0 (disabled).
 .B unicast_listen
 When enabled, this option allows the port to grant unicast message
 contracts.  Incoming requests for will be granted limited only by the
-amount of memory available.
+amount of memory available and the rate specified by the following option.
 The default is 0 (disabled).
 .TP
+.B unicast_max_message_rate
+The maximum rate of announce and sync messages in all unicast contracts granted
+by the port. It's specified in messages per second. The rate limits the maximum
+number of unicast clients.
+The default is 1024 messages per second, which corresponds to about 680 clients
+using the default announce and sync intervals.
+.TP
 .B unicast_master_table
 When set to a positive integer, this option specifies the table id to
 be used for unicast discovery.  Each table lives in its own section
diff --git a/unicast_service.c b/unicast_service.c
index c6c17c6..90669f3 100644
--- a/unicast_service.c
+++ b/unicast_service.c
@@ -55,6 +55,7 @@ struct unicast_service_interval {
 struct unicast_service {
        LIST_HEAD(usi, unicast_service_interval) intervals;
        struct pqueue *queue;
+       uint64_t scaled_max_rate;
 };
 
 static struct timespec log_to_timespec(int log_seconds);
@@ -160,6 +161,18 @@ static void timespec_normalize(struct timespec *ts)
        }
 }
 
+static uint64_t get_scaled_rate(int log_period, int mask)
+{
+       int messages = 0;
+
+       if (mask & (1 << ANNOUNCE))
+               messages++;
+       if (mask & (1 << SYNC))
+               messages++;
+
+       return messages * (1 << (MAX_LOG_INTER_MESSAGE_PERIOD - log_period));
+}
+
 static int unicast_service_clients(struct port *p,
                                   struct unicast_service_interval *interval)
 {
@@ -270,6 +283,7 @@ int unicast_service_add(struct port *p, struct ptp_message 
*m,
        struct unicast_client_address *client = NULL, *ctmp, *next;
        struct unicast_service_interval *interval = NULL, *itmp;
        struct request_unicast_xmit_tlv *req;
+       uint64_t cur_rate = 0;
        unsigned int mask;
        uint8_t mtype;
 
@@ -312,6 +326,9 @@ int unicast_service_add(struct port *p, struct ptp_message 
*m,
                 * Find any client records, and remove any stale contract.
                 */
                LIST_FOREACH_SAFE(ctmp, &itmp->clients, list, next) {
+                       cur_rate += get_scaled_rate(itmp->log_period,
+                                                   ctmp->message_types);
+
                        if (!addreq(transport_type(p->trp),
                                    &ctmp->addr, &m->address)) {
                                continue;
@@ -326,15 +343,26 @@ int unicast_service_add(struct port *p, struct 
ptp_message *m,
                                client = ctmp;
                                continue;
                        }
-                       /* Clear any stale contracts. */
+
+                       if (!(ctmp->message_types & mask))
+                               continue;
+
+                       /* Clear stale contracts. */
                        ctmp->message_types &= ~mask;
                        if (!ctmp->message_types) {
                                LIST_REMOVE(ctmp, list);
                                free(ctmp);
                        }
+                       cur_rate -= get_scaled_rate(itmp->log_period, mask);
                }
        }
 
+       if (cur_rate + get_scaled_rate(req->logInterMessagePeriod, mask) >
+           p->unicast_service->scaled_max_rate) {
+               pr_debug("unicast service denied to limit message rate");
+               return SERVICE_DENIED;
+       }
+
        if (client) {
                client->message_types |= mask;
                unicast_service_extend(client, req);
@@ -429,6 +457,8 @@ int unicast_service_initialize(struct port *p)
                free(p->unicast_service);
                return -1;
        }
+       p->unicast_service->scaled_max_rate = get_scaled_rate(0, 1 << SYNC) *
+               config_get_int(cfg, p->name, "unicast_max_message_rate");
        p->inhibit_multicast_service =
                config_get_int(cfg, p->name, "inhibit_multicast_service");
 
-- 
2.17.2



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to