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

This commit is contained in:
Nikos Mavrogiannopoulos
2013-11-05 20:31:10 +01:00
parent 0759125652
commit 615e16cc41
6 changed files with 47 additions and 33 deletions

View File

@@ -165,8 +165,8 @@ ping-leases = false
# Unset to enable bandwidth restrictions (in bytes/sec). The
# setting here is global, but can also be set per user or per group.
#rx-per-sec = 40960
#tx-per-sec = 40960
#rx-data-per-sec = 40960
#tx-data-per-sec = 40960
# The number of packets (of MTU size) that are available in
# 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
# or the groupname.
# 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
# based on a user or group. The syntax depends on the input accepted

View File

@@ -86,8 +86,8 @@ static struct cfg_options available_options[] = {
{ .name = "min-reauth-time", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "max-same-clients", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "rx-per-sec", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "tx-per-sec", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "rx-data-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-group", .type = OPTION_STRING, .mandatory = 0 },
@@ -319,8 +319,10 @@ unsigned prefix = 0;
READ_NUMERIC("mtu", config->default_mtu);
READ_NUMERIC("output-buffer", config->output_buffer);
READ_NUMERIC("rx-per-sec", config->rx_per_sec);
READ_NUMERIC("tx-per-sec", config->tx_per_sec);
READ_NUMERIC("rx-data-per-sec", config->rx_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("auth-timeout", config->auth_timeout);

View File

@@ -51,8 +51,8 @@ static struct cfg_options available_options[] = {
{ .name = "ipv4-netmask", .type = OPTION_STRING },
{ .name = "ipv6-prefix", .type = OPTION_NUMERIC },
{ .name = "ipv6-netmask", .type = OPTION_STRING },
{ .name = "rx-per-sec", .type = OPTION_NUMERIC, },
{ .name = "tx-per-sec", .type = OPTION_NUMERIC, },
{ .name = "rx-data-per-sec", .type = OPTION_NUMERIC, },
{ .name = "tx-data-per-sec", .type = OPTION_NUMERIC, },
};
#define READ_RAW_MULTI_LINE(name, s_name, num) \
@@ -144,8 +144,10 @@ unsigned prefix = 0;
if (prefix > 0)
config->ipv6_netmask = ipv6_prefix_to_mask(prefix);
READ_RAW_NUMERIC("rx-per-sec", config->rx_per_sec);
READ_RAW_NUMERIC("tx-per-sec", config->tx_per_sec);
READ_RAW_NUMERIC("rx-data-per-sec", config->rx_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);

View File

@@ -257,8 +257,8 @@ ping-leases = false
# Unset to enable bandwidth restrictions (in bytes/sec). The
# setting here is global, but can also be set per user or per group.
#rx-per-sec = 40000
#tx-per-sec = 40000
#rx-data-per-sec = 40000
#tx-data-per-sec = 40000
# The number of packets (of MTU size) that are available in
# 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
# or the groupname.
# 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
# based on a user or group. The syntax depends on the input accepted

View File

@@ -26,40 +26,35 @@
#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;
struct timespec now;
ssize_t t, new_allowed_bytes, remain;
ssize_t t, remain;
unsigned int diff;
/* if bandwidth control is disabled */
if (b->bytes_per_sec == 0)
return 1;
size_t transferred_kb;
gettime(&now);
diff = timespec_sub_ms(&now, &b->count_start);
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));
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;
t = new_allowed_bytes + remain;
b->allowed_bytes = MIN(t, new_allowed_bytes*1000/COUNT_UPDATE_MS);
b->allowed_kb = MIN(t, b->kb_per_sec);
b->transferred_bytes = bytes;
return 1;
}
sum = b->transferred_bytes + bytes;
if (sum > b->allowed_bytes)
if (sum > b->allowed_kb*1000)
return 0; /* NO */
b->transferred_bytes = sum;

View File

@@ -24,23 +24,38 @@
#include <time.h>
#include <unistd.h>
#define COUNT_UPDATE_MS 500
typedef struct bandwidth_st {
struct timespec count_start;
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;
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));
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
* 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