diff options
author | Dominique Martinet <asmadeus@codewreck.org> | 2023-04-16 16:14:49 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2023-04-18 08:23:55 +0900 |
commit | 25d9c6cdaf82d3f627db92b69f3be3e2a68e06fa (patch) | |
tree | 3a699e9bf78703bd7471a6fcda4d277411e03d5d /src | |
parent | 38cdd08b22565f861ae6dd83b02bc6b189ba2ef5 (diff) | |
download | systemd-25d9c6cdaf82d3f627db92b69f3be3e2a68e06fa.tar.gz |
bpf-firewall: give a name to maps used
Running systemd with IP accounting enabled generates many bpf maps (two
per unit for accounting, another two if IPAddressAllow/Deny are used).
Systemd itself knows which maps belong to what unit and commands like
`systemctl status <unit>` can be used to query what service has which
map, but monitoring these values all the time costs 4 dbus requests
(calling the .IP{E,I}gress{Bytes,Packets} method for each unit) and
makes services like the prometheus systemd_exporter[1] somewhat slow
when doing that for every units, while less precise information could
quickly be obtained by looking directly at the maps.
Unfortunately, bpf map names are rather limited:
- only 15 characters in length (16, but last byte must be 0)
- only allows isalnum(), _ and . characters
If it wasn't for the length limit we could use the normal unit escape
functions but I've opted to just make any forbidden character into
underscores for maximum brievty -- the map prefix is also rather short:
This isn't meant as a precise mapping, but as a hint for admins who want
to look at these.
(Note there is no problem if multiple maps have the same name)
Link: https://github.com/povilasv/systemd_exporter [1]
Diffstat (limited to 'src')
-rw-r--r-- | src/core/bpf-firewall.c | 11 | ||||
-rw-r--r-- | src/shared/bpf-program.c | 17 | ||||
-rw-r--r-- | src/shared/bpf-program.h | 3 |
3 files changed, 26 insertions, 5 deletions
diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c index 5878a81879..0861b4b829 100644 --- a/src/core/bpf-firewall.c +++ b/src/core/bpf-firewall.c @@ -451,7 +451,9 @@ static int bpf_firewall_prepare_access_maps( } if (n_ipv4 > 0) { + char *name = strjoina("4_", u->id); ipv4_map_fd = bpf_map_new( + name, BPF_MAP_TYPE_LPM_TRIE, offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t), sizeof(uint64_t), @@ -462,7 +464,9 @@ static int bpf_firewall_prepare_access_maps( } if (n_ipv6 > 0) { + char *name = strjoina("6_", u->id); ipv6_map_fd = bpf_map_new( + name, BPF_MAP_TYPE_LPM_TRIE, offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t)*4, sizeof(uint64_t), @@ -500,7 +504,8 @@ static int bpf_firewall_prepare_accounting_maps(Unit *u, bool enabled, int *fd_i if (enabled) { if (*fd_ingress < 0) { - r = bpf_map_new(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(uint64_t), 2, 0); + char *name = strjoina("I_", u->id); + r = bpf_map_new(name, BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(uint64_t), 2, 0); if (r < 0) return r; @@ -508,8 +513,8 @@ static int bpf_firewall_prepare_accounting_maps(Unit *u, bool enabled, int *fd_i } if (*fd_egress < 0) { - - r = bpf_map_new(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(uint64_t), 2, 0); + char *name = strjoina("E_", u->id); + r = bpf_map_new(name, BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(uint64_t), 2, 0); if (r < 0) return r; diff --git a/src/shared/bpf-program.c b/src/shared/bpf-program.c index 531ae9b680..d5eb6f4ccb 100644 --- a/src/shared/bpf-program.c +++ b/src/shared/bpf-program.c @@ -300,8 +300,16 @@ int bpf_program_cgroup_detach(BPFProgram *p) { return 0; } -int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags) { +int bpf_map_new( + const char *name, + enum bpf_map_type type, + size_t key_size, + size_t value_size, + size_t max_entries, + uint32_t flags) { + union bpf_attr attr; + const char *n = name; zero(attr); attr.map_type = type; @@ -310,6 +318,13 @@ int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size attr.max_entries = max_entries; attr.map_flags = flags; + /* The map name is primarily informational for debugging purposes, and typically too short + * to carry the full unit name, hence we employ a trivial lossy escaping to make it fit + * (truncation + only alphanumerical, "." and "_" are allowed as per + * https://www.kernel.org/doc/html/next/bpf/maps.html#usage-notes) */ + for (size_t i = 0; i < sizeof(attr.map_name) - 1 && *n; i++, n++) + attr.map_name[i] = strchr(ALPHANUMERICAL ".", *n) ? *n : '_'; + return RET_NERRNO(bpf(BPF_MAP_CREATE, &attr, sizeof(attr))); } diff --git a/src/shared/bpf-program.h b/src/shared/bpf-program.h index b640fb9d9f..0e0b666df6 100644 --- a/src/shared/bpf-program.h +++ b/src/shared/bpf-program.h @@ -54,7 +54,8 @@ int bpf_program_deserialize_attachment_set(const char *v, FDSet *fds, Set **bpfs extern const struct hash_ops bpf_program_hash_ops; -int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags); +int bpf_map_new(const char *name, enum bpf_map_type type, size_t key_size, size_t value_size, + size_t max_entries, uint32_t flags); int bpf_map_update_element(int fd, const void *key, void *value); int bpf_map_lookup_element(int fd, const void *key, void *value); |