count bandwidth in kb/sec to avoid overflows on high bandwidth.

This commit is contained in:
Nikos Mavrogiannopoulos
2013-11-05 20:32:23 +01:00
parent 0759125652
commit 615e16cc41
6 changed files with 47 additions and 33 deletions
+3 -3
View File
@@ -165,8 +165,8 @@ ping-leases = false
# Unset to enable bandwidth restrictions (in bytes/sec). The # Unset to enable bandwidth restrictions (in bytes/sec). The
# setting here is global, but can also be set per user or per group. # setting here is global, but can also be set per user or per group.
#rx-per-sec = 40960 #rx-data-per-sec = 40960
#tx-per-sec = 40960 #tx-data-per-sec = 40960
# The number of packets (of MTU size) that are available in # The number of packets (of MTU size) that are available in
# the output buffer. The default is low to improve latency. # the output buffer. The default is low to improve latency.
@@ -180,7 +180,7 @@ route = 192.168.1.0/255.255.255.0
# per group. Each file name on these directories must match the username # per group. Each file name on these directories must match the username
# or the groupname. # or the groupname.
# The options allowed in the configuration files are ipv?-dns, ipv?-nbns, # The options allowed in the configuration files are ipv?-dns, ipv?-nbns,
# ipv?-network, ipv?-netmask, ipv6-prefix, iroute and route. # ipv?-network, ipv?-netmask, ipv6-prefix, rx/tx-per-sec, iroute and route.
# #
# Note that the 'iroute' option allows to add routes on the server # Note that the 'iroute' option allows to add routes on the server
# based on a user or group. The syntax depends on the input accepted # based on a user or group. The syntax depends on the input accepted
+6 -4
View File
@@ -86,8 +86,8 @@ static struct cfg_options available_options[] = {
{ .name = "min-reauth-time", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "min-reauth-time", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "max-same-clients", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "max-same-clients", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "rx-per-sec", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "rx-data-per-sec", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "tx-per-sec", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "tx-data-per-sec", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "run-as-user", .type = OPTION_STRING, .mandatory = 0 }, { .name = "run-as-user", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "run-as-group", .type = OPTION_STRING, .mandatory = 0 }, { .name = "run-as-group", .type = OPTION_STRING, .mandatory = 0 },
@@ -319,8 +319,10 @@ unsigned prefix = 0;
READ_NUMERIC("mtu", config->default_mtu); READ_NUMERIC("mtu", config->default_mtu);
READ_NUMERIC("output-buffer", config->output_buffer); READ_NUMERIC("output-buffer", config->output_buffer);
READ_NUMERIC("rx-per-sec", config->rx_per_sec); READ_NUMERIC("rx-data-per-sec", config->rx_per_sec);
READ_NUMERIC("tx-per-sec", config->tx_per_sec); READ_NUMERIC("tx-data-per-sec", config->tx_per_sec);
config->rx_per_sec /= 1000; /* in kb */
config->tx_per_sec /= 1000;
READ_NUMERIC("cookie-validity", config->cookie_validity); READ_NUMERIC("cookie-validity", config->cookie_validity);
READ_NUMERIC("auth-timeout", config->auth_timeout); READ_NUMERIC("auth-timeout", config->auth_timeout);
+6 -4
View File
@@ -51,8 +51,8 @@ static struct cfg_options available_options[] = {
{ .name = "ipv4-netmask", .type = OPTION_STRING }, { .name = "ipv4-netmask", .type = OPTION_STRING },
{ .name = "ipv6-prefix", .type = OPTION_NUMERIC }, { .name = "ipv6-prefix", .type = OPTION_NUMERIC },
{ .name = "ipv6-netmask", .type = OPTION_STRING }, { .name = "ipv6-netmask", .type = OPTION_STRING },
{ .name = "rx-per-sec", .type = OPTION_NUMERIC, }, { .name = "rx-data-per-sec", .type = OPTION_NUMERIC, },
{ .name = "tx-per-sec", .type = OPTION_NUMERIC, }, { .name = "tx-data-per-sec", .type = OPTION_NUMERIC, },
}; };
#define READ_RAW_MULTI_LINE(name, s_name, num) \ #define READ_RAW_MULTI_LINE(name, s_name, num) \
@@ -144,8 +144,10 @@ unsigned prefix = 0;
if (prefix > 0) if (prefix > 0)
config->ipv6_netmask = ipv6_prefix_to_mask(prefix); config->ipv6_netmask = ipv6_prefix_to_mask(prefix);
READ_RAW_NUMERIC("rx-per-sec", config->rx_per_sec); READ_RAW_NUMERIC("rx-data-per-sec", config->rx_per_sec);
READ_RAW_NUMERIC("tx-per-sec", config->tx_per_sec); READ_RAW_NUMERIC("tx-data-per-sec", config->tx_per_sec);
config->rx_per_sec /= 1000; /* in kb */
config->tx_per_sec /= 1000; /* in kb */
optionUnloadNested(pov); optionUnloadNested(pov);
+3 -3
View File
@@ -257,8 +257,8 @@ ping-leases = false
# Unset to enable bandwidth restrictions (in bytes/sec). The # Unset to enable bandwidth restrictions (in bytes/sec). The
# setting here is global, but can also be set per user or per group. # setting here is global, but can also be set per user or per group.
#rx-per-sec = 40000 #rx-data-per-sec = 40000
#tx-per-sec = 40000 #tx-data-per-sec = 40000
# The number of packets (of MTU size) that are available in # The number of packets (of MTU size) that are available in
# the output buffer. The default is low to improve latency. # the output buffer. The default is low to improve latency.
@@ -275,7 +275,7 @@ route = 192.168.5.0/255.255.255.0
# per group. Each file name on these directories must match the username # per group. Each file name on these directories must match the username
# or the groupname. # or the groupname.
# The options allowed in the configuration files are ipv?-dns, ipv?-nbns, # The options allowed in the configuration files are ipv?-dns, ipv?-nbns,
# ipv?-network, ipv?-netmask, ipv6-prefix, iroute and route. # ipv?-network, ipv?-netmask, ipv6-prefix, rx/tx-per-sec, iroute and route.
# #
# Note that the 'iroute' option allows to add routes on the server # Note that the 'iroute' option allows to add routes on the server
# based on a user or group. The syntax depends on the input accepted # based on a user or group. The syntax depends on the input accepted
+9 -14
View File
@@ -26,40 +26,35 @@
#include <stdio.h> #include <stdio.h>
#define COUNT_UPDATE_MS 500
int bandwidth_update(bandwidth_st* b, size_t bytes, size_t mtu) int _bandwidth_update(bandwidth_st* b, size_t bytes, size_t mtu)
{ {
size_t sum; size_t sum;
struct timespec now; struct timespec now;
ssize_t t, new_allowed_bytes, remain; ssize_t t, remain;
unsigned int diff; unsigned int diff;
size_t transferred_kb;
/* if bandwidth control is disabled */
if (b->bytes_per_sec == 0)
return 1;
gettime(&now); gettime(&now);
diff = timespec_sub_ms(&now, &b->count_start); diff = timespec_sub_ms(&now, &b->count_start);
if (diff >= COUNT_UPDATE_MS) { if (diff >= COUNT_UPDATE_MS) {
b->transferred_bytes = (b->transferred_bytes*COUNT_UPDATE_MS)/diff; transferred_kb = b->transferred_bytes / 1000;
transferred_kb = (transferred_kb*COUNT_UPDATE_MS)/diff;
memcpy(&b->count_start, &now, sizeof(now)); memcpy(&b->count_start, &now, sizeof(now));
new_allowed_bytes = mtu - 1 + ((b->bytes_per_sec*COUNT_UPDATE_MS)/1000); remain = b->allowed_kb - transferred_kb;
t = b->allowed_kb_per_count + remain;
remain = b->allowed_bytes - b->transferred_bytes; b->allowed_kb = MIN(t, b->kb_per_sec);
t = new_allowed_bytes + remain;
b->allowed_bytes = MIN(t, new_allowed_bytes*1000/COUNT_UPDATE_MS);
b->transferred_bytes = bytes; b->transferred_bytes = bytes;
return 1; return 1;
} }
sum = b->transferred_bytes + bytes; sum = b->transferred_bytes + bytes;
if (sum > b->allowed_bytes) if (sum > b->allowed_kb*1000)
return 0; /* NO */ return 0; /* NO */
b->transferred_bytes = sum; b->transferred_bytes = sum;
+20 -5
View File
@@ -24,23 +24,38 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#define COUNT_UPDATE_MS 500
typedef struct bandwidth_st { typedef struct bandwidth_st {
struct timespec count_start; struct timespec count_start;
size_t transferred_bytes; size_t transferred_bytes;
size_t allowed_bytes; size_t allowed_kb;
size_t bytes_per_sec; /* only touched once */
size_t allowed_kb_per_count;
size_t kb_per_sec;
} bandwidth_st; } bandwidth_st;
inline static void bandwidth_init(bandwidth_st* b, size_t bytes_per_sec) inline static void bandwidth_init(bandwidth_st* b, size_t kb_per_sec)
{ {
memset(b, 0, sizeof(*b)); memset(b, 0, sizeof(*b));
b->bytes_per_sec = bytes_per_sec; b->kb_per_sec = kb_per_sec;
b->allowed_kb_per_count = (b->kb_per_sec*COUNT_UPDATE_MS)/1000;
} }
int _bandwidth_update(bandwidth_st* b, size_t bytes, size_t mtu);
/* returns true or false, depending on whether to send /* returns true or false, depending on whether to send
* the bytes */ * the bytes */
int bandwidth_update(bandwidth_st* b, size_t bytes, size_t mtu); inline static
int bandwidth_update(bandwidth_st* b, size_t bytes, size_t mtu)
{
/* if bandwidth control is disabled */
if (b->kb_per_sec == 0)
return 1;
return _bandwidth_update(b, bytes, mtu);
}
#endif #endif