added holdoff support for PPPoE and PPPoL2TP when persist mode is used

This commit is contained in:
Sylvain Rochet 2012-07-11 23:50:33 +02:00
parent f534e80c71
commit de6be743c6
6 changed files with 64 additions and 15 deletions

View File

@ -106,10 +106,11 @@ PACK_STRUCT_END
#define PPPOE_STATE_INITIAL 0
#define PPPOE_STATE_PADI_SENT 1
#define PPPOE_STATE_PADR_SENT 2
#define PPPOE_STATE_SESSION 3
#define PPPOE_STATE_CLOSING 4
#define PPPOE_STATE_HOLDOFF 1
#define PPPOE_STATE_PADI_SENT 2
#define PPPOE_STATE_PADR_SENT 3
#define PPPOE_STATE_SESSION 4
#define PPPOE_STATE_CLOSING 5
/* passive */
#define PPPOE_STATE_PADO_SENT 1
@ -172,6 +173,7 @@ err_t pppoe_create(struct netif *ethif, ppp_pcb *pcb, void (*link_status_cb)(ppp
err_t pppoe_destroy(struct netif *ifp);
int pppoe_connect(struct pppoe_softc *sc);
void pppoe_reconnect(struct pppoe_softc *sc);
void pppoe_disconnect(struct pppoe_softc *sc);
void pppoe_disc_input(struct netif *netif, struct pbuf *p);

View File

@ -150,11 +150,12 @@
/* L2TP Session state */
#define PPPOL2TP_STATE_INITIAL 0
#define PPPOL2TP_STATE_SCCRQ_SENT 1
#define PPPOL2TP_STATE_ICRQ_SENT 2
#define PPPOL2TP_STATE_ICCN_SENT 3
#define PPPOL2TP_STATE_DATA 4
#define PPPOL2TP_STATE_CLOSING 5
#define PPPOL2TP_STATE_HOLDOFF 1
#define PPPOL2TP_STATE_SCCRQ_SENT 2
#define PPPOL2TP_STATE_ICRQ_SENT 3
#define PPPOL2TP_STATE_ICCN_SENT 4
#define PPPOL2TP_STATE_DATA 5
#define PPPOL2TP_STATE_CLOSING 6
#define PPPOL2TP_CB_STATE_UP 0 /* PPPoL2TP link is UP */
#define PPPOL2TP_CB_STATE_DOWN 1 /* PPPo2TP link is DOWN - normal condition */
@ -210,7 +211,7 @@ err_t pppol2tp_connect(pppol2tp_pcb *l2tp, ip_addr_t *ipaddr, u16_t port);
void pppol2tp_disconnect(pppol2tp_pcb *l2tp);
/* Reconnect to a LNS, using previously set L2TP server IP address and port. */
err_t pppol2tp_reconnect(pppol2tp_pcb *l2tp);
void pppol2tp_reconnect(pppol2tp_pcb *l2tp);
/* Data packet from PPP to L2TP */
err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb);

View File

@ -270,6 +270,7 @@ ppp_pcb *ppp_new(void) {
/* default configuration */
pcb->settings.usepeerdns = 1;
pcb->settings.persist = 1;
pcb->settings.holdoff = 30;
#if CHAP_SUPPORT
pcb->settings.chap_timeout_time = 3;
pcb->settings.chap_max_transmits = 10;
@ -1808,7 +1809,7 @@ static void ppp_over_ethernet_link_status_cb(ppp_pcb *pcb, int state) {
if(pcb->link_status_cb)
pcb->link_status_cb(pcb, pcb->err_code ? pcb->err_code : pppoe_err_code, pcb->link_status_ctx);
new_phase(pcb, PHASE_INITIALIZE);
pppoe_connect(pcb->pppoe_sc);
pppoe_reconnect(pcb->pppoe_sc);
return;
}

View File

@ -206,6 +206,8 @@ typedef struct ppp_settings_s {
u16_t listen_time; /* time to listen first (ms), waiting for peer to send LCP packet */
u16_t holdoff; /* time to wait (s) before re-initiating the link after it terminates */
#if PPP_IDLETIMELIMIT
u16_t idle_time_limit; /* Disconnect if idle for this many seconds */
#endif /* PPP_IDLETIMELIMIT */

View File

@ -788,6 +788,10 @@ pppoe_timeout(void *arg)
case PPPOE_STATE_CLOSING:
pppoe_do_disconnect(sc);
break;
case PPPOE_STATE_HOLDOFF:
sc->sc_state = PPPOE_STATE_INITIAL;
pppoe_connect(sc);
break;
default:
return; /* all done, work in peace */
}
@ -823,6 +827,23 @@ pppoe_connect(struct pppoe_softc *sc)
return err;
}
/* Start a reconnection */
void pppoe_reconnect(struct pppoe_softc *sc) {
if (sc->sc_state != PPPOE_STATE_INITIAL) {
return;
}
if (sc->pcb->settings.holdoff == 0) {
pppoe_connect(sc);
return;
}
sc->sc_state = PPPOE_STATE_HOLDOFF;
sys_timeout((u32_t)sc->pcb->settings.holdoff*1000, pppoe_timeout, sc);
return;
}
/* disconnect */
void
pppoe_disconnect(struct pppoe_softc *sc)

View File

@ -71,6 +71,7 @@
#endif /* PPPOL2TP_AUTH_SUPPORT */
/* Prototypes for procedures local to this file. */
static void pppol2tp_do_reconnect(pppol2tp_pcb *l2tp);
static void pppol2tp_do_disconnect(pppol2tp_pcb *l2tp);
static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, struct ip_addr *addr, u16_t port,
@ -168,15 +169,27 @@ err_t pppol2tp_connect(pppol2tp_pcb *l2tp, ip_addr_t *ipaddr, u16_t port) {
}
/* Reconnect to a LNS, using previously set L2TP server IP address and port. */
err_t pppol2tp_reconnect(pppol2tp_pcb *l2tp) {
err_t err;
void pppol2tp_reconnect(pppol2tp_pcb *l2tp) {
if (l2tp->phase != PPPOL2TP_STATE_INITIAL) {
return ERR_VAL;
return;
}
pppol2tp_clear(l2tp);
if (l2tp->ppp->settings.holdoff == 0) {
pppol2tp_do_reconnect(l2tp);
return;
}
l2tp->phase = PPPOL2TP_STATE_HOLDOFF;
sys_timeout((u32_t)l2tp->ppp->settings.holdoff*1000, pppol2tp_timeout, l2tp);
return;
}
static void pppol2tp_do_reconnect(pppol2tp_pcb *l2tp) {
err_t err;
do {
l2tp->remote_tunnel_id = magic();
} while(l2tp->remote_tunnel_id == 0);
@ -187,7 +200,7 @@ err_t pppol2tp_reconnect(pppol2tp_pcb *l2tp) {
PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err));
}
sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp);
return err;
return;
}
/* Disconnect */
@ -220,6 +233,10 @@ static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, struc
u16_t hflags, hlen, len=0, tunnel_id=0, session_id=0, ns=0, nr=0, offset=0;
u8_t *inp;
if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) {
goto free_and_return;
}
printf("-----------\nL2TP INPUT, %d\n", p->len);
p = ppp_singlebuf(p);
@ -396,6 +413,7 @@ static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, struct ip_addr
break;
/* Stop Control Connection Notification */
case PPPOL2TP_MESSAGETYPE_STOPCCN:
pppol2tp_send_zlb(l2tp, l2tp->our_ns); /* Ack the StopCCN before we switch to down state */
if (l2tp->phase < PPPOL2TP_STATE_DATA) {
pppol2tp_abort_connect(l2tp);
} else if (l2tp->phase == PPPOL2TP_STATE_DATA) {
@ -601,6 +619,10 @@ static void pppol2tp_timeout(void *arg) {
pppol2tp_do_disconnect(l2tp);
break;
case PPPOL2TP_STATE_HOLDOFF:
pppol2tp_do_reconnect(l2tp);
break;
default:
return; /* all done, work in peace */
}