Currently, the update-set operation requires us to rebuild the entire chain, recompile the bytecode, and then swap the new program in for the old program. This adds a latency cost on each update-set operation. However, all we are doing is swapping out the content of a map with different contents and, ideally, we'd like to make this very performant (each ns matters when it comes to dynamically updating rulesets to prevent DDoS attacks).
Currently, BPF_MAP_TYPE_HASH does not allow for resizing, which means there is no trivial way to do this. We have considered a few options:
- Make the initial
BPF_MAP_TYPE_HASH larger than necessary, so we likely will have enough room whenever we call update-set. This approach comes with unnecessary memory usage, is non-atomic, and won't work in cases where the contents grow quickly.
- There is an upstream patch-set https://lore.kernel.org/bpf/20260408-rhash-v2-0-3b3675da1f6e@meta.com/ that offers a re-sizable map. The negative here are that this won't be available on kernel versions < 7.2.
- We can use
BPF_MAP_TYPE_ARRAY_OF_MAPS with a single element that contains a BPF_MAP_TYPE_HASH. The update-set operation would then just create a new BPF_MAP_TYPE_HASH and atomically swap it in that single element. This is atomic, supported by all kernels that we seperate, and should not add noticeable memory overhead. The only downside here is that we are adding indirection, and thus a small amount latency. It's likely that this is fine, but would need to be benchmarked. If it is an issue, we can make this optional for sets that we want to have low-latency update-set operations.
This issue is non-trivial and requires design. If you are interested in working on this, make sure to discuss how you are planning on adding this with the current maintainers/contributors before sending a PR.
Currently, the
update-setoperation requires us to rebuild the entire chain, recompile the bytecode, and then swap the new program in for the old program. This adds a latency cost on eachupdate-setoperation. However, all we are doing is swapping out the content of a map with different contents and, ideally, we'd like to make this very performant (eachnsmatters when it comes to dynamically updating rulesets to prevent DDoS attacks).Currently,
BPF_MAP_TYPE_HASHdoes not allow for resizing, which means there is no trivial way to do this. We have considered a few options:BPF_MAP_TYPE_HASHlarger than necessary, so we likely will have enough room whenever we callupdate-set. This approach comes with unnecessary memory usage, is non-atomic, and won't work in cases where the contents grow quickly.BPF_MAP_TYPE_ARRAY_OF_MAPSwith a single element that contains aBPF_MAP_TYPE_HASH. Theupdate-setoperation would then just create a newBPF_MAP_TYPE_HASHand atomically swap it in that single element. This is atomic, supported by all kernels that we seperate, and should not add noticeable memory overhead. The only downside here is that we are adding indirection, and thus a small amount latency. It's likely that this is fine, but would need to be benchmarked. If it is an issue, we can make this optional for sets that we want to have low-latencyupdate-setoperations.This issue is non-trivial and requires design. If you are interested in working on this, make sure to discuss how you are planning on adding this with the current maintainers/contributors before sending a PR.