sctp_timer.c revision 1.1.2.4 1 1.1.2.2 skrll /* $KAME: sctp_timer.c,v 1.30 2005/06/16 18:29:25 jinmei Exp $ */
2 1.1.2.4 skrll /* $NetBSD: sctp_timer.c,v 1.1.2.4 2017/02/05 13:40:59 skrll Exp $ */
3 1.1.2.2 skrll
4 1.1.2.2 skrll /*
5 1.1.2.2 skrll * Copyright (C) 2002, 2003, 2004 Cisco Systems Inc,
6 1.1.2.2 skrll * All rights reserved.
7 1.1.2.2 skrll *
8 1.1.2.2 skrll * Redistribution and use in source and binary forms, with or without
9 1.1.2.2 skrll * modification, are permitted provided that the following conditions
10 1.1.2.2 skrll * are met:
11 1.1.2.2 skrll * 1. Redistributions of source code must retain the above copyright
12 1.1.2.2 skrll * notice, this list of conditions and the following disclaimer.
13 1.1.2.2 skrll * 2. Redistributions in binary form must reproduce the above copyright
14 1.1.2.2 skrll * notice, this list of conditions and the following disclaimer in the
15 1.1.2.2 skrll * documentation and/or other materials provided with the distribution.
16 1.1.2.2 skrll * 3. Neither the name of the project nor the names of its contributors
17 1.1.2.2 skrll * may be used to endorse or promote products derived from this software
18 1.1.2.2 skrll * without specific prior written permission.
19 1.1.2.2 skrll *
20 1.1.2.2 skrll * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 1.1.2.2 skrll * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 1.1.2.2 skrll * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 1.1.2.2 skrll * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 1.1.2.2 skrll * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 1.1.2.2 skrll * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 1.1.2.2 skrll * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 1.1.2.2 skrll * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 1.1.2.2 skrll * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 1.1.2.2 skrll * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 1.1.2.2 skrll * SUCH DAMAGE.
31 1.1.2.2 skrll */
32 1.1.2.2 skrll #include <sys/cdefs.h>
33 1.1.2.4 skrll __KERNEL_RCSID(0, "$NetBSD: sctp_timer.c,v 1.1.2.4 2017/02/05 13:40:59 skrll Exp $");
34 1.1.2.2 skrll
35 1.1.2.2 skrll #ifdef _KERNEL_OPT
36 1.1.2.2 skrll #include "opt_inet.h"
37 1.1.2.2 skrll #include "opt_sctp.h"
38 1.1.2.2 skrll #endif /* _KERNEL_OPT */
39 1.1.2.2 skrll
40 1.1.2.2 skrll #include <sys/param.h>
41 1.1.2.2 skrll #include <sys/systm.h>
42 1.1.2.2 skrll #include <sys/malloc.h>
43 1.1.2.2 skrll #include <sys/mbuf.h>
44 1.1.2.2 skrll #include <sys/domain.h>
45 1.1.2.2 skrll #include <sys/protosw.h>
46 1.1.2.2 skrll #include <sys/socket.h>
47 1.1.2.2 skrll #include <sys/socketvar.h>
48 1.1.2.2 skrll #include <sys/proc.h>
49 1.1.2.2 skrll #include <sys/kernel.h>
50 1.1.2.2 skrll #include <sys/sysctl.h>
51 1.1.2.2 skrll #ifdef INET6
52 1.1.2.2 skrll #include <sys/domain.h>
53 1.1.2.2 skrll #endif
54 1.1.2.2 skrll
55 1.1.2.2 skrll #include <machine/limits.h>
56 1.1.2.2 skrll
57 1.1.2.2 skrll #include <net/if.h>
58 1.1.2.2 skrll #include <net/if_types.h>
59 1.1.2.2 skrll #include <net/route.h>
60 1.1.2.2 skrll #include <netinet/in.h>
61 1.1.2.2 skrll #include <netinet/in_systm.h>
62 1.1.2.2 skrll #define _IP_VHL
63 1.1.2.2 skrll #include <netinet/ip.h>
64 1.1.2.2 skrll #include <netinet/in_pcb.h>
65 1.1.2.2 skrll #include <netinet/in_var.h>
66 1.1.2.2 skrll #include <netinet/ip_var.h>
67 1.1.2.2 skrll
68 1.1.2.2 skrll #ifdef INET6
69 1.1.2.2 skrll #include <netinet/ip6.h>
70 1.1.2.2 skrll #include <netinet6/ip6_var.h>
71 1.1.2.2 skrll #endif /* INET6 */
72 1.1.2.2 skrll
73 1.1.2.2 skrll #include <netinet/sctp_pcb.h>
74 1.1.2.2 skrll
75 1.1.2.2 skrll #ifdef IPSEC
76 1.1.2.3 skrll #include <netipsec/ipsec.h>
77 1.1.2.3 skrll #include <netipsec/key.h>
78 1.1.2.2 skrll #endif /* IPSEC */
79 1.1.2.2 skrll #ifdef INET6
80 1.1.2.2 skrll #include <netinet6/sctp6_var.h>
81 1.1.2.2 skrll #endif
82 1.1.2.2 skrll #include <netinet/sctp_var.h>
83 1.1.2.2 skrll #include <netinet/sctp_timer.h>
84 1.1.2.2 skrll #include <netinet/sctputil.h>
85 1.1.2.2 skrll #include <netinet/sctp_output.h>
86 1.1.2.2 skrll #include <netinet/sctp_hashdriver.h>
87 1.1.2.2 skrll #include <netinet/sctp_header.h>
88 1.1.2.2 skrll #include <netinet/sctp_indata.h>
89 1.1.2.2 skrll #include <netinet/sctp_asconf.h>
90 1.1.2.2 skrll
91 1.1.2.2 skrll #include <netinet/sctp.h>
92 1.1.2.2 skrll #include <netinet/sctp_uio.h>
93 1.1.2.2 skrll
94 1.1.2.2 skrll #include <net/net_osdep.h>
95 1.1.2.2 skrll
96 1.1.2.2 skrll #ifdef SCTP_DEBUG
97 1.1.2.2 skrll extern u_int32_t sctp_debug_on;
98 1.1.2.2 skrll #endif /* SCTP_DEBUG */
99 1.1.2.2 skrll
100 1.1.2.2 skrll void
101 1.1.2.2 skrll sctp_audit_retranmission_queue(struct sctp_association *asoc)
102 1.1.2.2 skrll {
103 1.1.2.2 skrll struct sctp_tmit_chunk *chk;
104 1.1.2.2 skrll
105 1.1.2.2 skrll #ifdef SCTP_DEBUG
106 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
107 1.1.2.2 skrll printf("Audit invoked on send queue cnt:%d onqueue:%d\n",
108 1.1.2.2 skrll asoc->sent_queue_retran_cnt,
109 1.1.2.2 skrll asoc->sent_queue_cnt);
110 1.1.2.2 skrll }
111 1.1.2.2 skrll #endif /* SCTP_DEBUG */
112 1.1.2.2 skrll asoc->sent_queue_retran_cnt = 0;
113 1.1.2.2 skrll asoc->sent_queue_cnt = 0;
114 1.1.2.2 skrll TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
115 1.1.2.2 skrll if (chk->sent == SCTP_DATAGRAM_RESEND) {
116 1.1.2.2 skrll asoc->sent_queue_retran_cnt++;
117 1.1.2.2 skrll }
118 1.1.2.2 skrll asoc->sent_queue_cnt++;
119 1.1.2.2 skrll }
120 1.1.2.2 skrll TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
121 1.1.2.2 skrll if (chk->sent == SCTP_DATAGRAM_RESEND) {
122 1.1.2.2 skrll asoc->sent_queue_retran_cnt++;
123 1.1.2.2 skrll }
124 1.1.2.2 skrll }
125 1.1.2.2 skrll #ifdef SCTP_DEBUG
126 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
127 1.1.2.2 skrll printf("Audit completes retran:%d onqueue:%d\n",
128 1.1.2.2 skrll asoc->sent_queue_retran_cnt,
129 1.1.2.2 skrll asoc->sent_queue_cnt);
130 1.1.2.2 skrll }
131 1.1.2.2 skrll #endif /* SCTP_DEBUG */
132 1.1.2.2 skrll }
133 1.1.2.2 skrll
134 1.1.2.2 skrll int
135 1.1.2.2 skrll sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
136 1.1.2.2 skrll struct sctp_nets *net, uint16_t threshold)
137 1.1.2.2 skrll {
138 1.1.2.2 skrll if (net) {
139 1.1.2.2 skrll net->error_count++;
140 1.1.2.2 skrll #ifdef SCTP_DEBUG
141 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
142 1.1.2.2 skrll printf("Error count for %p now %d thresh:%d\n",
143 1.1.2.2 skrll net, net->error_count,
144 1.1.2.2 skrll net->failure_threshold);
145 1.1.2.2 skrll }
146 1.1.2.2 skrll #endif /* SCTP_DEBUG */
147 1.1.2.2 skrll if (net->error_count >= net->failure_threshold) {
148 1.1.2.2 skrll /* We had a threshold failure */
149 1.1.2.2 skrll if (net->dest_state & SCTP_ADDR_REACHABLE) {
150 1.1.2.2 skrll net->dest_state &= ~SCTP_ADDR_REACHABLE;
151 1.1.2.2 skrll net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
152 1.1.2.2 skrll if (net == stcb->asoc.primary_destination) {
153 1.1.2.2 skrll net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
154 1.1.2.2 skrll }
155 1.1.2.2 skrll sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
156 1.1.2.2 skrll stcb,
157 1.1.2.2 skrll SCTP_FAILED_THRESHOLD,
158 1.1.2.2 skrll (void *)net);
159 1.1.2.2 skrll }
160 1.1.2.2 skrll }
161 1.1.2.2 skrll /*********HOLD THIS COMMENT FOR PATCH OF ALTERNATE
162 1.1.2.2 skrll *********ROUTING CODE
163 1.1.2.2 skrll */
164 1.1.2.2 skrll /*********HOLD THIS COMMENT FOR END OF PATCH OF ALTERNATE
165 1.1.2.2 skrll *********ROUTING CODE
166 1.1.2.2 skrll */
167 1.1.2.2 skrll }
168 1.1.2.2 skrll if (stcb == NULL)
169 1.1.2.2 skrll return (0);
170 1.1.2.2 skrll
171 1.1.2.2 skrll if (net) {
172 1.1.2.2 skrll if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
173 1.1.2.2 skrll stcb->asoc.overall_error_count++;
174 1.1.2.2 skrll }
175 1.1.2.2 skrll } else {
176 1.1.2.2 skrll stcb->asoc.overall_error_count++;
177 1.1.2.2 skrll }
178 1.1.2.2 skrll #ifdef SCTP_DEBUG
179 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
180 1.1.2.2 skrll printf("Overall error count for %p now %d thresh:%u state:%x\n",
181 1.1.2.2 skrll &stcb->asoc,
182 1.1.2.2 skrll stcb->asoc.overall_error_count,
183 1.1.2.2 skrll (u_int)threshold,
184 1.1.2.2 skrll ((net == NULL) ? (u_int)0 : (u_int)net->dest_state));
185 1.1.2.2 skrll }
186 1.1.2.2 skrll #endif /* SCTP_DEBUG */
187 1.1.2.2 skrll /* We specifically do not do >= to give the assoc one more
188 1.1.2.2 skrll * change before we fail it.
189 1.1.2.2 skrll */
190 1.1.2.2 skrll if (stcb->asoc.overall_error_count > threshold) {
191 1.1.2.2 skrll /* Abort notification sends a ULP notify */
192 1.1.2.2 skrll struct mbuf *oper;
193 1.1.2.2 skrll MGET(oper, M_DONTWAIT, MT_DATA);
194 1.1.2.2 skrll if (oper) {
195 1.1.2.2 skrll struct sctp_paramhdr *ph;
196 1.1.2.2 skrll u_int32_t *ippp;
197 1.1.2.2 skrll
198 1.1.2.2 skrll oper->m_len = sizeof(struct sctp_paramhdr) +
199 1.1.2.2 skrll sizeof(*ippp);
200 1.1.2.2 skrll ph = mtod(oper, struct sctp_paramhdr *);
201 1.1.2.2 skrll ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
202 1.1.2.2 skrll ph->param_length = htons(oper->m_len);
203 1.1.2.2 skrll ippp = (u_int32_t *)(ph + 1);
204 1.1.2.2 skrll *ippp = htonl(0x40000001);
205 1.1.2.2 skrll }
206 1.1.2.2 skrll sctp_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, oper);
207 1.1.2.2 skrll return (1);
208 1.1.2.2 skrll }
209 1.1.2.2 skrll return (0);
210 1.1.2.2 skrll }
211 1.1.2.2 skrll
212 1.1.2.2 skrll struct sctp_nets *
213 1.1.2.2 skrll sctp_find_alternate_net(struct sctp_tcb *stcb,
214 1.1.2.2 skrll struct sctp_nets *net)
215 1.1.2.2 skrll {
216 1.1.2.2 skrll /* Find and return an alternate network if possible */
217 1.1.2.2 skrll struct sctp_nets *alt, *mnet;
218 1.1.2.2 skrll struct rtentry *rt;
219 1.1.2.2 skrll int once;
220 1.1.2.2 skrll
221 1.1.2.2 skrll if (stcb->asoc.numnets == 1) {
222 1.1.2.2 skrll /* No others but net */
223 1.1.2.2 skrll return (TAILQ_FIRST(&stcb->asoc.nets));
224 1.1.2.2 skrll }
225 1.1.2.2 skrll mnet = net;
226 1.1.2.2 skrll once = 0;
227 1.1.2.2 skrll
228 1.1.2.2 skrll if (mnet == NULL) {
229 1.1.2.2 skrll mnet = TAILQ_FIRST(&stcb->asoc.nets);
230 1.1.2.2 skrll }
231 1.1.2.2 skrll do {
232 1.1.2.2 skrll alt = TAILQ_NEXT(mnet, sctp_next);
233 1.1.2.2 skrll if (alt == NULL) {
234 1.1.2.2 skrll once++;
235 1.1.2.2 skrll if (once > 1) {
236 1.1.2.2 skrll break;
237 1.1.2.2 skrll }
238 1.1.2.2 skrll alt = TAILQ_FIRST(&stcb->asoc.nets);
239 1.1.2.2 skrll }
240 1.1.2.2 skrll rt = rtcache_validate(&alt->ro);
241 1.1.2.2 skrll if (rt == NULL) {
242 1.1.2.2 skrll alt->src_addr_selected = 0;
243 1.1.2.2 skrll }
244 1.1.2.2 skrll if (
245 1.1.2.2 skrll ((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) &&
246 1.1.2.2 skrll (rt != NULL) &&
247 1.1.2.2 skrll (!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))
248 1.1.2.2 skrll ) {
249 1.1.2.2 skrll /* Found a reachable address */
250 1.1.2.4 skrll rtcache_unref(rt, &alt->ro);
251 1.1.2.2 skrll break;
252 1.1.2.2 skrll }
253 1.1.2.4 skrll rtcache_unref(rt, &alt->ro);
254 1.1.2.2 skrll mnet = alt;
255 1.1.2.2 skrll } while (alt != NULL);
256 1.1.2.2 skrll
257 1.1.2.2 skrll if (alt == NULL) {
258 1.1.2.2 skrll /* Case where NO insv network exists (dormant state) */
259 1.1.2.2 skrll /* we rotate destinations */
260 1.1.2.2 skrll once = 0;
261 1.1.2.2 skrll mnet = net;
262 1.1.2.2 skrll do {
263 1.1.2.2 skrll alt = TAILQ_NEXT(mnet, sctp_next);
264 1.1.2.2 skrll if (alt == NULL) {
265 1.1.2.2 skrll once++;
266 1.1.2.2 skrll if (once > 1) {
267 1.1.2.2 skrll break;
268 1.1.2.2 skrll }
269 1.1.2.2 skrll alt = TAILQ_FIRST(&stcb->asoc.nets);
270 1.1.2.2 skrll }
271 1.1.2.2 skrll if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
272 1.1.2.2 skrll (alt != net)) {
273 1.1.2.2 skrll /* Found an alternate address */
274 1.1.2.2 skrll break;
275 1.1.2.2 skrll }
276 1.1.2.2 skrll mnet = alt;
277 1.1.2.2 skrll } while (alt != NULL);
278 1.1.2.2 skrll }
279 1.1.2.2 skrll if (alt == NULL) {
280 1.1.2.2 skrll return (net);
281 1.1.2.2 skrll }
282 1.1.2.2 skrll return (alt);
283 1.1.2.2 skrll }
284 1.1.2.2 skrll
285 1.1.2.2 skrll static void
286 1.1.2.2 skrll sctp_backoff_on_timeout(struct sctp_tcb *stcb,
287 1.1.2.2 skrll struct sctp_nets *net,
288 1.1.2.2 skrll int win_probe,
289 1.1.2.2 skrll int num_marked)
290 1.1.2.2 skrll {
291 1.1.2.2 skrll #ifdef SCTP_DEBUG
292 1.1.2.2 skrll int oldRTO;
293 1.1.2.2 skrll
294 1.1.2.2 skrll oldRTO = net->RTO;
295 1.1.2.2 skrll #endif /* SCTP_DEBUG */
296 1.1.2.2 skrll net->RTO <<= 1;
297 1.1.2.2 skrll #ifdef SCTP_DEBUG
298 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER2) {
299 1.1.2.2 skrll printf("Timer doubles from %d ms -to-> %d ms\n",
300 1.1.2.2 skrll oldRTO, net->RTO);
301 1.1.2.2 skrll }
302 1.1.2.2 skrll #endif /* SCTP_DEBUG */
303 1.1.2.2 skrll
304 1.1.2.2 skrll if (net->RTO > stcb->asoc.maxrto) {
305 1.1.2.2 skrll net->RTO = stcb->asoc.maxrto;
306 1.1.2.2 skrll #ifdef SCTP_DEBUG
307 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER2) {
308 1.1.2.2 skrll printf("Growth capped by maxrto %d\n",
309 1.1.2.2 skrll net->RTO);
310 1.1.2.2 skrll }
311 1.1.2.2 skrll #endif /* SCTP_DEBUG */
312 1.1.2.2 skrll }
313 1.1.2.2 skrll
314 1.1.2.2 skrll
315 1.1.2.2 skrll if ((win_probe == 0) && num_marked) {
316 1.1.2.2 skrll /* We don't apply penalty to window probe scenarios */
317 1.1.2.2 skrll #ifdef SCTP_CWND_LOGGING
318 1.1.2.2 skrll int old_cwnd=net->cwnd;
319 1.1.2.2 skrll #endif
320 1.1.2.2 skrll net->ssthresh = net->cwnd >> 1;
321 1.1.2.2 skrll if (net->ssthresh < (net->mtu << 1)) {
322 1.1.2.2 skrll net->ssthresh = (net->mtu << 1);
323 1.1.2.2 skrll }
324 1.1.2.2 skrll net->cwnd = net->mtu;
325 1.1.2.2 skrll /* floor of 1 mtu */
326 1.1.2.2 skrll if (net->cwnd < net->mtu)
327 1.1.2.2 skrll net->cwnd = net->mtu;
328 1.1.2.2 skrll #ifdef SCTP_CWND_LOGGING
329 1.1.2.2 skrll sctp_log_cwnd(net, net->cwnd-old_cwnd, SCTP_CWND_LOG_FROM_RTX);
330 1.1.2.2 skrll #endif
331 1.1.2.2 skrll
332 1.1.2.2 skrll net->partial_bytes_acked = 0;
333 1.1.2.2 skrll #ifdef SCTP_DEBUG
334 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
335 1.1.2.2 skrll printf("collapse cwnd to 1MTU ssthresh to %d\n",
336 1.1.2.2 skrll net->ssthresh);
337 1.1.2.2 skrll }
338 1.1.2.2 skrll #endif
339 1.1.2.2 skrll
340 1.1.2.2 skrll }
341 1.1.2.2 skrll }
342 1.1.2.2 skrll
343 1.1.2.2 skrll
344 1.1.2.2 skrll static int
345 1.1.2.2 skrll sctp_mark_all_for_resend(struct sctp_tcb *stcb,
346 1.1.2.2 skrll struct sctp_nets *net,
347 1.1.2.2 skrll struct sctp_nets *alt,
348 1.1.2.2 skrll int *num_marked)
349 1.1.2.2 skrll {
350 1.1.2.2 skrll
351 1.1.2.2 skrll /*
352 1.1.2.2 skrll * Mark all chunks (well not all) that were sent to *net for retransmission.
353 1.1.2.2 skrll * Move them to alt for there destination as well... We only
354 1.1.2.2 skrll * mark chunks that have been outstanding long enough to have
355 1.1.2.2 skrll * received feed-back.
356 1.1.2.2 skrll */
357 1.1.2.2 skrll struct sctp_tmit_chunk *chk, *tp2;
358 1.1.2.2 skrll struct sctp_nets *lnets;
359 1.1.2.2 skrll struct timeval now, min_wait, tv;
360 1.1.2.2 skrll int cur_rto;
361 1.1.2.2 skrll int win_probes, non_win_probes, orig_rwnd, audit_tf, num_mk, fir;
362 1.1.2.2 skrll unsigned int cnt_mk;
363 1.1.2.2 skrll u_int32_t orig_flight;
364 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
365 1.1.2.2 skrll u_int32_t tsnfirst, tsnlast;
366 1.1.2.2 skrll #endif
367 1.1.2.2 skrll
368 1.1.2.2 skrll /* none in flight now */
369 1.1.2.2 skrll audit_tf = 0;
370 1.1.2.2 skrll fir=0;
371 1.1.2.2 skrll /* figure out how long a data chunk must be pending
372 1.1.2.2 skrll * before we can mark it ..
373 1.1.2.2 skrll */
374 1.1.2.2 skrll SCTP_GETTIME_TIMEVAL(&now);
375 1.1.2.2 skrll /* get cur rto in micro-seconds */
376 1.1.2.2 skrll cur_rto = (((net->lastsa >> 2) + net->lastsv) >> 1);
377 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
378 1.1.2.2 skrll sctp_log_fr(cur_rto, 0, 0, SCTP_FR_T3_MARK_TIME);
379 1.1.2.2 skrll #endif
380 1.1.2.2 skrll cur_rto *= 1000;
381 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
382 1.1.2.2 skrll sctp_log_fr(cur_rto, 0, 0, SCTP_FR_T3_MARK_TIME);
383 1.1.2.2 skrll #endif
384 1.1.2.2 skrll tv.tv_sec = cur_rto / 1000000;
385 1.1.2.2 skrll tv.tv_usec = cur_rto % 1000000;
386 1.1.2.2 skrll #ifndef __FreeBSD__
387 1.1.2.2 skrll timersub(&now, &tv, &min_wait);
388 1.1.2.2 skrll #else
389 1.1.2.2 skrll min_wait = now;
390 1.1.2.2 skrll timevalsub(&min_wait, &tv);
391 1.1.2.2 skrll #endif
392 1.1.2.2 skrll if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) {
393 1.1.2.2 skrll /*
394 1.1.2.2 skrll * if we hit here, we don't
395 1.1.2.2 skrll * have enough seconds on the clock to account
396 1.1.2.2 skrll * for the RTO. We just let the lower seconds
397 1.1.2.2 skrll * be the bounds and don't worry about it. This
398 1.1.2.2 skrll * may mean we will mark a lot more than we should.
399 1.1.2.2 skrll */
400 1.1.2.2 skrll min_wait.tv_sec = min_wait.tv_usec = 0;
401 1.1.2.2 skrll }
402 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
403 1.1.2.2 skrll sctp_log_fr(cur_rto, now.tv_sec, now.tv_usec, SCTP_FR_T3_MARK_TIME);
404 1.1.2.2 skrll sctp_log_fr(0, min_wait.tv_sec, min_wait.tv_usec, SCTP_FR_T3_MARK_TIME);
405 1.1.2.2 skrll #endif
406 1.1.2.2 skrll if (stcb->asoc.total_flight >= net->flight_size) {
407 1.1.2.2 skrll stcb->asoc.total_flight -= net->flight_size;
408 1.1.2.2 skrll } else {
409 1.1.2.2 skrll audit_tf = 1;
410 1.1.2.2 skrll stcb->asoc.total_flight = 0;
411 1.1.2.2 skrll }
412 1.1.2.2 skrll /* Our rwnd will be incorrect here since we are not adding
413 1.1.2.2 skrll * back the cnt * mbuf but we will fix that down below.
414 1.1.2.2 skrll */
415 1.1.2.2 skrll orig_rwnd = stcb->asoc.peers_rwnd;
416 1.1.2.2 skrll orig_flight = net->flight_size;
417 1.1.2.2 skrll stcb->asoc.peers_rwnd += net->flight_size;
418 1.1.2.2 skrll net->flight_size = 0;
419 1.1.2.2 skrll net->rto_pending = 0;
420 1.1.2.2 skrll net->fast_retran_ip= 0;
421 1.1.2.2 skrll win_probes = non_win_probes = 0;
422 1.1.2.2 skrll #ifdef SCTP_DEBUG
423 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER2) {
424 1.1.2.2 skrll printf("Marking ALL un-acked for retransmission at t3-timeout\n");
425 1.1.2.2 skrll }
426 1.1.2.2 skrll #endif /* SCTP_DEBUG */
427 1.1.2.2 skrll /* Now on to each chunk */
428 1.1.2.2 skrll num_mk = cnt_mk = 0;
429 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
430 1.1.2.2 skrll tsnlast = tsnfirst = 0;
431 1.1.2.2 skrll #endif
432 1.1.2.2 skrll chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
433 1.1.2.2 skrll for (;chk != NULL; chk = tp2) {
434 1.1.2.2 skrll tp2 = TAILQ_NEXT(chk, sctp_next);
435 1.1.2.2 skrll if ((compare_with_wrap(stcb->asoc.last_acked_seq,
436 1.1.2.2 skrll chk->rec.data.TSN_seq,
437 1.1.2.2 skrll MAX_TSN)) ||
438 1.1.2.2 skrll (stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) {
439 1.1.2.2 skrll /* Strange case our list got out of order? */
440 1.1.2.2 skrll printf("Our list is out of order?\n");
441 1.1.2.2 skrll TAILQ_REMOVE(&stcb->asoc.sent_queue, chk, sctp_next);
442 1.1.2.2 skrll if (chk->data) {
443 1.1.2.2 skrll sctp_release_pr_sctp_chunk(stcb, chk, 0xffff,
444 1.1.2.2 skrll &stcb->asoc.sent_queue);
445 1.1.2.2 skrll if (chk->flags & SCTP_PR_SCTP_BUFFER) {
446 1.1.2.2 skrll stcb->asoc.sent_queue_cnt_removeable--;
447 1.1.2.2 skrll }
448 1.1.2.2 skrll }
449 1.1.2.2 skrll stcb->asoc.sent_queue_cnt--;
450 1.1.2.2 skrll sctp_free_remote_addr(chk->whoTo);
451 1.1.2.2 skrll sctppcbinfo.ipi_count_chunk--;
452 1.1.2.2 skrll if ((int)sctppcbinfo.ipi_count_chunk < 0) {
453 1.1.2.2 skrll panic("Chunk count is going negative");
454 1.1.2.2 skrll }
455 1.1.2.2 skrll SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
456 1.1.2.2 skrll sctppcbinfo.ipi_gencnt_chunk++;
457 1.1.2.2 skrll continue;
458 1.1.2.2 skrll }
459 1.1.2.2 skrll if ((chk->whoTo == net) && (chk->sent < SCTP_DATAGRAM_ACKED)) {
460 1.1.2.2 skrll /* found one to mark:
461 1.1.2.2 skrll * If it is less than DATAGRAM_ACKED it MUST
462 1.1.2.2 skrll * not be a skipped or marked TSN but instead
463 1.1.2.2 skrll * one that is either already set for retransmission OR
464 1.1.2.2 skrll * one that needs retransmission.
465 1.1.2.2 skrll */
466 1.1.2.2 skrll
467 1.1.2.2 skrll /* validate its been outstanding long enough */
468 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
469 1.1.2.2 skrll sctp_log_fr(chk->rec.data.TSN_seq,
470 1.1.2.2 skrll chk->sent_rcv_time.tv_sec,
471 1.1.2.2 skrll chk->sent_rcv_time.tv_usec,
472 1.1.2.2 skrll SCTP_FR_T3_MARK_TIME);
473 1.1.2.2 skrll #endif
474 1.1.2.2 skrll if (chk->sent_rcv_time.tv_sec > min_wait.tv_sec) {
475 1.1.2.2 skrll /* we have reached a chunk that was sent some
476 1.1.2.2 skrll * seconds past our min.. forget it we will
477 1.1.2.2 skrll * find no more to send.
478 1.1.2.2 skrll */
479 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
480 1.1.2.2 skrll sctp_log_fr(0,
481 1.1.2.2 skrll chk->sent_rcv_time.tv_sec,
482 1.1.2.2 skrll chk->sent_rcv_time.tv_usec,
483 1.1.2.2 skrll SCTP_FR_T3_STOPPED);
484 1.1.2.2 skrll #endif
485 1.1.2.2 skrll continue;
486 1.1.2.2 skrll } else if (chk->sent_rcv_time.tv_sec == min_wait.tv_sec) {
487 1.1.2.2 skrll /* we must look at the micro seconds to know.
488 1.1.2.2 skrll */
489 1.1.2.2 skrll if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) {
490 1.1.2.2 skrll /* ok it was sent after our boundary time. */
491 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
492 1.1.2.2 skrll sctp_log_fr(0,
493 1.1.2.2 skrll chk->sent_rcv_time.tv_sec,
494 1.1.2.2 skrll chk->sent_rcv_time.tv_usec,
495 1.1.2.2 skrll SCTP_FR_T3_STOPPED);
496 1.1.2.2 skrll #endif
497 1.1.2.2 skrll continue;
498 1.1.2.2 skrll }
499 1.1.2.2 skrll }
500 1.1.2.2 skrll if (stcb->asoc.total_flight_count > 0) {
501 1.1.2.2 skrll stcb->asoc.total_flight_count--;
502 1.1.2.2 skrll }
503 1.1.2.2 skrll if ((chk->flags & (SCTP_PR_SCTP_ENABLED|SCTP_PR_SCTP_BUFFER)) == SCTP_PR_SCTP_ENABLED) {
504 1.1.2.2 skrll /* Is it expired? */
505 1.1.2.2 skrll if ((now.tv_sec > chk->rec.data.timetodrop.tv_sec) ||
506 1.1.2.2 skrll ((chk->rec.data.timetodrop.tv_sec == now.tv_sec) &&
507 1.1.2.2 skrll (now.tv_usec > chk->rec.data.timetodrop.tv_usec))) {
508 1.1.2.2 skrll /* Yes so drop it */
509 1.1.2.2 skrll if (chk->data) {
510 1.1.2.2 skrll sctp_release_pr_sctp_chunk(stcb,
511 1.1.2.2 skrll chk,
512 1.1.2.2 skrll (SCTP_RESPONSE_TO_USER_REQ|SCTP_NOTIFY_DATAGRAM_SENT),
513 1.1.2.2 skrll &stcb->asoc.sent_queue);
514 1.1.2.2 skrll }
515 1.1.2.2 skrll }
516 1.1.2.2 skrll continue;
517 1.1.2.2 skrll }
518 1.1.2.2 skrll if (chk->sent != SCTP_DATAGRAM_RESEND) {
519 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt++;
520 1.1.2.2 skrll num_mk++;
521 1.1.2.2 skrll if (fir == 0) {
522 1.1.2.2 skrll fir = 1;
523 1.1.2.2 skrll #ifdef SCTP_DEBUG
524 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
525 1.1.2.2 skrll printf("First TSN marked was %x\n",
526 1.1.2.2 skrll chk->rec.data.TSN_seq);
527 1.1.2.2 skrll }
528 1.1.2.2 skrll #endif
529 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
530 1.1.2.2 skrll tsnfirst = chk->rec.data.TSN_seq;
531 1.1.2.2 skrll #endif
532 1.1.2.2 skrll }
533 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
534 1.1.2.2 skrll tsnlast = chk->rec.data.TSN_seq;
535 1.1.2.2 skrll sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count,
536 1.1.2.2 skrll 0, SCTP_FR_T3_MARKED);
537 1.1.2.2 skrll
538 1.1.2.2 skrll #endif
539 1.1.2.2 skrll }
540 1.1.2.2 skrll chk->sent = SCTP_DATAGRAM_RESEND;
541 1.1.2.2 skrll /* reset the TSN for striking and other FR stuff */
542 1.1.2.2 skrll chk->rec.data.doing_fast_retransmit = 0;
543 1.1.2.2 skrll #ifdef SCTP_DEBUG
544 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER3) {
545 1.1.2.2 skrll printf("mark TSN:%x for retransmission\n", chk->rec.data.TSN_seq);
546 1.1.2.2 skrll }
547 1.1.2.2 skrll #endif /* SCTP_DEBUG */
548 1.1.2.2 skrll /* Clear any time so NO RTT is being done */
549 1.1.2.2 skrll chk->do_rtt = 0;
550 1.1.2.2 skrll /* Bump up the count */
551 1.1.2.2 skrll if (compare_with_wrap(chk->rec.data.TSN_seq,
552 1.1.2.2 skrll stcb->asoc.t3timeout_highest_marked,
553 1.1.2.2 skrll MAX_TSN)) {
554 1.1.2.2 skrll /* TSN_seq > than t3timeout so update */
555 1.1.2.2 skrll stcb->asoc.t3timeout_highest_marked = chk->rec.data.TSN_seq;
556 1.1.2.2 skrll }
557 1.1.2.2 skrll if (alt != net) {
558 1.1.2.2 skrll sctp_free_remote_addr(chk->whoTo);
559 1.1.2.2 skrll chk->whoTo = alt;
560 1.1.2.2 skrll alt->ref_count++;
561 1.1.2.2 skrll }
562 1.1.2.2 skrll if ((chk->rec.data.state_flags & SCTP_WINDOW_PROBE) !=
563 1.1.2.2 skrll SCTP_WINDOW_PROBE) {
564 1.1.2.2 skrll non_win_probes++;
565 1.1.2.2 skrll } else {
566 1.1.2.2 skrll chk->rec.data.state_flags &= ~SCTP_WINDOW_PROBE;
567 1.1.2.2 skrll win_probes++;
568 1.1.2.2 skrll }
569 1.1.2.2 skrll }
570 1.1.2.2 skrll if (chk->sent == SCTP_DATAGRAM_RESEND) {
571 1.1.2.2 skrll cnt_mk++;
572 1.1.2.2 skrll }
573 1.1.2.2 skrll }
574 1.1.2.2 skrll
575 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
576 1.1.2.2 skrll sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT);
577 1.1.2.2 skrll #endif
578 1.1.2.2 skrll /* compensate for the number we marked */
579 1.1.2.2 skrll stcb->asoc.peers_rwnd += (num_mk /* * sizeof(struct mbuf)*/);
580 1.1.2.2 skrll
581 1.1.2.2 skrll #ifdef SCTP_DEBUG
582 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
583 1.1.2.2 skrll if (num_mk) {
584 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
585 1.1.2.2 skrll printf("LAST TSN marked was %x\n", tsnlast);
586 1.1.2.2 skrll #endif
587 1.1.2.2 skrll printf("Num marked for retransmission was %d peer-rwd:%ld\n",
588 1.1.2.2 skrll num_mk, (u_long)stcb->asoc.peers_rwnd);
589 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
590 1.1.2.2 skrll printf("LAST TSN marked was %x\n", tsnlast);
591 1.1.2.2 skrll #endif
592 1.1.2.2 skrll printf("Num marked for retransmission was %d peer-rwd:%d\n",
593 1.1.2.2 skrll num_mk,
594 1.1.2.2 skrll (int)stcb->asoc.peers_rwnd
595 1.1.2.2 skrll );
596 1.1.2.2 skrll }
597 1.1.2.2 skrll }
598 1.1.2.2 skrll #endif
599 1.1.2.2 skrll *num_marked = num_mk;
600 1.1.2.2 skrll if (stcb->asoc.sent_queue_retran_cnt != cnt_mk) {
601 1.1.2.2 skrll printf("Local Audit says there are %d for retran asoc cnt:%d\n",
602 1.1.2.2 skrll cnt_mk, stcb->asoc.sent_queue_retran_cnt);
603 1.1.2.2 skrll #ifndef SCTP_AUDITING_ENABLED
604 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt = cnt_mk;
605 1.1.2.2 skrll #endif
606 1.1.2.2 skrll }
607 1.1.2.2 skrll #ifdef SCTP_DEBUG
608 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER3) {
609 1.1.2.2 skrll printf("**************************\n");
610 1.1.2.2 skrll }
611 1.1.2.2 skrll #endif /* SCTP_DEBUG */
612 1.1.2.2 skrll
613 1.1.2.2 skrll /* Now check for a ECN Echo that may be stranded */
614 1.1.2.2 skrll TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
615 1.1.2.2 skrll if ((chk->whoTo == net) &&
616 1.1.2.2 skrll (chk->rec.chunk_id == SCTP_ECN_ECHO)) {
617 1.1.2.2 skrll sctp_free_remote_addr(chk->whoTo);
618 1.1.2.2 skrll chk->whoTo = alt;
619 1.1.2.2 skrll if (chk->sent != SCTP_DATAGRAM_RESEND) {
620 1.1.2.2 skrll chk->sent = SCTP_DATAGRAM_RESEND;
621 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt++;
622 1.1.2.2 skrll }
623 1.1.2.2 skrll alt->ref_count++;
624 1.1.2.2 skrll }
625 1.1.2.2 skrll }
626 1.1.2.2 skrll if ((orig_rwnd == 0) && (stcb->asoc.total_flight == 0) &&
627 1.1.2.2 skrll (orig_flight <= net->mtu)) {
628 1.1.2.2 skrll /*
629 1.1.2.2 skrll * If the LAST packet sent was not acked and our rwnd is 0
630 1.1.2.2 skrll * then we are in a win-probe state.
631 1.1.2.2 skrll */
632 1.1.2.2 skrll win_probes = 1;
633 1.1.2.2 skrll non_win_probes = 0;
634 1.1.2.2 skrll #ifdef SCTP_DEBUG
635 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
636 1.1.2.2 skrll printf("WIN_PROBE set via o_rwnd=0 tf=0 and all:%d fit in mtu:%d\n",
637 1.1.2.2 skrll orig_flight, net->mtu);
638 1.1.2.2 skrll }
639 1.1.2.2 skrll #endif
640 1.1.2.2 skrll }
641 1.1.2.2 skrll
642 1.1.2.2 skrll if (audit_tf) {
643 1.1.2.2 skrll #ifdef SCTP_DEBUG
644 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
645 1.1.2.2 skrll printf("Audit total flight due to negative value net:%p\n",
646 1.1.2.2 skrll net);
647 1.1.2.2 skrll }
648 1.1.2.2 skrll #endif /* SCTP_DEBUG */
649 1.1.2.2 skrll stcb->asoc.total_flight = 0;
650 1.1.2.2 skrll stcb->asoc.total_flight_count = 0;
651 1.1.2.2 skrll /* Clear all networks flight size */
652 1.1.2.2 skrll TAILQ_FOREACH(lnets, &stcb->asoc.nets, sctp_next) {
653 1.1.2.2 skrll lnets->flight_size = 0;
654 1.1.2.2 skrll #ifdef SCTP_DEBUG
655 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER4) {
656 1.1.2.2 skrll printf("Net:%p c-f cwnd:%d ssthresh:%d\n",
657 1.1.2.2 skrll lnets, lnets->cwnd, lnets->ssthresh);
658 1.1.2.2 skrll }
659 1.1.2.2 skrll #endif /* SCTP_DEBUG */
660 1.1.2.2 skrll }
661 1.1.2.2 skrll TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
662 1.1.2.2 skrll if (chk->sent < SCTP_DATAGRAM_RESEND) {
663 1.1.2.2 skrll stcb->asoc.total_flight += chk->book_size;
664 1.1.2.2 skrll chk->whoTo->flight_size += chk->book_size;
665 1.1.2.2 skrll stcb->asoc.total_flight_count++;
666 1.1.2.2 skrll }
667 1.1.2.2 skrll }
668 1.1.2.2 skrll }
669 1.1.2.2 skrll /* Setup the ecn nonce re-sync point. We
670 1.1.2.2 skrll * do this since retranmissions are NOT
671 1.1.2.2 skrll * setup for ECN. This means that do to
672 1.1.2.2 skrll * Karn's rule, we don't know the total
673 1.1.2.2 skrll * of the peers ecn bits.
674 1.1.2.2 skrll */
675 1.1.2.2 skrll chk = TAILQ_FIRST(&stcb->asoc.send_queue);
676 1.1.2.2 skrll if (chk == NULL) {
677 1.1.2.2 skrll stcb->asoc.nonce_resync_tsn = stcb->asoc.sending_seq;
678 1.1.2.2 skrll } else {
679 1.1.2.2 skrll stcb->asoc.nonce_resync_tsn = chk->rec.data.TSN_seq;
680 1.1.2.2 skrll }
681 1.1.2.2 skrll stcb->asoc.nonce_wait_for_ecne = 0;
682 1.1.2.2 skrll stcb->asoc.nonce_sum_check = 0;
683 1.1.2.2 skrll /* We return 1 if we only have a window probe outstanding */
684 1.1.2.2 skrll if (win_probes && (non_win_probes == 0)) {
685 1.1.2.2 skrll return (1);
686 1.1.2.2 skrll }
687 1.1.2.2 skrll return (0);
688 1.1.2.2 skrll }
689 1.1.2.2 skrll
690 1.1.2.2 skrll static void
691 1.1.2.2 skrll sctp_move_all_chunks_to_alt(struct sctp_tcb *stcb,
692 1.1.2.2 skrll struct sctp_nets *net,
693 1.1.2.2 skrll struct sctp_nets *alt)
694 1.1.2.2 skrll {
695 1.1.2.2 skrll struct sctp_association *asoc;
696 1.1.2.2 skrll struct sctp_stream_out *outs;
697 1.1.2.2 skrll struct sctp_tmit_chunk *chk;
698 1.1.2.2 skrll
699 1.1.2.2 skrll if (net == alt)
700 1.1.2.2 skrll /* nothing to do */
701 1.1.2.2 skrll return;
702 1.1.2.2 skrll
703 1.1.2.2 skrll asoc = &stcb->asoc;
704 1.1.2.2 skrll
705 1.1.2.2 skrll /*
706 1.1.2.2 skrll * now through all the streams checking for chunks sent to our
707 1.1.2.2 skrll * bad network.
708 1.1.2.2 skrll */
709 1.1.2.2 skrll TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
710 1.1.2.2 skrll /* now clean up any chunks here */
711 1.1.2.2 skrll TAILQ_FOREACH(chk, &outs->outqueue, sctp_next) {
712 1.1.2.2 skrll if (chk->whoTo == net) {
713 1.1.2.2 skrll sctp_free_remote_addr(chk->whoTo);
714 1.1.2.2 skrll chk->whoTo = alt;
715 1.1.2.2 skrll alt->ref_count++;
716 1.1.2.2 skrll }
717 1.1.2.2 skrll }
718 1.1.2.2 skrll }
719 1.1.2.2 skrll /* Now check the pending queue */
720 1.1.2.2 skrll TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
721 1.1.2.2 skrll if (chk->whoTo == net) {
722 1.1.2.2 skrll sctp_free_remote_addr(chk->whoTo);
723 1.1.2.2 skrll chk->whoTo = alt;
724 1.1.2.2 skrll alt->ref_count++;
725 1.1.2.2 skrll }
726 1.1.2.2 skrll }
727 1.1.2.2 skrll
728 1.1.2.2 skrll }
729 1.1.2.2 skrll
730 1.1.2.2 skrll int
731 1.1.2.2 skrll sctp_t3rxt_timer(struct sctp_inpcb *inp,
732 1.1.2.2 skrll struct sctp_tcb *stcb,
733 1.1.2.2 skrll struct sctp_nets *net)
734 1.1.2.2 skrll {
735 1.1.2.2 skrll struct sctp_nets *alt;
736 1.1.2.2 skrll int win_probe, num_mk;
737 1.1.2.2 skrll
738 1.1.2.2 skrll
739 1.1.2.2 skrll #ifdef SCTP_FR_LOGGING
740 1.1.2.2 skrll sctp_log_fr(0, 0, 0, SCTP_FR_T3_TIMEOUT);
741 1.1.2.2 skrll #endif
742 1.1.2.2 skrll /* Find an alternate and mark those for retransmission */
743 1.1.2.2 skrll alt = sctp_find_alternate_net(stcb, net);
744 1.1.2.2 skrll win_probe = sctp_mark_all_for_resend(stcb, net, alt, &num_mk);
745 1.1.2.2 skrll
746 1.1.2.2 skrll /* FR Loss recovery just ended with the T3. */
747 1.1.2.2 skrll stcb->asoc.fast_retran_loss_recovery = 0;
748 1.1.2.2 skrll
749 1.1.2.2 skrll /* setup the sat loss recovery that prevents
750 1.1.2.2 skrll * satellite cwnd advance.
751 1.1.2.2 skrll */
752 1.1.2.2 skrll stcb->asoc.sat_t3_loss_recovery = 1;
753 1.1.2.2 skrll stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq;
754 1.1.2.2 skrll
755 1.1.2.2 skrll /* Backoff the timer and cwnd */
756 1.1.2.2 skrll sctp_backoff_on_timeout(stcb, net, win_probe, num_mk);
757 1.1.2.2 skrll if (win_probe == 0) {
758 1.1.2.2 skrll /* We don't do normal threshold management on window probes */
759 1.1.2.2 skrll if (sctp_threshold_management(inp, stcb, net,
760 1.1.2.2 skrll stcb->asoc.max_send_times)) {
761 1.1.2.2 skrll /* Association was destroyed */
762 1.1.2.2 skrll return (1);
763 1.1.2.2 skrll } else {
764 1.1.2.2 skrll if (net != stcb->asoc.primary_destination) {
765 1.1.2.2 skrll /* send a immediate HB if our RTO is stale */
766 1.1.2.2 skrll struct timeval now;
767 1.1.2.2 skrll unsigned int ms_goneby;
768 1.1.2.2 skrll SCTP_GETTIME_TIMEVAL(&now);
769 1.1.2.2 skrll if (net->last_sent_time.tv_sec) {
770 1.1.2.2 skrll ms_goneby = (now.tv_sec - net->last_sent_time.tv_sec) * 1000;
771 1.1.2.2 skrll } else {
772 1.1.2.2 skrll ms_goneby = 0;
773 1.1.2.2 skrll }
774 1.1.2.2 skrll if ((ms_goneby > net->RTO) || (net->RTO == 0)) {
775 1.1.2.2 skrll /* no recent feed back in an RTO or more, request a RTT update */
776 1.1.2.2 skrll sctp_send_hb(stcb, 1, net);
777 1.1.2.2 skrll }
778 1.1.2.2 skrll }
779 1.1.2.2 skrll }
780 1.1.2.2 skrll } else {
781 1.1.2.2 skrll /*
782 1.1.2.2 skrll * For a window probe we don't penalize the net's but only
783 1.1.2.2 skrll * the association. This may fail it if SACKs are not coming
784 1.1.2.2 skrll * back. If sack's are coming with rwnd locked at 0, we will
785 1.1.2.2 skrll * continue to hold things waiting for rwnd to raise
786 1.1.2.2 skrll */
787 1.1.2.2 skrll if (sctp_threshold_management(inp, stcb, NULL,
788 1.1.2.2 skrll stcb->asoc.max_send_times)) {
789 1.1.2.2 skrll /* Association was destroyed */
790 1.1.2.2 skrll return (1);
791 1.1.2.2 skrll }
792 1.1.2.2 skrll }
793 1.1.2.2 skrll if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
794 1.1.2.2 skrll /* Move all pending over too */
795 1.1.2.2 skrll sctp_move_all_chunks_to_alt(stcb, net, alt);
796 1.1.2.2 skrll /* Was it our primary? */
797 1.1.2.2 skrll if ((stcb->asoc.primary_destination == net) && (alt != net)) {
798 1.1.2.2 skrll /*
799 1.1.2.2 skrll * Yes, note it as such and find an alternate
800 1.1.2.2 skrll * note: this means HB code must use this to resent
801 1.1.2.2 skrll * the primary if it goes active AND if someone does
802 1.1.2.2 skrll * a change-primary then this flag must be cleared
803 1.1.2.2 skrll * from any net structures.
804 1.1.2.2 skrll */
805 1.1.2.2 skrll if (sctp_set_primary_addr(stcb,
806 1.1.2.2 skrll (struct sockaddr *)NULL,
807 1.1.2.2 skrll alt) == 0) {
808 1.1.2.2 skrll net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
809 1.1.2.2 skrll net->src_addr_selected = 0;
810 1.1.2.2 skrll }
811 1.1.2.2 skrll }
812 1.1.2.2 skrll }
813 1.1.2.2 skrll /*
814 1.1.2.2 skrll * Special case for cookie-echo'ed case, we don't do output
815 1.1.2.2 skrll * but must await the COOKIE-ACK before retransmission
816 1.1.2.2 skrll */
817 1.1.2.2 skrll if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
818 1.1.2.2 skrll /*
819 1.1.2.2 skrll * Here we just reset the timer and start again since we
820 1.1.2.2 skrll * have not established the asoc
821 1.1.2.2 skrll */
822 1.1.2.2 skrll #ifdef SCTP_DEBUG
823 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
824 1.1.2.2 skrll printf("Special cookie case return\n");
825 1.1.2.2 skrll }
826 1.1.2.2 skrll #endif /* SCTP_DEBUG */
827 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
828 1.1.2.2 skrll return (0);
829 1.1.2.2 skrll }
830 1.1.2.2 skrll if (stcb->asoc.peer_supports_prsctp) {
831 1.1.2.2 skrll struct sctp_tmit_chunk *lchk;
832 1.1.2.2 skrll lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc);
833 1.1.2.2 skrll /* C3. See if we need to send a Fwd-TSN */
834 1.1.2.2 skrll if (compare_with_wrap(stcb->asoc.advanced_peer_ack_point,
835 1.1.2.2 skrll stcb->asoc.last_acked_seq, MAX_TSN)) {
836 1.1.2.2 skrll /*
837 1.1.2.2 skrll * ISSUE with ECN, see FWD-TSN processing for notes
838 1.1.2.2 skrll * on issues that will occur when the ECN NONCE stuff
839 1.1.2.2 skrll * is put into SCTP for cross checking.
840 1.1.2.2 skrll */
841 1.1.2.2 skrll #ifdef SCTP_DEBUG
842 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
843 1.1.2.2 skrll printf("Forward TSN time\n");
844 1.1.2.2 skrll }
845 1.1.2.2 skrll #endif /* SCTP_DEBUG */
846 1.1.2.2 skrll send_forward_tsn(stcb, &stcb->asoc);
847 1.1.2.2 skrll if (lchk) {
848 1.1.2.2 skrll /* Assure a timer is up */
849 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, lchk->whoTo);
850 1.1.2.2 skrll }
851 1.1.2.2 skrll }
852 1.1.2.2 skrll }
853 1.1.2.2 skrll return (0);
854 1.1.2.2 skrll }
855 1.1.2.2 skrll
856 1.1.2.2 skrll int
857 1.1.2.2 skrll sctp_t1init_timer(struct sctp_inpcb *inp,
858 1.1.2.2 skrll struct sctp_tcb *stcb,
859 1.1.2.2 skrll struct sctp_nets *net)
860 1.1.2.2 skrll {
861 1.1.2.2 skrll /* bump the thresholds */
862 1.1.2.2 skrll if (stcb->asoc.delayed_connection) {
863 1.1.2.2 skrll /* special hook for delayed connection. The
864 1.1.2.2 skrll * library did NOT complete the rest of its
865 1.1.2.2 skrll * sends.
866 1.1.2.2 skrll */
867 1.1.2.2 skrll stcb->asoc.delayed_connection = 0;
868 1.1.2.2 skrll sctp_send_initiate(inp, stcb);
869 1.1.2.2 skrll return (0);
870 1.1.2.2 skrll }
871 1.1.2.2 skrll if (sctp_threshold_management(inp, stcb, net,
872 1.1.2.2 skrll stcb->asoc.max_init_times)) {
873 1.1.2.2 skrll /* Association was destroyed */
874 1.1.2.2 skrll return (1);
875 1.1.2.2 skrll }
876 1.1.2.2 skrll stcb->asoc.dropped_special_cnt = 0;
877 1.1.2.2 skrll sctp_backoff_on_timeout(stcb, stcb->asoc.primary_destination, 1, 0);
878 1.1.2.2 skrll if (stcb->asoc.initial_init_rto_max < net->RTO) {
879 1.1.2.2 skrll net->RTO = stcb->asoc.initial_init_rto_max;
880 1.1.2.2 skrll }
881 1.1.2.2 skrll if (stcb->asoc.numnets > 1) {
882 1.1.2.2 skrll /* If we have more than one addr use it */
883 1.1.2.2 skrll struct sctp_nets *alt;
884 1.1.2.2 skrll alt = sctp_find_alternate_net(stcb, stcb->asoc.primary_destination);
885 1.1.2.2 skrll if ((alt != NULL) && (alt != stcb->asoc.primary_destination)) {
886 1.1.2.2 skrll sctp_move_all_chunks_to_alt(stcb, stcb->asoc.primary_destination, alt);
887 1.1.2.2 skrll stcb->asoc.primary_destination = alt;
888 1.1.2.2 skrll }
889 1.1.2.2 skrll }
890 1.1.2.2 skrll /* Send out a new init */
891 1.1.2.2 skrll sctp_send_initiate(inp, stcb);
892 1.1.2.2 skrll return (0);
893 1.1.2.2 skrll }
894 1.1.2.2 skrll
895 1.1.2.2 skrll /*
896 1.1.2.2 skrll * For cookie and asconf we actually need to find and mark for resend,
897 1.1.2.2 skrll * then increment the resend counter (after all the threshold management
898 1.1.2.2 skrll * stuff of course).
899 1.1.2.2 skrll */
900 1.1.2.2 skrll int sctp_cookie_timer(struct sctp_inpcb *inp,
901 1.1.2.2 skrll struct sctp_tcb *stcb,
902 1.1.2.2 skrll struct sctp_nets *net)
903 1.1.2.2 skrll {
904 1.1.2.2 skrll struct sctp_nets *alt;
905 1.1.2.2 skrll struct sctp_tmit_chunk *cookie;
906 1.1.2.2 skrll /* first before all else we must find the cookie */
907 1.1.2.2 skrll TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, sctp_next) {
908 1.1.2.2 skrll if (cookie->rec.chunk_id == SCTP_COOKIE_ECHO) {
909 1.1.2.2 skrll break;
910 1.1.2.2 skrll }
911 1.1.2.2 skrll }
912 1.1.2.2 skrll if (cookie == NULL) {
913 1.1.2.2 skrll if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
914 1.1.2.2 skrll /* FOOBAR! */
915 1.1.2.2 skrll struct mbuf *oper;
916 1.1.2.2 skrll MGET(oper, M_DONTWAIT, MT_DATA);
917 1.1.2.2 skrll if (oper) {
918 1.1.2.2 skrll struct sctp_paramhdr *ph;
919 1.1.2.2 skrll u_int32_t *ippp;
920 1.1.2.2 skrll
921 1.1.2.2 skrll oper->m_len = sizeof(struct sctp_paramhdr) +
922 1.1.2.2 skrll sizeof(*ippp);
923 1.1.2.2 skrll ph = mtod(oper, struct sctp_paramhdr *);
924 1.1.2.2 skrll ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
925 1.1.2.2 skrll ph->param_length = htons(oper->m_len);
926 1.1.2.2 skrll ippp = (u_int32_t *)(ph + 1);
927 1.1.2.2 skrll *ippp = htonl(0x40000002);
928 1.1.2.2 skrll }
929 1.1.2.2 skrll sctp_abort_an_association(inp, stcb, SCTP_INTERNAL_ERROR,
930 1.1.2.2 skrll oper);
931 1.1.2.2 skrll }
932 1.1.2.2 skrll return (1);
933 1.1.2.2 skrll }
934 1.1.2.2 skrll /* Ok we found the cookie, threshold management next */
935 1.1.2.2 skrll if (sctp_threshold_management(inp, stcb, cookie->whoTo,
936 1.1.2.2 skrll stcb->asoc.max_init_times)) {
937 1.1.2.2 skrll /* Assoc is over */
938 1.1.2.2 skrll return (1);
939 1.1.2.2 skrll }
940 1.1.2.2 skrll /*
941 1.1.2.2 skrll * cleared theshold management now lets backoff the address &
942 1.1.2.2 skrll * select an alternate
943 1.1.2.2 skrll */
944 1.1.2.2 skrll stcb->asoc.dropped_special_cnt = 0;
945 1.1.2.2 skrll sctp_backoff_on_timeout(stcb, cookie->whoTo, 1, 0);
946 1.1.2.2 skrll alt = sctp_find_alternate_net(stcb, cookie->whoTo);
947 1.1.2.2 skrll if (alt != cookie->whoTo) {
948 1.1.2.2 skrll sctp_free_remote_addr(cookie->whoTo);
949 1.1.2.2 skrll cookie->whoTo = alt;
950 1.1.2.2 skrll alt->ref_count++;
951 1.1.2.2 skrll }
952 1.1.2.2 skrll /* Now mark the retran info */
953 1.1.2.2 skrll if (cookie->sent != SCTP_DATAGRAM_RESEND) {
954 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt++;
955 1.1.2.2 skrll }
956 1.1.2.2 skrll cookie->sent = SCTP_DATAGRAM_RESEND;
957 1.1.2.2 skrll /*
958 1.1.2.2 skrll * Now call the output routine to kick out the cookie again, Note we
959 1.1.2.2 skrll * don't mark any chunks for retran so that FR will need to kick in
960 1.1.2.2 skrll * to move these (or a send timer).
961 1.1.2.2 skrll */
962 1.1.2.2 skrll return (0);
963 1.1.2.2 skrll }
964 1.1.2.2 skrll
965 1.1.2.2 skrll int sctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
966 1.1.2.2 skrll struct sctp_nets *net)
967 1.1.2.2 skrll {
968 1.1.2.2 skrll struct sctp_nets *alt;
969 1.1.2.2 skrll struct sctp_tmit_chunk *strrst, *chk;
970 1.1.2.2 skrll struct sctp_stream_reset_req *strreq;
971 1.1.2.2 skrll /* find the existing STRRESET */
972 1.1.2.2 skrll TAILQ_FOREACH(strrst, &stcb->asoc.control_send_queue,
973 1.1.2.2 skrll sctp_next) {
974 1.1.2.2 skrll if (strrst->rec.chunk_id == SCTP_STREAM_RESET) {
975 1.1.2.2 skrll /* is it what we want */
976 1.1.2.2 skrll strreq = mtod(strrst->data, struct sctp_stream_reset_req *);
977 1.1.2.2 skrll if (strreq->sr_req.ph.param_type == ntohs(SCTP_STR_RESET_REQUEST)) {
978 1.1.2.2 skrll break;
979 1.1.2.2 skrll }
980 1.1.2.2 skrll }
981 1.1.2.2 skrll }
982 1.1.2.2 skrll if (strrst == NULL) {
983 1.1.2.2 skrll #ifdef SCTP_DEBUG
984 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
985 1.1.2.2 skrll printf("Strange, strreset timer fires, but I can't find an str-reset?\n");
986 1.1.2.2 skrll }
987 1.1.2.2 skrll #endif /* SCTP_DEBUG */
988 1.1.2.2 skrll return (0);
989 1.1.2.2 skrll }
990 1.1.2.2 skrll /* do threshold management */
991 1.1.2.2 skrll if (sctp_threshold_management(inp, stcb, strrst->whoTo,
992 1.1.2.2 skrll stcb->asoc.max_send_times)) {
993 1.1.2.2 skrll /* Assoc is over */
994 1.1.2.2 skrll return (1);
995 1.1.2.2 skrll }
996 1.1.2.2 skrll
997 1.1.2.2 skrll /*
998 1.1.2.2 skrll * cleared theshold management
999 1.1.2.2 skrll * now lets backoff the address & select an alternate
1000 1.1.2.2 skrll */
1001 1.1.2.2 skrll sctp_backoff_on_timeout(stcb, strrst->whoTo, 1, 0);
1002 1.1.2.2 skrll alt = sctp_find_alternate_net(stcb, strrst->whoTo);
1003 1.1.2.2 skrll sctp_free_remote_addr(strrst->whoTo);
1004 1.1.2.2 skrll strrst->whoTo = alt;
1005 1.1.2.2 skrll alt->ref_count++;
1006 1.1.2.2 skrll
1007 1.1.2.2 skrll /* See if a ECN Echo is also stranded */
1008 1.1.2.2 skrll TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
1009 1.1.2.2 skrll if ((chk->whoTo == net) &&
1010 1.1.2.2 skrll (chk->rec.chunk_id == SCTP_ECN_ECHO)) {
1011 1.1.2.2 skrll sctp_free_remote_addr(chk->whoTo);
1012 1.1.2.2 skrll if (chk->sent != SCTP_DATAGRAM_RESEND) {
1013 1.1.2.2 skrll chk->sent = SCTP_DATAGRAM_RESEND;
1014 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt++;
1015 1.1.2.2 skrll }
1016 1.1.2.2 skrll chk->whoTo = alt;
1017 1.1.2.2 skrll alt->ref_count++;
1018 1.1.2.2 skrll }
1019 1.1.2.2 skrll }
1020 1.1.2.2 skrll if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
1021 1.1.2.2 skrll /*
1022 1.1.2.2 skrll * If the address went un-reachable, we need to move
1023 1.1.2.2 skrll * to alternates for ALL chk's in queue
1024 1.1.2.2 skrll */
1025 1.1.2.2 skrll sctp_move_all_chunks_to_alt(stcb, net, alt);
1026 1.1.2.2 skrll }
1027 1.1.2.2 skrll /* mark the retran info */
1028 1.1.2.2 skrll if (strrst->sent != SCTP_DATAGRAM_RESEND)
1029 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt++;
1030 1.1.2.2 skrll strrst->sent = SCTP_DATAGRAM_RESEND;
1031 1.1.2.2 skrll
1032 1.1.2.2 skrll /* restart the timer */
1033 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, inp, stcb, strrst->whoTo);
1034 1.1.2.2 skrll return (0);
1035 1.1.2.2 skrll }
1036 1.1.2.2 skrll
1037 1.1.2.2 skrll int sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1038 1.1.2.2 skrll struct sctp_nets *net)
1039 1.1.2.2 skrll {
1040 1.1.2.2 skrll struct sctp_nets *alt;
1041 1.1.2.2 skrll struct sctp_tmit_chunk *asconf, *chk;
1042 1.1.2.2 skrll
1043 1.1.2.2 skrll /* is this the first send, or a retransmission? */
1044 1.1.2.2 skrll if (stcb->asoc.asconf_sent == 0) {
1045 1.1.2.2 skrll /* compose a new ASCONF chunk and send it */
1046 1.1.2.2 skrll sctp_send_asconf(stcb, net);
1047 1.1.2.2 skrll } else {
1048 1.1.2.2 skrll /* Retransmission of the existing ASCONF needed... */
1049 1.1.2.2 skrll
1050 1.1.2.2 skrll /* find the existing ASCONF */
1051 1.1.2.2 skrll TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue,
1052 1.1.2.2 skrll sctp_next) {
1053 1.1.2.2 skrll if (asconf->rec.chunk_id == SCTP_ASCONF) {
1054 1.1.2.2 skrll break;
1055 1.1.2.2 skrll }
1056 1.1.2.2 skrll }
1057 1.1.2.2 skrll if (asconf == NULL) {
1058 1.1.2.2 skrll #ifdef SCTP_DEBUG
1059 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1060 1.1.2.2 skrll printf("Strange, asconf timer fires, but I can't find an asconf?\n");
1061 1.1.2.2 skrll }
1062 1.1.2.2 skrll #endif /* SCTP_DEBUG */
1063 1.1.2.2 skrll return (0);
1064 1.1.2.2 skrll }
1065 1.1.2.2 skrll /* do threshold management */
1066 1.1.2.2 skrll if (sctp_threshold_management(inp, stcb, asconf->whoTo,
1067 1.1.2.2 skrll stcb->asoc.max_send_times)) {
1068 1.1.2.2 skrll /* Assoc is over */
1069 1.1.2.2 skrll return (1);
1070 1.1.2.2 skrll }
1071 1.1.2.2 skrll
1072 1.1.2.2 skrll /* PETER? FIX? How will the following code ever run? If
1073 1.1.2.2 skrll * the max_send_times is hit, threshold managment will
1074 1.1.2.2 skrll * blow away the association?
1075 1.1.2.2 skrll */
1076 1.1.2.2 skrll if (asconf->snd_count > stcb->asoc.max_send_times) {
1077 1.1.2.2 skrll /*
1078 1.1.2.2 skrll * Something is rotten, peer is not responding to
1079 1.1.2.2 skrll * ASCONFs but maybe is to data etc. e.g. it is not
1080 1.1.2.2 skrll * properly handling the chunk type upper bits
1081 1.1.2.2 skrll * Mark this peer as ASCONF incapable and cleanup
1082 1.1.2.2 skrll */
1083 1.1.2.2 skrll #ifdef SCTP_DEBUG
1084 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1085 1.1.2.2 skrll printf("asconf_timer: Peer has not responded to our repeated ASCONFs\n");
1086 1.1.2.2 skrll }
1087 1.1.2.2 skrll #endif /* SCTP_DEBUG */
1088 1.1.2.2 skrll sctp_asconf_cleanup(stcb, net);
1089 1.1.2.2 skrll return (0);
1090 1.1.2.2 skrll }
1091 1.1.2.2 skrll /*
1092 1.1.2.2 skrll * cleared theshold management
1093 1.1.2.2 skrll * now lets backoff the address & select an alternate
1094 1.1.2.2 skrll */
1095 1.1.2.2 skrll sctp_backoff_on_timeout(stcb, asconf->whoTo, 1, 0);
1096 1.1.2.2 skrll alt = sctp_find_alternate_net(stcb, asconf->whoTo);
1097 1.1.2.2 skrll sctp_free_remote_addr(asconf->whoTo);
1098 1.1.2.2 skrll asconf->whoTo = alt;
1099 1.1.2.2 skrll alt->ref_count++;
1100 1.1.2.2 skrll
1101 1.1.2.2 skrll /* See if a ECN Echo is also stranded */
1102 1.1.2.2 skrll TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
1103 1.1.2.2 skrll if ((chk->whoTo == net) &&
1104 1.1.2.2 skrll (chk->rec.chunk_id == SCTP_ECN_ECHO)) {
1105 1.1.2.2 skrll sctp_free_remote_addr(chk->whoTo);
1106 1.1.2.2 skrll chk->whoTo = alt;
1107 1.1.2.2 skrll if (chk->sent != SCTP_DATAGRAM_RESEND) {
1108 1.1.2.2 skrll chk->sent = SCTP_DATAGRAM_RESEND;
1109 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt++;
1110 1.1.2.2 skrll }
1111 1.1.2.2 skrll alt->ref_count++;
1112 1.1.2.2 skrll
1113 1.1.2.2 skrll }
1114 1.1.2.2 skrll }
1115 1.1.2.2 skrll if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
1116 1.1.2.2 skrll /*
1117 1.1.2.2 skrll * If the address went un-reachable, we need to move
1118 1.1.2.2 skrll * to alternates for ALL chk's in queue
1119 1.1.2.2 skrll */
1120 1.1.2.2 skrll sctp_move_all_chunks_to_alt(stcb, net, alt);
1121 1.1.2.2 skrll }
1122 1.1.2.2 skrll /* mark the retran info */
1123 1.1.2.2 skrll if (asconf->sent != SCTP_DATAGRAM_RESEND)
1124 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt++;
1125 1.1.2.2 skrll asconf->sent = SCTP_DATAGRAM_RESEND;
1126 1.1.2.2 skrll }
1127 1.1.2.2 skrll return (0);
1128 1.1.2.2 skrll }
1129 1.1.2.2 skrll
1130 1.1.2.2 skrll /*
1131 1.1.2.2 skrll * For the shutdown and shutdown-ack, we do not keep one around on the
1132 1.1.2.2 skrll * control queue. This means we must generate a new one and call the general
1133 1.1.2.2 skrll * chunk output routine, AFTER having done threshold
1134 1.1.2.2 skrll * management.
1135 1.1.2.2 skrll */
1136 1.1.2.2 skrll int
1137 1.1.2.2 skrll sctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1138 1.1.2.2 skrll struct sctp_nets *net)
1139 1.1.2.2 skrll {
1140 1.1.2.2 skrll struct sctp_nets *alt;
1141 1.1.2.2 skrll /* first threshold managment */
1142 1.1.2.2 skrll if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
1143 1.1.2.2 skrll /* Assoc is over */
1144 1.1.2.2 skrll return (1);
1145 1.1.2.2 skrll }
1146 1.1.2.2 skrll /* second select an alternative */
1147 1.1.2.2 skrll alt = sctp_find_alternate_net(stcb, net);
1148 1.1.2.2 skrll
1149 1.1.2.2 skrll /* third generate a shutdown into the queue for out net */
1150 1.1.2.2 skrll #ifdef SCTP_DEBUG
1151 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_OUTPUT4) {
1152 1.1.2.2 skrll printf("%s:%d sends a shutdown\n",
1153 1.1.2.2 skrll __FILE__,
1154 1.1.2.2 skrll __LINE__
1155 1.1.2.2 skrll );
1156 1.1.2.2 skrll }
1157 1.1.2.2 skrll #endif
1158 1.1.2.2 skrll if (alt) {
1159 1.1.2.2 skrll sctp_send_shutdown(stcb, alt);
1160 1.1.2.2 skrll } else {
1161 1.1.2.2 skrll /* if alt is NULL, there is no dest
1162 1.1.2.2 skrll * to send to??
1163 1.1.2.2 skrll */
1164 1.1.2.2 skrll return (0);
1165 1.1.2.2 skrll }
1166 1.1.2.2 skrll /* fourth restart timer */
1167 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, inp, stcb, alt);
1168 1.1.2.2 skrll return (0);
1169 1.1.2.2 skrll }
1170 1.1.2.2 skrll
1171 1.1.2.2 skrll int sctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1172 1.1.2.2 skrll struct sctp_nets *net)
1173 1.1.2.2 skrll {
1174 1.1.2.2 skrll struct sctp_nets *alt;
1175 1.1.2.2 skrll /* first threshold managment */
1176 1.1.2.2 skrll if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
1177 1.1.2.2 skrll /* Assoc is over */
1178 1.1.2.2 skrll return (1);
1179 1.1.2.2 skrll }
1180 1.1.2.2 skrll /* second select an alternative */
1181 1.1.2.2 skrll alt = sctp_find_alternate_net(stcb, net);
1182 1.1.2.2 skrll
1183 1.1.2.2 skrll /* third generate a shutdown into the queue for out net */
1184 1.1.2.2 skrll sctp_send_shutdown_ack(stcb, alt);
1185 1.1.2.2 skrll
1186 1.1.2.2 skrll /* fourth restart timer */
1187 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, inp, stcb, alt);
1188 1.1.2.2 skrll return (0);
1189 1.1.2.2 skrll }
1190 1.1.2.2 skrll
1191 1.1.2.2 skrll static void
1192 1.1.2.2 skrll sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
1193 1.1.2.2 skrll struct sctp_tcb *stcb)
1194 1.1.2.2 skrll {
1195 1.1.2.2 skrll struct sctp_stream_out *outs;
1196 1.1.2.2 skrll struct sctp_tmit_chunk *chk;
1197 1.1.2.2 skrll unsigned int chks_in_queue=0;
1198 1.1.2.2 skrll
1199 1.1.2.2 skrll if ((stcb == NULL) || (inp == NULL))
1200 1.1.2.2 skrll return;
1201 1.1.2.2 skrll if (TAILQ_EMPTY(&stcb->asoc.out_wheel)) {
1202 1.1.2.2 skrll printf("Strange, out_wheel empty nothing on sent/send and tot=%lu?\n",
1203 1.1.2.2 skrll (u_long)stcb->asoc.total_output_queue_size);
1204 1.1.2.2 skrll stcb->asoc.total_output_queue_size = 0;
1205 1.1.2.2 skrll return;
1206 1.1.2.2 skrll }
1207 1.1.2.2 skrll if (stcb->asoc.sent_queue_retran_cnt) {
1208 1.1.2.2 skrll printf("Hmm, sent_queue_retran_cnt is non-zero %d\n",
1209 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt);
1210 1.1.2.2 skrll stcb->asoc.sent_queue_retran_cnt = 0;
1211 1.1.2.2 skrll }
1212 1.1.2.2 skrll /* Check to see if some data queued, if so report it */
1213 1.1.2.2 skrll TAILQ_FOREACH(outs, &stcb->asoc.out_wheel, next_spoke) {
1214 1.1.2.2 skrll if (!TAILQ_EMPTY(&outs->outqueue)) {
1215 1.1.2.2 skrll TAILQ_FOREACH(chk, &outs->outqueue, sctp_next) {
1216 1.1.2.2 skrll chks_in_queue++;
1217 1.1.2.2 skrll }
1218 1.1.2.2 skrll }
1219 1.1.2.2 skrll }
1220 1.1.2.2 skrll if (chks_in_queue != stcb->asoc.stream_queue_cnt) {
1221 1.1.2.2 skrll printf("Hmm, stream queue cnt at %d I counted %d in stream out wheel\n",
1222 1.1.2.2 skrll stcb->asoc.stream_queue_cnt, chks_in_queue);
1223 1.1.2.2 skrll }
1224 1.1.2.2 skrll if (chks_in_queue) {
1225 1.1.2.2 skrll /* call the output queue function */
1226 1.1.2.2 skrll sctp_chunk_output(inp, stcb, 1);
1227 1.1.2.2 skrll if ((TAILQ_EMPTY(&stcb->asoc.send_queue)) &&
1228 1.1.2.2 skrll (TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
1229 1.1.2.2 skrll /* Probably should go in and make it go back through and add fragments allowed */
1230 1.1.2.2 skrll printf("Still nothing moved %d chunks are stuck\n", chks_in_queue);
1231 1.1.2.2 skrll }
1232 1.1.2.2 skrll } else {
1233 1.1.2.2 skrll printf("Found no chunks on any queue tot:%lu\n",
1234 1.1.2.2 skrll (u_long)stcb->asoc.total_output_queue_size);
1235 1.1.2.2 skrll stcb->asoc.total_output_queue_size = 0;
1236 1.1.2.2 skrll }
1237 1.1.2.2 skrll }
1238 1.1.2.2 skrll
1239 1.1.2.2 skrll int
1240 1.1.2.2 skrll sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1241 1.1.2.2 skrll struct sctp_nets *net)
1242 1.1.2.2 skrll {
1243 1.1.2.2 skrll int cnt_of_unconf=0;
1244 1.1.2.2 skrll
1245 1.1.2.2 skrll if (net) {
1246 1.1.2.2 skrll if (net->hb_responded == 0) {
1247 1.1.2.2 skrll sctp_backoff_on_timeout(stcb, net, 1, 0);
1248 1.1.2.2 skrll }
1249 1.1.2.2 skrll /* Zero PBA, if it needs it */
1250 1.1.2.2 skrll if (net->partial_bytes_acked) {
1251 1.1.2.2 skrll net->partial_bytes_acked = 0;
1252 1.1.2.2 skrll }
1253 1.1.2.2 skrll }
1254 1.1.2.2 skrll TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1255 1.1.2.2 skrll if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
1256 1.1.2.2 skrll (net->dest_state & SCTP_ADDR_REACHABLE)) {
1257 1.1.2.2 skrll cnt_of_unconf++;
1258 1.1.2.2 skrll }
1259 1.1.2.2 skrll }
1260 1.1.2.2 skrll if ((stcb->asoc.total_output_queue_size > 0) &&
1261 1.1.2.2 skrll (TAILQ_EMPTY(&stcb->asoc.send_queue)) &&
1262 1.1.2.2 skrll (TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
1263 1.1.2.2 skrll sctp_audit_stream_queues_for_size(inp, stcb);
1264 1.1.2.2 skrll }
1265 1.1.2.2 skrll /* Send a new HB, this will do threshold managment, pick a new dest */
1266 1.1.2.2 skrll if (sctp_send_hb(stcb, 0, NULL) < 0) {
1267 1.1.2.2 skrll return (1);
1268 1.1.2.2 skrll }
1269 1.1.2.2 skrll if (cnt_of_unconf > 1) {
1270 1.1.2.2 skrll /*
1271 1.1.2.2 skrll * this will send out extra hb's up to maxburst if
1272 1.1.2.2 skrll * there are any unconfirmed addresses.
1273 1.1.2.2 skrll */
1274 1.1.2.2 skrll int cnt_sent = 1;
1275 1.1.2.2 skrll while ((cnt_sent < stcb->asoc.max_burst) && (cnt_of_unconf > 1)) {
1276 1.1.2.2 skrll if (sctp_send_hb(stcb, 0, NULL) == 0)
1277 1.1.2.2 skrll break;
1278 1.1.2.2 skrll cnt_of_unconf--;
1279 1.1.2.2 skrll cnt_sent++;
1280 1.1.2.2 skrll }
1281 1.1.2.2 skrll }
1282 1.1.2.2 skrll return (0);
1283 1.1.2.2 skrll }
1284 1.1.2.2 skrll
1285 1.1.2.2 skrll #define SCTP_NUMBER_OF_MTU_SIZES 18
1286 1.1.2.2 skrll static u_int32_t mtu_sizes[]={
1287 1.1.2.2 skrll 68,
1288 1.1.2.2 skrll 296,
1289 1.1.2.2 skrll 508,
1290 1.1.2.2 skrll 512,
1291 1.1.2.2 skrll 544,
1292 1.1.2.2 skrll 576,
1293 1.1.2.2 skrll 1006,
1294 1.1.2.2 skrll 1492,
1295 1.1.2.2 skrll 1500,
1296 1.1.2.2 skrll 1536,
1297 1.1.2.2 skrll 2002,
1298 1.1.2.2 skrll 2048,
1299 1.1.2.2 skrll 4352,
1300 1.1.2.2 skrll 4464,
1301 1.1.2.2 skrll 8166,
1302 1.1.2.2 skrll 17914,
1303 1.1.2.2 skrll 32000,
1304 1.1.2.2 skrll 65535
1305 1.1.2.2 skrll };
1306 1.1.2.2 skrll
1307 1.1.2.2 skrll
1308 1.1.2.2 skrll static u_int32_t
1309 1.1.2.2 skrll sctp_getnext_mtu(struct sctp_inpcb *inp, u_int32_t cur_mtu)
1310 1.1.2.2 skrll {
1311 1.1.2.2 skrll /* select another MTU that is just bigger than this one */
1312 1.1.2.2 skrll int i;
1313 1.1.2.2 skrll
1314 1.1.2.2 skrll for (i = 0; i < SCTP_NUMBER_OF_MTU_SIZES; i++) {
1315 1.1.2.2 skrll if (cur_mtu < mtu_sizes[i]) {
1316 1.1.2.2 skrll /* no max_mtu is bigger than this one */
1317 1.1.2.2 skrll return (mtu_sizes[i]);
1318 1.1.2.2 skrll }
1319 1.1.2.2 skrll }
1320 1.1.2.2 skrll /* here return the highest allowable */
1321 1.1.2.2 skrll return (cur_mtu);
1322 1.1.2.2 skrll }
1323 1.1.2.2 skrll
1324 1.1.2.2 skrll
1325 1.1.2.2 skrll void sctp_pathmtu_timer(struct sctp_inpcb *inp,
1326 1.1.2.2 skrll struct sctp_tcb *stcb,
1327 1.1.2.2 skrll struct sctp_nets *net)
1328 1.1.2.2 skrll {
1329 1.1.2.2 skrll u_int32_t next_mtu;
1330 1.1.2.2 skrll struct rtentry *rt;
1331 1.1.2.2 skrll
1332 1.1.2.2 skrll /* restart the timer in any case */
1333 1.1.2.2 skrll next_mtu = sctp_getnext_mtu(inp, net->mtu);
1334 1.1.2.2 skrll if (next_mtu <= net->mtu) {
1335 1.1.2.2 skrll /* nothing to do */
1336 1.1.2.2 skrll return;
1337 1.1.2.2 skrll }
1338 1.1.2.2 skrll rt = rtcache_validate(&net->ro);
1339 1.1.2.2 skrll if (rt != NULL) {
1340 1.1.2.2 skrll /* only if we have a route and interface do we
1341 1.1.2.2 skrll * set anything. Note we always restart
1342 1.1.2.2 skrll * the timer though just in case it is updated
1343 1.1.2.2 skrll * (i.e. the ifp) or route/ifp is populated.
1344 1.1.2.2 skrll */
1345 1.1.2.2 skrll if (rt->rt_ifp != NULL) {
1346 1.1.2.2 skrll if (rt->rt_ifp->if_mtu > next_mtu) {
1347 1.1.2.2 skrll /* ok it will fit out the door */
1348 1.1.2.2 skrll net->mtu = next_mtu;
1349 1.1.2.2 skrll }
1350 1.1.2.2 skrll }
1351 1.1.2.4 skrll rtcache_unref(rt, &net->ro);
1352 1.1.2.2 skrll }
1353 1.1.2.2 skrll /* restart the timer */
1354 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
1355 1.1.2.2 skrll }
1356 1.1.2.2 skrll
1357 1.1.2.2 skrll void sctp_autoclose_timer(struct sctp_inpcb *inp,
1358 1.1.2.2 skrll struct sctp_tcb *stcb,
1359 1.1.2.2 skrll struct sctp_nets *net)
1360 1.1.2.2 skrll {
1361 1.1.2.2 skrll struct timeval tn, *tim_touse;
1362 1.1.2.2 skrll struct sctp_association *asoc;
1363 1.1.2.2 skrll int ticks_gone_by;
1364 1.1.2.2 skrll
1365 1.1.2.2 skrll SCTP_GETTIME_TIMEVAL(&tn);
1366 1.1.2.2 skrll if (stcb->asoc.sctp_autoclose_ticks &&
1367 1.1.2.2 skrll (inp->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
1368 1.1.2.2 skrll /* Auto close is on */
1369 1.1.2.2 skrll asoc = &stcb->asoc;
1370 1.1.2.2 skrll /* pick the time to use */
1371 1.1.2.2 skrll if (asoc->time_last_rcvd.tv_sec >
1372 1.1.2.2 skrll asoc->time_last_sent.tv_sec) {
1373 1.1.2.2 skrll tim_touse = &asoc->time_last_rcvd;
1374 1.1.2.2 skrll } else {
1375 1.1.2.2 skrll tim_touse = &asoc->time_last_sent;
1376 1.1.2.2 skrll }
1377 1.1.2.2 skrll /* Now has long enough transpired to autoclose? */
1378 1.1.2.2 skrll ticks_gone_by = ((tn.tv_sec - tim_touse->tv_sec) * hz);
1379 1.1.2.2 skrll if ((ticks_gone_by > 0) &&
1380 1.1.2.2 skrll (ticks_gone_by >= (int)asoc->sctp_autoclose_ticks)) {
1381 1.1.2.2 skrll /*
1382 1.1.2.2 skrll * autoclose time has hit, call the output routine,
1383 1.1.2.2 skrll * which should do nothing just to be SURE we don't
1384 1.1.2.2 skrll * have hanging data. We can then safely check the
1385 1.1.2.2 skrll * queues and know that we are clear to send shutdown
1386 1.1.2.2 skrll */
1387 1.1.2.2 skrll sctp_chunk_output(inp, stcb, 9);
1388 1.1.2.2 skrll /* Are we clean? */
1389 1.1.2.2 skrll if (TAILQ_EMPTY(&asoc->send_queue) &&
1390 1.1.2.2 skrll TAILQ_EMPTY(&asoc->sent_queue)) {
1391 1.1.2.2 skrll /*
1392 1.1.2.2 skrll * there is nothing queued to send,
1393 1.1.2.2 skrll * so I'm done...
1394 1.1.2.2 skrll */
1395 1.1.2.2 skrll if (SCTP_GET_STATE(asoc) !=
1396 1.1.2.2 skrll SCTP_STATE_SHUTDOWN_SENT) {
1397 1.1.2.2 skrll /* only send SHUTDOWN 1st time thru */
1398 1.1.2.2 skrll #ifdef SCTP_DEBUG
1399 1.1.2.2 skrll if (sctp_debug_on & SCTP_DEBUG_OUTPUT4) {
1400 1.1.2.2 skrll printf("%s:%d sends a shutdown\n",
1401 1.1.2.2 skrll __FILE__,
1402 1.1.2.2 skrll __LINE__
1403 1.1.2.2 skrll );
1404 1.1.2.2 skrll }
1405 1.1.2.2 skrll #endif
1406 1.1.2.2 skrll sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
1407 1.1.2.2 skrll asoc->state = SCTP_STATE_SHUTDOWN_SENT;
1408 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1409 1.1.2.2 skrll stcb->sctp_ep, stcb,
1410 1.1.2.2 skrll asoc->primary_destination);
1411 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1412 1.1.2.2 skrll stcb->sctp_ep, stcb,
1413 1.1.2.2 skrll asoc->primary_destination);
1414 1.1.2.2 skrll }
1415 1.1.2.2 skrll }
1416 1.1.2.2 skrll } else {
1417 1.1.2.2 skrll /*
1418 1.1.2.2 skrll * No auto close at this time, reset t-o to
1419 1.1.2.2 skrll * check later
1420 1.1.2.2 skrll */
1421 1.1.2.2 skrll int tmp;
1422 1.1.2.2 skrll /* fool the timer startup to use the time left */
1423 1.1.2.2 skrll tmp = asoc->sctp_autoclose_ticks;
1424 1.1.2.2 skrll asoc->sctp_autoclose_ticks -= ticks_gone_by;
1425 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb,
1426 1.1.2.2 skrll net);
1427 1.1.2.2 skrll /* restore the real tick value */
1428 1.1.2.2 skrll asoc->sctp_autoclose_ticks = tmp;
1429 1.1.2.2 skrll }
1430 1.1.2.2 skrll }
1431 1.1.2.2 skrll }
1432 1.1.2.2 skrll
1433 1.1.2.2 skrll void
1434 1.1.2.2 skrll sctp_iterator_timer(struct sctp_iterator *it)
1435 1.1.2.2 skrll {
1436 1.1.2.2 skrll int cnt= 0;
1437 1.1.2.2 skrll /* only one iterator can run at a
1438 1.1.2.2 skrll * time. This is the only way we
1439 1.1.2.2 skrll * can cleanly pull ep's from underneath
1440 1.1.2.2 skrll * all the running interators when a
1441 1.1.2.2 skrll * ep is freed.
1442 1.1.2.2 skrll */
1443 1.1.2.2 skrll SCTP_ITERATOR_LOCK();
1444 1.1.2.2 skrll if (it->inp == NULL) {
1445 1.1.2.2 skrll /* iterator is complete */
1446 1.1.2.2 skrll done_with_iterator:
1447 1.1.2.2 skrll SCTP_ITERATOR_UNLOCK();
1448 1.1.2.2 skrll SCTP_INP_INFO_WLOCK();
1449 1.1.2.2 skrll LIST_REMOVE(it, sctp_nxt_itr);
1450 1.1.2.2 skrll /* stopping the callout is not needed, in theory,
1451 1.1.2.2 skrll * but I am paranoid.
1452 1.1.2.2 skrll */
1453 1.1.2.2 skrll SCTP_INP_INFO_WUNLOCK();
1454 1.1.2.2 skrll callout_stop(&it->tmr.timer);
1455 1.1.2.2 skrll if (it->function_atend != NULL) {
1456 1.1.2.2 skrll (*it->function_atend)(it->pointer, it->val);
1457 1.1.2.2 skrll }
1458 1.1.2.2 skrll callout_destroy(&it->tmr.timer);
1459 1.1.2.2 skrll free(it, M_PCB);
1460 1.1.2.2 skrll return;
1461 1.1.2.2 skrll }
1462 1.1.2.2 skrll select_a_new_ep:
1463 1.1.2.2 skrll SCTP_INP_WLOCK(it->inp);
1464 1.1.2.2 skrll while ((it->pcb_flags) && ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) {
1465 1.1.2.2 skrll /* we do not like this ep */
1466 1.1.2.2 skrll if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1467 1.1.2.2 skrll SCTP_INP_WUNLOCK(it->inp);
1468 1.1.2.2 skrll goto done_with_iterator;
1469 1.1.2.2 skrll }
1470 1.1.2.2 skrll SCTP_INP_WUNLOCK(it->inp);
1471 1.1.2.2 skrll it->inp = LIST_NEXT(it->inp, sctp_list);
1472 1.1.2.2 skrll if (it->inp == NULL) {
1473 1.1.2.2 skrll goto done_with_iterator;
1474 1.1.2.2 skrll }
1475 1.1.2.2 skrll SCTP_INP_WLOCK(it->inp);
1476 1.1.2.2 skrll }
1477 1.1.2.2 skrll if ((it->inp->inp_starting_point_for_iterator != NULL) &&
1478 1.1.2.2 skrll (it->inp->inp_starting_point_for_iterator != it)) {
1479 1.1.2.2 skrll printf("Iterator collision, we must wait for other iterator at %p\n",
1480 1.1.2.2 skrll it->inp);
1481 1.1.2.2 skrll SCTP_INP_WUNLOCK(it->inp);
1482 1.1.2.2 skrll goto start_timer_return;
1483 1.1.2.2 skrll }
1484 1.1.2.2 skrll /* now we do the actual write to this guy */
1485 1.1.2.2 skrll it->inp->inp_starting_point_for_iterator = it;
1486 1.1.2.2 skrll SCTP_INP_WUNLOCK(it->inp);
1487 1.1.2.2 skrll SCTP_INP_RLOCK(it->inp);
1488 1.1.2.2 skrll /* if we reach here we found a inp acceptable, now through each
1489 1.1.2.2 skrll * one that has the association in the right state
1490 1.1.2.2 skrll */
1491 1.1.2.2 skrll if (it->stcb == NULL) {
1492 1.1.2.2 skrll it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
1493 1.1.2.2 skrll }
1494 1.1.2.2 skrll if (it->stcb->asoc.stcb_starting_point_for_iterator == it) {
1495 1.1.2.2 skrll it->stcb->asoc.stcb_starting_point_for_iterator = NULL;
1496 1.1.2.2 skrll }
1497 1.1.2.2 skrll while (it->stcb) {
1498 1.1.2.2 skrll SCTP_TCB_LOCK(it->stcb);
1499 1.1.2.2 skrll if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
1500 1.1.2.2 skrll SCTP_TCB_UNLOCK(it->stcb);
1501 1.1.2.2 skrll it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
1502 1.1.2.2 skrll continue;
1503 1.1.2.2 skrll }
1504 1.1.2.2 skrll cnt++;
1505 1.1.2.2 skrll /* run function on this one */
1506 1.1.2.2 skrll SCTP_INP_RUNLOCK(it->inp);
1507 1.1.2.2 skrll (*it->function_toapply)(it->inp, it->stcb, it->pointer, it->val);
1508 1.1.2.2 skrll sctp_chunk_output(it->inp, it->stcb, 1);
1509 1.1.2.2 skrll SCTP_TCB_UNLOCK(it->stcb);
1510 1.1.2.2 skrll /* see if we have limited out */
1511 1.1.2.2 skrll if (cnt > SCTP_MAX_ITERATOR_AT_ONCE) {
1512 1.1.2.2 skrll it->stcb->asoc.stcb_starting_point_for_iterator = it;
1513 1.1.2.2 skrll start_timer_return:
1514 1.1.2.2 skrll SCTP_ITERATOR_UNLOCK();
1515 1.1.2.2 skrll sctp_timer_start(SCTP_TIMER_TYPE_ITERATOR, (struct sctp_inpcb *)it, NULL, NULL);
1516 1.1.2.2 skrll return;
1517 1.1.2.2 skrll }
1518 1.1.2.2 skrll SCTP_INP_RLOCK(it->inp);
1519 1.1.2.2 skrll it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
1520 1.1.2.2 skrll }
1521 1.1.2.2 skrll /* if we reach here, we ran out of stcb's in the inp we are looking at */
1522 1.1.2.2 skrll SCTP_INP_RUNLOCK(it->inp);
1523 1.1.2.2 skrll SCTP_INP_WLOCK(it->inp);
1524 1.1.2.2 skrll it->inp->inp_starting_point_for_iterator = NULL;
1525 1.1.2.2 skrll SCTP_INP_WUNLOCK(it->inp);
1526 1.1.2.2 skrll if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1527 1.1.2.2 skrll it->inp = NULL;
1528 1.1.2.2 skrll } else {
1529 1.1.2.2 skrll SCTP_INP_INFO_RLOCK();
1530 1.1.2.2 skrll it->inp = LIST_NEXT(it->inp, sctp_list);
1531 1.1.2.2 skrll SCTP_INP_INFO_RUNLOCK();
1532 1.1.2.2 skrll }
1533 1.1.2.2 skrll if (it->inp == NULL) {
1534 1.1.2.2 skrll goto done_with_iterator;
1535 1.1.2.2 skrll }
1536 1.1.2.2 skrll goto select_a_new_ep;
1537 1.1.2.2 skrll }
1538