kernel accel: if switching takes a long time, back off
That can happen even with not many sessions, e.g. on a loaded machine with a lot of routes
This commit is contained in:
parent
b2942b3c53
commit
a56de89a4c
1 changed files with 19 additions and 7 deletions
26
l2tpns.c
26
l2tpns.c
|
|
@ -140,6 +140,7 @@ 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
|
#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
|
static int kernel_switches = 0; // How many kernel switches we performed since last cleanup
|
||||||
|
static double last_poll_time = 0; // Last time we polled fds
|
||||||
linked_list *loaded_plugins;
|
linked_list *loaded_plugins;
|
||||||
linked_list *plugins[MAX_PLUGIN_TYPES];
|
linked_list *plugins[MAX_PLUGIN_TYPES];
|
||||||
|
|
||||||
|
|
@ -1387,7 +1388,7 @@ 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
|
||||||
// If now is 0, we may delay this if we have already made a lot of switches since last cleanup
|
// 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)
|
static void set_kernel_accel(sessionidt s, int set, int nodelay)
|
||||||
{
|
{
|
||||||
if (set && !can_kernel_accel(s))
|
if (set && !can_kernel_accel(s))
|
||||||
/* Still cannot enable it */
|
/* Still cannot enable it */
|
||||||
|
|
@ -1418,10 +1419,14 @@ static void set_kernel_accel(sessionidt s, int set, int now)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set && !now && kernel_switches >= MAX_KERNEL_SWITCHES)
|
double cur_switch;
|
||||||
|
now(&cur_switch);
|
||||||
|
if (set && !nodelay &&
|
||||||
|
(kernel_switches >= MAX_KERNEL_SWITCHES
|
||||||
|
|| cur_switch - last_poll_time > 0.02))
|
||||||
{
|
{
|
||||||
// We already performed many switches, throttle a bit by just
|
// We have already been switching a lot or working at for 20ms since last poll,
|
||||||
// marking as pending
|
// throttle a bit by just marking as pending
|
||||||
sess_local[s].needs_switch = 1;
|
sess_local[s].needs_switch = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -5999,7 +6004,7 @@ static void mainloop(void)
|
||||||
n = epoll_wait(epollfd, events, maxevent, 100); // timeout 100ms (1/10th sec)
|
n = epoll_wait(epollfd, events, maxevent, 100); // timeout 100ms (1/10th sec)
|
||||||
STAT(select_called);
|
STAT(select_called);
|
||||||
|
|
||||||
TIME = now(NULL);
|
TIME = now(&last_poll_time);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
{
|
{
|
||||||
if (errno == EINTR ||
|
if (errno == EINTR ||
|
||||||
|
|
@ -6387,7 +6392,7 @@ static void mainloop(void)
|
||||||
// Handle trying to enable kernel accel
|
// Handle trying to enable kernel accel
|
||||||
{
|
{
|
||||||
static double last_switch = 0;
|
static double last_switch = 0;
|
||||||
double this_switch;
|
double this_switch, cur_switch;
|
||||||
double diff;
|
double diff;
|
||||||
|
|
||||||
TIME = now(&this_switch);
|
TIME = now(&this_switch);
|
||||||
|
|
@ -6399,14 +6404,21 @@ static void mainloop(void)
|
||||||
{
|
{
|
||||||
kernel_switches = 0;
|
kernel_switches = 0;
|
||||||
|
|
||||||
|
cur_switch = this_switch;
|
||||||
for (i = 1; i <= config->cluster_highest_sessionid; i++)
|
for (i = 1; i <= config->cluster_highest_sessionid; i++)
|
||||||
{
|
{
|
||||||
// Delayed kernel switch
|
// Delayed kernel switch
|
||||||
if (session[i].ppp.lcp == Opened && sess_local[i].needs_switch)
|
if (session[i].ppp.lcp == Opened && sess_local[i].needs_switch)
|
||||||
|
{
|
||||||
set_kernel_accel(i, can_kernel_accel(i), 0);
|
set_kernel_accel(i, can_kernel_accel(i), 0);
|
||||||
|
TIME = now(&cur_switch);
|
||||||
|
if (cur_switch - this_switch > 0.02)
|
||||||
|
// We have already taken 20ms sec doing switches, backoff
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
last_switch = this_switch;
|
last_switch = cur_switch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue