From b88670c92455455e747ca683dd9ab6e7fd5d26f4 Mon Sep 17 00:00:00 2001 From: Kozlov Dmitry Date: Tue, 7 Dec 2010 16:03:53 +0300 Subject: pppoe: implemented ability to change PADO delay in relation of connection count --- accel-pptpd/ctrl/pppoe/CMakeLists.txt | 1 + accel-pptpd/ctrl/pppoe/cli.c | 16 ++-- accel-pptpd/ctrl/pppoe/dpado.c | 162 ++++++++++++++++++++++++++++++++++ accel-pptpd/ctrl/pppoe/pppoe.c | 23 ++--- accel-pptpd/ctrl/pppoe/pppoe.h | 11 ++- 5 files changed, 188 insertions(+), 25 deletions(-) create mode 100644 accel-pptpd/ctrl/pppoe/dpado.c (limited to 'accel-pptpd/ctrl/pppoe') diff --git a/accel-pptpd/ctrl/pppoe/CMakeLists.txt b/accel-pptpd/ctrl/pppoe/CMakeLists.txt index e29cbf7..6e70e4c 100644 --- a/accel-pptpd/ctrl/pppoe/CMakeLists.txt +++ b/accel-pptpd/ctrl/pppoe/CMakeLists.txt @@ -3,6 +3,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) ADD_LIBRARY(pppoe SHARED pppoe.c mac_filter.c + dpado.c cli.c ) diff --git a/accel-pptpd/ctrl/pppoe/cli.c b/accel-pptpd/ctrl/pppoe/cli.c index c3088aa..7a62952 100644 --- a/accel-pptpd/ctrl/pppoe/cli.c +++ b/accel-pptpd/ctrl/pppoe/cli.c @@ -77,7 +77,7 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, static void set_verbose_help(char * const *f, int f_cnt, void *cli) { cli_send(cli, "pppoe set verbose - set verbosity of pppoe logging\r\n"); - cli_send(cli, "pppoe set PADO-delay - set PADO delay (ms)\r\n"); + cli_send(cli, "pppoe set PADO-delay - set PADO delays (ms)\r\n"); cli_send(cli, "pppoe set Service-Name - set Service-Name to respond\r\n"); cli_send(cli, "pppoe set Service-Name * - respond with client's Service-Name\r\n"); cli_send(cli, "pppoe set AC-Name - set AC-Name tag value\r\n"); @@ -102,7 +102,7 @@ static int show_pado_delay_exec(const char *cmd, char * const *f, int f_cnt, voi if (f_cnt != 3) return CLI_CMD_SYNTAX; - cli_sendv(cli, "%i\r\n", conf_pado_delay); + cli_sendv(cli, "%s\r\n", conf_pado_delay); return CLI_CMD_OK; } @@ -147,18 +147,12 @@ static int set_verbose_exec(const char *cmd, char * const *f, int f_cnt, void *c static int set_pado_delay_exec(const char *cmd, char * const *f, int f_cnt, void *cli) { - char *endptr; - int d; - if (f_cnt != 4) return CLI_CMD_SYNTAX; - - d = strtol(f[3], &endptr, 10); - if (*endptr || d < 0) + + if (dpado_parse(f[3])) return CLI_CMD_INVAL; - - conf_pado_delay = d; - + return CLI_CMD_OK; } diff --git a/accel-pptpd/ctrl/pppoe/dpado.c b/accel-pptpd/ctrl/pppoe/dpado.c new file mode 100644 index 0000000..765803c --- /dev/null +++ b/accel-pptpd/ctrl/pppoe/dpado.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "list.h" +#include "cli.h" +#include "triton.h" +#include "log.h" +#include "memdebug.h" + +#include "pppoe.h" + +struct dpado_range_t +{ + struct list_head entry; + unsigned int conn_cnt; + int pado_delay; +}; + +static pthread_mutex_t dpado_range_lock = PTHREAD_MUTEX_INITIALIZER; +static LIST_HEAD(dpado_range_list); +static struct dpado_range_t *dpado_range_next; +static struct dpado_range_t *dpado_range_prev; +int pado_delay; + +void dpado_check_next(int conn_cnt) +{ + pthread_mutex_lock(&dpado_range_lock); + if (dpado_range_next && conn_cnt == dpado_range_next->conn_cnt) { + pado_delay = dpado_range_next->pado_delay; + dpado_range_prev = dpado_range_next; + if (dpado_range_next->entry.next != &dpado_range_list) + dpado_range_next = list_entry(dpado_range_next->entry.next, typeof(*dpado_range_next), entry); + else + dpado_range_next = NULL; + printf("active=%i, prev=%i:%i, next=%i:%i, pado_delay=%i\n", stat_active, + dpado_range_prev?dpado_range_prev->pado_delay:0,dpado_range_prev?dpado_range_prev->conn_cnt:0, + dpado_range_next?dpado_range_next->pado_delay:0,dpado_range_next?dpado_range_next->conn_cnt:0, + pado_delay); + } + pthread_mutex_unlock(&dpado_range_lock); +} + +void dpado_check_prev(int conn_cnt) +{ + pthread_mutex_lock(&dpado_range_lock); + if (dpado_range_prev && conn_cnt == dpado_range_prev->conn_cnt) { + dpado_range_next = dpado_range_prev; + dpado_range_prev = list_entry(dpado_range_prev->entry.prev, typeof(*dpado_range_prev), entry); + pado_delay = dpado_range_prev->pado_delay; + printf("active=%i, prev=%i:%i, next=%i:%i, pado_delay=%i\n", stat_active, + dpado_range_prev?dpado_range_prev->pado_delay:0,dpado_range_prev?dpado_range_prev->conn_cnt:0, + dpado_range_next?dpado_range_next->pado_delay:0,dpado_range_next?dpado_range_next->conn_cnt:0, + pado_delay); + } + pthread_mutex_unlock(&dpado_range_lock); +} + +static void strip(char *str) +{ + char *ptr = str; + char *endptr = strchr(str, 0); + while (1) { + ptr = strchr(ptr, ' '); + if (ptr) + memmove(ptr, ptr + 1, endptr - ptr - 1); + else + break; + } +} + +int dpado_parse(const char *str) +{ + char *str1 = _strdup(str); + char *ptr1, *ptr2, *ptr3, *endptr; + LIST_HEAD(range_list); + struct dpado_range_t *r; + + strip(str1); + + ptr1 = str1; + + while (1) { + ptr2 = strchr(ptr1, ','); + if (ptr2) + *ptr2 = 0; + ptr3 = strchr(ptr1, ':'); + if (ptr3) + *ptr3 = 0; + + r = _malloc(sizeof(*r)); + memset(r, 0, sizeof(*r)); + + r->pado_delay = strtol(ptr1, &endptr, 10); + if (*endptr) + goto out_err; + + if (list_empty(&range_list)) + r->conn_cnt = INT_MAX; + else { + if (!ptr3) + goto out_err; + r->conn_cnt = strtol(ptr3 + 1, &endptr, 10); + if (*endptr) + goto out_err; + } + + list_add_tail(&r->entry, &range_list); + printf("parsed range: %i:%i\n", r->pado_delay, r->conn_cnt); + + if (!ptr2) + break; + + ptr1 = ptr2 + 1; + } + + pthread_mutex_lock(&dpado_range_lock); + while (!list_empty(&dpado_range_list)) { + r = list_entry(dpado_range_list.next, typeof(*r), entry); + list_del(&r->entry); + _free(r); + } + + dpado_range_next = NULL; + dpado_range_prev = NULL; + + while (!list_empty(&range_list)) { + r = list_entry(range_list.next, typeof(*r), entry); + list_del(&r->entry); + list_add_tail(&r->entry, &dpado_range_list); + + if (!dpado_range_prev || stat_active >= r->conn_cnt) + dpado_range_prev = r; + else if (!dpado_range_next) + dpado_range_next = r; + } + + pado_delay = dpado_range_prev->pado_delay; + + if (conf_pado_delay) + _free(conf_pado_delay); + conf_pado_delay = _strdup(str); + printf("active=%i, prev=%i:%i, next=%i:%i, pado_delay=%i\n", stat_active, + dpado_range_prev?dpado_range_prev->pado_delay:0,dpado_range_prev?dpado_range_prev->conn_cnt:0, + dpado_range_next?dpado_range_next->pado_delay:0,dpado_range_next?dpado_range_next->conn_cnt:0, + pado_delay); + + pthread_mutex_unlock(&dpado_range_lock); + + _free(str1); + return 0; + +out_err: + _free(str1); + log_emerg("pppoe: pado_delay: invalid format\n"); + return -1; +} + diff --git a/accel-pptpd/ctrl/pppoe/pppoe.c b/accel-pptpd/ctrl/pppoe/pppoe.c index 57342ba..89525bc 100644 --- a/accel-pptpd/ctrl/pppoe/pppoe.c +++ b/accel-pptpd/ctrl/pppoe/pppoe.c @@ -59,16 +59,16 @@ struct delayed_pado_t int conf_verbose; char *conf_service_name; char *conf_ac_name; -int conf_pado_delay; int conf_ifname_in_sid; +char *conf_pado_delay; static int shutdown_soft; static mempool_t conn_pool; static mempool_t pado_pool; -uint32_t stat_active; -uint32_t stat_delayed_pado; +unsigned int stat_active; +unsigned int stat_delayed_pado; pthread_rwlock_t serv_lock = PTHREAD_RWLOCK_INITIALIZER; LIST_HEAD(serv_list); @@ -83,7 +83,7 @@ static int init_secret(struct pppoe_serv_t *serv); static void disconnect(struct pppoe_conn_t *conn) { if (conn->ppp_started) { - __sync_sub_and_fetch(&stat_active, 1); + dpado_check_prev(__sync_fetch_and_sub(&stat_active, 1)); conn->ppp_started = 0; ppp_terminate(&conn->ppp, TERM_USER_REQUEST, 1); } @@ -132,7 +132,7 @@ static void ppp_finished(struct ppp_t *ppp) log_ppp_debug("pppoe: ppp finished\n"); if (conn->ppp_started) { - __sync_sub_and_fetch(&stat_active, 1); + dpado_check_prev(__sync_fetch_and_sub(&stat_active, 1)); conn->ppp_started = 0; triton_context_call(&conn->ctx, (triton_event_func)disconnect, conn); } @@ -270,9 +270,10 @@ static void connect_channel(struct pppoe_conn_t *conn) if (establish_ppp(&conn->ppp)) goto out_err_close; - __sync_add_and_fetch(&stat_active, 1); conn->ppp_started = 1; + dpado_check_next(__sync_add_and_fetch(&stat_active, 1)); + return; out_err_close: @@ -647,7 +648,7 @@ static void pppoe_recv_PADI(struct pppoe_serv_t *serv, uint8_t *pack, int size) int n, service_match = 0; struct delayed_pado_t *pado; - if (shutdown_soft) + if (shutdown_soft || pado_delay == -1) return; if (hdr->sid) { @@ -692,7 +693,7 @@ static void pppoe_recv_PADI(struct pppoe_serv_t *serv, uint8_t *pack, int size) return; } - if (conf_pado_delay) { + if (pado_delay) { list_for_each_entry(pado, &serv->pado_list, entry) { if (memcmp(pado->addr, ethhdr->h_source, ETH_ALEN)) continue; @@ -721,7 +722,7 @@ static void pppoe_recv_PADI(struct pppoe_serv_t *serv, uint8_t *pack, int size) } pado->timer.expire = pado_timer; - pado->timer.period = conf_pado_delay; + pado->timer.period = pado_delay; triton_timer_add(&serv->ctx, &pado->timer, 0); @@ -1202,8 +1203,8 @@ static void __init pppoe_init(void) if (opt->val && strlen(opt->val)) conf_service_name = _strdup(opt->val); } else if (!strcmp(opt->name, "pado-delay") || !strcmp(opt->name, "PADO-delay")) { - if (opt->val && atoi(opt->val) > 0) - conf_pado_delay = atoi(opt->val); + if (dpado_parse(opt->val)) + _exit(EXIT_FAILURE); } else if (!strcmp(opt->name, "ifname-in-sid")) { if (!opt->val) continue; diff --git a/accel-pptpd/ctrl/pppoe/pppoe.h b/accel-pptpd/ctrl/pppoe/pppoe.h index 5db3a49..323715d 100644 --- a/accel-pptpd/ctrl/pppoe/pppoe.h +++ b/accel-pptpd/ctrl/pppoe/pppoe.h @@ -85,10 +85,10 @@ struct pppoe_serv_t extern int conf_verbose; extern char *conf_service_name; extern char *conf_ac_name; -extern int conf_pado_delay; +extern char *conf_pado_delay; -extern uint32_t stat_active; -extern uint32_t stat_delayed_pado; +extern unsigned int stat_active; +extern unsigned int stat_delayed_pado; extern pthread_rwlock_t serv_lock; extern struct list_head serv_list; @@ -97,5 +97,10 @@ int mac_filter_check(const uint8_t *addr); void pppoe_server_start(const char *intf, void *client); void pppoe_server_stop(const char *intf); +extern int pado_delay; +void dpado_check_next(int conn_cnt); +void dpado_check_prev(int conn_cnt); +int dpado_parse(const char *str); + #endif -- cgit v1.2.3