diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-06-05 14:24:31 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-06-05 14:27:57 +0400 |
commit | fa315a7a7584f6f4954888c010e3cc84c2b33330 (patch) | |
tree | 778396449f9e19c52d8b83e7fabdb1c37706e16f /accel-pppd/ppp/ppp.c | |
parent | 6f01783f2b67cd0b82805240f2aeea9a39606d65 (diff) | |
download | accel-ppp-fa315a7a7584f6f4954888c010e3cc84c2b33330.tar.gz accel-ppp-fa315a7a7584f6f4954888c010e3cc84c2b33330.zip |
ppp: implemented unit cache
If enabled accel-pppd will not destroy interface immediately after corresponding session is terminated, instead interface will be brought down and placed to cache for later use for new sessions.
It should reduce kernel interface creation/deletion rate lack and increase responsibility of daemon
Diffstat (limited to 'accel-pppd/ppp/ppp.c')
-rw-r--r-- | accel-pppd/ppp/ppp.c | 144 |
1 files changed, 79 insertions, 65 deletions
diff --git a/accel-pppd/ppp/ppp.c b/accel-pppd/ppp/ppp.c index 4f3beb9..814240c 100644 --- a/accel-pppd/ppp/ppp.c +++ b/accel-pppd/ppp/ppp.c @@ -5,10 +5,11 @@ #include <stdint.h> #include <string.h> #include <errno.h> -#include <sys/ioctl.h> #include <arpa/inet.h> #include <features.h> #include <signal.h> +#include <sys/socket.h> +#include <sys/ioctl.h> #include "linux_ppp.h" #include "crypto.h" @@ -18,6 +19,7 @@ #include "events.h" #include "ppp.h" #include "ppp_fsm.h" +#include "ipdb.h" #include "log.h" #include "spinlock.h" #include "mempool.h" @@ -27,6 +29,7 @@ int __export conf_ppp_verbose; int conf_sid_ucase; int conf_single_session = -1; +int conf_unit_cache = 0; pthread_rwlock_t __export ppp_lock = PTHREAD_RWLOCK_INITIALIZER; __export LIST_HEAD(ppp_list); @@ -55,6 +58,18 @@ struct layer_node_t struct list_head items; }; +struct pppunit_cache +{ + struct list_head entry; + int fd; + int unit_idx; +}; + +static pthread_mutex_t uc_lock = PTHREAD_MUTEX_INITIALIZER; +static LIST_HEAD(uc_list); +static int uc_size; +static mempool_t uc_pool; + static int ppp_chan_read(struct triton_md_handler_t*); static int ppp_unit_read(struct triton_md_handler_t*); static void init_layers(struct ppp_t *); @@ -68,6 +83,9 @@ void __export ppp_init(struct ppp_t *ppp) INIT_LIST_HEAD(&ppp->chan_handlers); INIT_LIST_HEAD(&ppp->unit_handlers); INIT_LIST_HEAD(&ppp->pd_list); + ppp->fd = -1; + ppp->chan_fd = -1; + ppp->unit_fd = -1; } static void generate_sessionid(struct ppp_t *ppp) @@ -91,6 +109,7 @@ static void generate_sessionid(struct ppp_t *ppp) int __export establish_ppp(struct ppp_t *ppp) { struct ifreq ifr; + struct pppunit_cache *uc = NULL; /* Open an instance of /dev/ppp and connect the channel to it */ if (ioctl(ppp->fd, PPPIOCGCHAN, &ppp->chan_idx) == -1) { @@ -111,18 +130,39 @@ int __export establish_ppp(struct ppp_t *ppp) goto exit_close_chan; } - ppp->unit_fd = open("/dev/ppp", O_RDWR); - if (ppp->unit_fd < 0) { - log_ppp_error("open(unit) /dev/ppp: %s\n", strerror(errno)); - goto exit_close_chan; + if (uc_size) { + pthread_mutex_lock(&uc_lock); + if (!list_empty(&uc_list)) { + uc = list_entry(uc_list.next, typeof(*uc), entry); + list_del(&uc->entry); + --uc_size; + } + pthread_mutex_unlock(&uc_lock); } - - fcntl(ppp->unit_fd, F_SETFD, fcntl(ppp->unit_fd, F_GETFD) | FD_CLOEXEC); - ppp->unit_idx = -1; - if (ioctl(ppp->unit_fd, PPPIOCNEWUNIT, &ppp->unit_idx) < 0) { - log_ppp_error("ioctl(PPPIOCNEWUNIT): %s\n", strerror(errno)); - goto exit_close_unit; + if (uc) { + ppp->unit_fd = uc->fd; + ppp->unit_idx = uc->unit_idx; + mempool_free(uc); + } else { + ppp->unit_fd = open("/dev/ppp", O_RDWR); + if (ppp->unit_fd < 0) { + log_ppp_error("open(unit) /dev/ppp: %s\n", strerror(errno)); + goto exit_close_chan; + } + + fcntl(ppp->unit_fd, F_SETFD, fcntl(ppp->unit_fd, F_GETFD) | FD_CLOEXEC); + + ppp->unit_idx = -1; + if (ioctl(ppp->unit_fd, PPPIOCNEWUNIT, &ppp->unit_idx) < 0) { + log_ppp_error("ioctl(PPPIOCNEWUNIT): %s\n", strerror(errno)); + goto exit_close_unit; + } + + if (fcntl(ppp->unit_fd, F_SETFL, O_NONBLOCK)) { + log_ppp_error("ppp: cann't to set nonblocking mode: %s\n", strerror(errno)); + goto exit_close_unit; + } } if (ioctl(ppp->chan_fd, PPPIOCCONNECT, &ppp->unit_idx) < 0) { @@ -135,11 +175,6 @@ int __export establish_ppp(struct ppp_t *ppp) goto exit_close_unit; } - if (fcntl(ppp->unit_fd, F_SETFL, O_NONBLOCK)) { - log_ppp_error("ppp: cann't to set nonblocking mode: %s\n", strerror(errno)); - goto exit_close_unit; - } - ppp->start_time = time(NULL); generate_sessionid(ppp); sprintf(ppp->ifname, "ppp%i", ppp->unit_idx); @@ -202,6 +237,8 @@ exit_close_chan: static void destablish_ppp(struct ppp_t *ppp) { + struct pppunit_cache *uc; + triton_event_fire(EV_PPP_PRE_FINISHED, ppp); pthread_rwlock_wrlock(&ppp_lock); @@ -223,7 +260,18 @@ static void destablish_ppp(struct ppp_t *ppp) triton_md_unregister_handler(&ppp->chan_hnd); triton_md_unregister_handler(&ppp->unit_hnd); - close(ppp->unit_fd); + if (uc_size < conf_unit_cache) { + uc = mempool_alloc(uc_pool); + uc->fd = ppp->unit_fd; + uc->unit_idx = ppp->unit_idx; + + pthread_mutex_lock(&uc_lock); + list_add_tail(&uc->entry, &uc_list); + ++uc_size; + pthread_mutex_unlock(&uc_lock); + } else + close(ppp->unit_fd); + close(ppp->chan_fd); close(ppp->fd); @@ -356,13 +404,15 @@ cont: return 0; } - //printf("ppp_unit_read: "); + //printf("ppp_unit_read: %i\n", ppp->buf_size); + if (ppp->buf_size == 0) + return 0; //print_buf(ppp->buf,ppp->buf_size); - if (ppp->buf_size == 0) { + /*if (ppp->buf_size == 0) { ppp_terminate(ppp, TERM_NAS_ERROR, 1); return 1; - } + }*/ if (ppp->buf_size < 2) { log_ppp_error("ppp_unit_read: short read %i\n", ppp->buf_size); @@ -406,51 +456,6 @@ void ppp_recv_proto_rej(struct ppp_t *ppp, uint16_t proto) } } -static void ppp_ifup(struct ppp_t *ppp) -{ - struct ifreq ifr; - struct npioctl np; - - triton_event_fire(EV_PPP_ACCT_START, ppp); - if (ppp->stop_time) - return; - - triton_event_fire(EV_PPP_PRE_UP, ppp); - if (ppp->stop_time) - return; - - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, ppp->ifname); - - if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr)) - log_ppp_error("ppp: failed to get interface flags: %s\n", strerror(errno)); - - ifr.ifr_flags |= IFF_UP | IFF_POINTOPOINT; - - if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr)) - log_ppp_error("ppp: failed to set interface flags: %s\n", strerror(errno)); - - if (ppp->ipv4) { - np.protocol = PPP_IP; - np.mode = NPMODE_PASS; - - if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np)) - log_ppp_error("ppp: failed to set NP (IPv4) mode: %s\n", strerror(errno)); - } - - if (ppp->ipv6) { - np.protocol = PPP_IPV6; - np.mode = NPMODE_PASS; - - if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np)) - log_ppp_error("ppp: failed to set NP (IPv6) mode: %s\n", strerror(errno)); - } - - ppp->ctrl->started(ppp); - - triton_event_fire(EV_PPP_STARTED, ppp); -} - static void __ppp_layer_started(struct ppp_t *ppp, struct ppp_layer_data_t *d) { struct layer_node_t *n = d->node; @@ -553,6 +558,8 @@ void __export ppp_terminate(struct ppp_t *ppp, int cause, int hard) log_ppp_debug("ppp_terminate\n"); + ppp_ifdown(ppp); + triton_event_fire(EV_PPP_FINISHING, ppp); if (hard) { @@ -749,6 +756,12 @@ static void load_config(void) conf_single_session = 1; } else conf_single_session = -1; + + opt = conf_get_opt("ppp", "unit-cache"); + if (opt && atoi(opt) > 0) + conf_unit_cache = atoi(opt); + else + conf_unit_cache = 0; } static void init(void) @@ -757,6 +770,7 @@ static void init(void) FILE *f; buf_pool = mempool_create(PPP_MRU); + uc_pool = mempool_create(sizeof(struct pppunit_cache)); sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if (sock_fd < 0) { |