]>
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 | */ |
fc7ab6d2 | 27 | void rxrpc_set_timer(struct rxrpc_call *call, enum rxrpc_timer_trace why) |
17926a79 | 28 | { |
248f219c | 29 | unsigned long t, now = jiffies; |
17926a79 | 30 | |
248f219c | 31 | read_lock_bh(&call->state_lock); |
17926a79 | 32 | |
248f219c | 33 | if (call->state < RXRPC_CALL_COMPLETE) { |
01a88f7f DH |
34 | t = call->expire_at; |
35 | if (time_before_eq(t, now)) | |
36 | goto out; | |
37 | ||
38 | if (time_after(call->resend_at, now) && | |
39 | time_before(call->resend_at, t)) | |
248f219c | 40 | t = call->resend_at; |
01a88f7f DH |
41 | |
42 | if (time_after(call->ack_at, now) && | |
43 | time_before(call->ack_at, t)) | |
44 | t = call->ack_at; | |
45 | ||
46 | if (call->timer.expires != t || !timer_pending(&call->timer)) { | |
248f219c | 47 | mod_timer(&call->timer, t); |
fc7ab6d2 | 48 | trace_rxrpc_timer(call, why, now); |
17926a79 | 49 | } |
17926a79 | 50 | } |
01a88f7f DH |
51 | |
52 | out: | |
17926a79 DH |
53 | read_unlock_bh(&call->state_lock); |
54 | } | |
55 | ||
56 | /* | |
248f219c | 57 | * propose an ACK be sent |
17926a79 | 58 | */ |
248f219c DH |
59 | static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, |
60 | u16 skew, u32 serial, bool immediate, | |
9c7ad434 DH |
61 | bool background, |
62 | enum rxrpc_propose_ack_trace why) | |
17926a79 | 63 | { |
9c7ad434 | 64 | enum rxrpc_propose_ack_outcome outcome = rxrpc_propose_ack_use; |
248f219c | 65 | unsigned long now, ack_at, expiry = rxrpc_soft_ack_delay; |
17926a79 DH |
66 | s8 prior = rxrpc_ack_priority[ack_reason]; |
67 | ||
248f219c DH |
68 | /* Update DELAY, IDLE, REQUESTED and PING_RESPONSE ACK serial |
69 | * numbers, but we don't alter the timeout. | |
70 | */ | |
71 | _debug("prior %u %u vs %u %u", | |
72 | ack_reason, prior, | |
73 | call->ackr_reason, rxrpc_ack_priority[call->ackr_reason]); | |
74 | if (ack_reason == call->ackr_reason) { | |
75 | if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) { | |
9c7ad434 | 76 | outcome = rxrpc_propose_ack_update; |
248f219c DH |
77 | call->ackr_serial = serial; |
78 | call->ackr_skew = skew; | |
17926a79 | 79 | } |
248f219c | 80 | if (!immediate) |
9c7ad434 | 81 | goto trace; |
248f219c DH |
82 | } else if (prior > rxrpc_ack_priority[call->ackr_reason]) { |
83 | call->ackr_reason = ack_reason; | |
84 | call->ackr_serial = serial; | |
85 | call->ackr_skew = skew; | |
9c7ad434 DH |
86 | } else { |
87 | outcome = rxrpc_propose_ack_subsume; | |
17926a79 DH |
88 | } |
89 | ||
248f219c DH |
90 | switch (ack_reason) { |
91 | case RXRPC_ACK_REQUESTED: | |
92 | if (rxrpc_requested_ack_delay < expiry) | |
93 | expiry = rxrpc_requested_ack_delay; | |
94 | if (serial == 1) | |
95 | immediate = false; | |
96 | break; | |
17926a79 | 97 | |
248f219c DH |
98 | case RXRPC_ACK_DELAY: |
99 | if (rxrpc_soft_ack_delay < expiry) | |
100 | expiry = rxrpc_soft_ack_delay; | |
101 | break; | |
17926a79 | 102 | |
248f219c | 103 | case RXRPC_ACK_IDLE: |
91c2c7b6 | 104 | if (rxrpc_idle_ack_delay < expiry) |
248f219c DH |
105 | expiry = rxrpc_idle_ack_delay; |
106 | break; | |
17926a79 | 107 | |
248f219c DH |
108 | default: |
109 | immediate = true; | |
110 | break; | |
17926a79 DH |
111 | } |
112 | ||
248f219c DH |
113 | now = jiffies; |
114 | if (test_bit(RXRPC_CALL_EV_ACK, &call->events)) { | |
115 | _debug("already scheduled"); | |
116 | } else if (immediate || expiry == 0) { | |
117 | _debug("immediate ACK %lx", call->events); | |
118 | if (!test_and_set_bit(RXRPC_CALL_EV_ACK, &call->events) && | |
119 | background) | |
120 | rxrpc_queue_call(call); | |
121 | } else { | |
122 | ack_at = now + expiry; | |
123 | _debug("deferred ACK %ld < %ld", expiry, call->ack_at - now); | |
124 | if (time_before(ack_at, call->ack_at)) { | |
125 | call->ack_at = ack_at; | |
fc7ab6d2 | 126 | rxrpc_set_timer(call, rxrpc_timer_set_for_ack); |
17926a79 DH |
127 | } |
128 | } | |
9c7ad434 DH |
129 | |
130 | trace: | |
131 | trace_rxrpc_propose_ack(call, why, ack_reason, serial, immediate, | |
132 | background, outcome); | |
17926a79 DH |
133 | } |
134 | ||
135 | /* | |
248f219c | 136 | * propose an ACK be sent, locking the call structure |
17926a79 | 137 | */ |
248f219c | 138 | void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, |
9c7ad434 DH |
139 | u16 skew, u32 serial, bool immediate, bool background, |
140 | enum rxrpc_propose_ack_trace why) | |
17926a79 | 141 | { |
248f219c DH |
142 | spin_lock_bh(&call->lock); |
143 | __rxrpc_propose_ACK(call, ack_reason, skew, serial, | |
9c7ad434 | 144 | immediate, background, why); |
248f219c | 145 | spin_unlock_bh(&call->lock); |
17926a79 DH |
146 | } |
147 | ||
148 | /* | |
248f219c | 149 | * Perform retransmission of NAK'd and unack'd packets. |
17926a79 | 150 | */ |
248f219c | 151 | static void rxrpc_resend(struct rxrpc_call *call) |
17926a79 DH |
152 | { |
153 | struct rxrpc_skb_priv *sp; | |
154 | struct sk_buff *skb; | |
248f219c | 155 | rxrpc_seq_t cursor, seq, top; |
fc943f67 | 156 | ktime_t now = ktime_get_real(), max_age, oldest, resend_at; |
248f219c | 157 | int ix; |
f07373ea | 158 | u8 annotation, anno_type; |
17926a79 | 159 | |
248f219c | 160 | _enter("{%d,%d}", call->tx_hard_ack, call->tx_top); |
17926a79 | 161 | |
50235c4b DH |
162 | max_age = ktime_sub_ms(now, rxrpc_resend_timeout); |
163 | ||
17926a79 DH |
164 | spin_lock_bh(&call->lock); |
165 | ||
248f219c DH |
166 | cursor = call->tx_hard_ack; |
167 | top = call->tx_top; | |
168 | ASSERT(before_eq(cursor, top)); | |
169 | if (cursor == top) | |
170 | goto out_unlock; | |
171 | ||
172 | /* Scan the packet list without dropping the lock and decide which of | |
173 | * the packets in the Tx buffer we're going to resend and what the new | |
174 | * resend timeout will be. | |
175 | */ | |
50235c4b | 176 | oldest = now; |
dfa7d920 | 177 | for (seq = cursor + 1; before_eq(seq, top); seq++) { |
248f219c DH |
178 | ix = seq & RXRPC_RXTX_BUFF_MASK; |
179 | annotation = call->rxtx_annotations[ix]; | |
f07373ea DH |
180 | anno_type = annotation & RXRPC_TX_ANNO_MASK; |
181 | annotation &= ~RXRPC_TX_ANNO_MASK; | |
182 | if (anno_type == RXRPC_TX_ANNO_ACK) | |
248f219c | 183 | continue; |
17926a79 | 184 | |
248f219c | 185 | skb = call->rxtx_buffer[ix]; |
71f3ca40 | 186 | rxrpc_see_skb(skb, rxrpc_skb_tx_seen); |
17926a79 DH |
187 | sp = rxrpc_skb(skb); |
188 | ||
f07373ea | 189 | if (anno_type == RXRPC_TX_ANNO_UNACK) { |
50235c4b DH |
190 | if (ktime_after(skb->tstamp, max_age)) { |
191 | if (ktime_before(skb->tstamp, oldest)) | |
192 | oldest = skb->tstamp; | |
248f219c | 193 | continue; |
33c40e24 | 194 | } |
17926a79 | 195 | } |
17926a79 | 196 | |
248f219c | 197 | /* Okay, we need to retransmit a packet. */ |
f07373ea | 198 | call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation; |
dfa7d920 | 199 | } |
248f219c | 200 | |
90bd684d | 201 | resend_at = ktime_sub(ktime_add_ms(oldest, rxrpc_resend_timeout), now); |
50235c4b | 202 | call->resend_at = jiffies + nsecs_to_jiffies(ktime_to_ns(resend_at)); |
248f219c DH |
203 | |
204 | /* Now go through the Tx window and perform the retransmissions. We | |
205 | * have to drop the lock for each send. If an ACK comes in whilst the | |
206 | * lock is dropped, it may clear some of the retransmission markers for | |
207 | * packets that it soft-ACKs. | |
208 | */ | |
dfa7d920 | 209 | for (seq = cursor + 1; before_eq(seq, top); seq++) { |
248f219c DH |
210 | ix = seq & RXRPC_RXTX_BUFF_MASK; |
211 | annotation = call->rxtx_annotations[ix]; | |
f07373ea DH |
212 | anno_type = annotation & RXRPC_TX_ANNO_MASK; |
213 | if (anno_type != RXRPC_TX_ANNO_RETRANS) | |
248f219c | 214 | continue; |
17926a79 | 215 | |
248f219c | 216 | skb = call->rxtx_buffer[ix]; |
71f3ca40 | 217 | rxrpc_get_skb(skb, rxrpc_skb_tx_got); |
17926a79 | 218 | spin_unlock_bh(&call->lock); |
17926a79 | 219 | |
5a924b89 | 220 | if (rxrpc_send_data_packet(call, skb) < 0) { |
71f3ca40 | 221 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
248f219c DH |
222 | return; |
223 | } | |
17926a79 | 224 | |
248f219c DH |
225 | if (rxrpc_is_client_call(call)) |
226 | rxrpc_expose_client_call(call); | |
17926a79 | 227 | |
71f3ca40 | 228 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
17926a79 | 229 | spin_lock_bh(&call->lock); |
17926a79 | 230 | |
248f219c DH |
231 | /* We need to clear the retransmit state, but there are two |
232 | * things we need to be aware of: A new ACK/NAK might have been | |
233 | * received and the packet might have been hard-ACK'd (in which | |
234 | * case it will no longer be in the buffer). | |
235 | */ | |
f07373ea DH |
236 | if (after(seq, call->tx_hard_ack)) { |
237 | annotation = call->rxtx_annotations[ix]; | |
238 | anno_type = annotation & RXRPC_TX_ANNO_MASK; | |
239 | if (anno_type == RXRPC_TX_ANNO_RETRANS || | |
240 | anno_type == RXRPC_TX_ANNO_NAK) { | |
241 | annotation &= ~RXRPC_TX_ANNO_MASK; | |
242 | annotation |= RXRPC_TX_ANNO_UNACK; | |
243 | } | |
244 | annotation |= RXRPC_TX_ANNO_RESENT; | |
245 | call->rxtx_annotations[ix] = annotation; | |
246 | } | |
248f219c DH |
247 | |
248 | if (after(call->tx_hard_ack, seq)) | |
249 | seq = call->tx_hard_ack; | |
dfa7d920 | 250 | } |
248f219c DH |
251 | |
252 | out_unlock: | |
253 | spin_unlock_bh(&call->lock); | |
254 | _leave(""); | |
17926a79 DH |
255 | } |
256 | ||
257 | /* | |
248f219c | 258 | * Handle retransmission and deferred ACK/abort generation. |
17926a79 DH |
259 | */ |
260 | void rxrpc_process_call(struct work_struct *work) | |
261 | { | |
262 | struct rxrpc_call *call = | |
263 | container_of(work, struct rxrpc_call, processor); | |
248f219c | 264 | unsigned long now; |
17926a79 | 265 | |
e34d4234 DH |
266 | rxrpc_see_call(call); |
267 | ||
17926a79 | 268 | //printk("\n--------------------\n"); |
248f219c DH |
269 | _enter("{%d,%s,%lx}", |
270 | call->debug_id, rxrpc_call_states[call->state], call->events); | |
17926a79 | 271 | |
248f219c DH |
272 | recheck_state: |
273 | if (test_and_clear_bit(RXRPC_CALL_EV_ABORT, &call->events)) { | |
274 | rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ABORT); | |
275 | goto recheck_state; | |
17926a79 DH |
276 | } |
277 | ||
248f219c DH |
278 | if (call->state == RXRPC_CALL_COMPLETE) { |
279 | del_timer_sync(&call->timer); | |
280 | goto out_put; | |
17926a79 DH |
281 | } |
282 | ||
248f219c DH |
283 | now = jiffies; |
284 | if (time_after_eq(now, call->expire_at)) { | |
5a42976d | 285 | rxrpc_abort_call("EXP", call, 0, RX_CALL_TIMEOUT, ETIME); |
248f219c | 286 | set_bit(RXRPC_CALL_EV_ABORT, &call->events); |
17926a79 DH |
287 | } |
288 | ||
248f219c DH |
289 | if (test_and_clear_bit(RXRPC_CALL_EV_ACK, &call->events) || |
290 | time_after_eq(now, call->ack_at)) { | |
291 | call->ack_at = call->expire_at; | |
292 | if (call->ackr_reason) { | |
293 | rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ACK); | |
294 | goto recheck_state; | |
17926a79 DH |
295 | } |
296 | } | |
297 | ||
248f219c DH |
298 | if (test_and_clear_bit(RXRPC_CALL_EV_RESEND, &call->events) || |
299 | time_after_eq(now, call->resend_at)) { | |
17926a79 | 300 | rxrpc_resend(call); |
248f219c | 301 | goto recheck_state; |
17926a79 DH |
302 | } |
303 | ||
fc7ab6d2 | 304 | rxrpc_set_timer(call, rxrpc_timer_set_for_resend); |
17926a79 DH |
305 | |
306 | /* other events may have been raised since we started checking */ | |
248f219c | 307 | if (call->events && call->state < RXRPC_CALL_COMPLETE) { |
8d94aa38 | 308 | __rxrpc_queue_call(call); |
248f219c | 309 | goto out; |
17926a79 DH |
310 | } |
311 | ||
248f219c DH |
312 | out_put: |
313 | rxrpc_put_call(call, rxrpc_call_put); | |
314 | out: | |
17926a79 | 315 | _leave(""); |
17926a79 | 316 | } |