Skip to content

Commit

Permalink
pppoe: Simply pppoe-bundle handling
Browse files Browse the repository at this point in the history
You now only need to define a pppoe-bundle as a list of pppoe instance like :
pppoe-bundle TEST_BUNDLE
 instance ETH0
 instance ETH1

first instance in the bundle will be considered as 'primary' and all the others as 'secondary'.
Secondary instances will refer to Primary instance tracking elements (session, hunique,
session_timer, ppp_timer).
During normal operations primary instance will be used to initiate PPPoE negorication.
Secondary instances can also serve PPPoE traffic since they are sharing same tracking as
primary. This is why Primary and Secondary instances are active and serving traffic.
During error on interface PPPoE instance will transit to FAULT state, then new instance
will be elected to serve new PPPoE negociation traffic (first secondary instance available);
  • Loading branch information
acassen committed Apr 7, 2024
1 parent 8801992 commit 1eea97c
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 99 deletions.
51 changes: 34 additions & 17 deletions src/gtp_ppp.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,12 +293,14 @@ void
sppp_increasing_timeout(const struct cp *cp, sppp_t *sp)
{
gtp_pppoe_t *pppoe = sp->s_pppoe->pppoe;
timer_thread_t *ppp_timer;
int timo;

timo = sp->lcp.max_configure - sp->rst_counter[cp->protoidx];
if (timo < 1)
timo = 1;
timer_node_add(&pppoe->ppp_timer, &sp->ch[cp->protoidx], timo * sp->lcp.timeout);
ppp_timer = gtp_pppoe_get_ppp_timer(pppoe);
timer_node_add(ppp_timer, &sp->ch[cp->protoidx], timo * sp->lcp.timeout);
}

