Skip to content

Commit

Permalink
dccp: Allow to distinguish original and retransmitted packets
Browse files Browse the repository at this point in the history
This patch allows the sender to distinguish original and retransmitted packets,
which is in particular needed for the retransmission of DCCP-Requests:
 * the first Request uses ISS (generated in net/dccp/ip*.c), and sets GSS = ISS;
 * all retransmitted Requests use GSS' = GSS + 1, so that the n-th retransmitted
   Request has sequence number ISS + n (mod 48).

To add generic support, the patch reorganises existing code so that:
 * icsk_retransmits == 0     for the original packet and
 * icsk_retransmits = n > 0  for the n-th retransmitted packet
at the time dccp_transmit_skb() is called, via dccp_retransmit_skb().
 
Thanks to Wei Yongjun for pointing this problem out.

Further changes:
----------------
 * removed the `skb' argument from dccp_retransmit_skb(), since sk_send_head
   is used for all retransmissions (the exception is client-Acks in PARTOPEN
   state, but these do not use sk_send_head);
 * since sk_send_head always contains the original skb (via dccp_entail()),
   skb_cloned() never evaluated to true and thus pskb_copy() was never used.

Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
  • Loading branch information
Gerrit Renker committed Jul 26, 2008
1 parent cdec7e5 commit 5943544
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 21 deletions.
2 changes: 1 addition & 1 deletion net/dccp/dccp.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ static inline void dccp_csum_outgoing(struct sk_buff *skb)

extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);

extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
extern int dccp_retransmit_skb(struct sock *sk);

extern void dccp_send_ack(struct sock *sk);
extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk);
Expand Down
20 changes: 16 additions & 4 deletions net/dccp/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,26 @@ void dccp_write_xmit(struct sock *sk, int block)
}
}

int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
/**
* dccp_retransmit_skb - Retransmit Request, Close, or CloseReq packets
* There are only four retransmittable packet types in DCCP:
* - Request in client-REQUEST state (sec. 8.1.1),
* - CloseReq in server-CLOSEREQ state (sec. 8.3),
* - Close in node-CLOSING state (sec. 8.3),
* - Acks in client-PARTOPEN state (sec. 8.1.5, handled by dccp_delack_timer()).
* This function expects sk->sk_send_head to contain the original skb.
*/
int dccp_retransmit_skb(struct sock *sk)
{
WARN_ON(sk->sk_send_head == NULL);

if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
return -EHOSTUNREACH; /* Routing failure or similar. */

return dccp_transmit_skb(sk, (skb_cloned(skb) ?
pskb_copy(skb, GFP_ATOMIC):
skb_clone(skb, GFP_ATOMIC)));
/* this count is used to distinguish original and retransmitted skb */
inet_csk(sk)->icsk_retransmits++;

return dccp_transmit_skb(sk, skb_clone(sk->sk_send_head, GFP_ATOMIC));
}

struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
Expand Down
20 changes: 4 additions & 16 deletions net/dccp/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,12 @@ static void dccp_retransmit_timer(struct sock *sk)
goto backoff;
}

/*
* sk->sk_send_head has to have one skb with
* DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
* packet types. The only packets eligible for retransmission are:
* -- Requests in client-REQUEST state (sec. 8.1.1)
* -- Acks in client-PARTOPEN state (sec. 8.1.5)
* -- CloseReq in server-CLOSEREQ state (sec. 8.3)
* -- Close in node-CLOSING state (sec. 8.3) */
WARN_ON(sk->sk_send_head == NULL);

/*
* More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
* sent, no need to retransmit, this sock is dead.
*/
if (dccp_write_timeout(sk))
goto out;
return;

/*
* We want to know the number of packets retransmitted, not the
Expand All @@ -122,30 +112,28 @@ static void dccp_retransmit_timer(struct sock *sk)
if (icsk->icsk_retransmits == 0)
DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS);

if (dccp_retransmit_skb(sk, sk->sk_send_head) < 0) {
if (dccp_retransmit_skb(sk) != 0) {
/*
* Retransmission failed because of local congestion,
* do not backoff.
*/
if (icsk->icsk_retransmits == 0)
if (--icsk->icsk_retransmits == 0)
icsk->icsk_retransmits = 1;
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
min(icsk->icsk_rto,
TCP_RESOURCE_PROBE_INTERVAL),
DCCP_RTO_MAX);
goto out;
return;
}

backoff:
icsk->icsk_backoff++;
icsk->icsk_retransmits++;

icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
DCCP_RTO_MAX);
if (icsk->icsk_retransmits > sysctl_dccp_retries1)
__sk_dst_reset(sk);
out:;
}

static void dccp_write_timer(unsigned long data)
Expand Down

0 comments on commit 5943544

Please sign in to comment.