Added support for cgroups

This commit is contained in:
Nikos Mavrogiannopoulos
2013-12-10 11:05:26 +01:00
parent fd25969aca
commit c6a08db6db
8 changed files with 99 additions and 17 deletions

View File

@@ -134,6 +134,17 @@ socket-file = /var/run/ocserv-socket
run-as-user = nobody
run-as-group = nobody
# Set the protocol-defined priority (SO_PRIORITY) for packets to
# be sent. That is a number from 0 to 6 with 0 being the lowest
# priority. Alternatively this can be used to set the IP Type-
# Of-Service, by setting it to a hexadecimal number (e.g., 0x20).
# This can be set per user/group or globally.
#net-priority = 3
# Set the VPN worker process into a specific cgroup. This is Linux
# specific and can be set per user/group or globally.
#cgroup = "cpuset,cpu:test"
# Network settings
device = vpns
@@ -173,13 +184,6 @@ ping-leases = false
# Setting it higher will improve throughput.
output-buffer = 10
# Set the protocol-defined priority (SO_PRIORITY) for packets to
# be sent. That is a number from 0 to 6 with 0 being the lowest
# priority. Alternatively this can be used to set the IP Type-
# Of-Service, by setting it to a hexadecimal number (e.g., 0x20).
# This can be set per user/group or globally.
#net-priority = 3
route = 192.168.1.0/255.255.255.0
#route = 192.168.5.0/255.255.255.0
@@ -196,6 +200,7 @@ route = 192.168.1.0/255.255.255.0
config-per-user = /etc/ocserv/config-per-user/
config-per-group = /etc/ocserv/config-per-group/
# The system command to use to setup a route. %R will be replaced with the
# route/mask and %D with the (tun) device.
#

View File

@@ -93,6 +93,7 @@ static struct cfg_options available_options[] = {
{ .name = "run-as-user", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "run-as-group", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "device", .type = OPTION_STRING, .mandatory = 1 },
{ .name = "cgroup", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "ipv4-network", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "ipv4-netmask", .type = OPTION_STRING, .mandatory = 0 },
@@ -371,6 +372,7 @@ unsigned prefix = 0;
}
READ_STRING("device", config->network.name);
READ_STRING("cgroup", config->cgroup);
READ_STRING("ipv4-network", config->network.ipv4);
READ_STRING("ipv4-netmask", config->network.ipv4_netmask);
@@ -523,6 +525,7 @@ unsigned i;
DEL(config->xml_config_hash);
DEL(config->cert_hash);
#endif
DEL(config->cgroup);
DEL(config->route_add_cmd);
DEL(config->route_del_cmd);
DEL(config->per_user_dir);

View File

@@ -54,6 +54,7 @@ static struct cfg_options available_options[] = {
{ .name = "rx-data-per-sec", .type = OPTION_NUMERIC, },
{ .name = "tx-data-per-sec", .type = OPTION_NUMERIC, },
{ .name = "net-priority", .type = OPTION_STRING, },
{ .name = "cgroup", .type = OPTION_STRING, },
};
#define READ_RAW_MULTI_LINE(name, s_name, num) \
@@ -147,6 +148,7 @@ unsigned prefix = 0;
READ_RAW_MULTI_LINE("route", config->routes, config->routes_size);
READ_RAW_MULTI_LINE("iroute", config->iroutes, config->iroutes_size);
READ_RAW_STRING("cgroup", config->cgroup);
READ_RAW_STRING("ipv4-dns", config->ipv4_dns);
READ_RAW_STRING("ipv6-dns", config->ipv6_dns);
READ_RAW_STRING("ipv4-nbns", config->ipv4_nbns);
@@ -187,6 +189,7 @@ unsigned i;
}
free(config->iroutes);
free(config->cgroup);
free(config->ipv4_dns);
free(config->ipv6_dns);
free(config->ipv4_nbns);

View File