/*
Expand All @@ -309,21 +311,23 @@ void
sppp_cp_change_state(const struct cp *cp, sppp_t *sp, int newstate)
{
gtp_pppoe_t *pppoe = sp->s_pppoe->pppoe;
timer_thread_t *ppp_timer;

if (debug & 8 && sp->state[cp->protoidx] != newstate)
printf("%s: %s %s->%s\n",
pppoe->ifname, cp->name,
sppp_state_name(sp->state[cp->protoidx]),
sppp_state_name(newstate));
sp->state[cp->protoidx] = newstate;
ppp_timer = gtp_pppoe_get_ppp_timer(pppoe);

switch (newstate) {
case STATE_INITIAL:
case STATE_STARTING:
case STATE_CLOSED:
case STATE_STOPPED:
case STATE_OPENED:
timer_node_del(&pppoe->ppp_timer, &sp->ch[cp->protoidx]);
timer_node_del(ppp_timer, &sp->ch[cp->protoidx]);
break;
case STATE_CLOSING:
case STATE_STOPPING:
Expand Down Expand Up @@ -2378,6 +2382,7 @@ sppp_pap_input(sppp_t *sp, pkt_t *pkt)
gtp_pppoe_t *pppoe = sp->s_pppoe->pppoe;
pkt_buffer_t *pbuff = pkt->pbuff;
int len = pbuff->end - pbuff->data;
timer_thread_t *ppp_timer;
lcp_hdr_t *h;
uint8_t *name, *passwd, mlen;
int name_len, passwd_len;
Expand All @@ -2388,6 +2393,7 @@ sppp_pap_input(sppp_t *sp, pkt_t *pkt)
return;
}

ppp_timer = gtp_pppoe_get_ppp_timer(pppoe);
h = (lcp_hdr_t *) pbuff->data;
if (len > ntohs(h->len))
len = ntohs(h->len);
Expand Down Expand Up @@ -2451,7 +2457,7 @@ sppp_pap_input(sppp_t *sp, pkt_t *pkt)

/* ack and nak are his authproto */
case PAP_ACK:
timer_node_del(&pppoe->ppp_timer, &sp->pap_my_to_ch);
timer_node_del(ppp_timer, &sp->pap_my_to_ch);
if (debug & 8) {
PPPDEBUG(("%s: pap success", pppoe->ifname));
name_len = *((char *)h);
Expand All @@ -2477,7 +2483,7 @@ sppp_pap_input(sppp_t *sp, pkt_t *pkt)
break;

case PAP_NAK:
timer_node_del(&pppoe->ppp_timer, &sp->pap_my_to_ch);
timer_node_del(ppp_timer, &sp->pap_my_to_ch);
if (debug & 8) {
PPPDEBUG(("%s: pap failure", pppoe->ifname));
name_len = *((char *)h);
Expand Down Expand Up @@ -2519,6 +2525,7 @@ void
sppp_pap_open(sppp_t *sp)
{
gtp_pppoe_t *pppoe = sp->s_pppoe->pppoe;
timer_thread_t *ppp_timer;

if (sp->hisauth.proto == PPP_PAP &&
(sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) {
Expand All @@ -2529,7 +2536,8 @@ sppp_pap_open(sppp_t *sp)
if (sp->myauth.proto == PPP_PAP) {
/* we are peer, send a request, and start a timer */
pap.scr(sp);
timer_node_add(&pppoe->ppp_timer, &sp->pap_my_to_ch, sp->lcp.timeout);
ppp_timer = gtp_pppoe_get_ppp_timer(pppoe);
timer_node_add(ppp_timer, &sp->pap_my_to_ch, sp->lcp.timeout);
}
}

Expand Down Expand Up @@ -2619,10 +2627,12 @@ void
sppp_pap_tld(sppp_t *sp)
{
gtp_pppoe_t *pppoe = sp->s_pppoe->pppoe;
timer_thread_t *ppp_timer;

PPPDEBUG(("%s: pap tld\n", pppoe->ifname));
timer_node_del(&pppoe->ppp_timer, &sp->ch[IDX_PAP]);
timer_node_del(&pppoe->ppp_timer, &sp->pap_my_to_ch);
ppp_timer = gtp_pppoe_get_ppp_timer(pppoe);
timer_node_del(ppp_timer, &sp->ch[IDX_PAP]);
timer_node_del(ppp_timer, &sp->pap_my_to_ch);
sp->lcp.protos &= ~(1 << IDX_PAP);

lcp.Close(sp);
Expand Down Expand Up @@ -2654,6 +2664,7 @@ sppp_keepalive(void *arg)
{
sppp_t *sp = arg;
gtp_pppoe_t *pppoe = sp->s_pppoe->pppoe;
timer_thread_t *ppp_timer;
timeval_t tv;

/* Keepalive mode disabled */
Expand Down Expand Up @@ -2703,7 +2714,8 @@ sppp_keepalive(void *arg)
}

next_timer:
timer_node_add(&pppoe->ppp_timer, &sp->keepalive, pppoe->keepalive);
ppp_timer = gtp_pppoe_get_ppp_timer(pppoe);
timer_node_add(ppp_timer, &sp->keepalive, pppoe->keepalive);
return 0;
}

Expand All @@ -2716,14 +2728,16 @@ sppp_up(spppoe_t *s)
{
gtp_pppoe_t *pppoe = s->pppoe;
sppp_t *sp = s->s_ppp;
timer_thread_t *ppp_timer;

/* LCP layer */
(sp->pp_up)(sp);

/* Register keepalive timer */
if (__test_bit(PPPOE_FL_KEEPALIVE_BIT, &pppoe->flags)) {
sp->pp_flags |= PP_KEEPALIVE;
timer_node_add(&pppoe->ppp_timer, &sp->keepalive, pppoe->keepalive);
ppp_timer = gtp_pppoe_get_ppp_timer(pppoe);
timer_node_add(ppp_timer, &sp->keepalive, pppoe->keepalive);
}
return 0;
}
Expand All @@ -2733,19 +2747,22 @@ sppp_down(spppoe_t *s)
{
gtp_pppoe_t *pppoe = s->pppoe;
sppp_t *sp = s->s_ppp;
timer_thread_t *ppp_timer;
int i;

ppp_timer = gtp_pppoe_get_ppp_timer(pppoe);

/* LCP layer */
(sp->pp_down)(sp);

for (i = 0; i < IDX_COUNT; i++)
timer_node_del(&pppoe->ppp_timer, &sp->ch[i]);
timer_node_del(&pppoe->ppp_timer, &sp->pap_my_to_ch);
timer_node_del(ppp_timer, &sp->ch[i]);
timer_node_del(ppp_timer, &sp->pap_my_to_ch);

/* Release keepalive timer */
if (__test_bit(PPPOE_FL_KEEPALIVE_BIT, &pppoe->flags)) {
sp->pp_flags &= ~PP_KEEPALIVE;
timer_node_del(&pppoe->ppp_timer, &sp->keepalive);
timer_node_del(ppp_timer, &sp->keepalive);
}
return 0;
}
Expand Down Expand Up @@ -2811,17 +2828,19 @@ void
sppp_destroy(sppp_t *sp)
{
gtp_pppoe_t *pppoe = sp->s_pppoe->pppoe;
timer_thread_t *ppp_timer;
int i;

ppp_timer = gtp_pppoe_get_ppp_timer(pppoe);
sppp_ipcp_destroy(sp);
sppp_ipv6cp_destroy(sp);

/* Stop keepalive handler. */
timer_node_del(&pppoe->ppp_timer, &sp->keepalive);
timer_node_del(ppp_timer, &sp->keepalive);

for (i = 0; i < IDX_COUNT; i++)
timer_node_del(&pppoe->ppp_timer, &sp->ch[i]);
timer_node_del(&pppoe->ppp_timer, &sp->pap_my_to_ch);
timer_node_del(ppp_timer, &sp->ch[i]);
timer_node_del(ppp_timer, &sp->pap_my_to_ch);

/* release authentication data */
if (sp->hisauth.name != NULL)
Expand Down Expand Up @@ -2869,7 +2888,5 @@ int
gtp_ppp_destroy(gtp_pppoe_t *pppoe)
{
gtp_ppp_timer_destroy(pppoe);


return 0;
}
62 changes: 44 additions & 18 deletions src/gtp_pppoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,46 @@ pthread_mutex_t gtp_pppoe_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* PPPoE utilities
*/
gtp_htab_t *
gtp_pppoe_get_session_tab(gtp_pppoe_t *pppoe)
{
if (!pppoe->bundle || __test_bit(PPPOE_FL_PRIMARY_BIT, &pppoe->flags))
return &pppoe->session_tab;

/* Secondary instance in bundle to primary tracking */
return &pppoe->bundle->pppoe[0]->session_tab;
}

gtp_htab_t *
gtp_pppoe_get_unique_tab(gtp_pppoe_t *pppoe)
{
if (!pppoe->bundle || __test_bit(PPPOE_FL_PRIMARY_BIT, &pppoe->flags))
return &pppoe->unique_tab;

/* Secondary instance in bundle to primary tracking */
return &pppoe->bundle->pppoe[0]->unique_tab;
}

timer_thread_t *
gtp_pppoe_get_session_timer(gtp_pppoe_t *pppoe)
{
if (!pppoe->bundle || __test_bit(PPPOE_FL_PRIMARY_BIT, &pppoe->flags))
return &pppoe->session_timer;

/* Secondary instance in bundle to primary tracking */
return &pppoe->bundle->pppoe[0]->session_timer;
}

timer_thread_t *
gtp_pppoe_get_ppp_timer(gtp_pppoe_t *pppoe)
{
if (!pppoe->bundle || __test_bit(PPPOE_FL_PRIMARY_BIT, &pppoe->flags))
return &pppoe->ppp_timer;

/* Secondary instance in bundle refer to primary tracking */
return &pppoe->bundle->pppoe[0]->ppp_timer;
}

gtp_pppoe_t *
gtp_pppoe_get_by_name(const char *name)
{
Expand Down Expand Up @@ -347,11 +387,6 @@ gtp_pppoe_worker_task(void *arg)
goto shoot_again;
}

if (!__test_bit(PPPOE_FL_SERVICE_BIT, &pppoe->flags)) {
mpkt_reset(&w->mpkt);
goto shoot_again;
}

/* mpkt processing */
mpkt_process(&w->mpkt, ret, gtp_pppoe_ingress, w);
mpkt_reset(&w->mpkt);
Expand Down Expand Up @@ -575,8 +610,6 @@ gtp_pppoe_bundle_init(const char *name)
}
strlcpy(bundle->name, name, GTP_NAME_MAX_LEN);
INIT_LIST_HEAD(&bundle->next);
gtp_htab_init(&bundle->session_tab, CONN_HASHTAB_SIZE);
gtp_htab_init(&bundle->unique_tab, CONN_HASHTAB_SIZE);
bundle->pppoe = MALLOC(sizeof(gtp_pppoe_t) * PPPOE_BUNDLE_MAXSIZE);

gtp_pppoe_bundle_add(bundle);
Expand All @@ -590,24 +623,20 @@ gtp_pppoe_bundle_get_active_instance(gtp_pppoe_bundle_t *bundle)
gtp_pppoe_t *pppoe;
int i;

/* try match active !fault instance */
/* try match primary !fault instance */
for (i = 0; i < PPPOE_BUNDLE_MAXSIZE && bundle->pppoe[i]; i++) {
pppoe = bundle->pppoe[i];
if (__test_bit(PPPOE_FL_MASTER_BIT, &pppoe->flags) &&
if (__test_bit(PPPOE_FL_PRIMARY_BIT, &pppoe->flags) &&
!__test_bit(PPPOE_FL_FAULT_BIT, &pppoe->flags)) {
if (!__test_and_set_bit(PPPOE_FL_SERVICE_BIT, &pppoe->flags))
log_message(LOG_INFO, "PPPoE:%s now serving", pppoe->name);
return pppoe;
}
}

/* No match, fallback to the first standby !fault instance */
/* No match, fallback to the first secondary !fault instance */
for (i = 0; i < PPPOE_BUNDLE_MAXSIZE && bundle->pppoe[i]; i++) {
pppoe = bundle->pppoe[i];
if (__test_bit(PPPOE_FL_BACKUP_BIT, &pppoe->flags) &&
if (__test_bit(PPPOE_FL_SECONDARY_BIT, &pppoe->flags) &&
!__test_bit(PPPOE_FL_FAULT_BIT, &pppoe->flags)) {
if (!__test_and_set_bit(PPPOE_FL_SERVICE_BIT, &pppoe->flags))
log_message(LOG_INFO, "PPPoE:%s now serving", pppoe->name);
return pppoe;
}
}
Expand All @@ -619,9 +648,6 @@ int
__gtp_pppoe_bundle_release(gtp_pppoe_bundle_t *bundle)
{
list_head_del(&bundle->next);
spppoe_sessions_destroy(&bundle->session_tab);
gtp_htab_destroy(&bundle->session_tab);
gtp_htab_destroy(&bundle->unique_tab);
FREE(bundle->pppoe);
return 0;
}
Expand Down
Loading

0 comments on commit 1eea97c

Please sign in to comment.