mxge: properly remove the sysctls
[dragonfly.git] / sys / net / i4b / layer4 / i4b_l4.c
blob4da5f765753e054b4435fedf3ea1b157e39ff37a
1 /*
2 * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
25 *---------------------------------------------------------------------------
27 * i4b_l4.c - kernel interface to userland
28 * -----------------------------------------
30 * $Id: i4b_l4.c,v 1.54 2000/08/28 07:24:59 hm Exp $
32 * $FreeBSD: src/sys/i4b/layer4/i4b_l4.c,v 1.6.2.2 2001/12/16 15:12:59 hm Exp $
33 * $DragonFly: src/sys/net/i4b/layer4/i4b_l4.c,v 1.7 2005/06/14 21:19:19 joerg Exp $
35 * last edit-date: [Sun Aug 27 14:53:42 2000]
37 *---------------------------------------------------------------------------*/
39 #include "use_i4b.h"
40 #include "use_i4bipr.h"
42 #if NI4B > 0
44 #include <sys/param.h>
45 #include <sys/kernel.h>
46 #include <sys/systm.h>
47 #include <sys/mbuf.h>
48 #include <sys/thread2.h>
50 #include "use_i4bing.h"
51 #include "use_i4bisppp.h"
52 #include "use_i4brbch.h"
53 #include "use_i4btel.h"
55 #include <net/i4b/include/machine/i4b_debug.h>
56 #include <net/i4b/include/machine/i4b_ioctl.h>
57 #include <net/i4b/include/machine/i4b_cause.h>
59 #include "../include/i4b_global.h"
60 #include "../include/i4b_l3l4.h"
61 #include "../include/i4b_mbuf.h"
62 #include "i4b_l4.h"
64 unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT;
66 struct ctrl_type_desc ctrl_types[CTRL_NUMTYPES] = { { NULL, NULL} };
68 static int i4b_link_bchandrvr(call_desc_t *cd);
69 static void i4b_unlink_bchandrvr(call_desc_t *cd);
70 static void i4b_l4_setup_timeout(call_desc_t *cd);
71 static void i4b_idle_check_fix_unit(call_desc_t *cd);
72 static void i4b_idle_check_var_unit(call_desc_t *cd);
73 static void i4b_l4_setup_timeout_fix_unit(call_desc_t *cd);
74 static void i4b_l4_setup_timeout_var_unit(call_desc_t *cd);
75 static time_t i4b_get_idletime(call_desc_t *cd);
76 #if NI4BISPPP > 0
77 extern time_t i4bisppp_idletime(int);
78 #endif
80 /*---------------------------------------------------------------------------*
81 * send MSG_PDEACT_IND message to userland
82 *---------------------------------------------------------------------------*/
83 void
84 i4b_l4_pdeact(int controller, int numactive)
86 struct mbuf *m;
87 int i;
88 call_desc_t *cd;
90 for(i=0; i < N_CALL_DESC; i++)
92 if((call_desc[i].cdid != CDID_UNUSED) &&
93 (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
94 (ctrl_desc[call_desc[i].controller].unit == controller))
96 cd = &call_desc[i];
98 if(cd->timeout_active)
100 callout_stop(&cd->idle_timeout);
103 if(cd->dlt != NULL)
105 (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd);
106 i4b_unlink_bchandrvr(cd);
109 if((cd->channelid >= 0) & (cd->channelid < ctrl_desc[cd->controller].nbch))
111 ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE;
114 cd->cdid = CDID_UNUSED;
118 if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL)
120 msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data;
122 md->header.type = MSG_PDEACT_IND;
123 md->header.cdid = -1;
125 md->controller = controller;
126 md->numactive = numactive;
128 i4bputqueue_hipri(m); /* URGENT !!! */
132 /*---------------------------------------------------------------------------*
133 * send MSG_L12STAT_IND message to userland
134 *---------------------------------------------------------------------------*/
135 void
136 i4b_l4_l12stat(int controller, int layer, int state)
138 struct mbuf *m;
140 if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL)
142 msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data;
144 md->header.type = MSG_L12STAT_IND;
145 md->header.cdid = -1;
147 md->controller = controller;
148 md->layer = layer;
149 md->state = state;
151 i4bputqueue(m);
155 /*---------------------------------------------------------------------------*
156 * send MSG_TEIASG_IND message to userland
157 *---------------------------------------------------------------------------*/
158 void
159 i4b_l4_teiasg(int controller, int tei)
161 struct mbuf *m;
163 if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL)
165 msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data;
167 md->header.type = MSG_TEIASG_IND;
168 md->header.cdid = -1;
170 md->controller = controller;
171 md->tei = ctrl_desc[controller].tei;
173 i4bputqueue(m);
177 /*---------------------------------------------------------------------------*
178 * send MSG_DIALOUT_IND message to userland
179 *---------------------------------------------------------------------------*/
180 void
181 i4b_l4_dialout(int driver, int driver_unit)
183 struct mbuf *m;
185 if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL)
187 msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data;
189 md->header.type = MSG_DIALOUT_IND;
190 md->header.cdid = -1;
192 md->driver = driver;
193 md->driver_unit = driver_unit;
195 i4bputqueue(m);
199 /*---------------------------------------------------------------------------*
200 * send MSG_DIALOUTNUMBER_IND message to userland
201 *---------------------------------------------------------------------------*/
202 void
203 i4b_l4_dialoutnumber(int driver, int driver_unit, int cmdlen, char *cmd)
205 struct mbuf *m;
207 if((m = i4b_Dgetmbuf(sizeof(msg_dialoutnumber_ind_t))) != NULL)
209 msg_dialoutnumber_ind_t *md = (msg_dialoutnumber_ind_t *)m->m_data;
211 md->header.type = MSG_DIALOUTNUMBER_IND;
212 md->header.cdid = -1;
214 md->driver = driver;
215 md->driver_unit = driver_unit;
217 if(cmdlen > TELNO_MAX)
218 cmdlen = TELNO_MAX;
220 md->cmdlen = cmdlen;
221 bcopy(cmd, md->cmd, cmdlen);
222 i4bputqueue(m);
226 /*---------------------------------------------------------------------------*
227 * send MSG_KEYPAD_IND message to userland
228 *---------------------------------------------------------------------------*/
229 void
230 i4b_l4_keypad(int driver, int driver_unit, int cmdlen, char *cmd)
232 struct mbuf *m;
234 if((m = i4b_Dgetmbuf(sizeof(msg_keypad_ind_t))) != NULL)
236 msg_keypad_ind_t *md = (msg_keypad_ind_t *)m->m_data;
238 md->header.type = MSG_KEYPAD_IND;
239 md->header.cdid = -1;
241 md->driver = driver;
242 md->driver_unit = driver_unit;
244 if(cmdlen > KEYPAD_MAX)
245 cmdlen = KEYPAD_MAX;
247 md->cmdlen = cmdlen;
248 bcopy(cmd, md->cmd, cmdlen);
249 i4bputqueue(m);
253 /*---------------------------------------------------------------------------*
254 * send MSG_NEGOTIATION_COMPL message to userland
255 *---------------------------------------------------------------------------*/
256 void
257 i4b_l4_negcomplete(call_desc_t *cd)
259 struct mbuf *m;
261 if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL)
263 msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data;
265 md->header.type = MSG_NEGCOMP_IND;
266 md->header.cdid = cd->cdid;
268 i4bputqueue(m);
272 /*---------------------------------------------------------------------------*
273 * send MSG_IFSTATE_CHANGED_IND message to userland
274 *---------------------------------------------------------------------------*/
275 void
276 i4b_l4_ifstate_changed(call_desc_t *cd, int new_state)
278 struct mbuf *m;
280 if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL)
282 msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data;
284 md->header.type = MSG_IFSTATE_CHANGED_IND;
285 md->header.cdid = cd->cdid;
286 md->state = new_state;
288 i4bputqueue(m);
292 /*---------------------------------------------------------------------------*
293 * send MSG_DRVRDISC_REQ message to userland
294 *---------------------------------------------------------------------------*/
295 void
296 i4b_l4_drvrdisc(int driver, int driver_unit)
298 struct mbuf *m;
300 if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL)
302 msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data;
304 md->header.type = MSG_DRVRDISC_REQ;
305 md->header.cdid = -1;
307 md->driver = driver;
308 md->driver_unit = driver_unit;
310 i4bputqueue(m);
314 /*---------------------------------------------------------------------------*
315 * send MSG_ACCT_IND message to userland
316 *---------------------------------------------------------------------------*/
317 void
318 i4b_l4_accounting(int driver, int driver_unit, int accttype, int ioutbytes,
319 int iinbytes, int ro, int ri, int outbytes, int inbytes)
321 struct mbuf *m;
323 if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL)
325 msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data;
327 md->header.type = MSG_ACCT_IND;
328 md->header.cdid = -1;
330 md->driver = driver;
331 md->driver_unit = driver_unit;
333 md->accttype = accttype;
334 md->ioutbytes = ioutbytes;
335 md->iinbytes = iinbytes;
336 md->outbps = ro;
337 md->inbps = ri;
338 md->outbytes = outbytes;
339 md->inbytes = inbytes;
341 i4bputqueue(m);
345 /*---------------------------------------------------------------------------*
346 * send MSG_CONNECT_IND message to userland
347 *---------------------------------------------------------------------------*/
348 void
349 i4b_l4_connect_ind(call_desc_t *cd)
351 struct mbuf *m;
353 if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL)
355 msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data;
357 mp->header.type = MSG_CONNECT_IND;
358 mp->header.cdid = cd->cdid;
360 mp->controller = cd->controller;
361 mp->channel = cd->channelid;
362 mp->bprot = cd->bprot;
364 cd->dir = DIR_INCOMING;
366 if(strlen(cd->dst_telno) > 0)
367 strcpy(mp->dst_telno, cd->dst_telno);
368 else
369 strcpy(mp->dst_telno, TELNO_EMPTY);
371 if(strlen(cd->src_telno) > 0)
372 strcpy(mp->src_telno, cd->src_telno);
373 else
374 strcpy(mp->src_telno, TELNO_EMPTY);
376 strcpy(mp->display, cd->display);
378 mp->scr_ind = cd->scr_ind;
379 mp->prs_ind = cd->prs_ind;
381 T400_start(cd);
383 i4bputqueue(m);
387 /*---------------------------------------------------------------------------*
388 * send MSG_CONNECT_ACTIVE_IND message to userland
389 *---------------------------------------------------------------------------*/
390 void
391 i4b_l4_connect_active_ind(call_desc_t *cd)
393 struct mbuf *m;
395 crit_enter();
397 cd->last_active_time = cd->connect_time = SECOND;
399 NDBGL4(L4_TIMO, "last_active/connect_time=%ld", (long)cd->connect_time);
401 i4b_link_bchandrvr(cd);
403 (*cd->dlt->line_connected)(cd->driver_unit, (void *)cd);
405 i4b_l4_setup_timeout(cd);
407 crit_exit();
409 if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL)
411 msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data;
413 mp->header.type = MSG_CONNECT_ACTIVE_IND;
414 mp->header.cdid = cd->cdid;
415 mp->controller = cd->controller;
416 mp->channel = cd->channelid;
417 if(cd->datetime[0] != '\0')
418 strcpy(mp->datetime, cd->datetime);
419 else
420 mp->datetime[0] = '\0';
421 i4bputqueue(m);
425 /*---------------------------------------------------------------------------*
426 * send MSG_DISCONNECT_IND message to userland
427 *---------------------------------------------------------------------------*/
428 void
429 i4b_l4_disconnect_ind(call_desc_t *cd)
431 struct mbuf *m;
433 if(cd->timeout_active)
434 callout_stop(&cd->idle_timeout);
436 if(cd->dlt != NULL)
438 (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd);
439 i4b_unlink_bchandrvr(cd);
442 if((cd->channelid >= 0) && (cd->channelid < ctrl_desc[cd->controller].nbch))
444 ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE;
446 else
448 /* no error, might be hunting call for callback */
449 NDBGL4(L4_MSG, "channel free not valid but %d!", cd->channelid);
452 if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL)
454 msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data;
456 mp->header.type = MSG_DISCONNECT_IND;
457 mp->header.cdid = cd->cdid;
458 mp->cause = cd->cause_in;
460 i4bputqueue(m);
464 /*---------------------------------------------------------------------------*
465 * send MSG_IDLE_TIMEOUT_IND message to userland
466 *---------------------------------------------------------------------------*/
467 void
468 i4b_l4_idle_timeout_ind(call_desc_t *cd)
470 struct mbuf *m;
472 if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL)
474 msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data;
476 mp->header.type = MSG_IDLE_TIMEOUT_IND;
477 mp->header.cdid = cd->cdid;
479 i4bputqueue(m);
483 /*---------------------------------------------------------------------------*
484 * send MSG_CHARGING_IND message to userland
485 *---------------------------------------------------------------------------*/
486 void
487 i4b_l4_charging_ind(call_desc_t *cd)
489 struct mbuf *m;
491 if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL)
493 msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data;
495 mp->header.type = MSG_CHARGING_IND;
496 mp->header.cdid = cd->cdid;
497 mp->units_type = cd->units_type;
499 /*XXX*/ if(mp->units_type == CHARGE_CALC)
500 mp->units = cd->cunits;
501 else
502 mp->units = cd->units;
504 i4bputqueue(m);
508 /*---------------------------------------------------------------------------*
509 * send MSG_STATUS_IND message to userland
510 *---------------------------------------------------------------------------*/
511 void
512 i4b_l4_status_ind(call_desc_t *cd)
516 /*---------------------------------------------------------------------------*
517 * send MSG_ALERT_IND message to userland
518 *---------------------------------------------------------------------------*/
519 void
520 i4b_l4_alert_ind(call_desc_t *cd)
522 struct mbuf *m;
524 if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL)
526 msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data;
528 mp->header.type = MSG_ALERT_IND;
529 mp->header.cdid = cd->cdid;
531 i4bputqueue(m);
535 /*---------------------------------------------------------------------------*
536 * send MSG_INFO_IND message to userland
537 *---------------------------------------------------------------------------*/
538 void
539 i4b_l4_info_ind(call_desc_t *cd)
543 /*---------------------------------------------------------------------------*
544 * send MSG_INFO_IND message to userland
545 *---------------------------------------------------------------------------*/
546 void
547 i4b_l4_proceeding_ind(call_desc_t *cd)
549 struct mbuf *m;
551 if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL)
553 msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data;
555 mp->header.type = MSG_PROCEEDING_IND;
556 mp->header.cdid = cd->cdid;
557 mp->controller = cd->controller;
558 mp->channel = cd->channelid;
559 i4bputqueue(m);
563 /*---------------------------------------------------------------------------*
564 * send MSG_PACKET_IND message to userland
565 *---------------------------------------------------------------------------*/
566 void
567 i4b_l4_packet_ind(int driver, int driver_unit, int dir, struct mbuf *pkt)
569 struct mbuf *m;
570 int len = pkt->m_pkthdr.len;
571 unsigned char *ip = pkt->m_data;
573 if((m = i4b_Dgetmbuf(sizeof(msg_packet_ind_t))) != NULL)
575 msg_packet_ind_t *mp = (msg_packet_ind_t *)m->m_data;
577 mp->header.type = MSG_PACKET_IND;
578 mp->header.cdid = -1;
579 mp->driver = driver;
580 mp->driver_unit = driver_unit;
581 mp->direction = dir;
582 memcpy(mp->pktdata, ip,
583 len <MAX_PACKET_LOG ? len : MAX_PACKET_LOG);
584 i4bputqueue(m);
588 /*---------------------------------------------------------------------------*
589 * link a driver(unit) to a B-channel(controller,unit,channel)
590 *---------------------------------------------------------------------------*/
591 static int
592 i4b_link_bchandrvr(call_desc_t *cd)
594 int t = ctrl_desc[cd->controller].ctrl_type;
596 if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL)
598 cd->ilt = NULL;
600 else
602 cd->ilt = ctrl_types[t].get_linktab(
603 ctrl_desc[cd->controller].unit,
604 cd->channelid);
607 switch(cd->driver)
609 #if NI4BRBCH > 0
610 case BDRV_RBCH:
611 cd->dlt = rbch_ret_linktab(cd->driver_unit);
612 break;
613 #endif
615 #if NI4BTEL > 0
616 case BDRV_TEL:
617 cd->dlt = tel_ret_linktab(cd->driver_unit);
618 break;
619 #endif
621 #if NI4BIPR > 0
622 case BDRV_IPR:
623 cd->dlt = ipr_ret_linktab(cd->driver_unit);
624 break;
625 #endif
627 #if NI4BISPPP > 0
628 case BDRV_ISPPP:
629 cd->dlt = i4bisppp_ret_linktab(cd->driver_unit);
630 break;
631 #endif
633 #if NI4BING > 0
634 case BDRV_ING:
635 cd->dlt = ing_ret_linktab(cd->driver_unit);
636 break;
637 #endif
639 default:
640 cd->dlt = NULL;
641 break;
644 if(cd->dlt == NULL || cd->ilt == NULL)
645 return(-1);
647 if(t >= 0 && t < CTRL_NUMTYPES && ctrl_types[t].set_linktab != NULL)
649 ctrl_types[t].set_linktab(
650 ctrl_desc[cd->controller].unit,
651 cd->channelid,
652 cd->dlt);
655 switch(cd->driver)
657 #if NI4BRBCH > 0
658 case BDRV_RBCH:
659 rbch_set_linktab(cd->driver_unit, cd->ilt);
660 break;
661 #endif
663 #if NI4BTEL > 0
664 case BDRV_TEL:
665 tel_set_linktab(cd->driver_unit, cd->ilt);
666 break;
667 #endif
669 #if NI4BIPR > 0
670 case BDRV_IPR:
671 ipr_set_linktab(cd->driver_unit, cd->ilt);
672 break;
673 #endif
675 #if NI4BISPPP > 0
676 case BDRV_ISPPP:
677 i4bisppp_set_linktab(cd->driver_unit, cd->ilt);
678 break;
679 #endif
681 #if NI4BING > 0
682 case BDRV_ING:
683 ing_set_linktab(cd->driver_unit, cd->ilt);
684 break;
685 #endif
687 default:
688 return(0);
689 break;
692 /* activate B channel */
694 (*cd->ilt->bch_config)(cd->ilt->unit, cd->ilt->channel, cd->bprot, 1);
696 return(0);
699 /*---------------------------------------------------------------------------*
700 * unlink a driver(unit) from a B-channel(controller,unit,channel)
701 *---------------------------------------------------------------------------*/
702 static void
703 i4b_unlink_bchandrvr(call_desc_t *cd)
705 int t = ctrl_desc[cd->controller].ctrl_type;
707 if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL)
709 cd->ilt = NULL;
710 return;
712 else
714 cd->ilt = ctrl_types[t].get_linktab(
715 ctrl_desc[cd->controller].unit,
716 cd->channelid);
719 /* deactivate B channel */
721 (*cd->ilt->bch_config)(cd->ilt->unit, cd->ilt->channel, cd->bprot, 0);
724 /*---------------------------------------------------------------------------
726 How shorthold mode works for OUTGOING connections
727 =================================================
729 |<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>|
731 idletime_state: IST_NONCHK IST_CHECK IST_SAFE
733 | | | |
734 time>>+-------------------------------+---------------+---------------+-...
735 | | | |
736 | |<--idle_time-->|<--earlyhup--->|
737 |<-----------------------unitlen------------------------------->|
740 unitlen - specifies the time a charging unit lasts
741 idle_time - specifies the thime the line must be idle at the
742 end of the unit to be elected for hangup
743 earlyhup - is the beginning of a timing safety zone before the
744 next charging unit starts
746 The algorithm works as follows: lets assume the unitlen is 100
747 secons, idle_time is 40 seconds and earlyhup is 10 seconds.
748 The line then must be idle 50 seconds after the begin of the
749 current unit and it must then be quiet for 40 seconds. if it
750 has been quiet for this 40 seconds, the line is closed 10
751 seconds before the next charging unit starts. In case there was
752 any traffic within the idle_time, the line is not closed.
753 It does not matter whether there was any traffic between second
754 0 and second 50 or not.
757 How shorthold mode works for INCOMING connections
758 =================================================
760 it is just possible to specify a maximum idle time for incoming
761 connections, after this time of no activity on the line the line
762 is closed.
764 ---------------------------------------------------------------------------*/
766 static time_t
767 i4b_get_idletime(call_desc_t *cd)
769 switch (cd->driver) {
770 #if NI4BISPPP > 0
771 case BDRV_ISPPP:
772 return i4bisppp_idletime(cd->driver_unit);
773 break;
774 #endif
775 default:
776 return cd->last_active_time;
777 break;
780 /*---------------------------------------------------------------------------*
781 * B channel idle check timeout setup
782 *---------------------------------------------------------------------------*/
783 static void
784 i4b_l4_setup_timeout(call_desc_t *cd)
786 NDBGL4(L4_TIMO, "%ld: direction %d, shorthold algorithm %d",
787 (long)SECOND, cd->dir, cd->shorthold_data.shorthold_algorithm);
789 cd->timeout_active = 0;
790 cd->idletime_state = IST_IDLE;
792 if((cd->dir == DIR_INCOMING) && (cd->max_idle_time > 0))
794 /* incoming call: simple max idletime check */
796 callout_reset(&cd->idle_timeout, hz / 2,
797 (void *)i4b_idle_check, cd);
798 cd->timeout_active = 1;
799 NDBGL4(L4_TIMO, "%ld: incoming-call, setup max_idle_time to %ld", (long)SECOND, (long)cd->max_idle_time);
801 else if((cd->dir == DIR_OUTGOING) && (cd->shorthold_data.idle_time > 0))
803 switch( cd->shorthold_data.shorthold_algorithm )
805 default: /* fall into the old fix algorithm */
806 case SHA_FIXU:
807 i4b_l4_setup_timeout_fix_unit( cd );
808 break;
810 case SHA_VARU:
811 i4b_l4_setup_timeout_var_unit( cd );
812 break;
815 else
817 NDBGL4(L4_TIMO, "no idle_timeout configured");
821 /*---------------------------------------------------------------------------*
822 * fixed unit algorithm B channel idle check timeout setup
823 *---------------------------------------------------------------------------*/
824 static void
825 i4b_l4_setup_timeout_fix_unit(call_desc_t *cd)
827 /* outgoing call */
829 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
831 /* outgoing call: simple max idletime check */
833 callout_reset(&cd->idle_timeout, hz / 2,
834 (void *)i4b_idle_check, cd);
835 cd->timeout_active = 1;
836 NDBGL4(L4_TIMO, "%ld: outgoing-call, setup idle_time to %ld",
837 (long)SECOND, (long)cd->shorthold_data.idle_time);
839 else if((cd->shorthold_data.unitlen_time > 0) && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
841 /* outgoing call: full shorthold mode check */
843 callout_reset(&cd->idle_timeout,
844 hz * (cd->shorthold_data.unitlen_time -
845 (cd->shorthold_data.idle_time +
846 cd->shorthold_data.earlyhup_time)),
847 (void *)i4b_idle_check, cd);
848 cd->timeout_active = 1;
849 cd->idletime_state = IST_NONCHK;
850 NDBGL4(L4_TIMO, "%ld: outgoing-call, start %ld sec nocheck window",
851 (long)SECOND, (long)(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
853 if(cd->aocd_flag == 0)
855 cd->units_type = CHARGE_CALC;
856 cd->cunits++;
857 i4b_l4_charging_ind(cd);
860 else
862 /* parms somehow got wrong .. */
864 NDBGL4(L4_ERR, "%ld: ERROR: idletime[%ld]+earlyhup[%ld] > unitlength[%ld]!",
865 (long)SECOND, (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time, (long)cd->shorthold_data.unitlen_time);
869 /*---------------------------------------------------------------------------*
870 * variable unit algorithm B channel idle check timeout setup
871 *---------------------------------------------------------------------------*/
872 static void
873 i4b_l4_setup_timeout_var_unit(call_desc_t *cd)
875 /* outgoing call: variable unit idletime check */
878 * start checking for an idle connect one second before the end of the unit.
879 * The one second takes into account of rounding due to the driver only
880 * using the seconds and not the uSeconds of the current time
882 cd->idletime_state = IST_CHECK; /* move directly to the checking state */
884 callout_reset(&cd->idle_timeout,
885 hz * (cd->shorthold_data.unitlen_time - 1),
886 (void *)i4b_idle_check, cd);
887 cd->timeout_active = 1;
888 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle time - setup to %ld",
889 (long)SECOND, (long)cd->shorthold_data.unitlen_time);
893 /*---------------------------------------------------------------------------*
894 * B channel idle check timeout function
895 *---------------------------------------------------------------------------*/
896 void
897 i4b_idle_check(call_desc_t *cd)
899 if(cd->cdid == CDID_UNUSED)
900 return;
902 crit_enter();
904 /* failsafe */
906 if(cd->timeout_active == 0)
908 NDBGL4(L4_ERR, "ERROR: timeout_active == 0 !!!");
910 else
912 cd->timeout_active = 0;
915 /* incoming connections, simple idletime check */
917 if(cd->dir == DIR_INCOMING)
919 if((i4b_get_idletime(cd) + cd->max_idle_time) <= SECOND)
921 NDBGL4(L4_TIMO, "%ld: incoming-call, line idle timeout, disconnecting!", (long)SECOND);
922 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid,
923 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
924 i4b_l4_idle_timeout_ind(cd);
926 else
928 NDBGL4(L4_TIMO, "%ld: incoming-call, activity, last_active=%ld, max_idle=%ld", (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->max_idle_time);
930 callout_reset(&cd->idle_timeout, hz / 2,
931 (void *)i4b_idle_check, cd);
932 cd->timeout_active = 1;
936 /* outgoing connections */
938 else if(cd->dir == DIR_OUTGOING)
940 switch( cd->shorthold_data.shorthold_algorithm )
942 case SHA_FIXU:
943 i4b_idle_check_fix_unit( cd );
944 break;
945 case SHA_VARU:
946 i4b_idle_check_var_unit( cd );
947 break;
948 default:
949 NDBGL4(L4_TIMO, "%ld: bad value for shorthold_algorithm of %d",
950 (long)SECOND, cd->shorthold_data.shorthold_algorithm);
951 i4b_idle_check_fix_unit( cd );
952 break;
955 crit_exit();
958 /*---------------------------------------------------------------------------*
959 * fixed unit algorithm B channel idle check timeout function
960 *---------------------------------------------------------------------------*/
961 static void
962 i4b_idle_check_fix_unit(call_desc_t *cd)
965 /* simple idletime calculation */
967 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
969 if((i4b_get_idletime(cd) + cd->shorthold_data.idle_time) <= SECOND)
971 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, idle timeout, disconnecting!", (long)SECOND);
972 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
973 i4b_l4_idle_timeout_ind(cd);
975 else
977 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, activity, last_active=%ld, max_idle=%ld",
978 (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->shorthold_data.idle_time);
979 callout_reset(&cd->idle_timeout, hz / 2,
980 (void *)i4b_idle_check, cd);
981 cd->timeout_active = 1;
985 /* full shorthold mode calculation */
987 else if((cd->shorthold_data.unitlen_time > 0)
988 && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
990 switch(cd->idletime_state)
993 case IST_NONCHK: /* end of non-check time */
995 callout_reset(&cd->idle_timeout,
996 hz*(cd->shorthold_data.idle_time),
997 (void *)i4b_idle_check, cd);
998 cd->idletimechk_start = SECOND;
999 cd->idletime_state = IST_CHECK;
1000 cd->timeout_active = 1;
1001 NDBGL4(L4_TIMO, "%ld: outgoing-call, idletime check window reached!", (long)SECOND);
1002 break;
1004 case IST_CHECK: /* end of idletime chk */
1005 if((i4b_get_idletime(cd) > cd->idletimechk_start) &&
1006 (i4b_get_idletime(cd) <= SECOND))
1007 { /* activity detected */
1008 callout_reset(&cd->idle_timeout,
1009 hz*(cd->shorthold_data.earlyhup_time),
1010 (void *)i4b_idle_check, cd);
1011 cd->timeout_active = 1;
1012 cd->idletime_state = IST_SAFE;
1013 NDBGL4(L4_TIMO, "%ld: outgoing-call, activity at %ld, wait earlyhup-end", (long)SECOND, (long)i4b_get_idletime(cd));
1015 else
1016 { /* no activity, hangup */
1017 NDBGL4(L4_TIMO, "%ld: outgoing-call, idle timeout, last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1018 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1019 i4b_l4_idle_timeout_ind(cd);
1020 cd->idletime_state = IST_IDLE;
1022 break;
1024 case IST_SAFE: /* end of earlyhup time */
1026 callout_reset(&cd->idle_timeout,
1027 hz*(cd->shorthold_data.unitlen_time -
1028 (cd->shorthold_data.idle_time +
1029 cd->shorthold_data.earlyhup_time)),
1030 (void *)i4b_idle_check, cd);
1031 cd->timeout_active = 1;
1032 cd->idletime_state = IST_NONCHK;
1034 if(cd->aocd_flag == 0)
1036 cd->units_type = CHARGE_CALC;
1037 cd->cunits++;
1038 i4b_l4_charging_ind(cd);
1041 NDBGL4(L4_TIMO, "%ld: outgoing-call, earlyhup end, wait for idletime start", (long)SECOND);
1042 break;
1044 default:
1045 NDBGL4(L4_ERR, "outgoing-call: invalid idletime_state value!");
1046 cd->idletime_state = IST_IDLE;
1047 break;
1052 /*---------------------------------------------------------------------------*
1053 * variable unit algorithm B channel idle check timeout function
1054 *---------------------------------------------------------------------------*/
1055 static void
1056 i4b_idle_check_var_unit(call_desc_t *cd)
1058 switch(cd->idletime_state)
1061 /* see if there has been any activity within the last idle_time seconds */
1062 case IST_CHECK:
1063 if( i4b_get_idletime(cd) > (SECOND - cd->shorthold_data.idle_time))
1064 { /* activity detected */
1065 /* check again in one second */
1066 callout_reset(&cd->idle_timeout, hz,
1067 (void *)i4b_idle_check, cd);
1068 cd->timeout_active = 1;
1069 cd->idletime_state = IST_CHECK;
1070 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - activity at %ld, continuing", (long)SECOND, (long)i4b_get_idletime(cd));
1072 else
1073 { /* no activity, hangup */
1074 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1075 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1076 i4b_l4_idle_timeout_ind(cd);
1077 cd->idletime_state = IST_IDLE;
1079 break;
1081 default:
1082 NDBGL4(L4_ERR, "outgoing-call: var idle timeout invalid idletime_state value!");
1083 cd->idletime_state = IST_IDLE;
1084 break;
1088 #endif /* NI4B > 0 */