[PATCH bpf-next 09/10] tcp: bpf: Add TCP_BPF_DELACK_MAX and TCP_BPF_RTO_MIN to bpf_setsockopt
From: Martin KaFai Lau <hidden>
Date: 2020-06-26 17:56:05
Also in:
bpf
Subsystem:
bpf [general] (safe dynamic programs and tools), bpf [networking] (tcx & tc bpf, sock_addr), networking [general], networking [tcp], the rest · Maintainers:
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Neal Cardwell, Linus Torvalds
This change is mostly from an internal patch and adapts it from sysctl config to the bpf_setsockopt setup. The bpf_prog can set the max delay ack by using bpf_setsockopt(TCP_BPF_DELACK_MAX). This max delay ack can be communicated to its peer through bpf header option. The receiving peer can then use this max delay ack and set a potentially lower rto by using bpf_setsockopt(TCP_BPF_RTO_MIN). A latter patch will use it like this in a test as an example. Signed-off-by: Martin KaFai Lau <redacted> --- include/net/inet_connection_sock.h | 2 ++ include/net/tcp.h | 2 +- include/uapi/linux/bpf.h | 2 ++ net/core/filter.c | 15 +++++++++++++++ net/ipv4/tcp.c | 4 ++++ net/ipv4/tcp_output.c | 2 ++ tools/include/uapi/linux/bpf.h | 2 ++ 7 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index e5b388f5fa20..43d45864e5f0 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h@@ -93,6 +93,8 @@ struct inet_connection_sock { struct timer_list icsk_retransmit_timer; struct timer_list icsk_delack_timer; __u32 icsk_rto; + __u32 icsk_rto_min; + __u32 icsk_delack_max; __u32 icsk_pmtu_cookie; const struct tcp_congestion_ops *icsk_ca_ops; const struct inet_connection_sock_af_ops *icsk_af_ops;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e93ef2d324f3..8a682d678971 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h@@ -703,7 +703,7 @@ static inline void tcp_fast_path_check(struct sock *sk) static inline u32 tcp_rto_min(struct sock *sk) { const struct dst_entry *dst = __sk_dst_get(sk); - u32 rto_min = TCP_RTO_MIN; + u32 rto_min = inet_csk(sk)->icsk_rto_min; if (dst && dst_metric_locked(dst, RTAX_RTO_MIN)) rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN);
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 479b83d05811..2ccc81548eef 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h@@ -4299,6 +4299,8 @@ enum { * is not saved by TCP_SAVE_SYN. */ TCP_BPF_SYN_HDR_OPT = 1003, + TCP_BPF_DELACK_MAX = 1004, /* Max delay ack in usecs */ + TCP_BPF_RTO_MIN = 1005, /* Min delay ack in usecs */ }; struct bpf_perf_event_value {
diff --git a/net/core/filter.c b/net/core/filter.c
index 5784f1bede2f..4b80934e6876 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c@@ -4431,6 +4431,7 @@ static int _bpf_setsockopt(struct sock *sk, int level, int optname, } else { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); + unsigned long timeout; if (optlen != sizeof(int)) return -EINVAL;
@@ -4452,6 +4453,20 @@ static int _bpf_setsockopt(struct sock *sk, int level, int optname, tp->snd_ssthresh = val; } break; + case TCP_BPF_DELACK_MAX: + timeout = usecs_to_jiffies(val); + if (timeout > TCP_DELACK_MAX || + timeout < TCP_TIMEOUT_MIN) + return -EINVAL; + inet_csk(sk)->icsk_delack_max = timeout; + break; + case TCP_BPF_RTO_MIN: + timeout = usecs_to_jiffies(val); + if (timeout > TCP_RTO_MIN || + timeout < TCP_TIMEOUT_MIN) + return -EINVAL; + inet_csk(sk)->icsk_rto_min = timeout; + break; case TCP_SAVE_SYN: if (val < 0 || val > 1) ret = -EINVAL;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 60093a211f4d..02be3e2a2fdb 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c@@ -418,6 +418,8 @@ void tcp_init_sock(struct sock *sk) INIT_LIST_HEAD(&tp->tsorted_sent_queue); icsk->icsk_rto = TCP_TIMEOUT_INIT; + icsk->icsk_rto_min = TCP_RTO_MIN; + icsk->icsk_delack_max = TCP_DELACK_MAX; tp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT); minmax_reset(&tp->rtt_min, tcp_jiffies32, ~0U);
@@ -2685,6 +2687,8 @@ int tcp_disconnect(struct sock *sk, int flags) icsk->icsk_backoff = 0; icsk->icsk_probes_out = 0; icsk->icsk_rto = TCP_TIMEOUT_INIT; + icsk->icsk_rto_min = TCP_RTO_MIN; + icsk->icsk_delack_max = TCP_DELACK_MAX; tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; tp->snd_cwnd = TCP_INIT_CWND; tp->snd_cwnd_cnt = 0;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index a78a29980e1f..db872a2a01c6 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c@@ -3899,6 +3899,8 @@ void tcp_send_delayed_ack(struct sock *sk) ato = min(ato, max_ato); } + ato = min_t(u32, ato, inet_csk(sk)->icsk_delack_max); + /* Stay within the limit we were given */ timeout = jiffies + ato;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 479b83d05811..2ccc81548eef 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h@@ -4299,6 +4299,8 @@ enum { * is not saved by TCP_SAVE_SYN. */ TCP_BPF_SYN_HDR_OPT = 1003, + TCP_BPF_DELACK_MAX = 1004, /* Max delay ack in usecs */ + TCP_BPF_RTO_MIN = 1005, /* Min delay ack in usecs */ }; struct bpf_perf_event_value {
--
2.24.1