Commit 13fad342 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Make idle timeout and retry wait parts of the state machine

parent 05fb5a37
...@@ -41,6 +41,7 @@ enum { ...@@ -41,6 +41,7 @@ enum {
ST_IN_WAIT_BCONN, ST_IN_WAIT_BCONN,
ST_ACTIVE, ST_ACTIVE,
ST_WAIT_BEFORE_CB, ST_WAIT_BEFORE_CB,
ST_OUT_DIAL_WAIT,
}; };
/* keep clear of ISDN_CMD_* and ISDN_STAT_* */ /* keep clear of ISDN_CMD_* and ISDN_STAT_* */
...@@ -48,10 +49,11 @@ enum { ...@@ -48,10 +49,11 @@ enum {
EV_NET_DIAL = 0x200, EV_NET_DIAL = 0x200,
EV_NET_TIMER_IN_DCONN = 0x201, EV_NET_TIMER_IN_DCONN = 0x201,
EV_NET_TIMER_IN_BCONN = 0x202, EV_NET_TIMER_IN_BCONN = 0x202,
EV_NET_TIMER_OUT_DCONN = 0x203, EV_NET_TIMER_DIAL = 0x203,
EV_NET_TIMER_OUT_BCONN = 0x204, EV_NET_TIMER_DIAL_WAIT = 0x204,
EV_NET_TIMER_CB = 0x205, EV_NET_TIMER_CB_OUT = 0x205,
EV_NET_TIMER_HUP = 0x206, EV_NET_TIMER_CB_IN = 0x206,
EV_NET_TIMER_HUP = 0x207,
}; };
/* /*
...@@ -261,6 +263,7 @@ static void isdn_net_connected(isdn_net_dev *idev) ...@@ -261,6 +263,7 @@ static void isdn_net_connected(isdn_net_dev *idev)
idev->dialstate = ST_ACTIVE; idev->dialstate = ST_ACTIVE;
idev->huptimer = 0;
idev->dial_event = EV_NET_TIMER_HUP; idev->dial_event = EV_NET_TIMER_HUP;
idev->dial_timer.expires = jiffies + HZ; idev->dial_timer.expires = jiffies + HZ;
add_timer(&idev->dial_timer); add_timer(&idev->dial_timer);
...@@ -274,10 +277,6 @@ static void isdn_net_connected(isdn_net_dev *idev) ...@@ -274,10 +277,6 @@ static void isdn_net_connected(isdn_net_dev *idev)
*/ */
idev->chargetime = jiffies; idev->chargetime = jiffies;
/* reset dial-timeout */
idev->dialstarted = 0;
idev->dialwait_timer = 0;
idev->transcount = 0; idev->transcount = 0;
idev->cps = 0; idev->cps = 0;
idev->last_jiffies = jiffies; idev->last_jiffies = jiffies;
...@@ -308,25 +307,39 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) ...@@ -308,25 +307,39 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
} }
/* Initiate dialout. Set phone-number-pointer to first number /* Initiate dialout. Set phone-number-pointer to first number
* of interface. * of interface, number of retries to 0.
*/ */
static void static void
init_dialout(isdn_net_dev *idev) init_dialout(isdn_net_dev *idev)
{ {
isdn_net_local *mlp = idev->mlp; isdn_net_local *mlp = idev->mlp;
idev->dial = 0; if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF)
return;
if (list_empty(&mlp->phone[1]))
return;
if (mlp->dialtimeout > 0 && idev->dial = 0;
(idev->dialstarted == 0 ||
time_after(jiffies, idev->dialstarted + mlp->dialtimeout + mlp->dialwait))) {
idev->dialstarted = jiffies;
idev->dialwait_timer = 0;
}
idev->dialretry = 0; idev->dialretry = 0;
do_dialout(idev); do_dialout(idev);
} }
/* find the idev->dial'th outgoing number */
static struct isdn_net_phone *
get_outgoing_phone(isdn_net_dev *idev)
{
isdn_net_local *mlp = idev->mlp;
struct isdn_net_phone *phone;
int i = 0;
list_for_each_entry(phone, &mlp->phone[1], list) {
if (i++ == idev->dial)
return phone;
}
return NULL;
}
/* Setup interface, dial current phone-number, switch to next number. /* Setup interface, dial current phone-number, switch to next number.
* If list of phone-numbers is exhausted, increment * If list of phone-numbers is exhausted, increment
* retry-counter. * retry-counter.
...@@ -335,83 +348,65 @@ static void ...@@ -335,83 +348,65 @@ static void
do_dialout(isdn_net_dev *idev) do_dialout(isdn_net_dev *idev)
{ {
isdn_net_local *mlp = idev->mlp; isdn_net_local *mlp = idev->mlp;
int i;
struct isdn_net_phone *phone;
struct dial_info dial = { struct dial_info dial = {
.l2_proto = mlp->l2_proto, .l2_proto = mlp->l2_proto,
.l3_proto = mlp->l3_proto, .l3_proto = mlp->l3_proto,
.si1 = 7, .si1 = 7,
.si2 = 0, .si2 = 0,
.msn = mlp->msn, .msn = mlp->msn,
.phone = get_outgoing_phone(idev)->num,
}; };
if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF) /* next time, try next number */
return;
if (list_empty(&mlp->phone[1])) {
return;
}
i = 0;
list_for_each_entry(phone, &mlp->phone[1], list) {
if (i++ == idev->dial)
goto found;
}
/* otherwise start in front */
phone = list_entry(mlp->phone[1].next, struct isdn_net_phone, list);
idev->dial = 0;
idev->dialretry++;
found:
idev->dial++; idev->dial++;
dial.phone = phone->num;
if (idev->dialretry > mlp->dialmax) {
if (mlp->dialtimeout == 0) {
idev->dialwait_timer = jiffies + mlp->dialwait;
idev->dialstarted = 0;
}
isdn_net_hangup(idev);
return;
}
if (mlp->dialtimeout > 0 &&
time_after(jiffies, idev->dialstarted + mlp->dialtimeout)) {
idev->dialwait_timer = jiffies + mlp->dialwait;
idev->dialstarted = 0;
isdn_net_hangup(idev);
return;
}
/*
* Switch to next number or back to start if at end of list.
*/
isdn_slot_dial(idev->isdn_slot, &dial);
idev->huptimer = 0;
idev->outgoing = 1; idev->outgoing = 1;
if (idev->chargeint) if (idev->chargeint)
idev->charge_state = ST_CHARGE_HAVE_CINT; idev->charge_state = ST_CHARGE_HAVE_CINT;
else else
idev->charge_state = ST_CHARGE_NULL; idev->charge_state = ST_CHARGE_NULL;
/* For outgoing callback, use cbdelay instead of dialtimeout */
if (mlp->cbdelay && (mlp->flags & ISDN_NET_CBOUT)) { if (mlp->cbdelay && (mlp->flags & ISDN_NET_CBOUT)) {
idev->dial_timer.expires = jiffies + mlp->cbdelay; idev->dial_timer.expires = jiffies + mlp->cbdelay;
idev->dial_event = EV_NET_TIMER_CB; idev->dial_event = EV_NET_TIMER_CB_OUT;
} else { } else {
idev->dial_timer.expires = jiffies + 10 * HZ; idev->dial_timer.expires = jiffies + mlp->dialtimeout;
idev->dial_event = EV_NET_TIMER_OUT_DCONN; idev->dial_event = EV_NET_TIMER_DIAL;
} }
idev->dialstate = ST_OUT_WAIT_DCONN; idev->dialstate = ST_OUT_WAIT_DCONN;
add_timer(&idev->dial_timer); add_timer(&idev->dial_timer);
/* Dial */
isdn_slot_dial(idev->isdn_slot, &dial);
} }
/* /* If we didn't connect within dialtimeout, we give up for now
* Perform auto-hangup for net-interfaces. * and wait for dialwait jiffies before trying again.
*
* auto-hangup:
* Increment idle-counter (this counter is reset on any incoming or
* outgoing packet), if counter exceeds configured limit either do a
* hangup immediately or - if configured - wait until just before the next
* charge-info.
*/ */
static void
dial_timeout(isdn_net_dev *idev)
{
isdn_net_local *mlp = idev->mlp;
isdn_ctrl cmd;
idev->dialstate = ST_OUT_DIAL_WAIT;
isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd);
/* get next phone number */
if (!get_outgoing_phone(idev)) {
/* otherwise start over at first entry */
idev->dial = 0;
idev->dialretry++;
}
if (idev->dialretry >= mlp->dialmax) {
isdn_net_hangup(idev);
return;
}
idev->dial_event = EV_NET_TIMER_DIAL_WAIT;
mod_timer(&idev->dial_timer, jiffies + mlp->dialwait);
}
static void static void
isdn_net_check_hup(isdn_net_dev *idev) isdn_net_check_hup(isdn_net_dev *idev)
...@@ -469,24 +464,17 @@ isdn_net_event_out_wait_dconn(isdn_net_dev *idev, int pr, void *arg) ...@@ -469,24 +464,17 @@ isdn_net_event_out_wait_dconn(isdn_net_dev *idev, int pr, void *arg)
isdn_ctrl cmd; isdn_ctrl cmd;
switch (pr) { switch (pr) {
case EV_NET_TIMER_OUT_DCONN: case EV_NET_TIMER_DIAL:
/* try again */ dial_timeout(idev);
do_dialout(idev);
return 1; return 1;
case EV_NET_TIMER_CB: case EV_NET_TIMER_CB_OUT:
/* Remote does callback. Hangup after cbdelay,
* then wait for incoming call */
printk(KERN_INFO "%s: hangup waiting for callback ...\n", idev->name); printk(KERN_INFO "%s: hangup waiting for callback ...\n", idev->name);
isdn_net_hangup(idev); isdn_net_hangup(idev);
return 1; return 1;
case ISDN_STAT_DCONN: case ISDN_STAT_DCONN:
/* Got D-Channel-Connect, send B-Channel-request */ /* Got D-Channel-Connect, send B-Channel-request */
del_timer(&idev->dial_timer);
idev->dialstate = ST_OUT_WAIT_BCONN; idev->dialstate = ST_OUT_WAIT_BCONN;
isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTB, &cmd); isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
idev->dial_timer.expires = jiffies + 10 * HZ;
idev->dial_event = EV_NET_TIMER_OUT_BCONN;
add_timer(&idev->dial_timer);
return 1; return 1;
case ISDN_STAT_DHUP: case ISDN_STAT_DHUP:
del_timer(&idev->dial_timer); del_timer(&idev->dial_timer);
...@@ -503,9 +491,8 @@ static int ...@@ -503,9 +491,8 @@ static int
isdn_net_event_out_wait_bconn(isdn_net_dev *idev, int pr, void *arg) isdn_net_event_out_wait_bconn(isdn_net_dev *idev, int pr, void *arg)
{ {
switch (pr) { switch (pr) {
case EV_NET_TIMER_OUT_BCONN: case EV_NET_TIMER_DIAL:
/* try again */ dial_timeout(idev);
do_dialout(idev);
return 1; return 1;
case ISDN_STAT_BCONN: case ISDN_STAT_BCONN:
del_timer(&idev->dial_timer); del_timer(&idev->dial_timer);
...@@ -578,8 +565,7 @@ static int ...@@ -578,8 +565,7 @@ static int
isdn_net_event_wait_before_cb(isdn_net_dev *idev, int pr, void *arg) isdn_net_event_wait_before_cb(isdn_net_dev *idev, int pr, void *arg)
{ {
switch (pr) { switch (pr) {
case EV_NET_TIMER_CB: case EV_NET_TIMER_CB_IN:
/* Callback Delay */
init_dialout(idev); init_dialout(idev);
return 1; return 1;
} }
...@@ -639,6 +625,18 @@ isdn_net_event_active(isdn_net_dev *idev, int pr, void *arg) ...@@ -639,6 +625,18 @@ isdn_net_event_active(isdn_net_dev *idev, int pr, void *arg)
return 0; return 0;
} }
static int
isdn_net_event_dial_wait(isdn_net_dev *idev, int pr, void *arg)
{
switch (pr) {
case EV_NET_TIMER_DIAL_WAIT:
do_dialout(idev);
return 1;
}
isdn_BUG();
return 0;
}
/* For EV_NET_DIAL, returns 1 if timer callback is needed /* For EV_NET_DIAL, returns 1 if timer callback is needed
* For ISDN_STAT_*, returns 1 if event was for us * For ISDN_STAT_*, returns 1 if event was for us
*/ */
...@@ -648,6 +646,9 @@ isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg) ...@@ -648,6 +646,9 @@ isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg)
dbg_net_dial("%s: dialstate=%d pr=%#x\n", idev->name, dbg_net_dial("%s: dialstate=%d pr=%#x\n", idev->name,
idev->dialstate, pr); idev->dialstate, pr);
if (pr == ISDN_STAT_DHUP)
return 1; // FIXME
switch (idev->dialstate) { switch (idev->dialstate) {
case ST_ACTIVE: case ST_ACTIVE:
return isdn_net_event_active(idev, pr, arg); return isdn_net_event_active(idev, pr, arg);
...@@ -661,6 +662,8 @@ isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg) ...@@ -661,6 +662,8 @@ isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg)
return isdn_net_event_in_wait_bconn(idev, pr, arg); return isdn_net_event_in_wait_bconn(idev, pr, arg);
case ST_WAIT_BEFORE_CB: case ST_WAIT_BEFORE_CB:
return isdn_net_event_wait_before_cb(idev, pr, arg); return isdn_net_event_wait_before_cb(idev, pr, arg);
case ST_OUT_DIAL_WAIT:
return isdn_net_event_dial_wait(idev, pr, arg);
default: default:
isdn_BUG(); isdn_BUG();
return 0; return 0;
...@@ -888,8 +891,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -888,8 +891,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
} }
/* we have our idev locked from now on */ /* we have our idev locked from now on */
/* Reset hangup-timeout */
idev->huptimer = 0; // FIXME?
isdn_net_writebuf_skb(idev, skb); isdn_net_writebuf_skb(idev, skb);
spin_unlock_bh(&idev->xmit_lock); spin_unlock_bh(&idev->xmit_lock);
...@@ -936,26 +937,12 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev) ...@@ -936,26 +937,12 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
isdn_net_dev *idev = list_entry(mlp->slaves.next, isdn_net_dev, slaves); isdn_net_dev *idev = list_entry(mlp->slaves.next, isdn_net_dev, slaves);
/* are we dialing already? */ /* are we dialing already? */
if (isdn_net_bound(idev)) { if (isdn_net_bound(idev))
netif_stop_queue(ndev); goto stop_queue;
return 1;
}
if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO) if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
goto discard; goto discard;
if (idev->dialwait_timer <= 0)
if (idev->dialstarted > 0 && mlp->dialtimeout > 0 &&
time_before(jiffies, idev->dialstarted + mlp->dialtimeout + mlp->dialwait))
idev->dialwait_timer = idev->dialstarted + mlp->dialtimeout + mlp->dialwait;
if (idev->dialwait_timer > 0) {
if(time_before(jiffies, idev->dialwait_timer))
goto discard;
idev->dialwait_timer = 0;
}
if (isdn_net_dev_dial(idev) < 0) if (isdn_net_dev_dial(idev) < 0)
goto discard; goto discard;
...@@ -963,6 +950,7 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev) ...@@ -963,6 +950,7 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
if (dev->net_verbose) if (dev->net_verbose)
isdn_net_log_skb(skb, idev); isdn_net_log_skb(skb, idev);
stop_queue:
netif_stop_queue(ndev); netif_stop_queue(ndev);
return 1; return 1;
...@@ -1041,7 +1029,7 @@ isdn_net_do_callback(isdn_net_dev *idev) ...@@ -1041,7 +1029,7 @@ isdn_net_do_callback(isdn_net_dev *idev)
/* Setup dialstate. */ /* Setup dialstate. */
idev->dial_timer.expires = jiffies + mlp->cbdelay; idev->dial_timer.expires = jiffies + mlp->cbdelay;
idev->dial_event = EV_NET_TIMER_CB; idev->dial_event = EV_NET_TIMER_CB_IN;
add_timer(&idev->dial_timer); add_timer(&idev->dial_timer);
idev->dialstate = ST_WAIT_BEFORE_CB; idev->dialstate = ST_WAIT_BEFORE_CB;
...@@ -1206,7 +1194,6 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -1206,7 +1194,6 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
isdn_net_bind_channel(idev, idx); isdn_net_bind_channel(idev, idx);
idev->outgoing = 0; idev->outgoing = 0;
idev->huptimer = 0;
idev->charge_state = ST_CHARGE_NULL; idev->charge_state = ST_CHARGE_NULL;
/* 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
......
...@@ -122,7 +122,7 @@ isdn_net_rm_from_bundle(isdn_net_dev *idev) ...@@ -122,7 +122,7 @@ isdn_net_rm_from_bundle(isdn_net_dev *idev)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&mlp->online_lock, flags); spin_lock_irqsave(&mlp->online_lock, flags);
list_del(&idev->online); // list_del(&idev->online); FIXME
spin_unlock_irqrestore(&mlp->online_lock, flags); spin_unlock_irqrestore(&mlp->online_lock, flags);
} }
......
...@@ -244,9 +244,6 @@ isdn_net_addif(char *name, isdn_net_local *mlp) ...@@ -244,9 +244,6 @@ isdn_net_addif(char *name, isdn_net_local *mlp)
idev->ppp_slot = -1; idev->ppp_slot = -1;
idev->pppbind = -1; idev->pppbind = -1;
idev->dialstarted = 0; /* Jiffies of last dial-start */
idev->dialwait_timer = 0; /* Jiffies of earliest next dial-start */
init_timer(&idev->dial_timer); init_timer(&idev->dial_timer);
idev->dial_timer.data = (unsigned long) idev; idev->dial_timer.data = (unsigned long) idev;
idev->dial_timer.function = isdn_net_dial_timer; idev->dial_timer.function = isdn_net_dial_timer;
...@@ -274,9 +271,9 @@ isdn_net_addif(char *name, isdn_net_local *mlp) ...@@ -274,9 +271,9 @@ isdn_net_addif(char *name, isdn_net_local *mlp)
mlp->onhtime = 10; mlp->onhtime = 10;
mlp->dialmax = 1; mlp->dialmax = 1;
mlp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; mlp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;
mlp->cbdelay = 5 * HZ; /* Wait 5 secs before Callback */ mlp->cbdelay = 5 * HZ; /* Wait 5 secs before Callback */
mlp->dialtimeout = -1; /* Infinite Dial-Timeout */ mlp->dialtimeout = 60 * HZ;/* Wait 1 min for connection */
mlp->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */ mlp->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
INIT_LIST_HEAD(&mlp->phone[0]); INIT_LIST_HEAD(&mlp->phone[0]);
INIT_LIST_HEAD(&mlp->phone[1]); INIT_LIST_HEAD(&mlp->phone[1]);
dev = &mlp->dev; dev = &mlp->dev;
......
...@@ -371,8 +371,6 @@ typedef struct isdn_net_dev_s { ...@@ -371,8 +371,6 @@ typedef struct isdn_net_dev_s {
int dialstate; /* State for dialing */ int dialstate; /* State for dialing */
int dial; /* # of phone number just dialed */ int dial; /* # of phone number just dialed */
int outgoing; /* Flag: outgoing call */ int outgoing; /* Flag: outgoing call */
unsigned long dialstarted; /* first dialing-attempt */
unsigned long dialwait_timer;/* earliest next dialing-attempt */
int dialretry; /* Counter for Dialout-retries */ int dialretry; /* Counter for Dialout-retries */
int cps; /* current speed of this interface */ int cps; /* current speed of this interface */
......
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