@@ -158,7 +158,7 @@ fail:
return ret;
}
static int read_config_file(main_server_st* s, struct proc_st* proc, const char* file, const char* type)
static int read_additional_config_file(main_server_st* s, struct proc_st* proc, const char* file, const char* type)
{
struct group_cfg_st cfg;
int ret;
@@ -239,6 +239,11 @@ unsigned i;
cfg.ipv6_netmask = NULL;
}
if (proc->config.cgroup == NULL) {
proc->config.cgroup = cfg.cgroup;
cfg.cgroup = NULL;
}
if (proc->config.rx_per_sec == 0) {
proc->config.rx_per_sec = cfg.rx_per_sec;
}
@@ -270,7 +275,7 @@ int ret;
if (s->config->per_user_dir != NULL) {
snprintf(file, sizeof(file), "%s/%s", s->config->per_user_dir, proc->username);
ret = read_config_file(s, proc, file, "user");
ret = read_additional_config_file(s, proc, file, "user");
if (ret < 0)
return ret;
}
@@ -278,10 +283,14 @@ int ret;
if (s->config->per_group_dir != NULL && proc->groupname[0] != 0) {
snprintf(file, sizeof(file), "%s/%s", s->config->per_group_dir, proc->groupname);
ret = read_config_file(s, proc, file, "group");
ret = read_additional_config_file(s, proc, file, "group");
if (ret < 0)
return ret;
}
if (proc->config.cgroup != NULL) {
put_into_cgroup(s, proc->config.cgroup, proc->pid);
}
return 0;
}
@@ -675,3 +684,51 @@ const char *p;
exit(1);
}
}
/* Puts the provided PIN into the config's cgroup */
void put_into_cgroup(main_server_st * s, const char* _cgroup, pid_t pid)
{
char* name, *p, *savep;
char cgroup[128];
char file[_POSIX_PATH_MAX];
FILE* fd;
if (_cgroup == NULL)
return;
#ifdef __linux__
/* format: cpu,memory:cgroup-name */
snprintf(cgroup, sizeof(cgroup), "%s", _cgroup);
name = strchr(cgroup, ':');
if (name == NULL) {
mslog(s, NULL, LOG_ERR, "error parsing cgroup name: %s", cgroup);
return;
}
name[0] = 0;
name++;
p = strtok_r(cgroup, ",", &savep);
while (p != NULL) {
mslog(s, NULL, LOG_DEBUG, "putting process %u to cgroup '%s:%s'", (unsigned)pid, p, name);
snprintf(file, sizeof(file), "/sys/fs/cgroup/%s/%s/tasks", p, name);
fd = fopen(file, "w");
if (fd == NULL) {
mslog(s, NULL, LOG_ERR, "cannot open: %s", file);
return;
}
if (fprintf(fd, "%u", (unsigned)pid) <= 0) {
mslog(s, NULL, LOG_ERR, "could not write to: %s", file);
}
fclose(fd);
p = strtok_r(NULL, ",", &savep);
}
return;
#else
mslog(s, NULL, LOG_DEBUG, "Ignoring cgroup option as it is not supported on this system");
#endif
}

View File

@@ -822,6 +822,7 @@ int main(int argc, char** argv)
setproctitle(PACKAGE_NAME"-worker");
kill_on_parent_kill(SIGTERM);
ws.config = &config;
ws.cmd_fd = cmd_fd[1];
@@ -853,6 +854,9 @@ fork_failed:
set_cloexec_flag (cmd_fd[0], 1);
list_add(&s.clist.head, &(ctmp->list));
put_into_cgroup(&s, s.config->cgroup, pid);
s.active_clients++;
}
close(cmd_fd[1]);

View File

@@ -215,4 +215,6 @@ int parse_group_cfg_file(main_server_st* s, const char* file, struct group_cfg_s
void del_additional_config(struct group_cfg_st* config);
void remove_proc(main_server_st* s, struct proc_st *proc, unsigned k);
void put_into_cgroup(main_server_st * s, const char* cgroup, pid_t pid);
#endif

View File

@@ -224,6 +224,17 @@ socket-file = /var/run/ocserv-socket
run-as-user = nobody
run-as-group = nogroup
# Set the protocol-defined priority (SO_PRIORITY) for packets to
# be sent. That is a number from 0 to 6 with 0 being the lowest
# priority. Alternatively this can be used to set the IP Type-
# Of-Service, by setting it to a hexadecimal number (e.g., 0x20).
# This can be set per user/group or globally.
#net-priority = 3
# Set the VPN worker process into a specific cgroup. This is Linux
# specific and can be set per user/group or globally.
cgroup = "cpuset,cpu:test"
#
# Network settings
#
@@ -271,13 +282,6 @@ ping-leases = false
# Setting it higher will improve throughput.
output-buffer = 10
# Set the protocol-defined priority (SO_PRIORITY) for packets to
# be sent. That is a number from 0 to 6 with 0 being the lowest
# priority. Alternatively this can be used to set the IP Type-
# Of-Service, by setting it to a hexadecimal number (e.g., 0x20).
# This can be set per user/group or globally.
#net-priority = 3
# Routes to be forwarded to the client. If you need the
# client to forward routes to the server, you may use the connect
# and disconnect scripts.

View File

@@ -98,6 +98,8 @@ struct group_cfg_st {
char *ipv6_network;
char *ipv4_netmask;
char *ipv6_netmask;
char *cgroup;
size_t rx_per_sec;
size_t tx_per_sec;
@@ -177,6 +179,8 @@ struct cfg_st {
char *connect_script;
char *disconnect_script;
char *cgroup;
#ifdef ANYCONNECT_CLIENT_COMPAT
char *xml_config_file;