Adds a new bpf_setsockopt for TCP sockets, TCP_BPF_IW, which sets the
initial congestion window. This can be used when the hosts are far
apart (large RTTs) and it is safe to start with a large inital cwnd.

Signed-off-by: Lawrence Brakmo <bra...@fb.com>
---
 include/uapi/linux/bpf.h |  2 ++
 net/core/filter.c        | 18 +++++++++++++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index cc47259..32755b5 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -783,4 +783,6 @@ enum {
                                         */
 };
 
+#define TCP_BPF_IW             1001    /* Set TCP initial congestion window */
+
 #endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/net/core/filter.c b/net/core/filter.c
index 12df527..794be0a 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2732,7 +2732,23 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, 
bpf_sock,
                                tcp_reinit_congestion_control(sk,
                                        inet_csk(sk)->icsk_ca_ops);
                } else {
-                       ret = -EINVAL;
+                       struct tcp_sock *tp = tcp_sk(sk);
+
+                       if (optlen != sizeof(int))
+                               return -EINVAL;
+
+                       val = *((int *)optval);
+                       /* Only some options are supported */
+                       switch (optname) {
+                       case TCP_BPF_IW:
+                               if (val <= 0 || tp->data_segs_out > 0)
+                                       ret = -EINVAL;
+                               else
+                                       tp->snd_cwnd = val;
+                               break;
+                       default:
+                               ret = -EINVAL;
+                       }
                }
 #else
                ret = -EINVAL;
-- 
2.9.3

Reply via email to