Skip to content

Commit be372e9

Browse files
committed
Merge branch 'tcp-tcp_v4_err-cleanups'
Eric Dumazet says: ==================== tcp: tcp_v4_err() cleanups This series is a followup of patch 2391749 ("tcp: tcp_v4_err() icmp skb is named icmp_skb"). Move the RFC 6069 code into a helper, and rename icmp_skb to standard skb name so that tcp_v4_err() and tcp_v6_err() are using consistent names. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents d6a3511 + a12daf1 commit be372e9

File tree

1 file changed

+54
-49
lines changed

1 file changed

+54
-49
lines changed

net/ipv4/tcp_ipv4.c

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,45 @@ void tcp_req_err(struct sock *sk, u32 seq, bool abort)
403403
}
404404
EXPORT_SYMBOL(tcp_req_err);
405405

406+
/* TCP-LD (RFC 6069) logic */
407+
static void tcp_ld_RTO_revert(struct sock *sk, u32 seq)
408+
{
409+
struct inet_connection_sock *icsk = inet_csk(sk);
410+
struct tcp_sock *tp = tcp_sk(sk);
411+
struct sk_buff *skb;
412+
s32 remaining;
413+
u32 delta_us;
414+
415+
if (sock_owned_by_user(sk))
416+
return;
417+
418+
if (seq != tp->snd_una || !icsk->icsk_retransmits ||
419+
!icsk->icsk_backoff)
420+
return;
421+
422+
skb = tcp_rtx_queue_head(sk);
423+
if (WARN_ON_ONCE(!skb))
424+
return;
425+
426+
icsk->icsk_backoff--;
427+
icsk->icsk_rto = tp->srtt_us ? __tcp_set_rto(tp) : TCP_TIMEOUT_INIT;
428+
icsk->icsk_rto = inet_csk_rto_backoff(icsk, TCP_RTO_MAX);
429+
430+
tcp_mstamp_refresh(tp);
431+
delta_us = (u32)(tp->tcp_mstamp - tcp_skb_timestamp_us(skb));
432+
remaining = icsk->icsk_rto - usecs_to_jiffies(delta_us);
433+
434+
if (remaining > 0) {
435+
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
436+
remaining, TCP_RTO_MAX);
437+
} else {
438+
/* RTO revert clocked out retransmission.
439+
* Will retransmit now.
440+
*/
441+
tcp_retransmit_timer(sk);
442+
}
443+
}
444+
406445
/*
407446
* This routine is called by the ICMP module when it gets some
408447
* sort of error condition. If err < 0 then the socket should
@@ -419,27 +458,23 @@ EXPORT_SYMBOL(tcp_req_err);
419458
*
420459
*/
421460

422-
int tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
461+
int tcp_v4_err(struct sk_buff *skb, u32 info)
423462
{
424-
const struct iphdr *iph = (const struct iphdr *)icmp_skb->data;
425-
struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2));
426-
struct inet_connection_sock *icsk;
463+
const struct iphdr *iph = (const struct iphdr *)skb->data;
464+
struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
427465
struct tcp_sock *tp;
428466
struct inet_sock *inet;
429-
const int type = icmp_hdr(icmp_skb)->type;
430-
const int code = icmp_hdr(icmp_skb)->code;
467+
const int type = icmp_hdr(skb)->type;
468+
const int code = icmp_hdr(skb)->code;
431469
struct sock *sk;
432-
struct sk_buff *skb;
433470
struct request_sock *fastopen;
434471
u32 seq, snd_una;
435-
s32 remaining;
436-
u32 delta_us;
437472
int err;
438-
struct net *net = dev_net(icmp_skb->dev);
473+
struct net *net = dev_net(skb->dev);
439474

440475
sk = __inet_lookup_established(net, &tcp_hashinfo, iph->daddr,
441476
th->dest, iph->saddr, ntohs(th->source),
442-
inet_iif(icmp_skb), 0);
477+
inet_iif(skb), 0);
443478
if (!sk) {
444479
__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
445480
return -ENOENT;
@@ -476,7 +511,6 @@ int tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
476511
goto out;
477512
}
478513

479-
icsk = inet_csk(sk);
480514
tp = tcp_sk(sk);
481515
/* XXX (TFO) - tp->snd_una should be ISN (tcp_create_openreq_child() */
482516
fastopen = rcu_dereference(tp->fastopen_rsk);
@@ -490,7 +524,7 @@ int tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
490524
switch (type) {
491525
case ICMP_REDIRECT:
492526
if (!sock_owned_by_user(sk))
493-
do_redirect(icmp_skb, sk);
527+
do_redirect(skb, sk);
494528
goto out;
495529
case ICMP_SOURCE_QUENCH:
496530
/* Just silently ignore these. */
@@ -521,41 +555,12 @@ int tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
521555
}
522556

523557
err = icmp_err_convert[code].errno;
524-
/* check if icmp_skb allows revert of backoff
525-
* (see draft-zimmermann-tcp-lcd) */
526-
if (code != ICMP_NET_UNREACH && code != ICMP_HOST_UNREACH)
527-
break;
528-
if (seq != tp->snd_una || !icsk->icsk_retransmits ||
529-
!icsk->icsk_backoff || fastopen)
530-
break;
531-
532-
if (sock_owned_by_user(sk))
533-
break;
534-
535-
skb = tcp_rtx_queue_head(sk);
536-
if (WARN_ON_ONCE(!skb))
537-
break;
538-
539-
icsk->icsk_backoff--;
540-
icsk->icsk_rto = tp->srtt_us ? __tcp_set_rto(tp) :
541-
TCP_TIMEOUT_INIT;
542-
icsk->icsk_rto = inet_csk_rto_backoff(icsk, TCP_RTO_MAX);
543-
544-
545-
tcp_mstamp_refresh(tp);
546-
delta_us = (u32)(tp->tcp_mstamp - tcp_skb_timestamp_us(skb));
547-
remaining = icsk->icsk_rto -
548-
usecs_to_jiffies(delta_us);
549-
550-
if (remaining > 0) {
551-
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
552-
remaining, TCP_RTO_MAX);
553-
} else {
554-
/* RTO revert clocked out retransmission.
555-
* Will retransmit now */
556-
tcp_retransmit_timer(sk);
557-
}
558-
558+
/* check if this ICMP message allows revert of backoff.
559+
* (see RFC 6069)
560+
*/
561+
if (!fastopen &&
562+
(code == ICMP_NET_UNREACH || code == ICMP_HOST_UNREACH))
563+
tcp_ld_RTO_revert(sk, seq);
559564
break;
560565
case ICMP_TIME_EXCEEDED:
561566
err = EHOSTUNREACH;
@@ -573,7 +578,7 @@ int tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
573578
if (fastopen && !fastopen->sk)
574579
break;
575580

576-
ip_icmp_error(sk, icmp_skb, err, th->dest, info, (u8 *)th);
581+
ip_icmp_error(sk, skb, err, th->dest, info, (u8 *)th);
577582

578583
if (!sock_owned_by_user(sk)) {
579584
sk->sk_err = err;

0 commit comments

Comments
 (0)