diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-07-26 06:59:09 -0400 |
---|---|---|
committer | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-07-26 06:59:09 -0400 |
commit | 59435444a13ed52d3444c5df26b73d3086bcd57b (patch) | |
tree | 72846dbcb8c6c41e6d630bcb81297801dfe7fb16 /net/dccp/output.c | |
parent | cdec7e50a4896c5197d5575d9ca635eea6825149 (diff) |
dccp: Allow to distinguish original and retransmitted packets
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>
Diffstat (limited to 'net/dccp/output.c')
-rw-r--r-- | net/dccp/output.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c index fe20068c5d8e..d19d48195013 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -284,14 +284,26 @@ void dccp_write_xmit(struct sock *sk, int block) | |||
284 | } | 284 | } |
285 | } | 285 | } |
286 | 286 | ||
287 | int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | 287 | /** |
288 | * dccp_retransmit_skb - Retransmit Request, Close, or CloseReq packets | ||
289 | * There are only four retransmittable packet types in DCCP: | ||
290 | * - Request in client-REQUEST state (sec. 8.1.1), | ||
291 | * - CloseReq in server-CLOSEREQ state (sec. 8.3), | ||
292 | * - Close in node-CLOSING state (sec. 8.3), | ||
293 | * - Acks in client-PARTOPEN state (sec. 8.1.5, handled by dccp_delack_timer()). | ||
294 | * This function expects sk->sk_send_head to contain the original skb. | ||
295 | */ | ||
296 | int dccp_retransmit_skb(struct sock *sk) | ||
288 | { | 297 | { |
298 | WARN_ON(sk->sk_send_head == NULL); | ||
299 | |||
289 | if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0) | 300 | if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0) |
290 | return -EHOSTUNREACH; /* Routing failure or similar. */ | 301 | return -EHOSTUNREACH; /* Routing failure or similar. */ |
291 | 302 | ||
292 | return dccp_transmit_skb(sk, (skb_cloned(skb) ? | 303 | /* this count is used to distinguish original and retransmitted skb */ |
293 | pskb_copy(skb, GFP_ATOMIC): | 304 | inet_csk(sk)->icsk_retransmits++; |
294 | skb_clone(skb, GFP_ATOMIC))); | 305 | |
306 | return dccp_transmit_skb(sk, skb_clone(sk->sk_send_head, GFP_ATOMIC)); | ||
295 | } | 307 | } |
296 | 308 | ||
297 | struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, | 309 | struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, |