提交 1e3691d2 编写于 作者: W Wang Yufen 提交者: Yang Yingliang

tcp_comp: add tcp comp option to SYN and SYN-ACK

hulk inclusion
category: feature
bugzilla: NA
CVE: NA

-------------------------------------------------

Add new tcp COMP option to SYN and SYN-ACK when tcp COMP
is enabled. connection compress payload only when both side
support it.

For KABI compatible, smc_ok bit in struct tcp_options_received
is reused for COMP option, so this config depends !CONFIG_SMC.
Signed-off-by: NWang Yufen <wangyufen@huawei.com>
Reviewed-by: NWei Yongjun <weiyongjun1@huawei.com>
Reviewed-by: NYue Haibing <yuehaibing@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 7708dd49
...@@ -110,7 +110,7 @@ static inline void tcp_clear_options(struct tcp_options_received *rx_opt) ...@@ -110,7 +110,7 @@ static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
{ {
rx_opt->tstamp_ok = rx_opt->sack_ok = 0; rx_opt->tstamp_ok = rx_opt->sack_ok = 0;
rx_opt->wscale_ok = rx_opt->snd_wscale = 0; rx_opt->wscale_ok = rx_opt->snd_wscale = 0;
#if IS_ENABLED(CONFIG_SMC) #if IS_ENABLED(CONFIG_SMC) || IS_ENABLED(CONFIG_TCP_COMP)
rx_opt->smc_ok = 0; rx_opt->smc_ok = 0;
#endif #endif
} }
......
...@@ -91,7 +91,8 @@ struct inet_request_sock { ...@@ -91,7 +91,8 @@ struct inet_request_sock {
ecn_ok : 1, ecn_ok : 1,
acked : 1, acked : 1,
no_srccheck: 1, no_srccheck: 1,
smc_ok : 1; smc_ok : 1,
comp_ok : 1;
u32 ir_mark; u32 ir_mark;
union { union {
struct ip_options_rcu __rcu *ireq_opt; struct ip_options_rcu __rcu *ireq_opt;
......
...@@ -833,6 +833,7 @@ enum sock_flags { ...@@ -833,6 +833,7 @@ enum sock_flags {
SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */ SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */
SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */ SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */
SOCK_TXTIME, SOCK_TXTIME,
SOCK_COMP,
}; };
#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
......
...@@ -192,6 +192,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo); ...@@ -192,6 +192,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
*/ */
#define TCPOPT_FASTOPEN_MAGIC 0xF989 #define TCPOPT_FASTOPEN_MAGIC 0xF989
#define TCPOPT_SMC_MAGIC 0xE2D4C3D9 #define TCPOPT_SMC_MAGIC 0xE2D4C3D9
#define TCPOPT_COMP_MAGIC 0x7954
/* /*
* TCP option lengths * TCP option lengths
...@@ -205,6 +206,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo); ...@@ -205,6 +206,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOLEN_FASTOPEN_BASE 2 #define TCPOLEN_FASTOPEN_BASE 2
#define TCPOLEN_EXP_FASTOPEN_BASE 4 #define TCPOLEN_EXP_FASTOPEN_BASE 4
#define TCPOLEN_EXP_SMC_BASE 6 #define TCPOLEN_EXP_SMC_BASE 6
#define TCPOLEN_EXP_COMP_BASE 4
/* But this is what stacks really send out. */ /* But this is what stacks really send out. */
#define TCPOLEN_TSTAMP_ALIGNED 12 #define TCPOLEN_TSTAMP_ALIGNED 12
...@@ -2208,4 +2210,14 @@ void clean_acked_data_disable(struct inet_connection_sock *icsk); ...@@ -2208,4 +2210,14 @@ void clean_acked_data_disable(struct inet_connection_sock *icsk);
#endif #endif
#if IS_ENABLED(CONFIG_TCP_COMP)
extern struct static_key_false tcp_have_comp;
bool tcp_syn_comp_enabled(const struct tcp_sock *tp);
#else
static inline bool tcp_syn_comp_enabled(const struct tcp_sock *tp)
{
return false;
}
#endif
#endif /* _TCP_H */ #endif /* _TCP_H */
...@@ -757,6 +757,7 @@ config TCP_MD5SIG ...@@ -757,6 +757,7 @@ config TCP_MD5SIG
config TCP_COMP config TCP_COMP
bool "TCP: Transport Layer Compression support" bool "TCP: Transport Layer Compression support"
depends on !SMC
---help--- ---help---
Enable kernel payload compression support for TCP protocol. This allows Enable kernel payload compression support for TCP protocol. This allows
payload compression handling of the TCP protocol to be done in-kernel. payload compression handling of the TCP protocol to be done in-kernel.
......
...@@ -64,6 +64,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o ...@@ -64,6 +64,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
obj-$(CONFIG_NETLABEL) += cipso_ipv4.o obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
obj-$(CONFIG_TCP_COMP) += tcp_comp.o
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
xfrm4_output.o xfrm4_protocol.o xfrm4_output.o xfrm4_protocol.o
...@@ -356,6 +356,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) ...@@ -356,6 +356,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
treq->tfo_listener = false; treq->tfo_listener = false;
if (IS_ENABLED(CONFIG_SMC)) if (IS_ENABLED(CONFIG_SMC))
ireq->smc_ok = 0; ireq->smc_ok = 0;
if (IS_ENABLED(CONFIG_TCP_COMP))
ireq->comp_ok = 0;
ireq->ir_iif = inet_request_bound_dev_if(sk, skb); ireq->ir_iif = inet_request_bound_dev_if(sk, skb);
......
...@@ -297,6 +297,10 @@ DEFINE_STATIC_KEY_FALSE(tcp_have_smc); ...@@ -297,6 +297,10 @@ DEFINE_STATIC_KEY_FALSE(tcp_have_smc);
EXPORT_SYMBOL(tcp_have_smc); EXPORT_SYMBOL(tcp_have_smc);
#endif #endif
#if IS_ENABLED(CONFIG_TCP_COMP)
DEFINE_STATIC_KEY_FALSE(tcp_have_comp);
#endif
/* /*
* Current number of TCP sockets. * Current number of TCP sockets.
*/ */
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* TCP compression support
*
* Copyright(c) 2021 Huawei Technologies Co., Ltd
*/
#include <net/tcp.h>
bool tcp_syn_comp_enabled(const struct tcp_sock *tp)
{
return true;
}
...@@ -3779,7 +3779,7 @@ static void tcp_parse_fastopen_option(int len, const unsigned char *cookie, ...@@ -3779,7 +3779,7 @@ static void tcp_parse_fastopen_option(int len, const unsigned char *cookie,
foc->exp = exp_opt; foc->exp = exp_opt;
} }
static void smc_parse_options(const struct tcphdr *th, static bool smc_parse_options(const struct tcphdr *th,
struct tcp_options_received *opt_rx, struct tcp_options_received *opt_rx,
const unsigned char *ptr, const unsigned char *ptr,
int opsize) int opsize)
...@@ -3788,10 +3788,31 @@ static void smc_parse_options(const struct tcphdr *th, ...@@ -3788,10 +3788,31 @@ static void smc_parse_options(const struct tcphdr *th,
if (static_branch_unlikely(&tcp_have_smc)) { if (static_branch_unlikely(&tcp_have_smc)) {
if (th->syn && !(opsize & 1) && if (th->syn && !(opsize & 1) &&
opsize >= TCPOLEN_EXP_SMC_BASE && opsize >= TCPOLEN_EXP_SMC_BASE &&
get_unaligned_be32(ptr) == TCPOPT_SMC_MAGIC) get_unaligned_be32(ptr) == TCPOPT_SMC_MAGIC) {
opt_rx->smc_ok = 1; opt_rx->smc_ok = 1;
return true;
}
} }
#endif #endif
return false;
}
static bool tcp_parse_comp_option(const struct tcphdr *th,
struct tcp_options_received *opt_rx,
const unsigned char *ptr,
int opsize)
{
#if IS_ENABLED(CONFIG_TCP_COMP)
if (static_branch_unlikely(&tcp_have_comp)) {
if (th->syn && !(opsize & 1) &&
opsize >= TCPOLEN_EXP_COMP_BASE &&
get_unaligned_be16(ptr) == TCPOPT_COMP_MAGIC) {
opt_rx->smc_ok = 1;
return true;
}
}
#endif
return false;
} }
/* Look for tcp options. Normally only called on SYN and SYNACK packets. /* Look for tcp options. Normally only called on SYN and SYNACK packets.
...@@ -3897,15 +3918,21 @@ void tcp_parse_options(const struct net *net, ...@@ -3897,15 +3918,21 @@ void tcp_parse_options(const struct net *net,
*/ */
if (opsize >= TCPOLEN_EXP_FASTOPEN_BASE && if (opsize >= TCPOLEN_EXP_FASTOPEN_BASE &&
get_unaligned_be16(ptr) == get_unaligned_be16(ptr) ==
TCPOPT_FASTOPEN_MAGIC) TCPOPT_FASTOPEN_MAGIC) {
tcp_parse_fastopen_option(opsize - tcp_parse_fastopen_option(opsize -
TCPOLEN_EXP_FASTOPEN_BASE, TCPOLEN_EXP_FASTOPEN_BASE,
ptr + 2, th->syn, foc, true); ptr + 2, th->syn, foc, true);
else break;
smc_parse_options(th, opt_rx, ptr, }
opsize);
break;
if (smc_parse_options(th, opt_rx, ptr, opsize))
break;
if (tcp_parse_comp_option(th, opt_rx, ptr,
opsize))
break;
break;
} }
ptr += opsize-2; ptr += opsize-2;
length -= opsize; length -= opsize;
...@@ -6362,6 +6389,9 @@ static void tcp_openreq_init(struct request_sock *req, ...@@ -6362,6 +6389,9 @@ static void tcp_openreq_init(struct request_sock *req,
#if IS_ENABLED(CONFIG_SMC) #if IS_ENABLED(CONFIG_SMC)
ireq->smc_ok = rx_opt->smc_ok; ireq->smc_ok = rx_opt->smc_ok;
#endif #endif
#if IS_ENABLED(CONFIG_TCP_COMP)
ireq->comp_ok = rx_opt->smc_ok;
#endif
} }
struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops, struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,
......
...@@ -529,6 +529,9 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, ...@@ -529,6 +529,9 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
newtp->rcv_ssthresh = req->rsk_rcv_wnd; newtp->rcv_ssthresh = req->rsk_rcv_wnd;
newtp->rcv_wnd = req->rsk_rcv_wnd; newtp->rcv_wnd = req->rsk_rcv_wnd;
newtp->rx_opt.wscale_ok = ireq->wscale_ok; newtp->rx_opt.wscale_ok = ireq->wscale_ok;
#if IS_ENABLED(CONFIG_TCP_COMP)
newtp->rx_opt.smc_ok = ireq->comp_ok;
#endif
if (newtp->rx_opt.wscale_ok) { if (newtp->rx_opt.wscale_ok) {
newtp->rx_opt.snd_wscale = ireq->snd_wscale; newtp->rx_opt.snd_wscale = ireq->snd_wscale;
newtp->rx_opt.rcv_wscale = ireq->rcv_wscale; newtp->rx_opt.rcv_wscale = ireq->rcv_wscale;
......
...@@ -401,6 +401,7 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp) ...@@ -401,6 +401,7 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp)
#define OPTION_WSCALE (1 << 3) #define OPTION_WSCALE (1 << 3)
#define OPTION_FAST_OPEN_COOKIE (1 << 8) #define OPTION_FAST_OPEN_COOKIE (1 << 8)
#define OPTION_SMC (1 << 9) #define OPTION_SMC (1 << 9)
#define OPTION_COMP (1 << 10)
static void smc_options_write(__be32 *ptr, u16 *options) static void smc_options_write(__be32 *ptr, u16 *options)
{ {
...@@ -417,6 +418,19 @@ static void smc_options_write(__be32 *ptr, u16 *options) ...@@ -417,6 +418,19 @@ static void smc_options_write(__be32 *ptr, u16 *options)
#endif #endif
} }
static void comp_options_write(__be32 *ptr, u16 *options)
{
#if IS_ENABLED(CONFIG_TCP_COMP)
if (static_branch_unlikely(&tcp_have_comp)) {
if (unlikely(OPTION_COMP & *options)) {
*ptr++ = htonl((TCPOPT_EXP << 24) |
(TCPOLEN_EXP_COMP_BASE << 16) |
(TCPOPT_COMP_MAGIC));
}
}
#endif
}
struct tcp_out_options { struct tcp_out_options {
u16 options; /* bit field of OPTION_* */ u16 options; /* bit field of OPTION_* */
u16 mss; /* 0 to disable */ u16 mss; /* 0 to disable */
...@@ -536,6 +550,8 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, ...@@ -536,6 +550,8 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
} }
smc_options_write(ptr, &options); smc_options_write(ptr, &options);
comp_options_write(ptr, &options);
} }
static void smc_set_option(const struct tcp_sock *tp, static void smc_set_option(const struct tcp_sock *tp,
...@@ -571,6 +587,39 @@ static void smc_set_option_cond(const struct tcp_sock *tp, ...@@ -571,6 +587,39 @@ static void smc_set_option_cond(const struct tcp_sock *tp,
#endif #endif
} }
static void comp_set_option(const struct tcp_sock *tp,
struct tcp_out_options *opts,
unsigned int *remaining)
{
#if IS_ENABLED(CONFIG_TCP_COMP)
if (static_branch_unlikely(&tcp_have_comp)) {
if (tcp_syn_comp_enabled(tp)) {
if (*remaining >= TCPOLEN_EXP_COMP_BASE) {
opts->options |= OPTION_COMP;
*remaining -= TCPOLEN_EXP_COMP_BASE;
}
}
}
#endif
}
static void comp_set_option_cond(const struct tcp_sock *tp,
const struct inet_request_sock *ireq,
struct tcp_out_options *opts,
unsigned int *remaining)
{
#if IS_ENABLED(CONFIG_TCP_COMP)
if (static_branch_unlikely(&tcp_have_comp)) {
if (tcp_syn_comp_enabled(tp) && ireq->comp_ok) {
if (*remaining >= TCPOLEN_EXP_COMP_BASE) {
opts->options |= OPTION_COMP;
*remaining -= TCPOLEN_EXP_COMP_BASE;
}
}
}
#endif
}
/* Compute TCP options for SYN packets. This is not the final /* Compute TCP options for SYN packets. This is not the final
* network wire format yet. * network wire format yet.
*/ */
...@@ -639,6 +688,8 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb, ...@@ -639,6 +688,8 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
smc_set_option(tp, opts, &remaining); smc_set_option(tp, opts, &remaining);
comp_set_option(tp, opts, &remaining);
return MAX_TCP_OPTION_SPACE - remaining; return MAX_TCP_OPTION_SPACE - remaining;
} }
...@@ -704,6 +755,8 @@ static unsigned int tcp_synack_options(const struct sock *sk, ...@@ -704,6 +755,8 @@ static unsigned int tcp_synack_options(const struct sock *sk,
smc_set_option_cond(tcp_sk(sk), ireq, opts, &remaining); smc_set_option_cond(tcp_sk(sk), ireq, opts, &remaining);
comp_set_option_cond(tcp_sk(sk), ireq, opts, &remaining);
return MAX_TCP_OPTION_SPACE - remaining; return MAX_TCP_OPTION_SPACE - remaining;
} }
......
...@@ -219,6 +219,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) ...@@ -219,6 +219,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
treq->txhash = net_tx_rndhash(); treq->txhash = net_tx_rndhash();
if (IS_ENABLED(CONFIG_SMC)) if (IS_ENABLED(CONFIG_SMC))
ireq->smc_ok = 0; ireq->smc_ok = 0;
if (IS_ENABLED(CONFIG_TCP_COMP))
ireq->comp_ok = 0;
/* /*
* We need to lookup the dst_entry to get the correct window size. * We need to lookup the dst_entry to get the correct window size.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册