Commit 55ef6a0e authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Start cleaning isdn_net hangup timeout handling

The isdn network interface provides a number of ways to set up
automatic hangup after inactivity, and unfortunately consequently
rather mysterious code which handles that - at this point of cleanup
it's now possible to grasp what's going on.
parent 0248cb12
...@@ -48,6 +48,12 @@ enum { ...@@ -48,6 +48,12 @@ enum {
ST_WAIT_BEFORE_CB, ST_WAIT_BEFORE_CB,
}; };
enum {
ST_CHARGE_NULL,
ST_CHARGE_GOT_CINF, /* got a first charge info */
ST_CHARGE_HAVE_CINT, /* got a second chare info and thus the timing */
};
/* keep clear of ISDN_CMD_* and ISDN_STAT_* */ /* keep clear of ISDN_CMD_* and ISDN_STAT_* */
enum { enum {
EV_NET_DIAL = 0x200, EV_NET_DIAL = 0x200,
...@@ -349,12 +355,7 @@ isdn_net_unbind_channel(isdn_net_local * lp) ...@@ -349,12 +355,7 @@ isdn_net_unbind_channel(isdn_net_local * lp)
* outgoing packet), if counter exceeds configured limit either do a * outgoing packet), if counter exceeds configured limit either do a
* hangup immediately or - if configured - wait until just before the next * hangup immediately or - if configured - wait until just before the next
* charge-info. * charge-info.
*
* cps-calculation (needed for dynamic channel-bundling):
* Since this function is called every second, simply reset the
* byte-counter of the interface after copying it to the cps-variable.
*/ */
unsigned long last_jiffies = -HZ;
void void
isdn_net_autohup() isdn_net_autohup()
...@@ -366,52 +367,54 @@ isdn_net_autohup() ...@@ -366,52 +367,54 @@ isdn_net_autohup()
list_for_each(l, &isdn_net_devs) { list_for_each(l, &isdn_net_devs) {
isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list); isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
isdn_net_local *l = &p->local; isdn_net_local *l = &p->local;
if ((l->flags & ISDN_NET_CONNECTED) && (l->dialstate == ST_ACTIVE)) {
if (!(l->flags & ISDN_NET_CONNECTED) || l->dialstate != ST_ACTIVE)
continue;
if(dev->global_flags & ISDN_GLOBAL_STOPPED ||
ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF) {
isdn_net_hangup(&p->dev);
continue;
}
dbg_net_dial("%s: huptimer %d, onhtime %d, chargetime %ld, chargeint %d\n",
l->name, l->huptimer, l->onhtime, l->chargetime, l->chargeint);
if (!(l->onhtime))
continue;
if (l->huptimer++ <= l->onhtime) {
anymore = 1; anymore = 1;
l->huptimer++; continue;
printk("huptimer %d, onhtime %d, chargetime %ld, chargeint %d\n", l->huptimer, l->onhtime, l->chargetime, l->chargeint); }
/* if (l->hupflags & ISDN_MANCHARGE && l->hupflags & ISDN_CHARGEHUP) {
* if there is some dialmode where timeout-hangup while (time_after(jiffies, l->chargetime + l->chargeint))
* should _not_ be done, check for that here l->chargetime += l->chargeint;
*/
if ((l->onhtime) && if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ)) {
(l->huptimer > l->onhtime)) if (l->outgoing || l->hupflags & ISDN_INHUP) {
{
if (l->hupflags & ISDN_MANCHARGE &&
l->hupflags & ISDN_CHARGEHUP) {
while (time_after(jiffies, l->chargetime + l->chargeint))
l->chargetime += l->chargeint;
if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
if (l->outgoing || l->hupflags & ISDN_INHUP) {
HERE;
isdn_net_hangup(&p->dev);
}
} else if (l->outgoing) {
if (l->hupflags & ISDN_CHARGEHUP) {
if (l->hupflags & ISDN_WAITCHARGE) {
printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
l->name, l->hupflags);
isdn_net_hangup(&p->dev);
} else if (time_after(jiffies, l->chargetime + l->chargeint)) {
printk(KERN_DEBUG
"isdn_net: %s: chtime = %lu, chint = %d\n",
l->name, l->chargetime, l->chargeint);
isdn_net_hangup(&p->dev);
}
}
} else if (l->hupflags & ISDN_INHUP) {
HERE;
isdn_net_hangup(&p->dev); isdn_net_hangup(&p->dev);
continue;
} }
} }
} else if (l->outgoing) {
if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) { if (l->hupflags & ISDN_CHARGEHUP) {
isdn_net_hangup(&p->dev); if (l->charge_state != ST_CHARGE_HAVE_CINT) {
break; dbg_net_dial("%s: did not get CINT\n", l->name);
isdn_net_hangup(&p->dev);
continue;
} else if (time_after(jiffies, l->chargetime + l->chargeint)) {
dbg_net_dial("%s: chtime = %lu, chint = %d\n",
l->name, l->chargetime, l->chargeint);
isdn_net_hangup(&p->dev);
continue;
}
} }
} else if (l->hupflags & ISDN_INHUP) {
isdn_net_hangup(&p->dev);
continue;
} }
anymore = 1;
} }
last_jiffies = jiffies;
isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore); isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
} }
...@@ -605,13 +608,11 @@ do_dialout(isdn_net_local *lp) ...@@ -605,13 +608,11 @@ do_dialout(isdn_net_local *lp)
} }
lp->huptimer = 0; lp->huptimer = 0;
lp->outgoing = 1; lp->outgoing = 1;
if (lp->chargeint) { if (lp->chargeint)
lp->hupflags |= ISDN_HAVECHARGE; lp->charge_state = ST_CHARGE_HAVE_CINT;
lp->hupflags &= ~ISDN_WAITCHARGE; else
} else { lp->charge_state = ST_CHARGE_NULL;
lp->hupflags |= ISDN_WAITCHARGE;
lp->hupflags &= ~ISDN_HAVECHARGE;
}
if (lp->cbdelay && (lp->flags & ISDN_NET_CBOUT)) { if (lp->cbdelay && (lp->flags & ISDN_NET_CBOUT)) {
lp->dial_timer.expires = jiffies + lp->cbdelay; lp->dial_timer.expires = jiffies + lp->cbdelay;
lp->dial_event = EV_NET_TIMER_CB; lp->dial_event = EV_NET_TIMER_CB;
...@@ -698,15 +699,19 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -698,15 +699,19 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
* usage by isdn_net_autohup() * usage by isdn_net_autohup()
*/ */
lp->charge++; lp->charge++;
if (lp->hupflags & ISDN_HAVECHARGE) { switch (lp->charge_state) {
lp->hupflags &= ~ISDN_WAITCHARGE; case ST_CHARGE_NULL:
lp->chargeint = jiffies - lp->chargetime - (2 * HZ); lp->charge_state = ST_CHARGE_GOT_CINF;
break;
case ST_CHARGE_GOT_CINF:
lp->charge_state = ST_CHARGE_HAVE_CINT;
/* fall through */
case ST_CHARGE_HAVE_CINT:
lp->chargeint = jiffies - lp->chargetime - 2 * HZ;
break;
} }
if (lp->hupflags & ISDN_WAITCHARGE)
lp->hupflags |= ISDN_HAVECHARGE;
lp->chargetime = jiffies; lp->chargetime = jiffies;
printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n", dbg_net_dial("%s: got CINF\n", lp->name);
lp->name, lp->chargetime);
return 1; return 1;
} }
break; break;
...@@ -2386,8 +2391,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -2386,8 +2391,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
lp->outgoing = 0; lp->outgoing = 0;
lp->huptimer = 0; lp->huptimer = 0;
lp->hupflags |= ISDN_WAITCHARGE; lp->charge_state = ST_CHARGE_NULL;
lp->hupflags &= ~ISDN_HAVECHARGE;
/* Got incoming Call, setup L2 and L3 protocols, /* Got incoming Call, setup L2 and L3 protocols,
* then wait for D-Channel-connect * then wait for D-Channel-connect
*/ */
...@@ -2842,8 +2846,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) ...@@ -2842,8 +2846,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
else else
lp->hupflags &= ~ISDN_INHUP; lp->hupflags &= ~ISDN_INHUP;
if (cfg->chargeint > 10) { if (cfg->chargeint > 10) {
lp->hupflags |= ISDN_HAVECHARGE | ISDN_MANCHARGE;
lp->chargeint = cfg->chargeint * HZ; lp->chargeint = cfg->chargeint * HZ;
lp->charge_state = ST_CHARGE_HAVE_CINT;
lp->hupflags |= ISDN_MANCHARGE;
} }
if (cfg->p_encap != lp->p_encap) { if (cfg->p_encap != lp->p_encap) {
if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) { if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
......
...@@ -12,8 +12,6 @@ ...@@ -12,8 +12,6 @@
*/ */
/* Definitions for hupflags: */ /* Definitions for hupflags: */
#define ISDN_WAITCHARGE 1 /* did not get a charge info yet */
#define ISDN_HAVECHARGE 2 /* We know a charge info */
#define ISDN_CHARGEHUP 4 /* We want to use the charge mechanism */ #define ISDN_CHARGEHUP 4 /* We want to use the charge mechanism */
#define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */ #define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */
#define ISDN_MANCHARGE 16 /* Charge Interval manually set */ #define ISDN_MANCHARGE 16 /* Charge Interval manually set */
......
...@@ -317,6 +317,7 @@ typedef struct isdn_net_local_s { ...@@ -317,6 +317,7 @@ typedef struct isdn_net_local_s {
/* 0 = Transparent */ /* 0 = Transparent */
int huptimer; /* Timeout-counter for auto-hangup */ int huptimer; /* Timeout-counter for auto-hangup */
int charge; /* Counter for charging units */ int charge; /* Counter for charging units */
int charge_state; /* ChargeInfo state machine */
ulong chargetime; /* Timer for Charging info */ ulong chargetime; /* Timer for Charging info */
int hupflags; /* Flags for charge-unit-hangup: */ int hupflags; /* Flags for charge-unit-hangup: */
/* bit0: chargeint is invalid */ /* bit0: chargeint is invalid */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment