2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
7 * This Host ATM Research Platform ("HARP") file (the "Software") is
8 * made available by Network Computing Services, Inc. ("NetworkCS")
9 * "AS IS". NetworkCS does not provide maintenance, improvements or
10 * support of any kind.
12 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
13 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
14 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
15 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
16 * In no event shall NetworkCS be responsible for any damages, including
17 * but not limited to consequential damages, arising from or relating to
18 * any use of the Software or related support.
20 * Copyright 1994-1998 Network Computing Services, Inc.
22 * Copies of this Software may be made, however, the above copyright
23 * notice must be reproduced on all copies.
27 * ATM Forum UNI Support
28 * ---------------------
30 * SSCOP - Timer processing
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42 #include <sys/syslog.h>
44 #include <netatm/port.h>
45 #include <netatm/queue.h>
46 #include <netatm/atm.h>
47 #include <netatm/atm_sys.h>
48 #include <netatm/atm_sap.h>
49 #include <netatm/atm_cm.h>
50 #include <netatm/atm_if.h>
51 #include <netatm/atm_stack.h>
52 #include <netatm/atm_pcb.h>
53 #include <netatm/atm_var.h>
55 #include <netatm/uni/sscop.h>
56 #include <netatm/uni/sscop_misc.h>
57 #include <netatm/uni/sscop_var.h>
62 static void sscop_poll_expire(struct sscop *);
63 static void sscop_noresponse_expire(struct sscop *);
64 static void sscop_cc_expire(struct sscop *);
65 static void sscop_idle_expire(struct sscop *);
70 static void (*sscop_expired[SSCOP_T_NUM])(struct sscop *) = {
72 sscop_noresponse_expire,
79 * Process an SSCOP timer tick
81 * This function is called SSCOP_HZ times a second in order to update
82 * all of the sscop connection timers. The sscop expiration function
83 * will be called to process all timer expirations.
88 * tip pointer to sscop timer control block
98 struct sscop *sop, **sprev;
103 * Schedule next timeout
105 atm_timeout(&sscop_timer, ATM_HZ/SSCOP_HZ, sscop_timeout);
108 * Run through all connections, updating each active timer.
109 * If an expired timer is found, notify that entry.
112 while ((sop = *sprev) != NULL) {
115 * Check out each timer
117 for (i =0; i < SSCOP_T_NUM; i++) {
120 * Decrement timer if it's active
122 if (sop->so_timer[i] && (--sop->so_timer[i] == 0)) {
126 static char *tn[] = {
132 ATM_DEBUG3("sscop_timer: %s expired, sop=%p, state=%d\n",
133 tn[i], sop, sop->so_state);
138 * Expired timer - process it
140 (*sscop_expired[i])(sop);
143 * Make sure connection still exists
151 * Update previous pointer if current control
152 * block wasn't deleted
155 sprev = &sop->so_next;
161 * Process an SSCOP Timer_POLL expiration
164 * sop pointer to sscop connection control block
171 sscop_poll_expire(sop)
176 * Validate current state
178 if ((sop->so_state != SOS_READY) &&
179 ((sop->so_state != SOS_INRESYN) ||
180 (sop->so_vers != SSCOP_VERS_QSAAL))) {
181 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
182 "Timer_POLL", sop, sop->so_state);
187 * Send next poll along its way
189 SEQ_INCR(sop->so_pollsend, 1);
190 (void) sscop_send_poll(sop);
193 * Reset data counter for this poll cycle
195 sop->so_polldata = 0;
198 * Reset polling timer
207 * Process an SSCOP Timer_IDLE expiration
210 * sop pointer to sscop connection control block
217 sscop_idle_expire(sop)
222 * Timer_IDLE only valid in READY state
224 if (sop->so_state != SOS_READY) {
225 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
226 "Timer_IDLE", sop, sop->so_state);
231 * Send next poll along its way
233 SEQ_INCR(sop->so_pollsend, 1);
234 (void) sscop_send_poll(sop);
237 * Reset data counter for this poll cycle
239 sop->so_polldata = 0;
242 * Start NO-RESPONSE timer
244 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
247 * Reset polling timer
256 * Process an SSCOP Timer_NORESPONSE expiration
259 * sop pointer to sscop connection control block
266 sscop_noresponse_expire(sop)
272 * Validate current state
274 if ((sop->so_state != SOS_READY) &&
275 ((sop->so_state != SOS_INRESYN) ||
276 (sop->so_vers != SSCOP_VERS_QSAAL))) {
277 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
278 "Timer_NORESPONSE", sop, sop->so_state);
283 * Peer seems to be dead, so terminate session
285 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
286 sop->so_toku, sop->so_connvc,
287 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
292 sop->so_timer[SSCOP_T_NORESP] = 1;
297 * Stop data transfer timers
299 sop->so_timer[SSCOP_T_POLL] = 0;
300 sop->so_timer[SSCOP_T_IDLE] = 0;
301 sop->so_flags &= ~SOF_KEEPALIVE;
304 * Notify peer of termination
306 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
309 * Report peer's failure
311 sscop_maa_error(sop, 'P');
313 if (sop->so_vers == SSCOP_VERS_QSAAL)
315 * Clear connection data
317 qsaal1_clear_connection(sop);
320 * Clear out appropriate queues
322 q2110_prep_retrieve(sop);
325 * Return to IDLE state
327 sop->so_state = SOS_IDLE;
334 * Process an SSCOP Timer_CC expiration
337 * sop pointer to sscop connection control block
350 * Process timeout based on protocol state
352 switch (sop->so_state) {
356 * No response to our BGN yet
358 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
361 * Send another BGN PDU
364 (void) sscop_send_bgn(sop, SSCOP_SOURCE_USER);
367 * Restart retransmit timer
369 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
374 * Retransmit limit exceeded, terminate session
376 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
377 sop->so_toku, sop->so_connvc,
378 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
383 sop->so_timer[SSCOP_T_CC] = 1;
388 * Notify peer of termination
390 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
393 * Report establishment failure
395 sscop_maa_error(sop, 'O');
398 * Clear reestablishment flag
400 sop->so_flags &= ~SOF_REESTAB;
403 * Return to IDLE state
405 sop->so_state = SOS_IDLE;
411 * No response to our END yet
413 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
416 * Send another END PDU
419 (void) sscop_send_end(sop, SSCOP_SOURCE_LAST);
422 * Restart retransmit timer
424 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
429 * Retransmit limit exceeded, force session termination
431 STACK_CALL(SSCOP_RELEASE_CNF, sop->so_upper,
432 sop->so_toku, sop->so_connvc, 0, 0, err);
437 sop->so_timer[SSCOP_T_CC] = 1;
442 * Report establishment failure
444 sscop_maa_error(sop, 'O');
447 * Return to IDLE state
449 sop->so_state = SOS_IDLE;
456 * No response to our RS yet
458 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
461 * Send another RS PDU
464 (void) sscop_send_rs(sop);
467 * Restart retransmit timer
469 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
474 * Retransmit limit exceeded, terminate session
476 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
477 sop->so_toku, sop->so_connvc,
478 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
483 sop->so_timer[SSCOP_T_CC] = 1;
488 * Notify peer of termination
490 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
493 * Report establishment failure
495 sscop_maa_error(sop, 'O');
497 if (sop->so_vers == SSCOP_VERS_QSAAL)
499 * Clear connection data
501 qsaal1_clear_connection(sop);
504 * Return to IDLE state
506 sop->so_state = SOS_IDLE;
510 case SOS_CONRESYN: /* Q.SAAL1 */
511 #if (SOS_OUTRECOV != SOS_CONRESYN)
512 case SOS_OUTRECOV: /* Q.2110 */
514 if (sop->so_vers == SSCOP_VERS_QSAAL) {
516 * Handle timeout for SOS_CONRESYN
522 * Handle timeout for SOS_OUTRECOV
526 * No response to our ER yet
528 if (sop->so_connctl < sop->so_parm.sp_maxcc) {
531 * Send another ER PDU
534 (void) sscop_send_er(sop);
537 * Restart retransmit timer
539 sop->so_timer[SSCOP_T_CC] = sop->so_parm.sp_timecc;
544 * Retransmit limit exceeded, terminate session
546 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper,
547 sop->so_toku, sop->so_connvc,
548 SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
553 sop->so_timer[SSCOP_T_CC] = 1;
558 * Notify peer of termination
560 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
563 * Report establishment failure
565 sscop_maa_error(sop, 'O');
568 * Clear receiver buffer
570 sscop_rcvr_drain(sop);
573 * Return to IDLE state
575 sop->so_state = SOS_IDLE;
580 log(LOG_ERR, "sscop: invalid %s state: sop=%p, state=%d\n",
581 "Timer_CC", sop, sop->so_state);