diff --git a/include/net/tcp.h b/include/net/tcp.h index 353a0d9e4c8ea7449fec41daaccc901270c8009f..cee41cca6d2c55707ec08053aba9134f417ca321 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -2384,8 +2384,11 @@ static inline u64 tcp_transmit_time(const struct sock *sk) extern struct static_key_false tcp_have_comp; extern unsigned long *sysctl_tcp_compression_ports; +extern int sysctl_tcp_compression_local; -bool tcp_syn_comp_enabled(const struct sock *sk, bool active); +bool tcp_syn_comp_enabled(const struct sock *sk); +bool tcp_synack_comp_enabled(const struct sock *sk, + const struct inet_request_sock *ireq); void tcp_init_compression(struct sock *sk); void tcp_cleanup_compression(struct sock *sk); #else @@ -2393,6 +2396,13 @@ static inline bool tcp_syn_comp_enabled(const struct tcp_sock *tp) { return false; } + +static inline bool tcp_synack_comp_enabled(const struct sock *sk, + const struct inet_request_sock *ireq) +{ + return false; +} + static inline void tcp_init_compression(struct sock *sk) { } diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index bbd641bb27f488db00fbeacd39fc9b275ba003c9..1cffacd985c1e5344ac853c029aa4f5d5d48e953 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -620,6 +620,15 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_tcp_compression_ports, }, + { + .procname = "tcp_compression_local", + .data = &sysctl_tcp_compression_local, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, #endif { } }; diff --git a/net/ipv4/tcp_comp.c b/net/ipv4/tcp_comp.c index fb76813aa106a73f46941b1b8536274eb4f45169..afcd50c89e7809a7501e601c6c4c5facfa9755a3 100644 --- a/net/ipv4/tcp_comp.c +++ b/net/ipv4/tcp_comp.c @@ -10,18 +10,35 @@ static unsigned long tcp_compression_ports[65536 / 8]; unsigned long *sysctl_tcp_compression_ports = tcp_compression_ports; +int sysctl_tcp_compression_local __read_mostly; -bool tcp_syn_comp_enabled(const struct sock *sk, bool active) +static bool tcp_comp_enabled(__be32 saddr, __be32 daddr, int port) +{ + if (!sysctl_tcp_compression_local && + (saddr == daddr || ipv4_is_loopback(daddr))) + return false; + + return test_bit(port, sysctl_tcp_compression_ports); +} + +bool tcp_syn_comp_enabled(const struct sock *sk) { struct inet_sock *inet = inet_sk(sk); - int port; - if (active) - port = ntohs(inet->inet_dport); - else - port = ntohs(inet->inet_sport); + return tcp_comp_enabled(inet->inet_saddr, inet->inet_daddr, + ntohs(inet->inet_dport)); +} - return test_bit(port, sysctl_tcp_compression_ports); +bool tcp_synack_comp_enabled(const struct sock *sk, + const struct inet_request_sock *ireq) +{ + struct inet_sock *inet = inet_sk(sk); + + if (!ireq->comp_ok) + return false; + + return tcp_comp_enabled(ireq->ir_loc_addr, ireq->ir_rmt_addr, + ntohs(inet->inet_sport)); } void tcp_init_compression(struct sock *sk) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3ef6b1186f45b5824c3e479ac7c791a092a81958..c8420b48de36cba871b1a3a64777a047d8e09e5e 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -742,7 +742,7 @@ static void comp_set_option(const struct sock *sk, { #if IS_ENABLED(CONFIG_TCP_COMP) if (static_branch_unlikely(&tcp_have_comp)) { - if (tcp_syn_comp_enabled(sk, true)) { + if (tcp_syn_comp_enabled(sk)) { if (*remaining >= TCPOLEN_EXP_COMP_BASE) { opts->options |= OPTION_COMP; *remaining -= TCPOLEN_EXP_COMP_BASE; @@ -759,7 +759,7 @@ static void comp_set_option_cond(const struct sock *sk, { #if IS_ENABLED(CONFIG_TCP_COMP) if (static_branch_unlikely(&tcp_have_comp)) { - if (tcp_syn_comp_enabled(sk, false) && ireq->comp_ok) { + if (tcp_synack_comp_enabled(sk, ireq)) { if (*remaining >= TCPOLEN_EXP_COMP_BASE) { opts->options |= OPTION_COMP; *remaining -= TCPOLEN_EXP_COMP_BASE;