BpfNetworkStats: introduce poor man's ifindex2name() cache
Uses 16KiB ram, only caches ifindex < 1024, but in practice that should usually be the case, as these are assigned in sequential order by the kernel. Note that in progs/netd.c:86 we have: DEFINE_BPF_MAP_NO_NETD(iface_index_name_map, HASH, uint32_t, IfaceValue, 1000) so stuff doesn't really work right once we go past 1000-ish tracked interfaces... (and worst case we're no worse off then we are now...) Benefit should be significant as all our bpf map stats dumping logic has to convert from ifindex to ifname in order to strcmp against the interface we're trying to match, ie. that's the first thing 3 of the 4 cases we support do at the very top of their innermost loop. This effectively eliminates 1 bpf() lookup systemcall, thus getting us down to 2 (getNextKey + readValue/readValueAndDelete) Note: the tests work because they're consistent in how they map ifindex/ifname so they do not require cache clearing. I believe we don't have to worry about threading, as we're being called while traversing/consuming maps. Thus I believe there must be locking external to us. Also writes should be *super* uncommon, so even if this were to run multithreaded, races should happen very rarely. If they did, we'd just write in the same value twice (since the mapping from ifindex->ifname should rarely if ever change) Worst case once in a blue moon we'd fail to match an interface that had *just* shown up (because of reading only half the name), and we'd lose some stats... (and since the entire value fits in 16 bytes, and thus in a single cache line, in practice most cpus will probably write combine and thus avoid a half write/read anyway, both x86-64 and aarch64 can potentially even do a 16-byte read/write in 1 instruction... although unclear if that will happen, but worst case should be 2) Test: TreeHugger, atest libnetworkstats_test Flag: EXEMPT mainline Signed-off-by: Maciej Żenczykowski <maze@google.com> Change-Id: I0d3ea6c5f1f2945adccd479af6c65008bf7d7c51
This commit is contained in:
parent
c125d064f0
commit
6bd25b5fd4
2 changed files with 15 additions and 4 deletions
|
|
@ -82,7 +82,7 @@ DEFINE_BPF_MAP_RW_NETD(lock_hash_test_map, HASH, uint32_t, bool, 1)
|
|||
|
||||
DEFINE_BPF_SK_STORAGE(sk_storage, SkStorageValue)
|
||||
|
||||
/* never actually used from ebpf */
|
||||
// never used from eBpf, see cacheSize in service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
|
||||
DEFINE_BPF_MAP_NO_NETD(iface_index_name_map, HASH, uint32_t, IfaceValue, 1000)
|
||||
|
||||
// A single-element configuration array, packet tracing is enabled when 'true'.
|
||||
|
|
|
|||
|
|
@ -50,13 +50,23 @@ const BpfMapRO<uint32_t, StatsValue>& getIfaceStatsMap() {
|
|||
return ifaceStatsMap;
|
||||
}
|
||||
|
||||
static constexpr unsigned cacheSize = 1024; // see 'iface_index_name_map' bpf map size
|
||||
static IfaceValue cache[cacheSize];
|
||||
|
||||
static inline const IfaceValue& updateCache(unsigned i, const IfaceValue &v) {
|
||||
if (i < cacheSize) cache[i] = v;
|
||||
return v;
|
||||
}
|
||||
|
||||
Result<IfaceValue> ifindex2name(const uint32_t ifindex) {
|
||||
if (ifindex < cacheSize && cache[ifindex].name[0]) return cache[ifindex];
|
||||
|
||||
Result<IfaceValue> v = getIfaceIndexNameMap().readValue(ifindex);
|
||||
if (v.ok()) return v;
|
||||
if (v.ok()) return updateCache(ifindex, v.value());
|
||||
IfaceValue iv = {};
|
||||
if (!if_indextoname(ifindex, iv.name)) return v;
|
||||
if (!if_indextoname(ifindex, iv.name)) return v; // v is an error
|
||||
getIfaceIndexNameMap().writeValue(ifindex, iv, BPF_ANY);
|
||||
return iv;
|
||||
return updateCache(ifindex, iv);
|
||||
}
|
||||
|
||||
void bpfRegisterIface(const char* iface) {
|
||||
|
|
@ -67,6 +77,7 @@ void bpfRegisterIface(const char* iface) {
|
|||
IfaceValue ifname = {};
|
||||
strlcpy(ifname.name, iface, sizeof(ifname.name));
|
||||
getIfaceIndexNameMap().writeValue(ifindex, ifname, BPF_ANY);
|
||||
updateCache(ifindex, ifname);
|
||||
}
|
||||
|
||||
int bpfGetUidStatsInternal(uid_t uid, StatsValue* stats,
|
||||
|
|
|
|||
Loading…
Reference in a new issue