mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 08:33:17 +02:00
Merge branch 'tcp-misc-changes'
Eric Dumazet says: ==================== tcp: misc changes Minor changes, following recent changes in TCP stack. ==================== Link: https://patch.msgid.link/20250301201424.2046477-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
b84c523997
|
|
@ -40,6 +40,8 @@
|
|||
FN(TCP_OFOMERGE) \
|
||||
FN(TCP_RFC7323_PAWS) \
|
||||
FN(TCP_RFC7323_PAWS_ACK) \
|
||||
FN(TCP_RFC7323_TSECR) \
|
||||
FN(TCP_LISTEN_OVERFLOW) \
|
||||
FN(TCP_OLD_SEQUENCE) \
|
||||
FN(TCP_INVALID_SEQUENCE) \
|
||||
FN(TCP_INVALID_ACK_SEQUENCE) \
|
||||
|
|
@ -281,6 +283,13 @@ enum skb_drop_reason {
|
|||
* Corresponds to LINUX_MIB_PAWS_OLD_ACK.
|
||||
*/
|
||||
SKB_DROP_REASON_TCP_RFC7323_PAWS_ACK,
|
||||
/**
|
||||
* @SKB_DROP_REASON_TCP_RFC7323_TSECR: PAWS check, invalid TSEcr.
|
||||
* Corresponds to LINUX_MIB_TSECRREJECTED.
|
||||
*/
|
||||
SKB_DROP_REASON_TCP_RFC7323_TSECR,
|
||||
/** @SKB_DROP_REASON_TCP_LISTEN_OVERFLOW: listener queue full. */
|
||||
SKB_DROP_REASON_TCP_LISTEN_OVERFLOW,
|
||||
/** @SKB_DROP_REASON_TCP_OLD_SEQUENCE: Old SEQ field (duplicate packet) */
|
||||
SKB_DROP_REASON_TCP_OLD_SEQUENCE,
|
||||
/** @SKB_DROP_REASON_TCP_INVALID_SEQUENCE: Not acceptable SEQ field */
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
|
|||
int iif, int sdif,
|
||||
bool *refcounted)
|
||||
{
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
struct net *net = dev_net_rcu(skb_dst(skb)->dev);
|
||||
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||
struct sock *sk;
|
||||
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
|
|||
const int sdif,
|
||||
bool *refcounted)
|
||||
{
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
struct net *net = dev_net_rcu(skb_dst(skb)->dev);
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
struct sock *sk;
|
||||
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw,
|
|||
u32 *tw_isn);
|
||||
struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
||||
struct request_sock *req, bool fastopen,
|
||||
bool *lost_race);
|
||||
bool *lost_race, enum skb_drop_reason *drop_reason);
|
||||
enum skb_drop_reason tcp_child_process(struct sock *parent, struct sock *child,
|
||||
struct sk_buff *skb);
|
||||
void tcp_enter_loss(struct sock *sk);
|
||||
|
|
|
|||
|
|
@ -3693,33 +3693,33 @@ EXPORT_SYMBOL(tcp_sock_set_keepcnt);
|
|||
|
||||
int tcp_set_window_clamp(struct sock *sk, int val)
|
||||
{
|
||||
u32 old_window_clamp, new_window_clamp;
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
|
||||
if (!val) {
|
||||
if (sk->sk_state != TCP_CLOSE)
|
||||
return -EINVAL;
|
||||
WRITE_ONCE(tp->window_clamp, 0);
|
||||
} else {
|
||||
u32 new_rcv_ssthresh, old_window_clamp = tp->window_clamp;
|
||||
u32 new_window_clamp = val < SOCK_MIN_RCVBUF / 2 ?
|
||||
SOCK_MIN_RCVBUF / 2 : val;
|
||||
|
||||
if (new_window_clamp == old_window_clamp)
|
||||
return 0;
|
||||
|
||||
WRITE_ONCE(tp->window_clamp, new_window_clamp);
|
||||
if (new_window_clamp < old_window_clamp) {
|
||||
/* need to apply the reserved mem provisioning only
|
||||
* when shrinking the window clamp
|
||||
*/
|
||||
__tcp_adjust_rcv_ssthresh(sk, tp->window_clamp);
|
||||
|
||||
} else {
|
||||
new_rcv_ssthresh = min(tp->rcv_wnd, tp->window_clamp);
|
||||
tp->rcv_ssthresh = max(new_rcv_ssthresh,
|
||||
tp->rcv_ssthresh);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
old_window_clamp = tp->window_clamp;
|
||||
new_window_clamp = max_t(int, SOCK_MIN_RCVBUF / 2, val);
|
||||
|
||||
if (new_window_clamp == old_window_clamp)
|
||||
return 0;
|
||||
|
||||
WRITE_ONCE(tp->window_clamp, new_window_clamp);
|
||||
|
||||
/* Need to apply the reserved mem provisioning only
|
||||
* when shrinking the window clamp.
|
||||
*/
|
||||
if (new_window_clamp < old_window_clamp)
|
||||
__tcp_adjust_rcv_ssthresh(sk, new_window_clamp);
|
||||
else
|
||||
tp->rcv_ssthresh = clamp(new_window_clamp,
|
||||
tp->rcv_ssthresh,
|
||||
tp->rcv_wnd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6812,10 +6812,9 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
|
|||
WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
|
||||
sk->sk_state != TCP_FIN_WAIT1);
|
||||
|
||||
if (!tcp_check_req(sk, skb, req, true, &req_stolen)) {
|
||||
SKB_DR_SET(reason, TCP_FASTOPEN);
|
||||
SKB_DR_SET(reason, TCP_FASTOPEN);
|
||||
if (!tcp_check_req(sk, skb, req, true, &req_stolen, &reason))
|
||||
goto discard;
|
||||
}
|
||||
}
|
||||
|
||||
if (!th->ack && !th->rst && !th->syn) {
|
||||
|
|
|
|||
|
|
@ -494,14 +494,14 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
|
|||
{
|
||||
const struct iphdr *iph = (const struct iphdr *)skb->data;
|
||||
struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
|
||||
struct tcp_sock *tp;
|
||||
struct net *net = dev_net_rcu(skb->dev);
|
||||
const int type = icmp_hdr(skb)->type;
|
||||
const int code = icmp_hdr(skb)->code;
|
||||
struct sock *sk;
|
||||
struct request_sock *fastopen;
|
||||
struct tcp_sock *tp;
|
||||
u32 seq, snd_una;
|
||||
struct sock *sk;
|
||||
int err;
|
||||
struct net *net = dev_net(skb->dev);
|
||||
|
||||
sk = __inet_lookup_established(net, net->ipv4.tcp_death_row.hashinfo,
|
||||
iph->daddr, th->dest, iph->saddr,
|
||||
|
|
@ -786,7 +786,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb,
|
|||
arg.iov[0].iov_base = (unsigned char *)&rep;
|
||||
arg.iov[0].iov_len = sizeof(rep.th);
|
||||
|
||||
net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
|
||||
net = sk ? sock_net(sk) : dev_net_rcu(skb_dst(skb)->dev);
|
||||
|
||||
/* Invalid TCP option size or twice included auth */
|
||||
if (tcp_parse_auth_options(tcp_hdr(skb), &md5_hash_location, &aoh))
|
||||
|
|
@ -1155,7 +1155,7 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
|
|||
tcp_rsk(req)->rcv_nxt,
|
||||
tcp_synack_window(req) >> inet_rsk(req)->rcv_wscale,
|
||||
tcp_rsk_tsval(tcp_rsk(req)),
|
||||
READ_ONCE(req->ts_recent),
|
||||
req->ts_recent,
|
||||
0, &key,
|
||||
inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0,
|
||||
ip_hdr(skb)->tos,
|
||||
|
|
@ -1961,7 +1961,7 @@ EXPORT_SYMBOL(tcp_v4_do_rcv);
|
|||
|
||||
int tcp_v4_early_demux(struct sk_buff *skb)
|
||||
{
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct net *net = dev_net_rcu(skb->dev);
|
||||
const struct iphdr *iph;
|
||||
const struct tcphdr *th;
|
||||
struct sock *sk;
|
||||
|
|
@ -2172,7 +2172,7 @@ static void tcp_v4_fill_cb(struct sk_buff *skb, const struct iphdr *iph,
|
|||
|
||||
int tcp_v4_rcv(struct sk_buff *skb)
|
||||
{
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct net *net = dev_net_rcu(skb->dev);
|
||||
enum skb_drop_reason drop_reason;
|
||||
int sdif = inet_sdif(skb);
|
||||
int dif = inet_iif(skb);
|
||||
|
|
@ -2265,7 +2265,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
|
|||
th = (const struct tcphdr *)skb->data;
|
||||
iph = ip_hdr(skb);
|
||||
tcp_v4_fill_cb(skb, iph, th);
|
||||
nsk = tcp_check_req(sk, skb, req, false, &req_stolen);
|
||||
nsk = tcp_check_req(sk, skb, req, false, &req_stolen,
|
||||
&drop_reason);
|
||||
} else {
|
||||
drop_reason = SKB_DROP_REASON_SOCKET_FILTER;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
|
|||
bool reclaim = false;
|
||||
|
||||
spin_lock_bh(&tcp_metrics_lock);
|
||||
net = dev_net(dst->dev);
|
||||
net = dev_net_rcu(dst->dev);
|
||||
|
||||
/* While waiting for the spin-lock the cache might have been populated
|
||||
* with this entry and so we have to check again.
|
||||
|
|
@ -273,7 +273,7 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
net = dev_net(dst->dev);
|
||||
net = dev_net_rcu(dst->dev);
|
||||
hash ^= net_hash_mix(net);
|
||||
hash = hash_32(hash, tcp_metrics_hash_log);
|
||||
|
||||
|
|
@ -318,7 +318,7 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
|
|||
else
|
||||
return NULL;
|
||||
|
||||
net = dev_net(dst->dev);
|
||||
net = dev_net_rcu(dst->dev);
|
||||
hash ^= net_hash_mix(net);
|
||||
hash = hash_32(hash, tcp_metrics_hash_log);
|
||||
|
||||
|
|
|
|||
|
|
@ -585,7 +585,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
|
|||
|
||||
if (newtp->rx_opt.tstamp_ok) {
|
||||
newtp->tcp_usec_ts = treq->req_usec_ts;
|
||||
newtp->rx_opt.ts_recent = READ_ONCE(req->ts_recent);
|
||||
newtp->rx_opt.ts_recent = req->ts_recent;
|
||||
newtp->rx_opt.ts_recent_stamp = ktime_get_seconds();
|
||||
newtp->tcp_header_len = sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
|
||||
} else {
|
||||
|
|
@ -657,7 +657,8 @@ EXPORT_SYMBOL(tcp_create_openreq_child);
|
|||
|
||||
struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
||||
struct request_sock *req,
|
||||
bool fastopen, bool *req_stolen)
|
||||
bool fastopen, bool *req_stolen,
|
||||
enum skb_drop_reason *drop_reason)
|
||||
{
|
||||
struct tcp_options_received tmp_opt;
|
||||
struct sock *child;
|
||||
|
|
@ -672,7 +673,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
|||
tcp_parse_options(sock_net(sk), skb, &tmp_opt, 0, NULL);
|
||||
|
||||
if (tmp_opt.saw_tstamp) {
|
||||
tmp_opt.ts_recent = READ_ONCE(req->ts_recent);
|
||||
tmp_opt.ts_recent = req->ts_recent;
|
||||
if (tmp_opt.rcv_tsecr) {
|
||||
if (inet_rsk(req)->tstamp_ok && !fastopen)
|
||||
tsecr_reject = !between(tmp_opt.rcv_tsecr,
|
||||
|
|
@ -808,10 +809,15 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
|||
LINUX_MIB_TCPACKSKIPPEDSYNRECV,
|
||||
&tcp_rsk(req)->last_oow_ack_time))
|
||||
req->rsk_ops->send_ack(sk, skb, req);
|
||||
if (paws_reject)
|
||||
if (paws_reject) {
|
||||
SKB_DR_SET(*drop_reason, TCP_RFC7323_PAWS);
|
||||
NET_INC_STATS(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
|
||||
else if (tsecr_reject)
|
||||
} else if (tsecr_reject) {
|
||||
SKB_DR_SET(*drop_reason, TCP_RFC7323_TSECR);
|
||||
NET_INC_STATS(sock_net(sk), LINUX_MIB_TSECRREJECTED);
|
||||
} else {
|
||||
SKB_DR_SET(*drop_reason, TCP_OVERWINDOW);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -881,6 +887,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
|||
return inet_csk_complete_hashdance(sk, child, req, own_req);
|
||||
|
||||
listen_overflow:
|
||||
SKB_DR_SET(*drop_reason, TCP_LISTEN_OVERFLOW);
|
||||
if (sk != req->rsk_listener)
|
||||
__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMIGRATEREQFAILURE);
|
||||
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ static void tcp4_check_fraglist_gro(struct list_head *head, struct sk_buff *skb,
|
|||
|
||||
inet_get_iif_sdif(skb, &iif, &sdif);
|
||||
iph = skb_gro_network_header(skb);
|
||||
net = dev_net(skb->dev);
|
||||
net = dev_net_rcu(skb->dev);
|
||||
sk = __inet_lookup_established(net, net->ipv4.tcp_death_row.hashinfo,
|
||||
iph->saddr, th->source,
|
||||
iph->daddr, ntohs(th->dest),
|
||||
|
|
|
|||
|
|
@ -949,7 +949,7 @@ static unsigned int tcp_synack_options(const struct sock *sk,
|
|||
tcp_rsk(req)->snt_tsval_first = opts->tsval;
|
||||
}
|
||||
WRITE_ONCE(tcp_rsk(req)->snt_tsval_last, opts->tsval);
|
||||
opts->tsecr = READ_ONCE(req->ts_recent);
|
||||
opts->tsecr = req->ts_recent;
|
||||
remaining -= TCPOLEN_TSTAMP_ALIGNED;
|
||||
}
|
||||
if (likely(ireq->sack_ok)) {
|
||||
|
|
|
|||
|
|
@ -630,7 +630,7 @@ static struct sock *udp4_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
|
|||
__be16 dport)
|
||||
{
|
||||
const struct iphdr *iph = skb_gro_network_header(skb);
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct net *net = dev_net_rcu(skb->dev);
|
||||
int iif, sdif;
|
||||
|
||||
inet_get_iif_sdif(skb, &iif, &sdif);
|
||||
|
|
|
|||
|
|
@ -376,7 +376,7 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||
{
|
||||
const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
|
||||
const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct net *net = dev_net_rcu(skb->dev);
|
||||
struct request_sock *fastopen;
|
||||
struct ipv6_pinfo *np;
|
||||
struct tcp_sock *tp;
|
||||
|
|
@ -866,16 +866,16 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
|
|||
int oif, int rst, u8 tclass, __be32 label,
|
||||
u32 priority, u32 txhash, struct tcp_key *key)
|
||||
{
|
||||
const struct tcphdr *th = tcp_hdr(skb);
|
||||
struct tcphdr *t1;
|
||||
struct sk_buff *buff;
|
||||
struct flowi6 fl6;
|
||||
struct net *net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
|
||||
struct sock *ctl_sk = net->ipv6.tcp_sk;
|
||||
struct net *net = sk ? sock_net(sk) : dev_net_rcu(skb_dst(skb)->dev);
|
||||
unsigned int tot_len = sizeof(struct tcphdr);
|
||||
struct sock *ctl_sk = net->ipv6.tcp_sk;
|
||||
const struct tcphdr *th = tcp_hdr(skb);
|
||||
__be32 mrst = 0, *topt;
|
||||
struct dst_entry *dst;
|
||||
__u32 mark = 0;
|
||||
struct sk_buff *buff;
|
||||
struct tcphdr *t1;
|
||||
struct flowi6 fl6;
|
||||
u32 mark = 0;
|
||||
|
||||
if (tsecr)
|
||||
tot_len += TCPOLEN_TSTAMP_ALIGNED;
|
||||
|
|
@ -1041,7 +1041,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb,
|
|||
if (!sk && !ipv6_unicast_destination(skb))
|
||||
return;
|
||||
|
||||
net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
|
||||
net = sk ? sock_net(sk) : dev_net_rcu(skb_dst(skb)->dev);
|
||||
/* Invalid TCP option size or twice included auth */
|
||||
if (tcp_parse_auth_options(th, &md5_hash_location, &aoh))
|
||||
return;
|
||||
|
|
@ -1279,7 +1279,7 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
|
|||
tcp_rsk(req)->rcv_nxt,
|
||||
tcp_synack_window(req) >> inet_rsk(req)->rcv_wscale,
|
||||
tcp_rsk_tsval(tcp_rsk(req)),
|
||||
READ_ONCE(req->ts_recent), sk->sk_bound_dev_if,
|
||||
req->ts_recent, sk->sk_bound_dev_if,
|
||||
&key, ipv6_get_dsfield(ipv6_hdr(skb)), 0,
|
||||
READ_ONCE(sk->sk_priority),
|
||||
READ_ONCE(tcp_rsk(req)->txhash));
|
||||
|
|
@ -1740,6 +1740,7 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr,
|
|||
|
||||
INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
|
||||
{
|
||||
struct net *net = dev_net_rcu(skb->dev);
|
||||
enum skb_drop_reason drop_reason;
|
||||
int sdif = inet6_sdif(skb);
|
||||
int dif = inet6_iif(skb);
|
||||
|
|
@ -1749,7 +1750,6 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
|
|||
bool refcounted;
|
||||
int ret;
|
||||
u32 isn;
|
||||
struct net *net = dev_net(skb->dev);
|
||||
|
||||
drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
if (skb->pkt_type != PACKET_HOST)
|
||||
|
|
@ -1828,7 +1828,8 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
|
|||
th = (const struct tcphdr *)skb->data;
|
||||
hdr = ipv6_hdr(skb);
|
||||
tcp_v6_fill_cb(skb, hdr, th);
|
||||
nsk = tcp_check_req(sk, skb, req, false, &req_stolen);
|
||||
nsk = tcp_check_req(sk, skb, req, false, &req_stolen,
|
||||
&drop_reason);
|
||||
} else {
|
||||
drop_reason = SKB_DROP_REASON_SOCKET_FILTER;
|
||||
}
|
||||
|
|
@ -2000,7 +2001,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
|
|||
|
||||
void tcp_v6_early_demux(struct sk_buff *skb)
|
||||
{
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct net *net = dev_net_rcu(skb->dev);
|
||||
const struct ipv6hdr *hdr;
|
||||
const struct tcphdr *th;
|
||||
struct sock *sk;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ static void tcp6_check_fraglist_gro(struct list_head *head, struct sk_buff *skb,
|
|||
|
||||
inet6_get_iif_sdif(skb, &iif, &sdif);
|
||||
hdr = skb_gro_network_header(skb);
|
||||
net = dev_net(skb->dev);
|
||||
net = dev_net_rcu(skb->dev);
|
||||
sk = __inet6_lookup_established(net, net->ipv4.tcp_death_row.hashinfo,
|
||||
&hdr->saddr, th->source,
|
||||
&hdr->daddr, ntohs(th->dest),
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ static struct sock *udp6_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
|
|||
__be16 dport)
|
||||
{
|
||||
const struct ipv6hdr *iph = skb_gro_network_header(skb);
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct net *net = dev_net_rcu(skb->dev);
|
||||
int iif, sdif;
|
||||
|
||||
inet6_get_iif_sdif(skb, &iif, &sdif);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user