From de6be743c6ae01d34c704e355bafba0432e4e3c3 Mon Sep 17 00:00:00 2001 From: Sylvain Rochet Date: Wed, 11 Jul 2012 23:50:33 +0200 Subject: [PATCH] added holdoff support for PPPoE and PPPoL2TP when persist mode is used --- src/include/netif/ppp_oe.h | 10 ++++++---- src/include/netif/pppol2tp.h | 13 +++++++------ src/netif/ppp/ppp.c | 3 ++- src/netif/ppp/ppp.h | 2 ++ src/netif/ppp/ppp_oe.c | 21 +++++++++++++++++++++ src/netif/ppp/pppol2tp.c | 30 ++++++++++++++++++++++++++---- 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/include/netif/ppp_oe.h b/src/include/netif/ppp_oe.h index ac5deff8..c3021a14 100644 --- a/src/include/netif/ppp_oe.h +++ b/src/include/netif/ppp_oe.h @@ -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); diff --git a/src/include/netif/pppol2tp.h b/src/include/netif/pppol2tp.h index e417a07e..3dded088 100644 --- a/src/include/netif/pppol2tp.h +++ b/src/include/netif/pppol2tp.h @@ -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); diff --git a/src/netif/ppp/ppp.c b/src/netif/ppp/ppp.c index 69ebaf07..af2cadd2 100644 --- a/src/netif/ppp/ppp.c +++ b/src/netif/ppp/ppp.c @@ -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; } diff --git a/src/netif/ppp/ppp.h b/src/netif/ppp/ppp.h index 375a4c5f..bc7422df 100644 --- a/src/netif/ppp/ppp.h +++ b/src/netif/ppp/ppp.h @@ -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 */ diff --git a/src/netif/ppp/ppp_oe.c b/src/netif/ppp/ppp_oe.c index 1173db99..5a274b72 100644 --- a/src/netif/ppp/ppp_oe.c +++ b/src/netif/ppp/ppp_oe.c @@ -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) diff --git a/src/netif/ppp/pppol2tp.c b/src/netif/ppp/pppol2tp.c index c30174e3..f6940875 100644 --- a/src/netif/ppp/pppol2tp.c +++ b/src/netif/ppp/pppol2tp.c @@ -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 */ }