#include #include #include "triton.h" #include "ppp.h" #include "ppp_fsm.h" #include "ppp_lcp.h" #include "log.h" #include "events.h" #include "memdebug.h" static int conf_max_terminate = 2; static int conf_max_configure = 10; static int conf_max_failure = 10; static int conf_timeout = 3; void send_term_req(struct ppp_fsm_t *layer); void send_term_ack(struct ppp_fsm_t *layer); void send_echo_reply(struct ppp_fsm_t *layer); static void init_req_counter(struct ppp_fsm_t *layer,int timeout); static void zero_req_counter(struct ppp_fsm_t *layer); static void restart_timer_func(struct triton_timer_t *t); static void stop_timer(struct ppp_fsm_t *fsm); void ppp_fsm_init(struct ppp_fsm_t *layer) { layer->fsm_state = FSM_Initial; layer->restart_timer.expire = restart_timer_func; layer->restart_timer.period = conf_timeout * 1000; layer->restart_counter = 0; layer->max_terminate = conf_max_terminate; layer->max_configure = conf_max_configure; layer->max_failure = conf_max_failure; layer->id = 1; } void ppp_fsm_free(struct ppp_fsm_t *layer) { stop_timer(layer); } int ppp_fsm_lower_up(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Initial: layer->fsm_state=FSM_Closed; break; case FSM_Starting: //if (layer->init_req_cnt) layer->init_req_cnt(layer); init_req_counter(layer,layer->max_configure); --layer->restart_counter; if (layer->send_conf_req) if (layer->send_conf_req(layer)) return -1; layer->fsm_state=FSM_Req_Sent; break; default: break; } return 0; } void ppp_fsm_lower_down(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Closed: case FSM_Closing: layer->fsm_state=FSM_Initial; break; case FSM_Stopped: if (layer->layer_started) layer->layer_started(layer); layer->fsm_state=FSM_Starting; break; case FSM_Stopping: case FSM_Req_Sent: case FSM_Ack_Rcvd: case FSM_Ack_Sent: layer->fsm_state=FSM_Starting; break; case FSM_Opened: if (layer->layer_down) layer->layer_down(layer); layer->fsm_state=FSM_Starting; break; default: break; } } int ppp_fsm_open(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Initial: //if (layer->layer_started) layer->layer_started(layer); layer->fsm_state=FSM_Starting; break; case FSM_Starting: break; case FSM_Closed: //if (layer->init_req_cnt) layer->init_req_cnt(layer); init_req_counter(layer,layer->max_configure); --layer->restart_counter; layer->fsm_state=FSM_Req_Sent; if (layer->send_conf_req) if (layer->send_conf_req(layer)) return -1; break; case FSM_Closing: case FSM_Stopping: case FSM_Stopped: case FSM_Opened: ppp_fsm_lower_down(layer); ppp_fsm_lower_up(layer); break; default: break; } return 0; } void ppp_fsm_close(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Starting: stop_timer(layer); layer->fsm_state=FSM_Initial; if (layer->layer_finished) layer->layer_finished(layer); break; case FSM_Stopped: layer->fsm_state=FSM_Closed; stop_timer(layer); break; case FSM_Stopping: layer->fsm_state=FSM_Closing; break; case FSM_Opened: layer->fsm_state=FSM_Closing; if (layer->layer_down) layer->layer_down(layer); case FSM_Req_Sent: case FSM_Ack_Rcvd: case FSM_Ack_Sent: //if (layer->init_req_cnt) layer->init_req_cnt(layer); init_req_counter(layer,layer->max_terminate); layer->send_term_req(layer); layer->fsm_state=FSM_Closing; break; default: break; } } void ppp_fsm_close2(struct ppp_fsm_t *layer) { stop_timer(layer); layer->fsm_state=FSM_Closed; } void ppp_fsm_timeout0(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Closing: case FSM_Stopping: --layer->restart_counter; layer->send_term_req(layer); break; case FSM_Ack_Rcvd: layer->fsm_state=FSM_Req_Sent; case FSM_Req_Sent: case FSM_Ack_Sent: --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); break; default: break; } } void ppp_fsm_timeout1(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Closing: stop_timer(layer); layer->fsm_state=FSM_Closed; if (layer->layer_finished) layer->layer_finished(layer); break; case FSM_Stopping: stop_timer(layer); layer->fsm_state=FSM_Stopped; if (layer->layer_finished) layer->layer_finished(layer); break; case FSM_Ack_Rcvd: case FSM_Req_Sent: case FSM_Ack_Sent: stop_timer(layer); layer->fsm_state=FSM_Stopped; if (layer->layer_finished) layer->layer_finished(layer); break; default: break; } } void ppp_fsm_recv_conf_req_ack(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Closed: layer->send_term_ack(layer); break; case FSM_Stopped: //if (layer->init_req_cnt) layer->init_req_cnt(layer); init_req_counter(layer,layer->max_configure); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); case FSM_Req_Sent: case FSM_Ack_Sent: if (layer->send_conf_ack) layer->send_conf_ack(layer); layer->fsm_state=FSM_Ack_Sent; break; case FSM_Ack_Rcvd: if (layer->send_conf_ack) layer->send_conf_ack(layer); stop_timer(layer); if (layer->layer_up) layer->layer_up(layer); layer->fsm_state=FSM_Opened; break; case FSM_Opened: if (layer->layer_down) layer->layer_down(layer); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); if (layer->send_conf_ack) layer->send_conf_ack(layer); layer->fsm_state=FSM_Ack_Sent; break; default: break; } } void ppp_fsm_recv_conf_req_nak(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Closed: layer->send_term_ack(layer); break; case FSM_Stopped: //if (layer->init_req_cnt) layer->init_req_cnt(layer); init_req_counter(layer,layer->max_configure); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); case FSM_Ack_Sent: if (layer->send_conf_nak) layer->send_conf_nak(layer); layer->fsm_state=FSM_Req_Sent; break; case FSM_Req_Sent: case FSM_Ack_Rcvd: if (++layer->conf_failure == layer->max_failure) { if (layer->layer_finished) layer->layer_finished(layer); return; } if (layer->send_conf_nak) layer->send_conf_nak(layer); break; case FSM_Opened: if (layer->layer_down) layer->layer_down(layer); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); if (layer->send_conf_nak) layer->send_conf_nak(layer); layer->fsm_state=FSM_Req_Sent; break; default: break; } } void ppp_fsm_recv_conf_req_rej(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Closed: layer->send_term_ack(layer); break; case FSM_Stopped: //if (layer->init_req_cnt) layer->init_req_cnt(layer); init_req_counter(layer,layer->max_configure); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); case FSM_Ack_Sent: if (++layer->conf_failure == layer->max_failure) { if (layer->layer_down) layer->layer_down(layer); return; } if (layer->send_conf_rej) layer->send_conf_rej(layer); layer->fsm_state=FSM_Req_Sent; break; case FSM_Req_Sent: case FSM_Ack_Rcvd: if (++layer->conf_failure == layer->max_failure) { if (layer->layer_finished) layer->layer_finished(layer); return; } if (layer->send_conf_rej) layer->send_conf_rej(layer); break; case FSM_Opened: if (layer->layer_down) layer->layer_down(layer); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); if (layer->send_conf_rej) layer->send_conf_rej(layer); layer->fsm_state=FSM_Req_Sent; break; default: break; } } void ppp_fsm_recv_conf_ack(struct ppp_fsm_t *layer) { ++layer->id; switch(layer->fsm_state) { case FSM_Closed: case FSM_Stopped: layer->send_term_ack(layer); break; case FSM_Req_Sent: //if (layer->init_req_cnt) layer->init_req_cnt(layer); layer->fsm_state=FSM_Ack_Rcvd; break; case FSM_Ack_Rcvd: --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); layer->fsm_state=FSM_Req_Sent; break; case FSM_Ack_Sent: //if (layer->init_req_cnt) layer->init_req_cnt(layer); //init_req_counter(layer,layer->max_configure); //tlu stop_timer(layer); if (layer->layer_up) layer->layer_up(layer); layer->fsm_state=FSM_Opened; break; case FSM_Opened: if (layer->layer_down) layer->layer_down(layer); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); layer->fsm_state=FSM_Req_Sent; default: break; } } void ppp_fsm_recv_conf_rej(struct ppp_fsm_t *layer) { ++layer->id; switch(layer->fsm_state) { case FSM_Closed: case FSM_Stopped: layer->send_term_ack(layer); break; case FSM_Req_Sent: if (++layer->conf_failure == layer->max_failure) { if (layer->layer_down) layer->layer_down(layer); return; } //if (layer->init_req_cnt) layer->init_req_cnt(layer); init_req_counter(layer,layer->max_failure); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); break; case FSM_Ack_Rcvd: --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); layer->fsm_state=FSM_Req_Sent; break; case FSM_Ack_Sent: if (++layer->conf_failure == layer->max_failure) { if (layer->layer_down) layer->layer_down(layer); return; } init_req_counter(layer,layer->max_configure); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); break; case FSM_Opened: if (layer->layer_down) layer->layer_down(layer); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); layer->fsm_state=FSM_Req_Sent; break; default: break; } } void ppp_fsm_recv_term_req(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Opened: if (layer->layer_down) layer->layer_down(layer); //send_term_req(layer); layer->send_term_ack(layer); //if (layer->zero_req_cnt) layer->zero_req_cnt(layer); zero_req_counter(layer); layer->fsm_state=FSM_Stopping; break; case FSM_Req_Sent: case FSM_Ack_Rcvd: case FSM_Ack_Sent: layer->send_term_ack(layer); layer->fsm_state=FSM_Req_Sent; break; default: layer->send_term_ack(layer); break; } } void ppp_fsm_recv_term_ack(struct ppp_fsm_t *layer) { stop_timer(layer); switch(layer->fsm_state) { case FSM_Closing: layer->fsm_state=FSM_Closed; if (layer->layer_finished) layer->layer_finished(layer); break; case FSM_Stopping: layer->fsm_state=FSM_Stopped; if (layer->layer_finished) layer->layer_finished(layer); break; case FSM_Ack_Rcvd: layer->fsm_state=FSM_Req_Sent; break; case FSM_Opened: if (layer->layer_down) layer->layer_down(layer); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); layer->fsm_state=FSM_Req_Sent; break; default: break; } } void ppp_fsm_recv_unk(struct ppp_fsm_t *layer) { if (layer->send_code_rej) layer->send_code_rej(layer); } void ppp_fsm_recv_code_rej_perm(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Ack_Rcvd: layer->fsm_state=FSM_Req_Sent; break; default: break; } } void ppp_fsm_recv_code_rej_bad(struct ppp_fsm_t *layer) { switch(layer->fsm_state) { case FSM_Opened: if (layer->layer_down) layer->layer_down(layer); --layer->restart_counter; layer->send_term_req(layer); layer->fsm_state=FSM_Stopping; break; case FSM_Closing: layer->fsm_state=FSM_Closed; if (layer->layer_finished) layer->layer_finished(layer); break; case FSM_Stopping: case FSM_Req_Sent: case FSM_Ack_Rcvd: case FSM_Ack_Sent: layer->fsm_state=FSM_Stopped; if (layer->layer_finished) layer->layer_finished(layer); break; default: break; } } static void stop_timer(struct ppp_fsm_t *fsm) { if (fsm->restart_timer.tpd) triton_timer_del(&fsm->restart_timer); } static void init_req_counter(struct ppp_fsm_t *layer,int timeout) { layer->restart_counter = timeout; if (!layer->restart_timer.tpd) triton_timer_add(layer->ppp->ses.ctrl->ctx, &layer->restart_timer, 0); } static void zero_req_counter(struct ppp_fsm_t *layer) { layer->restart_counter=0; if (!layer->restart_timer.tpd) triton_timer_add(layer->ppp->ses.ctrl->ctx, &layer->restart_timer, 0); } static void restart_timer_func(struct triton_timer_t *t) { struct ppp_fsm_t *layer = container_of(t, typeof(*layer), restart_timer); log_ppp_debug("fsm timeout %i\n", layer->restart_counter); if (layer->restart_counter>0) ppp_fsm_timeout0(layer); else ppp_fsm_timeout1(layer); } static void load_config(void) { char *opt; opt = conf_get_opt("ppp", "max-terminate"); if (opt && atoi(opt) > 0) conf_max_terminate = atoi(opt); opt = conf_get_opt("ppp", "max-configure"); if (opt && atoi(opt) > 0) conf_max_configure = atoi(opt); opt = conf_get_opt("ppp", "max-failure"); if (opt && atoi(opt) > 0) conf_max_failure = atoi(opt); opt = conf_get_opt("ppp", "timeout"); if (opt && atoi(opt) > 0) conf_timeout = atoi(opt); } static void fsm_init(void) { load_config(); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } DEFINE_INIT(3, fsm_init);