net: introduce SO_MAX_PACING_RATE
authorEric Dumazet <edumazet@google.com>
Tue, 24 Sep 2013 15:20:52 +0000 (08:20 -0700)
committerDanny Wood <danwood76@gmail.com>
Thu, 15 Jul 2021 09:45:34 +0000 (10:45 +0100)
As mentioned in commit afe4fd062416b ("pkt_sched: fq: Fair Queue packet
scheduler"), this patch adds a new socket option.

SO_MAX_PACING_RATE offers the application the ability to cap the
rate computed by transport layer. Value is in bytes per second.

u32 val = 1000000;
setsockopt(sockfd, SOL_SOCKET, SO_MAX_PACING_RATE, &val, sizeof(val));

To be effectively paced, a flow must use FQ packet scheduler.

Note that a packet scheduler takes into account the headers for its
computations. The effective payload rate depends on MSS and retransmits
if any.

I chose to make this pacing rate a SOL_SOCKET option instead of a
TCP one because this can be used by other protocols.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Steinar H. Gunderson <sesse@google.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Change-Id: I5fda6798068d171868fd3d52873778c993f20a9f

18 files changed:
arch/alpha/include/uapi/asm/socket.h
arch/avr32/include/uapi/asm/socket.h
arch/cris/include/uapi/asm/socket.h
arch/frv/include/uapi/asm/socket.h
arch/h8300/include/uapi/asm/socket.h
arch/ia64/include/uapi/asm/socket.h
arch/m32r/include/uapi/asm/socket.h
arch/mips/include/uapi/asm/socket.h
arch/mn10300/include/uapi/asm/socket.h
arch/parisc/include/uapi/asm/socket.h
arch/powerpc/include/uapi/asm/socket.h
arch/s390/include/uapi/asm/socket.h
arch/sparc/include/uapi/asm/socket.h
arch/xtensa/include/uapi/asm/socket.h
include/net/sock.h
include/uapi/asm-generic/socket.h
net/core/sock.c
net/ipv4/tcp_input.c

index eee6ea76bdaff2d5bd2e07583e4e0259e595cda9..6ffce5b92befe5158267f59015fb5ac558e5d399 100644 (file)
@@ -81,4 +81,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _UAPI_ASM_SOCKET_H */
index 37401f535126695e22af87b35739aba1242dd219..8cc5927aa6c138301ef642c7cb37cbe5ffdf869c 100644 (file)
@@ -74,4 +74,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* __ASM_AVR32_SOCKET_H */
index ba409c9947bc2df933ca1d393b418f082424a57a..410b009af5e46ab89a1e0820f7c257b9cd828da9 100644 (file)
@@ -76,6 +76,8 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _ASM_SOCKET_H */
 
 
index 31dbb5d8e13debd569420493091189e5bc199aef..53b5f8d8751b60d5c40a8897b3f8d05015f471a8 100644 (file)
@@ -74,5 +74,7 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _ASM_SOCKET_H */
 
index 5d1c6d0870e653e1f2cbfecf6e9ad7f6cf180741..203f5f3396a23f3f3dc942359608ffb41e5a60e2 100644 (file)
@@ -74,4 +74,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _ASM_SOCKET_H */
index 6b4329f18b29f3878c7679c8a32a4a60d931904d..3239239bb0cc9d7caf2e5fa872e4ec0e9b957a88 100644 (file)
@@ -83,4 +83,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _ASM_IA64_SOCKET_H */
index 2a3b59e0e171d0fb19897f561028b1f0482180b3..dcaccec56d248067f60a363863156ab2029bedfc 100644 (file)
@@ -74,4 +74,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _ASM_M32R_SOCKET_H */
index 3b211507be7f56ffa4c125ce221a52d352f90a46..21f778d2580abf3b2cbb9f4c87605233465a947d 100644 (file)
@@ -92,4 +92,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _UAPI_ASM_SOCKET_H */
index b4ce844c9391c82dd36136c86a17141e6b5a93c0..6c88ccccaabf0d8ad8d734cc9ede8356b05124c6 100644 (file)
@@ -74,4 +74,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _ASM_SOCKET_H */
index 4fecb26230e7744a2a3fe2cbcdf790d1633a2419..15667ce251aace88c899f0b2d9a4689f7305046f 100644 (file)
@@ -73,4 +73,6 @@
 
 #define SO_SELECT_ERR_QUEUE    0x4026
 
-#endif /* _UAPI_ASM_SOCKET_H */
+#define SO_MAX_PACING_RATE     0x4027
+
+#endif /* _ASM_SOCKET_H */
index a36daf3c6f9a31faac9e922d0c77b4c5fe412c37..9dcd543eee1652fa32e0d3603a389624963d4537 100644 (file)
@@ -81,4 +81,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _ASM_POWERPC_SOCKET_H */
index 2dacb306835ce217e91fe40a2c09aeae7edc05eb..82d5d18f2febddf71b4a3edb992a5c013702194b 100644 (file)
@@ -80,4 +80,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _ASM_SOCKET_H */
index 89f49b68a21c0804d6cbc55931b8beadf19f6711..c024024f48de1baed412a1f163bda6f9522be18e 100644 (file)
@@ -70,6 +70,8 @@
 
 #define SO_SELECT_ERR_QUEUE    0x0029
 
+#define SO_MAX_PACING_RATE     0x0030
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
index a8f44f50e651064b2358c7c8ab906a2103d38acc..defe483a496b35921b8b411833d24fa66044047d 100644 (file)
@@ -85,4 +85,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* _XTENSA_SOCKET_H */
index 8fda4597ceb2eb740650505c8db0680c7d91b494..968dce4ce75ea8b3b984236c7579d0265cc9eb4f 100644 (file)
@@ -371,6 +371,7 @@ struct sock {
        int                     sk_wmem_queued;
        gfp_t                   sk_allocation;
        u32                     sk_pacing_rate; /* bytes per second */
+       u32                     sk_max_pacing_rate;
        netdev_features_t       sk_route_caps;
        netdev_features_t       sk_route_nocaps;
        int                     sk_gso_type;
index c5d2e3a1cf68743862049482406f2a49adbfb707..3779c99dcb24085c2e915d9aaef2f1e92bc64873 100644 (file)
@@ -76,4 +76,6 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
+#define SO_MAX_PACING_RATE     46
+
 #endif /* __ASM_GENERIC_SOCKET_H */
index 2adbbe05c85e0eb0f1d008dd4690f80852654bf4..f77dd6c0a560fc2713d03457d9cb63d8e9096d9d 100644 (file)
@@ -954,6 +954,12 @@ set_rcvbuf:
                sock_valbool_flag(sk, SOCK_SELECT_ERR_QUEUE, valbool);
                break;
 
+       case SO_MAX_PACING_RATE:
+               sk->sk_max_pacing_rate = val;
+               sk->sk_pacing_rate = min(sk->sk_pacing_rate,
+                                        sk->sk_max_pacing_rate);
+               break;
+
        default:
                ret = -ENOPROTOOPT;
                break;
@@ -1211,6 +1217,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE);
                break;
 
+       case SO_MAX_PACING_RATE:
+               v.val = sk->sk_max_pacing_rate;
+               break;
+
        default:
                return -ENOPROTOOPT;
        }
@@ -2344,6 +2354,8 @@ void sock_init_data(struct socket *sock, struct sock *sk)
        sk->sk_stamp = ktime_set(-1L, 0);
 
        sk->sk_pacing_rate = ~0U;
+
+       sk->sk_max_pacing_rate = ~0U;
        /*
         * Before updating sk_refcnt, we must commit prior changes to memory
         * (Documentation/RCU/rculist_nulls.txt for details)
index b0441424af4b3136b33b4d5bb3d01adf91767f7b..bce863a60e7af20a0715047da6a5658d6a0bf3a4 100644 (file)
@@ -727,7 +727,7 @@ static void tcp_update_pacing_rate(struct sock *sk)
        if (tp->srtt > 8 + 2)
                do_div(rate, tp->srtt);
 
-       sk->sk_pacing_rate = min_t(u64, rate, ~0U);
+       sk->sk_pacing_rate = min_t(u64, rate, sk->sk_max_pacing_rate);
 }
 
 /* Calculate rto without backoff.  This is the second half of Van Jacobson's