Throttle switching kernel acceleration
Creating/destroying interfaces etc. does take some time. When e.g. receiving a lot of sessions as new slave, we don't want to stay stuck creating hundreds of interfaces while we are already receiving control messages that we have to forward to master not too late. Switching kernel acceleration can wait a bit most of the time.
This commit is contained in:
parent
a22295d804
commit
a957ff08ee
2 changed files with 52 additions and 10 deletions
59
l2tpns.c
59
l2tpns.c
|
|
@ -137,6 +137,8 @@ static char time_now_string[64] = {0}; // Current time as a string.
|
||||||
static int time_changed = 0; // time_now changed
|
static int time_changed = 0; // time_now changed
|
||||||
char main_quit = 0; // True if we're in the process of exiting.
|
char main_quit = 0; // True if we're in the process of exiting.
|
||||||
static char main_reload = 0; // Re-load pending
|
static char main_reload = 0; // Re-load pending
|
||||||
|
#define MAX_KERNEL_SWITCHES 20 // Maximum number of kernel switches per 1/10th second
|
||||||
|
static int kernel_switches = 0; // How many kernel switches we performed since last cleanup
|
||||||
linked_list *loaded_plugins;
|
linked_list *loaded_plugins;
|
||||||
linked_list *plugins[MAX_PLUGIN_TYPES];
|
linked_list *plugins[MAX_PLUGIN_TYPES];
|
||||||
|
|
||||||
|
|
@ -1280,7 +1282,8 @@ static int delete_kernel_accel(sessionidt s)
|
||||||
//
|
//
|
||||||
// Enable (set=1) or disable (set=0) kernel PPP acceleration
|
// Enable (set=1) or disable (set=0) kernel PPP acceleration
|
||||||
// This basically calls create/delete_kernel_accel, but also updates routes
|
// This basically calls create/delete_kernel_accel, but also updates routes
|
||||||
static void set_kernel_accel(sessionidt s, int set)
|
// If now is 0, we may delay this if we have already made a lot of switches since last cleanup
|
||||||
|
static void set_kernel_accel(sessionidt s, int set, int now)
|
||||||
{
|
{
|
||||||
if (set && !can_kernel_accel(s))
|
if (set && !can_kernel_accel(s))
|
||||||
/* Still cannot enable it */
|
/* Still cannot enable it */
|
||||||
|
|
@ -1291,6 +1294,16 @@ static void set_kernel_accel(sessionidt s, int set)
|
||||||
/* We don't know the tunnel yet */
|
/* We don't know the tunnel yet */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (set && !now && kernel_switches >= MAX_KERNEL_SWITCHES)
|
||||||
|
{
|
||||||
|
// We already performed many switches, throttle a bit by just
|
||||||
|
// marking as pending
|
||||||
|
sess_local[s].needs_switch = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
kernel_switches++;
|
||||||
|
sess_local[s].needs_switch = 0;
|
||||||
|
|
||||||
routesset(s, &session[s], 0);
|
routesset(s, &session[s], 0);
|
||||||
if (session[s].ppp.ipv6cp == Opened)
|
if (session[s].ppp.ipv6cp == Opened)
|
||||||
routes6set(s, &session[s], 0);
|
routes6set(s, &session[s], 0);
|
||||||
|
|
@ -1323,7 +1336,7 @@ void switch_kernel_accel(sessionidt s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Try to enable */
|
/* Try to enable */
|
||||||
set_kernel_accel(s, 1);
|
set_kernel_accel(s, 1, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1334,7 +1347,7 @@ void switch_kernel_accel(sessionidt s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Has to disable it */
|
/* Has to disable it */
|
||||||
set_kernel_accel(s, 0);
|
set_kernel_accel(s, 0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5805,7 +5818,7 @@ static void mainloop(void)
|
||||||
sessionidt sid;
|
sessionidt sid;
|
||||||
for (sid = 1; sid <= config->cluster_highest_sessionid ; ++sid)
|
for (sid = 1; sid <= config->cluster_highest_sessionid ; ++sid)
|
||||||
if (session[sid].tunnel == tid)
|
if (session[sid].tunnel == tid)
|
||||||
set_kernel_accel(sid, 0);
|
set_kernel_accel(sid, 0, 1);
|
||||||
|
|
||||||
delete_kernel_tunnel(tid);
|
delete_kernel_tunnel(tid);
|
||||||
}
|
}
|
||||||
|
|
@ -5833,12 +5846,12 @@ static void mainloop(void)
|
||||||
if (s < 0)
|
if (s < 0)
|
||||||
{
|
{
|
||||||
LOG(1, sid, tid, "Error on pppox socket: %s\n", strerror(errno));
|
LOG(1, sid, tid, "Error on pppox socket: %s\n", strerror(errno));
|
||||||
set_kernel_accel(sid, 0);
|
set_kernel_accel(sid, 0, 1);
|
||||||
}
|
}
|
||||||
else if (s == 0)
|
else if (s == 0)
|
||||||
{
|
{
|
||||||
LOG(1, sid, tid, "EOF on pppox socket\n");
|
LOG(1, sid, tid, "EOF on pppox socket\n");
|
||||||
set_kernel_accel(sid, 0);
|
set_kernel_accel(sid, 0, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -5857,12 +5870,12 @@ static void mainloop(void)
|
||||||
if (s < 0)
|
if (s < 0)
|
||||||
{
|
{
|
||||||
LOG(1, sid, tid, "Error on ppp channel: %s\n", strerror(errno));
|
LOG(1, sid, tid, "Error on ppp channel: %s\n", strerror(errno));
|
||||||
set_kernel_accel(sid, 0);
|
set_kernel_accel(sid, 0, 1);
|
||||||
}
|
}
|
||||||
else if (s == 0)
|
else if (s == 0)
|
||||||
{
|
{
|
||||||
LOG(1, sid, tid, "EOF on ppp channel\n");
|
LOG(1, sid, tid, "EOF on ppp channel\n");
|
||||||
set_kernel_accel(sid, 0);
|
set_kernel_accel(sid, 0, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
processppp_from_kernel(sid, p, s, NULL);
|
processppp_from_kernel(sid, p, s, NULL);
|
||||||
|
|
@ -5878,12 +5891,12 @@ static void mainloop(void)
|
||||||
if (s < 0)
|
if (s < 0)
|
||||||
{
|
{
|
||||||
LOG(1, sid, tid, "Error on ppp if: %s\n", strerror(errno));
|
LOG(1, sid, tid, "Error on ppp if: %s\n", strerror(errno));
|
||||||
set_kernel_accel(sid, 0);
|
set_kernel_accel(sid, 0, 1);
|
||||||
}
|
}
|
||||||
else if (s == 0)
|
else if (s == 0)
|
||||||
{
|
{
|
||||||
LOG(1, sid, tid, "EOF on ppp if\n");
|
LOG(1, sid, tid, "EOF on ppp if\n");
|
||||||
set_kernel_accel(sid, 0);
|
set_kernel_accel(sid, 0, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
processppp_from_kernel(sid, p, s, NULL);
|
processppp_from_kernel(sid, p, s, NULL);
|
||||||
|
|
@ -6051,6 +6064,32 @@ static void mainloop(void)
|
||||||
next_cluster_ping = TIME + config->cluster_hb_interval;
|
next_cluster_ping = TIME + config->cluster_hb_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle trying to enable kernel accel
|
||||||
|
{
|
||||||
|
static double last_switch = 0;
|
||||||
|
double this_switch;
|
||||||
|
double diff;
|
||||||
|
|
||||||
|
TIME = now(&this_switch);
|
||||||
|
diff = this_switch - last_switch;
|
||||||
|
|
||||||
|
// Run during idle time (after we've handled
|
||||||
|
// all incoming packets) or every 1/10th sec
|
||||||
|
if (!more || diff > 0.1)
|
||||||
|
{
|
||||||
|
kernel_switches = 0;
|
||||||
|
|
||||||
|
for (i = 1; i <= config->cluster_highest_sessionid; i++)
|
||||||
|
{
|
||||||
|
// Delayed kernel switch
|
||||||
|
if (session[i].ppp.lcp == Opened && sess_local[i].needs_switch)
|
||||||
|
set_kernel_accel(i, can_kernel_accel(i), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
last_switch = this_switch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!config->cluster_iam_master)
|
if (!config->cluster_iam_master)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
||||||
3
l2tpns.h
3
l2tpns.h
|
|
@ -452,6 +452,9 @@ typedef struct
|
||||||
// time in milliseconds of the last fragment.
|
// time in milliseconds of the last fragment.
|
||||||
uint64_t prev_time;
|
uint64_t prev_time;
|
||||||
|
|
||||||
|
// Pending kernel switch
|
||||||
|
int needs_switch;
|
||||||
|
|
||||||
// l2tp PPPoL2TP socket
|
// l2tp PPPoL2TP socket
|
||||||
int pppox_fd;
|
int pppox_fd;
|
||||||
struct pppol2tp_ioc_stats last_stats;
|
struct pppol2tp_ioc_stats last_stats;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue