added a persist option (enabled by default for now until we add a way for users to pass a ppp_settings structure)

improved PPPoE state machine and added persist mode support
This commit is contained in:
Sylvain Rochet 2012-06-07 00:46:19 +02:00
parent e44aada634
commit 7ef99ee6f3
4 changed files with 52 additions and 33 deletions

View File

@ -145,7 +145,7 @@ struct pppoe_softc {
struct pppoe_softc *next; struct pppoe_softc *next;
struct netif *sc_ethif; /* ethernet interface we are using */ struct netif *sc_ethif; /* ethernet interface we are using */
int sc_pd; /* ppp unit number */ int sc_pd; /* ppp unit number */
void (*sc_linkStatusCB)(int pd, int up); void (*sc_link_status_cb)(int pd, int up);
int sc_state; /* discovery phase or session connected */ int sc_state; /* discovery phase or session connected */
struct eth_addr sc_dest; /* hardware address of concentrator */ struct eth_addr sc_dest; /* hardware address of concentrator */
@ -168,7 +168,7 @@ struct pppoe_softc {
#define pppoe_init() /* compatibility define, no initialization needed */ #define pppoe_init() /* compatibility define, no initialization needed */
err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr); err_t pppoe_create(struct netif *ethif, int pd, void (*link_status_cb)(int pd, int up), struct pppoe_softc **scptr);
err_t pppoe_destroy(struct netif *ifp); err_t pppoe_destroy(struct netif *ifp);
int pppoe_connect(struct pppoe_softc *sc); int pppoe_connect(struct pppoe_softc *sc);

View File

@ -380,6 +380,7 @@ int ppp_init(void) {
memset(&ppp_settings, 0, sizeof(ppp_settings)); memset(&ppp_settings, 0, sizeof(ppp_settings));
ppp_settings.usepeerdns = 1; ppp_settings.usepeerdns = 1;
ppp_settings.persist = 1;
ppp_set_auth(PPPAUTHTYPE_NONE, NULL, NULL); ppp_set_auth(PPPAUTHTYPE_NONE, NULL, NULL);
/* /*
@ -1835,39 +1836,46 @@ struct pbuf * ppp_singlebuf(struct pbuf *p) {
#if PPPOE_SUPPORT #if PPPOE_SUPPORT
static void ppp_over_ethernet_link_status_cb(int pd, int state) { static void ppp_over_ethernet_link_status_cb(int pd, int state) {
ppp_control *pc = &ppp_control_list[pd]; int pppoe_err_code = PPPERR_NONE;
ppp_control *pc;
switch(state) { switch(state) {
/* PPPoE link is established, starting PPP negotiation */
case PPPOE_CB_STATE_UP: case PPPOE_CB_STATE_UP:
PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: UP, connecting\n", pd)); PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: UP, connecting\n", pd));
ppp_start(pd); ppp_start(pd);
break; return;
/* FIXME: here we can handle the PPPoE persist, in case of DOWN or FAILED, we just have to /* PPPoE link normally down (i.e. asked to do so) */
* call pppoe_connect(sc); without setting pc->open_flag to 0.
*/
case PPPOE_CB_STATE_DOWN: case PPPOE_CB_STATE_DOWN:
PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: DOWN, disconnected\n", pd)); PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: DOWN, disconnected\n", pd));
ppp_hup(pd); pppoe_err_code = PPPERR_CONNECT;
ppp_stop(pd);
pppoe_destroy(&pc->netif);
pc->open_flag = 0;
if(pc->link_status_cb) {
pc->link_status_cb(pc->link_status_ctx, pc->err_code ? pc->err_code : PPPERR_CONNECT, NULL);
}
break; break;
/* PPPoE link failed to setup (i.e. PADI/PADO timeout */
case PPPOE_CB_STATE_FAILED: case PPPOE_CB_STATE_FAILED:
PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: FAILED, aborting\n", pd)); PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: FAILED, aborting\n", pd));
ppp_hup(pd); pppoe_err_code = PPPERR_OPEN;
ppp_stop(pd);
pppoe_destroy(&pc->netif);
pc->open_flag = 0;
if(pc->link_status_cb) {
pc->link_status_cb(pc->link_status_ctx, pc->err_code ? pc->err_code : PPPERR_PROTOCOL, NULL);
}
break; break;
} }
pc = &ppp_control_list[pd];
/* Reconnect if persist mode is enabled */
if(ppp_settings.persist) {
if(pc->link_status_cb)
pc->link_status_cb(pc->link_status_ctx, pc->err_code ? pc->err_code : pppoe_err_code, NULL);
pppoe_connect(pc->pppoe_sc);
return;
}
ppp_hup(pd);
ppp_stop(pd);
pppoe_destroy(&pc->netif);
pc->open_flag = 0;
if(pc->link_status_cb)
pc->link_status_cb(pc->link_status_ctx, pc->err_code ? pc->err_code : pppoe_err_code, NULL);
} }
#endif /* PPPOE_SUPPORT */ #endif /* PPPOE_SUPPORT */

View File

