]>
Commit | Line | Data |
---|---|---|
17926a79 DH |
1 | /* Management of Tx window, Tx resend, ACKs and out-of-sequence reception |
2 | * | |
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells (dhowells@redhat.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the License, or (at your option) any later version. | |
10 | */ | |
11 | ||
9b6d5398 JP |
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
13 | ||
17926a79 DH |
14 | #include <linux/module.h> |
15 | #include <linux/circ_buf.h> | |
16 | #include <linux/net.h> | |
17 | #include <linux/skbuff.h> | |
5a0e3ad6 | 18 | #include <linux/slab.h> |
17926a79 DH |
19 | #include <linux/udp.h> |
20 | #include <net/sock.h> | |
21 | #include <net/af_rxrpc.h> | |
22 | #include "ar-internal.h" | |
23 | ||
17926a79 | 24 | /* |
248f219c | 25 | * Set the timer |
17926a79 | 26 | */ |
248f219c | 27 | static void rxrpc_set_timer(struct rxrpc_call *call) |
17926a79 | 28 | { |
248f219c | 29 | unsigned long t, now = jiffies; |
17926a79 | 30 | |
248f219c DH |
31 | _enter("{%ld,%ld,%ld:%ld}", |
32 | call->ack_at - now, call->resend_at - now, call->expire_at - now, | |
33 | call->timer.expires - now); | |
fabf9201 | 34 | |
248f219c | 35 | read_lock_bh(&call->state_lock); |
17926a79 | 36 | |
248f219c DH |
37 | if (call->state < RXRPC_CALL_COMPLETE) { |
38 | t = call->ack_at; | |
39 | if (time_before(call->resend_at, t)) | |
40 | t = call->resend_at; | |
41 | if (time_before(call->expire_at, t)) | |
42 | t = call->expire_at; | |
43 | if (!timer_pending(&call->timer) || | |
44 | time_before(t, call->timer.expires)) { | |
45 | _debug("set timer %ld", t - now); | |
46 | mod_timer(&call->timer, t); | |
17926a79 | 47 | } |
17926a79 | 48 | } |
17926a79 DH |
49 | read_unlock_bh(&call->state_lock); |
50 | } | |
51 | ||
52 | /* | |
248f219c | 53 | * propose an ACK be sent |
17926a79 | 54 | */ |
248f219c DH |
55 | static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, |
56 | u16 skew, u32 serial, bool immediate, | |
57 | bool background) | |
17926a79 | 58 | { |
248f219c | 59 | unsigned long now, ack_at, expiry = rxrpc_soft_ack_delay; |
17926a79 DH |
60 | s8 prior = rxrpc_ack_priority[ack_reason]; |
61 | ||
248f219c DH |
62 | _enter("{%d},%s,%%%x,%u", |
63 | call->debug_id, rxrpc_acks(ack_reason), serial, immediate); | |
17926a79 | 64 | |
248f219c DH |
65 | /* Update DELAY, IDLE, REQUESTED and PING_RESPONSE ACK serial |
66 | * numbers, but we don't alter the timeout. | |
67 | */ | |
68 | _debug("prior %u %u vs %u %u", | |
69 | ack_reason, prior, | |
70 | call->ackr_reason, rxrpc_ack_priority[call->ackr_reason]); | |
71 | if (ack_reason == call->ackr_reason) { | |
72 | if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) { | |
73 | call->ackr_serial = serial; | |
74 | call->ackr_skew = skew; | |
17926a79 | 75 | } |
248f219c DH |
76 | if (!immediate) |
77 | return; | |
78 | } else if (prior > rxrpc_ack_priority[call->ackr_reason]) { | |
79 | call->ackr_reason = ack_reason; | |
80 | call->ackr_serial = serial; | |
81 | call->ackr_skew = skew; | |
17926a79 DH |
82 | } |
83 | ||
248f219c DH |
84 | switch (ack_reason) { |
85 | case RXRPC_ACK_REQUESTED: | |
86 | if (rxrpc_requested_ack_delay < expiry) | |
87 | expiry = rxrpc_requested_ack_delay; | |
88 | if (serial == 1) | |
89 | immediate = false; | |
90 | break; | |
17926a79 | 91 | |
248f219c DH |
92 | case RXRPC_ACK_DELAY: |
93 | if (rxrpc_soft_ack_delay < expiry) | |
94 | expiry = rxrpc_soft_ack_delay; | |
95 | break; | |
17926a79 | 96 | |
248f219c | 97 | case RXRPC_ACK_IDLE: |
91c2c7b6 | 98 | if (rxrpc_idle_ack_delay < expiry) |
248f219c DH |
99 | expiry = rxrpc_idle_ack_delay; |
100 | break; | |
17926a79 | 101 | |
248f219c DH |
102 | default: |
103 | immediate = true; | |
104 | break; | |
17926a79 DH |
105 | } |
106 | ||
248f219c DH |
107 | now = jiffies; |
108 | if (test_bit(RXRPC_CALL_EV_ACK, &call->events)) { | |
109 | _debug("already scheduled"); | |
110 | } else if (immediate || expiry == 0) { | |
111 | _debug("immediate ACK %lx", call->events); | |
112 | if (!test_and_set_bit(RXRPC_CALL_EV_ACK, &call->events) && | |
113 | background) | |
114 | rxrpc_queue_call(call); | |
115 | } else { | |
116 | ack_at = now + expiry; | |
117 | _debug("deferred ACK %ld < %ld", expiry, call->ack_at - now); | |
118 | if (time_before(ack_at, call->ack_at)) { | |
119 | call->ack_at = ack_at; | |
120 | rxrpc_set_timer(call); | |
17926a79 DH |
121 | } |
122 | } | |
17926a79 DH |
123 | } |
124 | ||
125 | /* | |
248f219c | 126 | * propose an ACK be sent, locking the call structure |
17926a79 | 127 | */ |
248f219c DH |
128 | void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, |
129 | u16 skew, u32 serial, bool immediate, bool background) | |
17926a79 | 130 | { |
248f219c DH |
131 | spin_lock_bh(&call->lock); |
132 | __rxrpc_propose_ACK(call, ack_reason, skew, serial, | |
133 | immediate, background); | |
134 | spin_unlock_bh(&call->lock); | |
17926a79 DH |
135 | } |
136 | ||
137 | /* | |
248f219c | 138 | * Perform retransmission of NAK'd and unack'd packets. |
17926a79 | 139 | */ |
248f219c | 140 | static void rxrpc_resend(struct rxrpc_call *call) |
17926a79 DH |
141 | { |
142 | struct rxrpc_skb_priv *sp; | |
143 | struct sk_buff *skb; | |
248f219c DH |
144 | rxrpc_seq_t cursor, seq, top; |
145 | unsigned long resend_at, now; | |
146 | int ix; | |
f07373ea | 147 | u8 annotation, anno_type; |
17926a79 | 148 | |
248f219c | 149 | _enter("{%d,%d}", call->tx_hard_ack, call->tx_top); |
17926a79 DH |
150 | |
151 | spin_lock_bh(&call->lock); | |
152 | ||
248f219c DH |
153 | cursor = call->tx_hard_ack; |
154 | top = call->tx_top; | |
155 | ASSERT(before_eq(cursor, top)); | |
156 | if (cursor == top) | |
157 | goto out_unlock; | |
158 | ||
159 | /* Scan the packet list without dropping the lock and decide which of | |
160 | * the packets in the Tx buffer we're going to resend and what the new | |
161 | * resend timeout will be. | |
162 | */ | |
163 | now = jiffies; | |
164 | resend_at = now + rxrpc_resend_timeout; | |
dfa7d920 | 165 | for (seq = cursor + 1; before_eq(seq, top); seq++) { |
248f219c DH |
166 | ix = seq & RXRPC_RXTX_BUFF_MASK; |
167 | annotation = call->rxtx_annotations[ix]; | |
f07373ea DH |
168 | anno_type = annotation & RXRPC_TX_ANNO_MASK; |
169 | annotation &= ~RXRPC_TX_ANNO_MASK; | |
170 | if (anno_type == RXRPC_TX_ANNO_ACK) | |
248f219c | 171 | continue; |
17926a79 | 172 | |
248f219c | 173 | skb = call->rxtx_buffer[ix]; |
71f3ca40 | 174 | rxrpc_see_skb(skb, rxrpc_skb_tx_seen); |
17926a79 DH |
175 | sp = rxrpc_skb(skb); |
176 | ||
f07373ea | 177 | if (anno_type == RXRPC_TX_ANNO_UNACK) { |
248f219c DH |
178 | if (time_after(sp->resend_at, now)) { |
179 | if (time_before(sp->resend_at, resend_at)) | |
180 | resend_at = sp->resend_at; | |
181 | continue; | |
33c40e24 | 182 | } |
17926a79 | 183 | } |
17926a79 | 184 | |
248f219c | 185 | /* Okay, we need to retransmit a packet. */ |
f07373ea | 186 | call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation; |
dfa7d920 | 187 | } |
248f219c DH |
188 | |
189 | call->resend_at = resend_at; | |
190 | ||
191 | /* Now go through the Tx window and perform the retransmissions. We | |
192 | * have to drop the lock for each send. If an ACK comes in whilst the | |
193 | * lock is dropped, it may clear some of the retransmission markers for | |
194 | * packets that it soft-ACKs. | |
195 | */ | |
dfa7d920 | 196 | for (seq = cursor + 1; before_eq(seq, top); seq++) { |
248f219c DH |
197 | ix = seq & RXRPC_RXTX_BUFF_MASK; |
198 | annotation = call->rxtx_annotations[ix]; | |
f07373ea DH |
199 | anno_type = annotation & RXRPC_TX_ANNO_MASK; |
200 | if (anno_type != RXRPC_TX_ANNO_RETRANS) | |
248f219c | 201 | continue; |
17926a79 | 202 | |
248f219c | 203 | skb = call->rxtx_buffer[ix]; |
71f3ca40 | 204 | rxrpc_get_skb(skb, rxrpc_skb_tx_got); |
17926a79 | 205 | spin_unlock_bh(&call->lock); |
17926a79 | 206 | |
5a924b89 | 207 | if (rxrpc_send_data_packet(call, skb) < 0) { |
248f219c | 208 | call->resend_at = now + 2; |
71f3ca40 | 209 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
248f219c DH |
210 | return; |
211 | } | |
17926a79 | 212 | |
248f219c DH |
213 | if (rxrpc_is_client_call(call)) |
214 | rxrpc_expose_client_call(call); | |
5a924b89 | 215 | sp = rxrpc_skb(skb); |
248f219c | 216 | sp->resend_at = now + rxrpc_resend_timeout; |
17926a79 | 217 | |
71f3ca40 | 218 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
17926a79 | 219 | spin_lock_bh(&call->lock); |
17926a79 | 220 | |
248f219c DH |
221 | /* We need to clear the retransmit state, but there are two |
222 | * things we need to be aware of: A new ACK/NAK might have been | |
223 | * received and the packet might have been hard-ACK'd (in which | |
224 | * case it will no longer be in the buffer). | |
225 | */ | |
f07373ea DH |
226 | if (after(seq, call->tx_hard_ack)) { |
227 | annotation = call->rxtx_annotations[ix]; | |
228 | anno_type = annotation & RXRPC_TX_ANNO_MASK; | |
229 | if (anno_type == RXRPC_TX_ANNO_RETRANS || | |
230 | anno_type == RXRPC_TX_ANNO_NAK) { | |
231 | annotation &= ~RXRPC_TX_ANNO_MASK; | |
232 | annotation |= RXRPC_TX_ANNO_UNACK; | |
233 | } | |
234 | annotation |= RXRPC_TX_ANNO_RESENT; | |
235 | call->rxtx_annotations[ix] = annotation; | |
236 | } | |
248f219c DH |
237 | |
238 | if (after(call->tx_hard_ack, seq)) | |
239 | seq = call->tx_hard_ack; | |
dfa7d920 | 240 | } |
248f219c DH |
241 | |
242 | out_unlock: | |
243 | spin_unlock_bh(&call->lock); | |
244 | _leave(""); | |
17926a79 DH |
245 | } |
246 | ||
247 | /* | |
248f219c | 248 | * Handle retransmission and deferred ACK/abort generation. |
17926a79 DH |
249 | */ |
250 | void rxrpc_process_call(struct work_struct *work) | |
251 | { | |
252 | struct rxrpc_call *call = | |
253 | container_of(work, struct rxrpc_call, processor); | |
248f219c | 254 | unsigned long now; |
17926a79 | 255 | |
e34d4234 DH |
256 | rxrpc_see_call(call); |
257 | ||
17926a79 | 258 | //printk("\n--------------------\n"); |
248f219c DH |
259 | _enter("{%d,%s,%lx}", |
260 | call->debug_id, rxrpc_call_states[call->state], call->events); | |
17926a79 | 261 | |
248f219c DH |
262 | recheck_state: |
263 | if (test_and_clear_bit(RXRPC_CALL_EV_ABORT, &call->events)) { | |
264 | rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ABORT); | |
265 | goto recheck_state; | |
17926a79 DH |
266 | } |
267 | ||
248f219c DH |
268 | if (call->state == RXRPC_CALL_COMPLETE) { |
269 | del_timer_sync(&call->timer); | |
270 | goto out_put; | |
17926a79 DH |
271 | } |
272 | ||
248f219c DH |
273 | now = jiffies; |
274 | if (time_after_eq(now, call->expire_at)) { | |
5a42976d | 275 | rxrpc_abort_call("EXP", call, 0, RX_CALL_TIMEOUT, ETIME); |
248f219c | 276 | set_bit(RXRPC_CALL_EV_ABORT, &call->events); |
17926a79 DH |
277 | } |
278 | ||
248f219c DH |
279 | if (test_and_clear_bit(RXRPC_CALL_EV_ACK, &call->events) || |
280 | time_after_eq(now, call->ack_at)) { | |
281 | call->ack_at = call->expire_at; | |
282 | if (call->ackr_reason) { | |
283 | rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ACK); | |
284 | goto recheck_state; | |
17926a79 DH |
285 | } |
286 | } | |
287 | ||
248f219c DH |
288 | if (test_and_clear_bit(RXRPC_CALL_EV_RESEND, &call->events) || |
289 | time_after_eq(now, call->resend_at)) { | |
17926a79 | 290 | rxrpc_resend(call); |
248f219c | 291 | goto recheck_state; |
17926a79 DH |
292 | } |
293 | ||
248f219c | 294 | rxrpc_set_timer(call); |
17926a79 DH |
295 | |
296 | /* other events may have been raised since we started checking */ | |
248f219c | 297 | if (call->events && call->state < RXRPC_CALL_COMPLETE) { |
8d94aa38 | 298 | __rxrpc_queue_call(call); |
248f219c | 299 | goto out; |
17926a79 DH |
300 | } |
301 | ||
248f219c DH |
302 | out_put: |
303 | rxrpc_put_call(call, rxrpc_call_put); | |
304 | out: | |
17926a79 | 305 | _leave(""); |
17926a79 | 306 | } |