From ab64113f9854fd6b12e92da1f148f60a2b8ea829 Mon Sep 17 00:00:00 2001 From: Herbert Wolverson Date: Fri, 17 May 2024 14:12:15 -0500 Subject: [PATCH] Add a "hot cache" to the XDP LPM lookup system. Adds a new BPF map (an LRU hash) containing IP addresses and TC mapping info. IPs are first checked against the hot cache, because a hashmap lookup is faster than an LPM lookup. If found, the cached value is used. If not found, then the key is inserted into the LRU map (so currently hot stays present, others expire over time) for future cache use. --- src/rust/lqos_sys/src/bpf/common/lpm.h | 48 +++++++++++++++++++-- src/rust/lqos_sys/src/bpf/common/maximums.h | 3 ++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/rust/lqos_sys/src/bpf/common/lpm.h b/src/rust/lqos_sys/src/bpf/common/lpm.h index 61200695..99f01cd6 100644 --- a/src/rust/lqos_sys/src/bpf/common/lpm.h +++ b/src/rust/lqos_sys/src/bpf/common/lpm.h @@ -9,7 +9,6 @@ #include #include #include "maximums.h" -#include "debug.h" #include "dissector.h" // Data structure used for map_ip_hash @@ -24,6 +23,22 @@ struct ip_hash_key { struct in6_addr address; // An IPv6 address. IPv4 uses the last 32 bits. }; +// Hot cache for recent IP lookups, an attempt +// at a speed improvement predicated on the idea +// that LPM isn't the fastest +// The cache is optional. define USE_HOTCACHE +// to enable it. +#define USE_HOTCACHE 1 + +#ifdef USE_HOTCACHE +struct { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, HOT_CACHE_SIZE); + __type(key, struct in6_addr); + __type(value, struct ip_hash_info); +} ip_to_cpu_and_tc_hotcache SEC(".maps"); +#endif + // Map describing IP to CPU/TC mappings struct { __uint(type, BPF_MAP_TYPE_LPM_TRIE); @@ -71,13 +86,39 @@ static __always_inline struct ip_hash_info * setup_lookup_key_and_tc_cpu( struct dissector_t * dissector ) { + struct ip_hash_info * ip_info; + lookup_key->prefixlen = 128; lookup_key->address = (direction == 1) ? dissector->dst_ip : dissector->src_ip; - struct ip_hash_info * ip_info = bpf_map_lookup_elem( + + #ifdef USE_HOTCACHE + // Try a hot cache search + ip_info = bpf_map_lookup_elem( + &ip_to_cpu_and_tc_hotcache, + &lookup_key->address + ); + if (ip_info) { + // We got a cache hit, so return + return ip_info; + } + #endif + + ip_info = bpf_map_lookup_elem( &map_ip_to_cpu_and_tc, lookup_key ); + #ifdef USE_HOTCACHE + if (ip_info) { + // We found it, so add it to the cache + bpf_map_update_elem( + &ip_to_cpu_and_tc_hotcache, + &lookup_key->address, + ip_info, + BPF_NOEXIST + ); + } + #endif return ip_info; } @@ -104,9 +145,10 @@ static __always_inline struct ip_hash_info * tc_setup_lookup_key_and_tc_cpu( lookup_key->prefixlen = 128; // Direction is reversed because we are operating on egress if (direction < 3) { - lookup_key->address = (direction == 1) ? dissector->src_ip : + lookup_key->address = (direction == 1) ? dissector->src_ip : dissector->dst_ip; *out_effective_direction = direction; + struct ip_hash_info * ip_info = bpf_map_lookup_elem( &map_ip_to_cpu_and_tc, lookup_key diff --git a/src/rust/lqos_sys/src/bpf/common/maximums.h b/src/rust/lqos_sys/src/bpf/common/maximums.h index 7520cbc9..2a3afe7f 100644 --- a/src/rust/lqos_sys/src/bpf/common/maximums.h +++ b/src/rust/lqos_sys/src/bpf/common/maximums.h @@ -14,3 +14,6 @@ // Maximum number of packet pairs to track per flow. #define MAX_PACKETS MAX_FLOWS + +// Hot Cache Size +#define HOT_CACHE_SIZE 512 \ No newline at end of file