summaryrefslogtreecommitdiff
path: root/accel-pppd/ppp/ppp.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/ppp/ppp.c')
-rw-r--r--accel-pppd/ppp/ppp.c144
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) {