aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 893286db4623..337f6011528a 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -76,6 +76,8 @@
76#include <asm/unaligned.h> 76#include <asm/unaligned.h>
77#include <linux/errqueue.h> 77#include <linux/errqueue.h>
78#include <trace/events/tcp.h> 78#include <trace/events/tcp.h>
79#include <linux/unaligned/access_ok.h>
80#include <linux/static_key.h>
79 81
80int sysctl_tcp_fack __read_mostly; 82int sysctl_tcp_fack __read_mostly;
81int sysctl_tcp_max_reordering __read_mostly = 300; 83int sysctl_tcp_max_reordering __read_mostly = 300;
@@ -3737,6 +3739,21 @@ static void tcp_parse_fastopen_option(int len, const unsigned char *cookie,
3737 foc->exp = exp_opt; 3739 foc->exp = exp_opt;
3738} 3740}
3739 3741
3742static void smc_parse_options(const struct tcphdr *th,
3743 struct tcp_options_received *opt_rx,
3744 const unsigned char *ptr,
3745 int opsize)
3746{
3747#if IS_ENABLED(CONFIG_SMC)
3748 if (static_branch_unlikely(&tcp_have_smc)) {
3749 if (th->syn && !(opsize & 1) &&
3750 opsize >= TCPOLEN_EXP_SMC_BASE &&
3751 get_unaligned_be32(ptr) == TCPOPT_SMC_MAGIC)
3752 opt_rx->smc_ok = 1;
3753 }
3754#endif
3755}
3756
3740/* Look for tcp options. Normally only called on SYN and SYNACK packets. 3757/* Look for tcp options. Normally only called on SYN and SYNACK packets.
3741 * But, this can also be called on packets in the established flow when 3758 * But, this can also be called on packets in the established flow when
3742 * the fast version below fails. 3759 * the fast version below fails.
@@ -3844,6 +3861,9 @@ void tcp_parse_options(const struct net *net,
3844 tcp_parse_fastopen_option(opsize - 3861 tcp_parse_fastopen_option(opsize -
3845 TCPOLEN_EXP_FASTOPEN_BASE, 3862 TCPOLEN_EXP_FASTOPEN_BASE,
3846 ptr + 2, th->syn, foc, true); 3863 ptr + 2, th->syn, foc, true);
3864 else
3865 smc_parse_options(th, opt_rx, ptr,
3866 opsize);
3847 break; 3867 break;
3848 3868
3849 } 3869 }
@@ -5598,6 +5618,16 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
5598 return false; 5618 return false;
5599} 5619}
5600 5620
5621static void smc_check_reset_syn(struct tcp_sock *tp)
5622{
5623#if IS_ENABLED(CONFIG_SMC)
5624 if (static_branch_unlikely(&tcp_have_smc)) {
5625 if (tp->syn_smc && !tp->rx_opt.smc_ok)
5626 tp->syn_smc = 0;
5627 }
5628#endif
5629}
5630
5601static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, 5631static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5602 const struct tcphdr *th) 5632 const struct tcphdr *th)
5603{ 5633{
@@ -5704,6 +5734,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5704 * is initialized. */ 5734 * is initialized. */
5705 tp->copied_seq = tp->rcv_nxt; 5735 tp->copied_seq = tp->rcv_nxt;
5706 5736
5737 smc_check_reset_syn(tp);
5738
5707 smp_mb(); 5739 smp_mb();
5708 5740
5709 tcp_finish_connect(sk, skb); 5741 tcp_finish_connect(sk, skb);
@@ -6157,6 +6189,9 @@ static void tcp_openreq_init(struct request_sock *req,
6157 ireq->ir_rmt_port = tcp_hdr(skb)->source; 6189 ireq->ir_rmt_port = tcp_hdr(skb)->source;
6158 ireq->ir_num = ntohs(tcp_hdr(skb)->dest); 6190 ireq->ir_num = ntohs(tcp_hdr(skb)->dest);
6159 ireq->ir_mark = inet_request_mark(sk, skb); 6191 ireq->ir_mark = inet_request_mark(sk, skb);
6192#if IS_ENABLED(CONFIG_SMC)
6193 ireq->smc_ok = rx_opt->smc_ok;
6194#endif
6160} 6195}
6161 6196
6162struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops, 6197struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,