net: introduce SO_MAX_PACING_RATE
authorEric Dumazet <edumazet@google.com>
Tue, 24 Sep 2013 15:20:52 +0000 (08:20 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 28 Sep 2013 22:35:41 +0000 (15:35 -0700)
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>
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 467de01..e3a1491 100644 (file)
@@ -81,6 +81,8 @@
 
 #define SO_SELECT_ERR_QUEUE    45
 
-#define SO_BUSY_POLL                   46
+#define SO_BUSY_POLL           46
+
+#define SO_MAX_PACING_RATE     47
 
 #endif /* _UAPI_ASM_SOCKET_H */
index 11c4259..4399364 100644 (file)
@@ -76,4 +76,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* __ASM_AVR32_SOCKET_H */
index eb723e5..13829aa 100644 (file)
@@ -78,6 +78,8 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _ASM_SOCKET_H */
 
 
index f0cb1c3..5d42997 100644 (file)
@@ -76,5 +76,7 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _ASM_SOCKET_H */
 
index 9490758..214ccaf 100644 (file)
@@ -76,4 +76,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _ASM_SOCKET_H */
index 556d070..c25302f 100644 (file)
@@ -85,4 +85,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _ASM_IA64_SOCKET_H */
index 24be7c8..5296665 100644 (file)
@@ -76,4 +76,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _ASM_M32R_SOCKET_H */
index 61c01f0..0df9787 100644 (file)
@@ -94,4 +94,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _UAPI_ASM_SOCKET_H */
index e2a2b20..71dedca 100644 (file)
@@ -76,4 +76,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _ASM_SOCKET_H */
index 71700e6..7c614d0 100644 (file)
@@ -75,6 +75,8 @@
 
 #define SO_BUSY_POLL           0x4027
 
+#define SO_MAX_PACING_RATE     0x4048
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
index a6d7446..fa69832 100644 (file)
@@ -83,4 +83,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _ASM_POWERPC_SOCKET_H */
index 9249449..c286c2e 100644 (file)
@@ -82,4 +82,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _ASM_SOCKET_H */
index 4e1d66c..0f21e9a 100644 (file)
@@ -72,6 +72,8 @@
 
 #define SO_BUSY_POLL           0x0030
 
+#define SO_MAX_PACING_RATE     0x0031
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
index c114483..7db5c22 100644 (file)
@@ -87,4 +87,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* _XTENSA_SOCKET_H */
index 4625d2e..240aa3f 100644 (file)
@@ -363,6 +363,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 f04b69b..38f14d0 100644 (file)
@@ -78,4 +78,6 @@
 
 #define SO_BUSY_POLL           46
 
+#define SO_MAX_PACING_RATE     47
+
 #endif /* __ASM_GENERIC_SOCKET_H */
index 5b6beba..2bd9b3f 100644 (file)
@@ -914,6 +914,13 @@ set_rcvbuf:
                }
                break;
 #endif
+
+       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;
@@ -1177,6 +1184,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                break;
 #endif
 
+       case SO_MAX_PACING_RATE:
+               v.val = sk->sk_max_pacing_rate;
+               break;
+
        default:
                return -ENOPROTOOPT;
        }
@@ -2319,6 +2330,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
        sk->sk_ll_usec          =       sysctl_net_busy_read;
 #endif
 
+       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 5d08385..66aa816 100644 (file)
@@ -735,7 +735,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