@ -437,6 +437,7 @@ struct ppp_settings {
#endif /* EAP_SUPPORT */ #endif /* EAP_SUPPORT */
u_int usehostname : 1; /* Use hostname for our_name */ u_int usehostname : 1; /* Use hostname for our_name */
u_int usepeerdns : 1; /* Ask peer for DNS adds */ u_int usepeerdns : 1; /* Ask peer for DNS adds */
u_int persist : 1; /* Persist mode, always try to reopen the connection */
u_short idle_time_limit; /* Shut down link if idle for this long */ u_short idle_time_limit; /* Shut down link if idle for this long */
int maxconnect; /* Maximum connect time (seconds) */ int maxconnect; /* Maximum connect time (seconds) */

View File

@ -141,7 +141,7 @@ static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct n
static struct pppoe_softc *pppoe_softc_list; static struct pppoe_softc *pppoe_softc_list;
err_t err_t
pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr) pppoe_create(struct netif *ethif, int pd, void (*link_status_cb)(int pd, int up), struct pppoe_softc **scptr)
{ {
struct pppoe_softc *sc; struct pppoe_softc *sc;
@ -156,7 +156,7 @@ pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up),
MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
sc->sc_pd = pd; sc->sc_pd = pd;
sc->sc_linkStatusCB = linkStatusCB; sc->sc_link_status_cb = link_status_cb;
sc->sc_ethif = ethif; sc->sc_ethif = ethif;
/* put the new interface at the head of the list */ /* put the new interface at the head of the list */
@ -277,7 +277,7 @@ pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif)
static void static void
pppoe_linkstatus_up(struct pppoe_softc *sc) pppoe_linkstatus_up(struct pppoe_softc *sc)
{ {
sc->sc_linkStatusCB(sc->sc_pd, PPPOE_CB_STATE_UP); sc->sc_link_status_cb(sc->sc_pd, PPPOE_CB_STATE_UP);
} }
/* analyze and handle a single received packet while not in session state */ /* analyze and handle a single received packet while not in session state */
@ -806,6 +806,12 @@ pppoe_connect(struct pppoe_softc *sc)
return EBUSY; return EBUSY;
} }
/* stop any timer */
sys_untimeout(pppoe_timeout, sc);
sc->sc_session = 0;
sc->sc_padi_retried = 0;
sc->sc_padr_retried = 0;
#ifdef PPPOE_SERVER #ifdef PPPOE_SERVER
/* wait PADI if IFF_PASSIVE */ /* wait PADI if IFF_PASSIVE */
if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) {
@ -814,7 +820,6 @@ pppoe_connect(struct pppoe_softc *sc)
#endif #endif
/* save state, in case we fail to send PADI */ /* save state, in case we fail to send PADI */
sc->sc_state = PPPOE_STATE_PADI_SENT; sc->sc_state = PPPOE_STATE_PADI_SENT;
sc->sc_padr_retried = 0;
if ((err = pppoe_send_padi(sc)) != 0) { if ((err = pppoe_send_padi(sc)) != 0) {
PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err));
} }
@ -862,8 +867,10 @@ pppoe_do_disconnect(struct pppoe_softc *sc)
sc->sc_hunique_len = 0; sc->sc_hunique_len = 0;
#endif #endif
sc->sc_session = 0; sc->sc_session = 0;
sc->sc_padi_retried = 0;
sc->sc_padr_retried = 0;
sc->sc_linkStatusCB(sc->sc_pd, PPPOE_CB_STATE_DOWN); /* notify upper layers */ sc->sc_link_status_cb(sc->sc_pd, PPPOE_CB_STATE_DOWN); /* notify upper layers */
return err; return err;
} }
@ -872,13 +879,16 @@ static void
pppoe_abort_connect(struct pppoe_softc *sc) pppoe_abort_connect(struct pppoe_softc *sc)
{ {
PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num));
sc->sc_state = PPPOE_STATE_CLOSING;
sc->sc_linkStatusCB(sc->sc_pd, PPPOE_CB_STATE_FAILED); /* notify upper layers */
/* clear connection state */ /* clear connection state */
MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
sc->sc_state = PPPOE_STATE_INITIAL; sc->sc_state = PPPOE_STATE_INITIAL;
MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
sc->sc_ac_cookie_len = 0;
sc->sc_session = 0;
sc->sc_padi_retried = 0;
sc->sc_padr_retried = 0;
sc->sc_link_status_cb(sc->sc_pd, PPPOE_CB_STATE_FAILED); /* notify upper layers */
} }
/* Send a PADR packet */ /* Send a PADR packet */
@ -1112,17 +1122,17 @@ pppoe_clear_softc(struct pppoe_softc *sc, const char *message)
/* stop timer */ /* stop timer */
sys_untimeout(pppoe_timeout, sc); sys_untimeout(pppoe_timeout, sc);
PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message));
/* fix our state */ /* fix our state */
sc->sc_state = PPPOE_STATE_INITIAL; sc->sc_state = PPPOE_STATE_INITIAL;
/* notify upper layers */ /* notify upper layers */
sc->sc_linkStatusCB(sc->sc_pd, PPPOE_CB_STATE_DOWN); sc->sc_link_status_cb(sc->sc_pd, PPPOE_CB_STATE_DOWN);
/* clean up softc */ /* clean up softc */
MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest));
sc->sc_ac_cookie_len = 0; sc->sc_ac_cookie_len = 0;
sc->sc_session = 0; sc->sc_session = 0;
sc->sc_padi_retried = 0;
sc->sc_padr_retried = 0;
} }
#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ #endif /* PPP_SUPPORT && PPPOE_SUPPORT */