net: add support for "net/core/*" sysctls

Submitted by Jan Dakinevich on April 16, 2019, 10:22 a.m.

Details

Message ID 1555410131-1588-1-git-send-email-jan.dakinevich@virtuozzo.com
State New
Series "net: add support for "net/core/*" sysctls"
Headers show

Commit Message

Jan Dakinevich April 16, 2019, 10:22 a.m.
- handle 'somaxconn' option.

https://jira.sw.ru/browse/PSBM-91415
Signed-off-by: Jan Dakinevich <jan.dakinevich@virtuozzo.com>
---
 criu/net.c          | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 images/netdev.proto |  2 ++
 2 files changed, 81 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/criu/net.c b/criu/net.c
index 3eebf48..6aa8bc6 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -334,6 +334,61 @@  static int ipv6_conf_op(char *tgt, SysctlEntry **conf, int n, int op, SysctlEntr
 			devconfs6, def_conf);
 }
 
+static char *coreconfs[] = {
+	"somaxconn",
+};
+
+static int core_conf_op(SysctlEntry **conf, int n, int op)
+{
+	struct sysctl_req req[ARRAY_SIZE(coreconfs)];
+	char path[ARRAY_SIZE(coreconfs)][256];
+	SysctlEntry *rconf[ARRAY_SIZE(coreconfs)];
+	int ret = 0;
+	int i, ri;
+
+	if (n > ARRAY_SIZE(coreconfs))
+		pr_warn("The image contains unknown sysctl-s\n");
+
+	for (i = 0, ri = 0; i < ARRAY_SIZE(coreconfs); i++) {
+		if (i >= n) {
+			pr_warn("Skip %s\n", coreconfs[i]);
+			continue;
+		}
+
+		if (conf[i]->type != SYSCTL_TYPE__CTL_32)
+			continue;
+		if (op == CTL_WRITE && !conf[i]->has_iarg)
+			continue;
+
+		snprintf(path[i], sizeof(path[i]), "net/core/%s", coreconfs[i]);
+		req[ri].name = path[i];
+		req[ri].type = CTL_32;
+		req[ri].arg = &conf[i]->iarg;
+		if (op == CTL_READ || opts.weak_sysctls)
+			req[ri].flags = CTL_FLAGS_OPTIONAL;
+		else
+			req[ri].flags = 0;
+
+		rconf[ri] = conf[i];
+		ri++;
+	}
+
+	ret = sysctl_op(req, ri, op, CLONE_NEWNET);
+	if (ret < 0) {
+		pr_err("Failed to %s\n", (op == CTL_READ ? "read" : "write"));
+		return ret;
+	}
+
+	if (op == CTL_READ) {
+		for (i = 0; i < ri; i++) {
+			if (req[i].flags & CTL_FLAGS_HAS)
+				rconf[i]->has_iarg = true;
+		}
+	}
+
+	return ret;
+}
+
 /*
  * I case if some entry is missing in
  * the kernel, simply write DEVCONFS_UNUSED
@@ -1827,6 +1882,8 @@  static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
 	char all_stable_secret[MAX_STR_CONF_LEN + 1] = {};
 	NetnsId	*ids;
 	struct netns_id *p;
+	int core_size = ARRAY_SIZE(coreconfs);
+	SysctlEntry *core_confs = NULL;
 
 	i = 0;
 	list_for_each_entry(p, &ns->net.ids, node)
@@ -1835,7 +1892,8 @@  static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
 	o_buf = buf = xmalloc(
 			i * (sizeof(NetnsId*) + sizeof(NetnsId)) +
 			size4 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
-			size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2
+			size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
+			core_size * (sizeof(SysctlEntry*) + sizeof(SysctlEntry))
 		     );
 	if (!buf)
 		goto out;
@@ -1891,6 +1949,16 @@  static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
 		}
 	}
 
+	netns.n_core_conf = core_size;
+	netns.core_conf = xptr_pull_s(&buf, core_size * sizeof(SysctlEntry*));
+	core_confs = xptr_pull_s(&buf, core_size * sizeof(SysctlEntry));
+
+	for (i = 0; i < core_size; i++) {
+		sysctl_entry__init(&core_confs[i]);
+		netns.core_conf[i] = &core_confs[i];
+		netns.core_conf[i]->type = CTL_32;
+	}
+
 	ret = ipv4_conf_op("default", netns.def_conf4, size4, CTL_READ, NULL);
 	if (ret < 0)
 		goto err_free;
@@ -1905,6 +1973,10 @@  static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
 	if (ret < 0)
 		goto err_free;
 
+	ret = core_conf_op(netns.core_conf, core_size, CTL_READ);
+	if (ret < 0)
+		goto err_free;
+
 	ret = pb_write_one(img_from_set(fds, CR_FD_NETNS), &netns, PB_NETNS);
 err_free:
 	xfree(o_buf);
@@ -2114,6 +2186,12 @@  static int restore_netns_conf(struct ns_id *ns)
 		ret = ipv6_conf_op("default", (netns)->def_conf6, (netns)->n_def_conf6, CTL_WRITE, NULL);
 	}
 
+	if ((netns)->core_conf) {
+		ret = core_conf_op((netns)->core_conf, (netns)->n_core_conf, CTL_WRITE);
+		if (ret)
+			goto out;
+	}
+
 	ns->net.netns = netns;
 out:
 	return ret;
diff --git a/images/netdev.proto b/images/netdev.proto
index 476a92c..7b9ab8d 100644
--- a/images/netdev.proto
+++ b/images/netdev.proto
@@ -71,4 +71,6 @@  message netns_entry {
 
 	repeated netns_id nsids		= 7;
 	optional string	ext_key		= 8;
+
+	repeated sysctl_entry core_conf	= 9;
 }

Comments

Pavel Tikhomirov April 17, 2019, 8:40 a.m.
Looks good to me except for a small naming confusion, e.g. ipv6_conf_op 
was named for "/proc/sys/net/ipv6/conf/" path to it, but in 
"/proc/sys/net/core" we don't have any conf, though we have coreconfs, 
core_conf_op, also arrays rconf and conf, and image field core_conf =). 
Think we can leave as is.

Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>

On 4/16/19 1:22 PM, Jan Dakinevich wrote:
>   - handle 'somaxconn' option.
> 
> https://jira.sw.ru/browse/PSBM-91415
> Signed-off-by: Jan Dakinevich <jan.dakinevich@virtuozzo.com>
> ---
>   criu/net.c          | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>   images/netdev.proto |  2 ++
>   2 files changed, 81 insertions(+), 1 deletion(-)
> 
> diff --git a/criu/net.c b/criu/net.c
> index 3eebf48..6aa8bc6 100644
> --- a/criu/net.c
> +++ b/criu/net.c
> @@ -334,6 +334,61 @@ static int ipv6_conf_op(char *tgt, SysctlEntry **conf, int n, int op, SysctlEntr
>   			devconfs6, def_conf);
>   }
>   
> +static char *coreconfs[] = {
> +	"somaxconn",
> +};
> +
> +static int core_conf_op(SysctlEntry **conf, int n, int op)
> +{
> +	struct sysctl_req req[ARRAY_SIZE(coreconfs)];
> +	char path[ARRAY_SIZE(coreconfs)][256];
> +	SysctlEntry *rconf[ARRAY_SIZE(coreconfs)];
> +	int ret = 0;
> +	int i, ri;
> +
> +	if (n > ARRAY_SIZE(coreconfs))
> +		pr_warn("The image contains unknown sysctl-s\n");
> +
> +	for (i = 0, ri = 0; i < ARRAY_SIZE(coreconfs); i++) {
> +		if (i >= n) {
> +			pr_warn("Skip %s\n", coreconfs[i]);
> +			continue;
> +		}
> +
> +		if (conf[i]->type != SYSCTL_TYPE__CTL_32)
> +			continue;
> +		if (op == CTL_WRITE && !conf[i]->has_iarg)
> +			continue;
> +
> +		snprintf(path[i], sizeof(path[i]), "net/core/%s", coreconfs[i]);
> +		req[ri].name = path[i];
> +		req[ri].type = CTL_32;
> +		req[ri].arg = &conf[i]->iarg;
> +		if (op == CTL_READ || opts.weak_sysctls)
> +			req[ri].flags = CTL_FLAGS_OPTIONAL;
> +		else
> +			req[ri].flags = 0;
> +
> +		rconf[ri] = conf[i];
> +		ri++;
> +	}
> +
> +	ret = sysctl_op(req, ri, op, CLONE_NEWNET);
> +	if (ret < 0) {
> +		pr_err("Failed to %s\n", (op == CTL_READ ? "read" : "write"));
> +		return ret;
> +	}
> +
> +	if (op == CTL_READ) {
> +		for (i = 0; i < ri; i++) {
> +			if (req[i].flags & CTL_FLAGS_HAS)
> +				rconf[i]->has_iarg = true;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
>   /*
>    * I case if some entry is missing in
>    * the kernel, simply write DEVCONFS_UNUSED
> @@ -1827,6 +1882,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
>   	char all_stable_secret[MAX_STR_CONF_LEN + 1] = {};
>   	NetnsId	*ids;
>   	struct netns_id *p;
> +	int core_size = ARRAY_SIZE(coreconfs);
> +	SysctlEntry *core_confs = NULL;
>   
>   	i = 0;
>   	list_for_each_entry(p, &ns->net.ids, node)
> @@ -1835,7 +1892,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
>   	o_buf = buf = xmalloc(
>   			i * (sizeof(NetnsId*) + sizeof(NetnsId)) +
>   			size4 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
> -			size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2
> +			size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
> +			core_size * (sizeof(SysctlEntry*) + sizeof(SysctlEntry))
>   		     );
>   	if (!buf)
>   		goto out;
> @@ -1891,6 +1949,16 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
>   		}
>   	}
>   
> +	netns.n_core_conf = core_size;
> +	netns.core_conf = xptr_pull_s(&buf, core_size * sizeof(SysctlEntry*));
> +	core_confs = xptr_pull_s(&buf, core_size * sizeof(SysctlEntry));
> +
> +	for (i = 0; i < core_size; i++) {
> +		sysctl_entry__init(&core_confs[i]);
> +		netns.core_conf[i] = &core_confs[i];
> +		netns.core_conf[i]->type = CTL_32;
> +	}
> +
>   	ret = ipv4_conf_op("default", netns.def_conf4, size4, CTL_READ, NULL);
>   	if (ret < 0)
>   		goto err_free;
> @@ -1905,6 +1973,10 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
>   	if (ret < 0)
>   		goto err_free;
>   
> +	ret = core_conf_op(netns.core_conf, core_size, CTL_READ);
> +	if (ret < 0)
> +		goto err_free;
> +
>   	ret = pb_write_one(img_from_set(fds, CR_FD_NETNS), &netns, PB_NETNS);
>   err_free:
>   	xfree(o_buf);
> @@ -2114,6 +2186,12 @@ static int restore_netns_conf(struct ns_id *ns)
>   		ret = ipv6_conf_op("default", (netns)->def_conf6, (netns)->n_def_conf6, CTL_WRITE, NULL);
>   	}
>   
> +	if ((netns)->core_conf) {
> +		ret = core_conf_op((netns)->core_conf, (netns)->n_core_conf, CTL_WRITE);
> +		if (ret)
> +			goto out;
> +	}
> +
>   	ns->net.netns = netns;
>   out:
>   	return ret;
> diff --git a/images/netdev.proto b/images/netdev.proto
> index 476a92c..7b9ab8d 100644
> --- a/images/netdev.proto
> +++ b/images/netdev.proto
> @@ -71,4 +71,6 @@ message netns_entry {
>   
>   	repeated netns_id nsids		= 7;
>   	optional string	ext_key		= 8;
> +
> +	repeated sysctl_entry core_conf	= 9;
>   }
>
Pavel Tikhomirov April 17, 2019, 8:46 a.m.
One more thing, we likely need a test for it to zdtm, something like 
test/zdtm/static/netns-dev.c

On 4/17/19 11:40 AM, Pavel Tikhomirov wrote:
> Looks good to me except for a small naming confusion, e.g. ipv6_conf_op
> was named for "/proc/sys/net/ipv6/conf/" path to it, but in
> "/proc/sys/net/core" we don't have any conf, though we have coreconfs,
> core_conf_op, also arrays rconf and conf, and image field core_conf =).
> Think we can leave as is.
> 
> Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
> 
> On 4/16/19 1:22 PM, Jan Dakinevich wrote:
>>    - handle 'somaxconn' option.
>>
>> https://jira.sw.ru/browse/PSBM-91415
>> Signed-off-by: Jan Dakinevich <jan.dakinevich@virtuozzo.com>
>> ---
>>    criu/net.c          | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>    images/netdev.proto |  2 ++
>>    2 files changed, 81 insertions(+), 1 deletion(-)
>>
>> diff --git a/criu/net.c b/criu/net.c
>> index 3eebf48..6aa8bc6 100644
>> --- a/criu/net.c
>> +++ b/criu/net.c
>> @@ -334,6 +334,61 @@ static int ipv6_conf_op(char *tgt, SysctlEntry **conf, int n, int op, SysctlEntr
>>    			devconfs6, def_conf);
>>    }
>>    
>> +static char *coreconfs[] = {
>> +	"somaxconn",
>> +};
>> +
>> +static int core_conf_op(SysctlEntry **conf, int n, int op)
>> +{
>> +	struct sysctl_req req[ARRAY_SIZE(coreconfs)];
>> +	char path[ARRAY_SIZE(coreconfs)][256];
>> +	SysctlEntry *rconf[ARRAY_SIZE(coreconfs)];
>> +	int ret = 0;
>> +	int i, ri;
>> +
>> +	if (n > ARRAY_SIZE(coreconfs))
>> +		pr_warn("The image contains unknown sysctl-s\n");
>> +
>> +	for (i = 0, ri = 0; i < ARRAY_SIZE(coreconfs); i++) {
>> +		if (i >= n) {
>> +			pr_warn("Skip %s\n", coreconfs[i]);
>> +			continue;
>> +		}
>> +
>> +		if (conf[i]->type != SYSCTL_TYPE__CTL_32)
>> +			continue;
>> +		if (op == CTL_WRITE && !conf[i]->has_iarg)
>> +			continue;
>> +
>> +		snprintf(path[i], sizeof(path[i]), "net/core/%s", coreconfs[i]);
>> +		req[ri].name = path[i];
>> +		req[ri].type = CTL_32;
>> +		req[ri].arg = &conf[i]->iarg;
>> +		if (op == CTL_READ || opts.weak_sysctls)
>> +			req[ri].flags = CTL_FLAGS_OPTIONAL;
>> +		else
>> +			req[ri].flags = 0;
>> +
>> +		rconf[ri] = conf[i];
>> +		ri++;
>> +	}
>> +
>> +	ret = sysctl_op(req, ri, op, CLONE_NEWNET);
>> +	if (ret < 0) {
>> +		pr_err("Failed to %s\n", (op == CTL_READ ? "read" : "write"));
>> +		return ret;
>> +	}
>> +
>> +	if (op == CTL_READ) {
>> +		for (i = 0; i < ri; i++) {
>> +			if (req[i].flags & CTL_FLAGS_HAS)
>> +				rconf[i]->has_iarg = true;
>> +		}
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>>    /*
>>     * I case if some entry is missing in
>>     * the kernel, simply write DEVCONFS_UNUSED
>> @@ -1827,6 +1882,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
>>    	char all_stable_secret[MAX_STR_CONF_LEN + 1] = {};
>>    	NetnsId	*ids;
>>    	struct netns_id *p;
>> +	int core_size = ARRAY_SIZE(coreconfs);
>> +	SysctlEntry *core_confs = NULL;
>>    
>>    	i = 0;
>>    	list_for_each_entry(p, &ns->net.ids, node)
>> @@ -1835,7 +1892,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
>>    	o_buf = buf = xmalloc(
>>    			i * (sizeof(NetnsId*) + sizeof(NetnsId)) +
>>    			size4 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
>> -			size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2
>> +			size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
>> +			core_size * (sizeof(SysctlEntry*) + sizeof(SysctlEntry))
>>    		     );
>>    	if (!buf)
>>    		goto out;
>> @@ -1891,6 +1949,16 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
>>    		}
>>    	}
>>    
>> +	netns.n_core_conf = core_size;
>> +	netns.core_conf = xptr_pull_s(&buf, core_size * sizeof(SysctlEntry*));
>> +	core_confs = xptr_pull_s(&buf, core_size * sizeof(SysctlEntry));
>> +
>> +	for (i = 0; i < core_size; i++) {
>> +		sysctl_entry__init(&core_confs[i]);
>> +		netns.core_conf[i] = &core_confs[i];
>> +		netns.core_conf[i]->type = CTL_32;
>> +	}
>> +
>>    	ret = ipv4_conf_op("default", netns.def_conf4, size4, CTL_READ, NULL);
>>    	if (ret < 0)
>>    		goto err_free;
>> @@ -1905,6 +1973,10 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
>>    	if (ret < 0)
>>    		goto err_free;
>>    
>> +	ret = core_conf_op(netns.core_conf, core_size, CTL_READ);
>> +	if (ret < 0)
>> +		goto err_free;
>> +
>>    	ret = pb_write_one(img_from_set(fds, CR_FD_NETNS), &netns, PB_NETNS);
>>    err_free:
>>    	xfree(o_buf);
>> @@ -2114,6 +2186,12 @@ static int restore_netns_conf(struct ns_id *ns)
>>    		ret = ipv6_conf_op("default", (netns)->def_conf6, (netns)->n_def_conf6, CTL_WRITE, NULL);
>>    	}
>>    
>> +	if ((netns)->core_conf) {
>> +		ret = core_conf_op((netns)->core_conf, (netns)->n_core_conf, CTL_WRITE);
>> +		if (ret)
>> +			goto out;
>> +	}
>> +
>>    	ns->net.netns = netns;
>>    out:
>>    	return ret;
>> diff --git a/images/netdev.proto b/images/netdev.proto
>> index 476a92c..7b9ab8d 100644
>> --- a/images/netdev.proto
>> +++ b/images/netdev.proto
>> @@ -71,4 +71,6 @@ message netns_entry {
>>    
>>    	repeated netns_id nsids		= 7;
>>    	optional string	ext_key		= 8;
>> +
>> +	repeated sysctl_entry core_conf	= 9;
>>    }
>>
>
Kirill Gorkunov April 17, 2019, 8:52 a.m.
On Wed, Apr 17, 2019 at 11:46:25AM +0300, Pavel Tikhomirov wrote:
> One more thing, we likely need a test for it to zdtm, something like 
> test/zdtm/static/netns-dev.c
>

Yes, Jan, please make a test once time permit.