File: cgroup_limits.h

package info (click to toggle)
falcosecurity-libs 0.1.1dev%2Bgit20220316.e5c53d64-5.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 4,732 kB
  • sloc: cpp: 55,770; ansic: 37,330; makefile: 74; sh: 13
file content (131 lines) | stat: -rw-r--r-- 3,697 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#pragma once

#include <string>
#include <utility>
#include "async_key_value_source.h"

namespace {
bool less_than(const std::string& lhs, const std::string& rhs, bool if_equal=false)
{
	int cmp = lhs.compare(rhs);
	if(cmp < 0)
	{
		return true;
	}
	else if(cmp > 0)
	{
		return false;
	}
	else
	{
		return if_equal;
	}
}
}

namespace libsinsp {
namespace cgroup_limits {

/**
 * \brief The key for cgroup value lookup
 *
 * It's effectively a (container_id, cpu_cgroup, mem_cgroup) tuple
 * that can be used as a hash key.
 */
struct cgroup_limits_key {
	cgroup_limits_key() {}

	cgroup_limits_key(std::string container_id,
			  std::string cpu_cgroup_dir,
			  std::string mem_cgroup_dir,
			  std::string cpuset_cgroup_dir) :
		m_container_id(std::move(container_id)),
		m_cpu_cgroup(std::move(cpu_cgroup_dir)),
		m_mem_cgroup(std::move(mem_cgroup_dir)),
		m_cpuset_cgroup(std::move(cpuset_cgroup_dir)) { }

	bool operator<(const cgroup_limits_key& rhs) const
	{
		return less_than(m_container_id, rhs.m_container_id,
				 less_than(m_cpu_cgroup, rhs.m_cpu_cgroup,
					   less_than(m_mem_cgroup, rhs.m_mem_cgroup,
						less_than(m_cpuset_cgroup, rhs.m_cpuset_cgroup))));
	}

	bool operator==(const cgroup_limits_key& rhs) const
	{
		return m_container_id == rhs.m_container_id &&
		       m_cpu_cgroup == rhs.m_cpu_cgroup &&
		       m_mem_cgroup == rhs.m_mem_cgroup &&
		       m_cpuset_cgroup == rhs.m_cpuset_cgroup;
	}

	explicit operator const std::string&() const
	{
		return m_container_id;
	}

	std::string m_container_id;
	std::string m_cpu_cgroup;
	std::string m_mem_cgroup;
	std::string m_cpuset_cgroup;
};

/**
 * \brief The result of an asynchronous cgroup lookup
 *
 * This contains all the cgroup values we read during the asynchronous lookup
 */
struct cgroup_limits_value {
	cgroup_limits_value() :
		m_cpu_shares(0),
		m_cpu_quota(0),
		m_cpu_period(0),
		m_memory_limit(0),
		m_cpuset_cpu_count(0) {}

	int64_t m_cpu_shares;
	int64_t m_cpu_quota;
	int64_t m_cpu_period;
	int64_t m_memory_limit;
	int32_t m_cpuset_cpu_count;
};

/**
 * \brief Read resource limits from cgroups
 * @param key the container to read limits for
 * @param value output value. when the return value is false, specific fields
 *         may or may not have been modified
 * @param name_check if true and the container doesn't use its own cgroups
 *         for mem/cpu, we log a message and we ignore the values.
 *         "Use its own cgroups" means the container id is present in the cgroup
 *         path, which may not be true for all container engines.
 * @return true when all values have been successfully read, false otherwise
 *
 * Note: reading a zero/negative/very large value is considered a failure,
 * because it might mean that resource limits haven't yet been set. Essentially,
 * `false` means "there's real chance the limits could conceivably change
 * in the future", while `true` means we really don't expect them to change
 * any more.
 */
bool get_cgroup_resource_limits(const cgroup_limits_key& key, cgroup_limits_value& value, bool name_check = true);

}
}

namespace std {
/**
 * \brief Specialization of std::hash for cgroup_limits_key
 *
 * It allows `cgroup_limits_key` instances to be used as `unordered_map` keys
 */
template<> struct hash<libsinsp::cgroup_limits::cgroup_limits_key> {
	std::size_t operator()(const libsinsp::cgroup_limits::cgroup_limits_key& h) const {
		size_t h1 = ::std::hash<std::string>{}(h.m_container_id);
		size_t h2 = ::std::hash<std::string>{}(h.m_cpu_cgroup);
		size_t h3 = ::std::hash<std::string>{}(h.m_mem_cgroup);
		size_t h4 = ::std::hash<std::string>{}(h.m_cpuset_cgroup);
		return h1 ^ (h2 << 1u) ^ (h3 << 2u) ^ (h4 << 3u);
	}
};
}