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 $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/sscop_timer.c,v 1.2 2003/06/17 04:28:49 dillon 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>
47 static void sscop_poll_expire __P((struct sscop *));
48 static void sscop_noresponse_expire __P((struct sscop *));
49 static void sscop_cc_expire __P((struct sscop *));
50 static void sscop_idle_expire __P((struct sscop *));
55 static void (*sscop_expired[SSCOP_T_NUM]) __P((struct sscop *)) = {
57 sscop_noresponse_expire,
64 * Process an SSCOP timer tick
66 * This function is called SSCOP_HZ times a second in order to update
67 * all of the sscop connection timers. The sscop expiration function
68 * will be called to process all timer expirations.
73 * tip pointer to sscop timer control block
83 struct sscop *sop, **sprev;
88 * Schedule next timeout
90 atm_timeout(&sscop_timer, ATM_HZ/SSCOP_HZ, sscop_timeout);
93 * Run through all connections, updating each active timer.
94 * If an expired timer is found, notify that entry.
97 while ((sop = *sprev) != NULL) {
100 * Check out each timer
102 for (i =0; i < SSCOP_T_NUM; i++) {
105 * Decrement timer if it's active
107 if (sop->so_timer[i] && (--sop->so_timer[i] == 0)) {
111 static char *tn[] = {
117 ATM_DEBUG3("sscop_timer: %s expired, sop=%p, state=%d\n",
118 tn[i], sop, sop->so_state);
123 * Expired timer - process it
125 (*sscop_expired[i])(sop);
128 * Make sure connection still exists
136 * Update previous pointer if current control
137 * block wasn't deleted
140 sprev = &sop->so_next;
146 * Process an SSCOP Timer_POLL expiration
149 * sop pointer to sscop connection control block
156 sscop_poll_expire(sop)
161 * Validate current state
163 if ((sop->so_state != SOS_READY) &&
164 ((sop->so_state != SOS_INRESYN) ||
165 (sop->so_vers != SSCOP_VERS_QSAAL))) {
166 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
167 "Timer_POLL", sop, sop->so_state);
172 * Send next poll along its way
174 SEQ_INCR(sop->so_pollsend, 1);
175 (void) sscop_send_poll(sop);
178 * Reset data counter for this poll cycle
180 sop->so_polldata = 0;
183 * Reset polling timer
192 * Process an SSCOP Timer_IDLE expiration
195 * sop pointer to sscop connection control block
202 sscop_idle_expire(sop)
207 * Timer_IDLE only valid in READY state
209 if (sop->so_state != SOS_READY) {
210 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
211 "Timer_IDLE", sop, sop->so_state);
216 * Send next poll along its way
218 SEQ_INCR(sop->so_pollsend, 1);
219 (void) sscop_send_poll(sop);
222 * Reset data counter for this poll cycle
224 sop->so_polldata = 0;
227 * Start NO-RESPONSE timer
229 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
232 * Reset polling timer
241 * Process an SSCOP Timer_NORESPONSE expiration
244 * sop pointer to sscop connection control block
251 sscop_noresponse_expire(sop)
257 * Validate current state
259 if ((sop->so_state != SOS_READY) &&
260 ((sop->so_state != SOS_INRESYN) ||
261 (sop->so_vers != SSCOP_VERS_QSAAL))) {
262 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
263 "Timer_NORESPONSE", sop, sop->so_state);
268 * Peer seems to be dead, so terminate session
270 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
271 sop->so_toku, sop->so_connvc,
272 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
277 sop->so_timer[SSCOP_T_NORESP] = 1;
282 * Stop data transfer timers
284 sop->so_timer[SSCOP_T_POLL] = 0;
285 sop->so_timer[SSCOP_T_IDLE] = 0;
286 sop->so_flags &= ~SOF_KEEPALIVE;
289 * Notify peer of termination
291 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
294 * Report peer's failure
296 sscop_maa_error(sop, 'P');
298 if (sop->so_vers == SSCOP_VERS_QSAAL)
300 * Clear connection data
302 qsaal1_clear_connection(sop);
305 * Clear out appropriate queues
307 q2110_prep_retrieve(sop);
310 * Return to IDLE state
312 sop->so_state = SOS_IDLE;
319 * Process an SSCOP Timer_CC expiration
322 * sop pointer to sscop connection control block
335 * Process timeout based on protocol state
337 switch (sop->so_state) {
341 * No response to our BGN yet
343 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
346 * Send another BGN PDU
349 (void) sscop_send_bgn(sop, SSCOP_SOURCE_USER);
352 * Restart retransmit timer
354 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
359 * Retransmit limit exceeded, terminate session
361 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
362 sop->so_toku, sop->so_connvc,
363 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
368 sop->so_timer[SSCOP_T_CC] = 1;
373 * Notify peer of termination
375 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
378 * Report establishment failure
380 sscop_maa_error(sop, 'O');
383 * Clear reestablishment flag
385 sop->so_flags &= ~SOF_REESTAB;
388 * Return to IDLE state
390 sop->so_state = SOS_IDLE;
396 * No response to our END yet
398 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
401 * Send another END PDU
404 (void) sscop_send_end(sop, SSCOP_SOURCE_LAST);
407 * Restart retransmit timer
409 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
414 * Retransmit limit exceeded, force session termination
416 STACK_CALL(SSCOP_RELEASE_CNF, sop->so_upper,
417 sop->so_toku, sop->so_connvc, 0, 0, err);
422 sop->so_timer[SSCOP_T_CC] = 1;
427 * Report establishment failure
429 sscop_maa_error(sop, 'O');
432 * Return to IDLE state
434 sop->so_state = SOS_IDLE;
441 * No response to our RS yet
443 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
446 * Send another RS PDU
449 (void) sscop_send_rs(sop);
452 * Restart retransmit timer
454 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
459 * Retransmit limit exceeded, terminate session
461 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
462 sop->so_toku, sop->so_connvc,
463 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
468 sop->so_timer[SSCOP_T_CC] = 1;
473 * Notify peer of termination
475 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
478 * Report establishment failure
480 sscop_maa_error(sop, 'O');
482 if (sop->so_vers == SSCOP_VERS_QSAAL)
484 * Clear connection data
486 qsaal1_clear_connection(sop);
489 * Return to IDLE state
491 sop->so_state = SOS_IDLE;
495 case SOS_CONRESYN: /* Q.SAAL1 */
496 #if (SOS_OUTRECOV != SOS_CONRESYN)
497 case SOS_OUTRECOV: /* Q.2110 */
499 if (sop->so_vers == SSCOP_VERS_QSAAL) {
501 * Handle timeout for SOS_CONRESYN
507 * Handle timeout for SOS_OUTRECOV
511 * No response to our ER yet
513 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
516 * Send another ER PDU
519 (void) sscop_send_er(sop);
522 * Restart retransmit timer
524 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
529 * Retransmit limit exceeded, terminate session
531 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
532 sop->so_toku, sop->so_connvc,
533 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
538 sop->so_timer[SSCOP_T_CC] = 1;
543 * Notify peer of termination
545 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
548 * Report establishment failure
550 sscop_maa_error(sop, 'O');
553 * Clear receiver buffer
555 sscop_rcvr_drain(sop);
558 * Return to IDLE state
560 sop->so_state = SOS_IDLE;
565 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
566 "Timer_CC", sop, sop->so_state);