diff --git a/include/net/tcp.h b/include/net/tcp.h index 41f7ebbc0091eeb22dce7592288ca79ae0ab05f5..dd4402a6cb2c36c1d8e0ea6483e71101cbfa8a49 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -2214,8 +2214,11 @@ void clean_acked_data_disable(struct inet_connection_sock *icsk); 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 @@ -2223,6 +2226,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 f566351384abf6427458c509f53c082c4d67f499..3311e7229c05fcd609f31206b7794eedcc4bc73a 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -592,6 +592,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 = &zero, + .extra2 = &one, + }, #endif { } }; diff --git a/net/ipv4/tcp_comp.c b/net/ipv4/tcp_comp.c index a71f23fceec610b12ca0e3a01ba5fc8ac006cc11..ec018c93b97d254d6d38f7ced8c4f7ba55c7bd0d 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 9453a98c936fdee4c0322b71d48b9dee368c6764..97b9d671a83c904897a582c25948e0d6a7b32865 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -593,7 +593,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; @@ -610,7 +610,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;