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.6 2006/01/14 13:36:39 swildner Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * SSCOP - Timer processing
38 #include <netproto/atm/kern_include.h>
41 #include "sscop_misc.h"
42 #include "sscop_var.h"
47 static void sscop_poll_expire (struct sscop *);
48 static void sscop_noresponse_expire (struct sscop *);
49 static void sscop_cc_expire (struct sscop *);
50 static void sscop_idle_expire (struct sscop *);
55 static void (*sscop_expired[SSCOP_T_NUM]) (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
80 sscop_timeout(struct atm_time *tip)
82 struct sscop *sop, **sprev;
87 * Schedule next timeout
89 atm_timeout(&sscop_timer, ATM_HZ/SSCOP_HZ, sscop_timeout);
92 * Run through all connections, updating each active timer.
93 * If an expired timer is found, notify that entry.
96 while ((sop = *sprev) != NULL) {
99 * Check out each timer
101 for (i =0; i < SSCOP_T_NUM; i++) {
104 * Decrement timer if it's active
106 if (sop->so_timer[i] && (--sop->so_timer[i] == 0)) {
110 static char *tn[] = {
116 ATM_DEBUG3("sscop_timer: %s expired, sop=%p, state=%d\n",
117 tn[i], sop, sop->so_state);
122 * Expired timer - process it
124 (*sscop_expired[i])(sop);
127 * Make sure connection still exists
135 * Update previous pointer if current control
136 * block wasn't deleted
139 sprev = &sop->so_next;
145 * Process an SSCOP Timer_POLL expiration
148 * sop pointer to sscop connection control block
155 sscop_poll_expire(struct sscop *sop)
159 * Validate current state
161 if ((sop->so_state != SOS_READY) &&
162 ((sop->so_state != SOS_INRESYN) ||
163 (sop->so_vers != SSCOP_VERS_QSAAL))) {
164 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
165 "Timer_POLL", sop, sop->so_state);
170 * Send next poll along its way
172 SEQ_INCR(sop->so_pollsend, 1);
173 sscop_send_poll(sop);
176 * Reset data counter for this poll cycle
178 sop->so_polldata = 0;
181 * Reset polling timer
190 * Process an SSCOP Timer_IDLE expiration
193 * sop pointer to sscop connection control block
200 sscop_idle_expire(struct sscop *sop)
204 * Timer_IDLE only valid in READY state
206 if (sop->so_state != SOS_READY) {
207 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
208 "Timer_IDLE", sop, sop->so_state);
213 * Send next poll along its way
215 SEQ_INCR(sop->so_pollsend, 1);
216 sscop_send_poll(sop);
219 * Reset data counter for this poll cycle
221 sop->so_polldata = 0;
224 * Start NO-RESPONSE timer
226 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
229 * Reset polling timer
238 * Process an SSCOP Timer_NORESPONSE expiration
241 * sop pointer to sscop connection control block
248 sscop_noresponse_expire(struct sscop *sop)
253 * Validate current state
255 if ((sop->so_state != SOS_READY) &&
256 ((sop->so_state != SOS_INRESYN) ||
257 (sop->so_vers != SSCOP_VERS_QSAAL))) {
258 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
259 "Timer_NORESPONSE", sop, sop->so_state);
264 * Peer seems to be dead, so terminate session
266 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
267 sop->so_toku, sop->so_connvc,
268 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
273 sop->so_timer[SSCOP_T_NORESP] = 1;
278 * Stop data transfer timers
280 sop->so_timer[SSCOP_T_POLL] = 0;
281 sop->so_timer[SSCOP_T_IDLE] = 0;
282 sop->so_flags &= ~SOF_KEEPALIVE;
285 * Notify peer of termination
287 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
290 * Report peer's failure
292 sscop_maa_error(sop, 'P');
294 if (sop->so_vers == SSCOP_VERS_QSAAL)
296 * Clear connection data
298 qsaal1_clear_connection(sop);
301 * Clear out appropriate queues
303 q2110_prep_retrieve(sop);
306 * Return to IDLE state
308 sop->so_state = SOS_IDLE;
315 * Process an SSCOP Timer_CC expiration
318 * sop pointer to sscop connection control block
325 sscop_cc_expire(struct sscop *sop)
330 * Process timeout based on protocol state
332 switch (sop->so_state) {
336 * No response to our BGN yet
338 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
341 * Send another BGN PDU
344 sscop_send_bgn(sop, SSCOP_SOURCE_USER);
347 * Restart retransmit timer
349 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
354 * Retransmit limit exceeded, terminate session
356 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
357 sop->so_toku, sop->so_connvc,
358 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
363 sop->so_timer[SSCOP_T_CC] = 1;
368 * Notify peer of termination
370 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
373 * Report establishment failure
375 sscop_maa_error(sop, 'O');
378 * Clear reestablishment flag
380 sop->so_flags &= ~SOF_REESTAB;
383 * Return to IDLE state
385 sop->so_state = SOS_IDLE;
391 * No response to our END yet
393 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
396 * Send another END PDU
399 sscop_send_end(sop, SSCOP_SOURCE_LAST);
402 * Restart retransmit timer
404 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
409 * Retransmit limit exceeded, force session termination
411 STACK_CALL(SSCOP_RELEASE_CNF, sop->so_upper,
412 sop->so_toku, sop->so_connvc, 0, 0, err);
417 sop->so_timer[SSCOP_T_CC] = 1;
422 * Report establishment failure
424 sscop_maa_error(sop, 'O');
427 * Return to IDLE state
429 sop->so_state = SOS_IDLE;
436 * No response to our RS yet
438 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
441 * Send another RS PDU
447 * Restart retransmit timer
449 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
454 * Retransmit limit exceeded, terminate session
456 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
457 sop->so_toku, sop->so_connvc,
458 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
463 sop->so_timer[SSCOP_T_CC] = 1;
468 * Notify peer of termination
470 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
473 * Report establishment failure
475 sscop_maa_error(sop, 'O');
477 if (sop->so_vers == SSCOP_VERS_QSAAL)
479 * Clear connection data
481 qsaal1_clear_connection(sop);
484 * Return to IDLE state
486 sop->so_state = SOS_IDLE;
490 case SOS_CONRESYN: /* Q.SAAL1 */
491 #if (SOS_OUTRECOV != SOS_CONRESYN)
492 case SOS_OUTRECOV: /* Q.2110 */
494 if (sop->so_vers == SSCOP_VERS_QSAAL) {
496 * Handle timeout for SOS_CONRESYN
502 * Handle timeout for SOS_OUTRECOV
506 * No response to our ER yet
508 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
511 * Send another ER PDU
517 * Restart retransmit timer
519 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
524 * Retransmit limit exceeded, terminate session
526 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
527 sop->so_toku, sop->so_connvc,
528 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
533 sop->so_timer[SSCOP_T_CC] = 1;
538 * Notify peer of termination
540 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
543 * Report establishment failure
545 sscop_maa_error(sop, 'O');
548 * Clear receiver buffer
550 sscop_rcvr_drain(sop);
553 * Return to IDLE state
555 sop->so_state = SOS_IDLE;
560 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
561 "Timer_CC", sop, sop->so_state);