]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
tc/police: enable use of 64 bit burst parameter
authorJay Vosburgh <jay.vosburgh@canonical.com>
Tue, 16 Sep 2025 21:57:31 +0000 (14:57 -0700)
committerDavid Ahern <dsahern@kernel.org>
Thu, 18 Sep 2025 02:18:52 +0000 (02:18 +0000)
Modify tc police to permit burst sizes up to the limit of the
kernel API, which may exceed 4 GB of burst size at higher rates.

 As presently implemented, the tc police burst option limits the
size of the burst to 4 GB in size.  This is a reasonable limit for the
rates common when this was developed.  However, the underlying
implementation of burst is expressed in terms of time at the specified
rate, and for higher rates, a burst size exceeding 4 GB is feasible
without modification to the kernel.

The kernel API specifies the burst size as the number of "psched
ticks" needed to send the burst at the specified rate.  As each psched
tick is 64 nsec, the actual kernel limit on burst size is approximately
274.88 seconds (UINT_MAX * 64 / NSEC_PER_SEC).

For example, at a rate of 10 Gbit/sec, the current 4 GB size limit
corresponds to just under 3.5 seconds.

Additionally, overflows (burst values that exceed UINT_MAX psched
ticks) are now correctly detected, and flagged as an error, rather than
passing arbitrary psched tick values to the kernel.

Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
tc/m_police.c

index 5c7438b94d83bce9f3eae0da976b8ac12fa16ca4..f5c538c93d2c832dc928ee9399c0baf509002e32 100644 (file)
@@ -54,12 +54,12 @@ static int act_parse_police(const struct action_util *a, int *argc_p, char ***ar
        __u32 ptab[256];
        __u32 avrate = 0;
        int presult = 0;
-       unsigned buffer = 0, mtu = 0, mpu = 0;
+       unsigned mtu = 0, mpu = 0;
        unsigned short overhead = 0;
        unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
        int Rcell_log =  -1, Pcell_log = -1;
        struct rtattr *tail;
-       __u64 rate64 = 0, prate64 = 0;
+       __u64 rate64 = 0, prate64 = 0, buffer64 = 0;
        __u64 pps64 = 0, ppsburst64 = 0;
 
        if (a) /* new way of doing things */
@@ -78,9 +78,10 @@ static int act_parse_police(const struct action_util *a, int *argc_p, char ***ar
                        strcmp(*argv, "buffer") == 0 ||
                        strcmp(*argv, "maxburst") == 0) {
                        NEXT_ARG();
-                       if (buffer)
+                       if (buffer64)
                                duparg("buffer/burst", *argv);
-                       if (get_size_and_cell(&buffer, &Rcell_log, *argv) < 0)
+                       if (get_size64_and_cell(&buffer64, &Rcell_log,
+                                               *argv) < 0)
                                invarg("buffer", *argv);
                } else if (strcmp(*argv, "mtu") == 0 ||
                           strcmp(*argv, "minburst") == 0) {
@@ -173,7 +174,7 @@ action_ctrl_ok:
        }
 
        /* When the TB policer is used, burst is required */
-       if (rate64 && !buffer && !avrate) {
+       if (rate64 && !buffer64 && !avrate) {
                fprintf(stderr, "'burst' requires 'rate'.\n");
                return -1;
        }
@@ -210,7 +211,11 @@ action_ctrl_ok:
                        fprintf(stderr, "POLICE: failed to calculate rate table.\n");
                        return -1;
                }
-               p.burst = tc_calc_xmittime(rate64, buffer);
+               p.burst = tc_calc_xmittime(rate64, buffer64);
+               if (p.burst == UINT_MAX) {
+                       fprintf(stderr, "POLICE: burst out of range\n");
+                       return -1;
+               }
        }
        p.mtu = mtu;
        if (prate64) {
@@ -265,9 +270,8 @@ static int print_police(const struct action_util *a, FILE *funused, struct rtatt
        SPRINT_BUF(b2);
        struct tc_police *p;
        struct rtattr *tb[TCA_POLICE_MAX+1];
-       unsigned int buffer;
        unsigned int linklayer;
-       __u64 rate64, prate64;
+       __u64 rate64, prate64, buffer64;
        __u64 pps64, ppsburst64;
 
        print_string(PRINT_JSON, "kind", "%s", "police");
@@ -296,8 +300,8 @@ static int print_police(const struct action_util *a, FILE *funused, struct rtatt
        print_hex(PRINT_FP, NULL, " police 0x%x ", p->index);
        print_uint(PRINT_JSON, "index", NULL, p->index);
        tc_print_rate(PRINT_FP, NULL, "rate %s ", rate64);
-       buffer = tc_calc_xmitsize(rate64, p->burst);
-       print_size(PRINT_FP, NULL, "burst %s ", buffer);
+       buffer64 = tc_calc_xmitsize(rate64, p->burst);
+       print_size(PRINT_FP, NULL, "burst %s ", buffer64);
        print_size(PRINT_FP, NULL, "mtu %s ", p->mtu);
        if (show_raw)
                print_hex(PRINT_FP, NULL, "[%08x] ", p->burst);