diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-05-02 14:30:37 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-05-02 14:30:37 +0400 |
commit | aff9450a3b95e848f761533a4c659269477a2fd4 (patch) | |
tree | 4b2eb94d5661aeeffced9daffe6e91ffd3598525 | |
parent | 7d5c456ceba4732293aa0e85c6fef87a48daa5a6 (diff) | |
download | accel-ppp-aff9450a3b95e848f761533a4c659269477a2fd4.tar.gz accel-ppp-aff9450a3b95e848f761533a4c659269477a2fd4.zip |
ppp: implemented adaptive lcp echo functionality
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 3 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp_lcp.c | 78 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp_lcp.h | 4 |
3 files changed, 71 insertions, 14 deletions
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 201ade7..71163db 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -174,6 +174,9 @@ seconds. .BI "lcp-echo-failure=" n Specifies maximum number of echo-requests may be sent without valid echo-reply, if exceeds connection will be terminated. .TP +.BI "lcp-echo-timeout=" sec +Specifies timeout in seconds to wait for any peer activity. If this option specified it turns on adaptive lcp echo functionality and "lcp-echo-failure" is not used. +.TP .SH [dns] .TP .BI "dns1=" x.x.x.x diff --git a/accel-pppd/ppp/ppp_lcp.c b/accel-pppd/ppp/ppp_lcp.c index cc07997..5813517 100644 --- a/accel-pppd/ppp/ppp_lcp.c +++ b/accel-pppd/ppp/ppp_lcp.c @@ -1,6 +1,7 @@ #include <stdlib.h> #include <string.h> #include <sys/socket.h> +#include <sys/ioctl.h> #include <arpa/inet.h> #include "linux_ppp.h" @@ -23,8 +24,9 @@ struct recv_opt_t struct lcp_option_t *lopt; }; -static int conf_echo_interval = 0; -static int conf_echo_failure = 3; +static int conf_echo_interval = 10; +static int conf_echo_failure = 0; +static int conf_echo_timeout = 60; static LIST_HEAD(option_handlers); static struct ppp_layer_t lcp_layer; @@ -575,6 +577,21 @@ static int lcp_recv_conf_ack(struct ppp_lcp_t *lcp, uint8_t *data, int size) return res; } +static void lcp_update_echo_timer(struct ppp_lcp_t *lcp) +{ + if (lcp->echo_timer.period != conf_echo_interval * 1000) { + if (!conf_echo_interval) + triton_timer_del(&lcp->echo_timer); + else { + lcp->echo_timer.period = conf_echo_interval * 1000; + if (lcp->echo_timer.tpd) + triton_timer_mod(&lcp->echo_timer, 0); + else + triton_timer_add(lcp->ppp->ctrl->ctx, &lcp->echo_timer, 0); + } + } +} + static void lcp_recv_echo_repl(struct ppp_lcp_t *lcp, uint8_t *data, int size) { uint32_t magic; @@ -594,8 +611,8 @@ static void lcp_recv_echo_repl(struct ppp_lcp_t *lcp, uint8_t *data, int size) } } - lcp->fsm.id++; lcp->echo_sent = 0; + lcp_update_echo_timer(lcp); } static void send_echo_reply(struct ppp_lcp_t *lcp) @@ -604,6 +621,7 @@ static void send_echo_reply(struct ppp_lcp_t *lcp) //uint32_t magic = *(uint32_t *)(hdr + 1); lcp->echo_sent = 0; + lcp_update_echo_timer(lcp); hdr->code = ECHOREP; *(uint32_t *)(hdr + 1) = htonl(lcp->magic); @@ -617,6 +635,9 @@ static void send_echo_reply(struct ppp_lcp_t *lcp) static void send_echo_request(struct triton_timer_t *t) { struct ppp_lcp_t *lcp = container_of(t, typeof(*lcp), echo_timer); + struct ifpppstatsreq ifreq; + int f = 0; + time_t ts; struct lcp_echo_req_t { struct lcp_hdr_t hdr; @@ -624,27 +645,56 @@ static void send_echo_request(struct triton_timer_t *t) } __attribute__((packed)) msg = { .hdr.proto = htons(PPP_LCP), .hdr.code = ECHOREQ, - .hdr.id = lcp->fsm.id, + .hdr.id = lcp->fsm.id++, .hdr.len = htons(8), .magic = lcp->magic, }; - if (++lcp->echo_sent > lcp->echo_failure) { + ++lcp->echo_sent; + + if (conf_echo_timeout) { + if (lcp->echo_sent == 2) { + memset(&ifreq, 0, sizeof(ifreq)); + ifreq.stats_ptr = (void *)&ifreq.stats; + strcpy(ifreq.ifr__name, lcp->ppp->ifname); + + if (ioctl(sock_fd, SIOCGPPPSTATS, &ifreq) == 0) + lcp->last_ipackets = ifreq.stats.p.ppp_ipackets; + + time(&lcp->last_echo_ts); + } else if (lcp->echo_sent > 2) { + time(&ts); + memset(&ifreq, 0, sizeof(ifreq)); + ifreq.stats_ptr = (void *)&ifreq.stats; + strcpy(ifreq.ifr__name, lcp->ppp->ifname); + if (ioctl(sock_fd, SIOCGPPPSTATS, &ifreq) == 0 && lcp->last_ipackets != ifreq.stats.p.ppp_ipackets) { + lcp->echo_sent = 1; + lcp_update_echo_timer(lcp); + } else if (ts - lcp->last_echo_ts > conf_echo_timeout) { + f = 1; + } else if (t->period > 3000) { + t->period = 0.8 * t->period; + triton_timer_mod(t, 0); + } + } + } else if (lcp->echo_sent > conf_echo_failure) + f = 1; + + if (f) { log_ppp_warn("lcp: no echo reply\n"); ppp_terminate(lcp->ppp, TERM_LOST_CARRIER, 1); - } else { - if (conf_ppp_verbose) - log_ppp_debug("send [LCP EchoReq id=%x <magic %x>]\n", msg.hdr.id, msg.magic); + return; + } + + if (conf_ppp_verbose) { + log_ppp_debug("send [LCP EchoReq id=%x <magic %x>]\n", msg.hdr.id, msg.magic); ppp_chan_send(lcp->ppp,&msg,ntohs(msg.hdr.len)+2); } } static void start_echo(struct ppp_lcp_t *lcp) { - lcp->echo_interval = conf_echo_interval; - lcp->echo_failure = conf_echo_failure; - - lcp->echo_timer.period = lcp->echo_interval * 1000; + lcp->echo_timer.period = conf_echo_interval * 1000; lcp->echo_timer.expire = send_echo_request; if (lcp->echo_timer.period && !lcp->echo_timer.tpd) triton_timer_add(lcp->ppp->ctrl->ctx, &lcp->echo_timer, 0); @@ -871,6 +921,10 @@ static void load_config(void) opt = conf_get_opt("ppp", "lcp-echo-failure"); if (opt && atoi(opt) >= 0) conf_echo_failure = atoi(opt); + + opt = conf_get_opt("ppp", "lcp-echo-timeout"); + if (opt && atoi(opt) >= 0) + conf_echo_timeout = atoi(opt); } static void lcp_init(void) diff --git a/accel-pppd/ppp/ppp_lcp.h b/accel-pppd/ppp/ppp_lcp.h index 6d67b69..465f0e9 100644 --- a/accel-pppd/ppp/ppp_lcp.h +++ b/accel-pppd/ppp/ppp_lcp.h @@ -118,10 +118,10 @@ struct ppp_lcp_t struct list_head options; struct triton_timer_t echo_timer; - int echo_interval; - int echo_failure; int echo_sent; int magic; + unsigned long last_ipackets; + time_t last_echo_ts; struct list_head ropt_list; // last received ConfReq int ropt_len; |