summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-09-07 14:07:13 +0200
committerSven Eden <yamakuzure@gmx.net>2017-09-07 14:07:13 +0200
commitaa963ca5f68ea9cb593c62547e91443651865d5c (patch)
treee0d330bb51552d124c4a4fcf35cc10ca27a07400
parent0efbdf51d1a26201cd76c3d2c0377dcc088150b5 (diff)
core: serialize/deserialize IP accounting across daemon reload/reexec
Make sure the current IP accounting counters aren't lost during reload/reexec. Note that we destroy all BPF file objects during a reload: the BPF programs, the access and the accounting maps. The former two need to be regenerated anyway with the newly loaded configuration data, but the latter one needs to survive reloads/reexec. In this implementation I opted to only save/restore the accounting map content instead of the map itself. While this opens a (theoretic) window where IP traffic is still accounted to the old map after we read it out, and we thus miss a few bytes this has the benefit that we can alter the map layout between versions should the need arise.
-rw-r--r--src/core/cgroup.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 4d15a1e3b..1d1e2d38e 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -2281,6 +2281,7 @@ int unit_get_ip_accounting(
CGroupIPAccountingMetric metric,
uint64_t *ret) {
+ uint64_t value;
int fd, r;
assert(u);
@@ -2296,9 +2297,17 @@ int unit_get_ip_accounting(
return -ENODATA;
if (IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_EGRESS_BYTES))
- r = bpf_firewall_read_accounting(fd, ret, NULL);
+ r = bpf_firewall_read_accounting(fd, &value, NULL);
else
- r = bpf_firewall_read_accounting(fd, NULL, ret);
+ r = bpf_firewall_read_accounting(fd, NULL, &value);
+ if (r < 0)
+ return r;
+
+ /* Add in additional metrics from a previous runtime. Note that when reexecing/reloading the daemon we compile
+ * all BPF programs and maps anew, but serialize the old counters. When deserializing we store them in the
+ * ip_accounting_extra[] field, and add them in here transparently. */
+
+ *ret = value + u->ip_accounting_extra[metric];
return r;
}
@@ -2332,6 +2341,8 @@ int unit_reset_ip_accounting(Unit *u) {
if (u->ip_accounting_egress_map_fd >= 0)
q = bpf_firewall_reset_accounting(u->ip_accounting_egress_map_fd);
+ zero(u->ip_accounting_extra);
+
return r < 0 ? r : q;
}