3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/uni/sscop_timer.c,v 1.6 2000/01/17 20:49:53 mks Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * SSCOP - Timer processing
38 #include <netatm/kern_include.h>
40 #include <netatm/uni/sscop.h>
41 #include <netatm/uni/sscop_misc.h>
42 #include <netatm/uni/sscop_var.h>
45 __RCSID("@(#) $FreeBSD: src/sys/netatm/uni/sscop_timer.c,v 1.6 2000/01/17 20:49:53 mks Exp $");
52 static void sscop_poll_expire __P((struct sscop *));
53 static void sscop_noresponse_expire __P((struct sscop *));
54 static void sscop_cc_expire __P((struct sscop *));
55 static void sscop_idle_expire __P((struct sscop *));
60 static void (*sscop_expired[SSCOP_T_NUM]) __P((struct sscop *)) = {
62 sscop_noresponse_expire,
69 * Process an SSCOP timer tick
71 * This function is called SSCOP_HZ times a second in order to update
72 * all of the sscop connection timers. The sscop expiration function
73 * will be called to process all timer expirations.
78 * tip pointer to sscop timer control block
88 struct sscop *sop, **sprev;
93 * Schedule next timeout
95 atm_timeout(&sscop_timer, ATM_HZ/SSCOP_HZ, sscop_timeout);
98 * Run through all connections, updating each active timer.
99 * If an expired timer is found, notify that entry.
102 while ((sop = *sprev) != NULL) {
105 * Check out each timer
107 for (i =0; i < SSCOP_T_NUM; i++) {
110 * Decrement timer if it's active
112 if (sop->so_timer[i] && (--sop->so_timer[i] == 0)) {
116 static char *tn[] = {
122 ATM_DEBUG3("sscop_timer: %s expired, sop=%p, state=%d\n",
123 tn[i], sop, sop->so_state);
128 * Expired timer - process it
130 (*sscop_expired[i])(sop);
133 * Make sure connection still exists
141 * Update previous pointer if current control
142 * block wasn't deleted
145 sprev = &sop->so_next;
151 * Process an SSCOP Timer_POLL expiration
154 * sop pointer to sscop connection control block
161 sscop_poll_expire(sop)
166 * Validate current state
168 if ((sop->so_state != SOS_READY) &&
169 ((sop->so_state != SOS_INRESYN) ||
170 (sop->so_vers != SSCOP_VERS_QSAAL))) {
171 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
172 "Timer_POLL", sop, sop->so_state);
177 * Send next poll along its way
179 SEQ_INCR(sop->so_pollsend, 1);
180 (void) sscop_send_poll(sop);
183 * Reset data counter for this poll cycle
185 sop->so_polldata = 0;
188 * Reset polling timer
197 * Process an SSCOP Timer_IDLE expiration
200 * sop pointer to sscop connection control block
207 sscop_idle_expire(sop)
212 * Timer_IDLE only valid in READY state
214 if (sop->so_state != SOS_READY) {
215 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
216 "Timer_IDLE", sop, sop->so_state);
221 * Send next poll along its way
223 SEQ_INCR(sop->so_pollsend, 1);
224 (void) sscop_send_poll(sop);
227 * Reset data counter for this poll cycle
229 sop->so_polldata = 0;
232 * Start NO-RESPONSE timer
234 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
237 * Reset polling timer
246 * Process an SSCOP Timer_NORESPONSE expiration
249 * sop pointer to sscop connection control block
256 sscop_noresponse_expire(sop)
262 * Validate current state
264 if ((sop->so_state != SOS_READY) &&
265 ((sop->so_state != SOS_INRESYN) ||
266 (sop->so_vers != SSCOP_VERS_QSAAL))) {
267 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
268 "Timer_NORESPONSE", sop, sop->so_state);
273 * Peer seems to be dead, so terminate session
275 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
276 sop->so_toku, sop->so_connvc,
277 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
282 sop->so_timer[SSCOP_T_NORESP] = 1;
287 * Stop data transfer timers
289 sop->so_timer[SSCOP_T_POLL] = 0;
290 sop->so_timer[SSCOP_T_IDLE] = 0;
291 sop->so_flags &= ~SOF_KEEPALIVE;
294 * Notify peer of termination
296 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
299 * Report peer's failure
301 sscop_maa_error(sop, 'P');
303 if (sop->so_vers == SSCOP_VERS_QSAAL)
305 * Clear connection data
307 qsaal1_clear_connection(sop);
310 * Clear out appropriate queues
312 q2110_prep_retrieve(sop);
315 * Return to IDLE state
317 sop->so_state = SOS_IDLE;
324 * Process an SSCOP Timer_CC expiration
327 * sop pointer to sscop connection control block
340 * Process timeout based on protocol state
342 switch (sop->so_state) {
346 * No response to our BGN yet
348 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
351 * Send another BGN PDU
354 (void) sscop_send_bgn(sop, SSCOP_SOURCE_USER);
357 * Restart retransmit timer
359 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
364 * Retransmit limit exceeded, terminate session
366 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
367 sop->so_toku, sop->so_connvc,
368 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
373 sop->so_timer[SSCOP_T_CC] = 1;
378 * Notify peer of termination
380 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
383 * Report establishment failure
385 sscop_maa_error(sop, 'O');
388 * Clear reestablishment flag
390 sop->so_flags &= ~SOF_REESTAB;
393 * Return to IDLE state
395 sop->so_state = SOS_IDLE;
401 * No response to our END yet
403 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
406 * Send another END PDU
409 (void) sscop_send_end(sop, SSCOP_SOURCE_LAST);
412 * Restart retransmit timer
414 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
419 * Retransmit limit exceeded, force session termination
421 STACK_CALL(SSCOP_RELEASE_CNF, sop->so_upper,
422 sop->so_toku, sop->so_connvc, 0, 0, err);
427 sop->so_timer[SSCOP_T_CC] = 1;
432 * Report establishment failure
434 sscop_maa_error(sop, 'O');
437 * Return to IDLE state
439 sop->so_state = SOS_IDLE;
446 * No response to our RS yet
448 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
451 * Send another RS PDU
454 (void) sscop_send_rs(sop);
457 * Restart retransmit timer
459 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
464 * Retransmit limit exceeded, terminate session
466 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
467 sop->so_toku, sop->so_connvc,
468 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
473 sop->so_timer[SSCOP_T_CC] = 1;
478 * Notify peer of termination
480 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
483 * Report establishment failure
485 sscop_maa_error(sop, 'O');
487 if (sop->so_vers == SSCOP_VERS_QSAAL)
489 * Clear connection data
491 qsaal1_clear_connection(sop);
494 * Return to IDLE state
496 sop->so_state = SOS_IDLE;
500 case SOS_CONRESYN: /* Q.SAAL1 */
501 #if (SOS_OUTRECOV != SOS_CONRESYN)
502 case SOS_OUTRECOV: /* Q.2110 */
504 if (sop->so_vers == SSCOP_VERS_QSAAL) {
506 * Handle timeout for SOS_CONRESYN
512 * Handle timeout for SOS_OUTRECOV
516 * No response to our ER yet
518 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
521 * Send another ER PDU
524 (void) sscop_send_er(sop);
527 * Restart retransmit timer
529 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
534 * Retransmit limit exceeded, terminate session
536 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
537 sop->so_toku, sop->so_connvc,
538 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
543 sop->so_timer[SSCOP_T_CC] = 1;
548 * Notify peer of termination
550 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
553 * Report establishment failure
555 sscop_maa_error(sop, 'O');
558 * Clear receiver buffer
560 sscop_rcvr_drain(sop);
563 * Return to IDLE state
565 sop->so_state = SOS_IDLE;
570 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
571 "Timer_CC", sop, sop->so_state);