aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-07-26 06:59:09 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-07-26 06:59:09 -0400
commit59435444a13ed52d3444c5df26b73d3086bcd57b (patch)
tree72846dbcb8c6c41e6d630bcb81297801dfe7fb16 /net
parentcdec7e50a4896c5197d5575d9ca635eea6825149 (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')
-rw-r--r--net/dccp/dccp.h2
-rw-r--r--net/dccp/output.c20
-rw-r--r--net/dccp/timer.c20
3 files changed, 21 insertions, 21 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 743d85fcd651..1c2e3ec2eb57 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -226,7 +226,7 @@ static inline void dccp_csum_outgoing(struct sk_buff *skb)
226 226
227extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); 227extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
228 228
229extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb); 229extern int dccp_retransmit_skb(struct sock *sk);
230 230
231extern void dccp_send_ack(struct sock *sk); 231extern void dccp_send_ack(struct sock *sk);
232extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk); 232extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk);
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
287int 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 */
296int 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
297struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, 309struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index 6a5b961b6f5c..54b3c7e9e016 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -99,21 +99,11 @@ static void dccp_retransmit_timer(struct sock *sk)
99 } 99 }
100 100
101 /* 101 /*
102 * sk->sk_send_head has to have one skb with
103 * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
104 * packet types. The only packets eligible for retransmission are:
105 * -- Requests in client-REQUEST state (sec. 8.1.1)
106 * -- Acks in client-PARTOPEN state (sec. 8.1.5)
107 * -- CloseReq in server-CLOSEREQ state (sec. 8.3)
108 * -- Close in node-CLOSING state (sec. 8.3) */
109 WARN_ON(sk->sk_send_head == NULL);
110
111 /*
112 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was 102 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
113 * sent, no need to retransmit, this sock is dead. 103 * sent, no need to retransmit, this sock is dead.
114 */ 104 */
115 if (dccp_write_timeout(sk)) 105 if (dccp_write_timeout(sk))
116 goto out; 106 return;
117 107
118 /* 108 /*
119 * We want to know the number of packets retransmitted, not the 109 * We want to know the number of packets retransmitted, not the
@@ -122,30 +112,28 @@ static void dccp_retransmit_timer(struct sock *sk)
122 if (icsk->icsk_retransmits == 0) 112 if (icsk->icsk_retransmits == 0)
123 DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS); 113 DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS);
124 114
125 if (dccp_retransmit_skb(sk, sk->sk_send_head) < 0) { 115 if (dccp_retransmit_skb(sk) != 0) {
126 /* 116 /*
127 * Retransmission failed because of local congestion, 117 * Retransmission failed because of local congestion,
128 * do not backoff. 118 * do not backoff.
129 */ 119 */
130 if (icsk->icsk_retransmits == 0) 120 if (--icsk->icsk_retransmits == 0)
131 icsk->icsk_retransmits = 1; 121 icsk->icsk_retransmits = 1;
132 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, 122 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
133 min(icsk->icsk_rto, 123 min(icsk->icsk_rto,
134 TCP_RESOURCE_PROBE_INTERVAL), 124 TCP_RESOURCE_PROBE_INTERVAL),
135 DCCP_RTO_MAX); 125 DCCP_RTO_MAX);
136 goto out; 126 return;
137 } 127 }
138 128
139backoff: 129backoff:
140 icsk->icsk_backoff++; 130 icsk->icsk_backoff++;
141 icsk->icsk_retransmits++;
142 131
143 icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX); 132 icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
144 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, 133 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
145 DCCP_RTO_MAX); 134 DCCP_RTO_MAX);
146 if (icsk->icsk_retransmits > sysctl_dccp_retries1) 135 if (icsk->icsk_retransmits > sysctl_dccp_retries1)
147 __sk_dst_reset(sk); 136 __sk_dst_reset(sk);
148out:;
149} 137}
150 138
151static void dccp_write_timer(unsigned long data) 139static void dccp_write_timer(unsigned long data)