Commit 230c9c00 authored by Javier Honduvilla Coto's avatar Javier Honduvilla Coto Committed by yonghong-song

Allow arbitrary hashtable increments. Fixes #1742 (#1897)

* Allow arbitrary hashtable increments. Fixes #1742

Right now incrementing some datastructure's values like maps or histograms can
be done with some boilerplate[1] or with `increment` which increments a value
by 1.

This patch allows a second optional parameter to use as the increment.

- [1]:
```
u64 zero = 0, *val;
val = map.lookup_or_init(&key, &zero);
(*val) += inc;
```

Notes:
- Some lines in the documentation where changed because of trailing spaces
deletion
- The test is quite simple right now
- Will update the tools to use `increment` in another PR

* CR changes
parent bfecc243
......@@ -756,9 +756,9 @@ Examples in situ:
### 17. map.increment()
Syntax: ```map.increment(key)```
Syntax: ```map.increment(key[, increment_amount])```
Increments the key's value by one. Used for histograms.
Increments the key's value by `increment_amount`, which defaults to 1. Used for histograms.
Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=increment+path%3Aexamples&type=Code),
......
......@@ -388,7 +388,7 @@ A recap from earlier lessons:
New things to learn:
1. ```BPF_HISTOGRAM(dist)```: Defines a BPF map object that is a histogram, and names it "dist".
1. ```dist.increment()```: Increments the histogram bucket index provided as an argument by one.
1. ```dist.increment()```: Increments the histogram bucket index provided as first argument by one by default. Optionally, custom increments can be passed as the second argument.
1. ```bpf_log2l()```: Returns the log-2 of the provided value. This becomes the index of our histogram, so that we're constructing a power-of-2 histogram.
1. ```b["dist"].print_log2_hist("kbytes")```: Prints the "dist" histogram as power-of-2, with a column header of "kbytes". The only data transferred from kernel to user space is the bucket counts, making this efficient.
......
......@@ -49,7 +49,7 @@ struct _name##_table_t { \
int (*insert) (_key_type *, _leaf_type *); \
int (*delete) (_key_type *); \
void (*call) (void *, int index); \
void (*increment) (_key_type); \
void (*increment) (_key_type, ...); \
int (*get_stackid) (void *, u64); \
u32 max_entries; \
int flags; \
......
......@@ -780,14 +780,22 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) {
} else if (memb_name == "increment") {
string name = Ref->getDecl()->getName();
string arg0 = rewriter_.getRewrittenText(expansionRange(Call->getArg(0)->getSourceRange()));
string increment_value = "1";
if (Call->getNumArgs() == 2) {
increment_value = rewriter_.getRewrittenText(expansionRange(Call->getArg(1)->getSourceRange()));
}
string lookup = "bpf_map_lookup_elem_(bpf_pseudo_fd(1, " + fd + ")";
string update = "bpf_map_update_elem_(bpf_pseudo_fd(1, " + fd + ")";
txt = "({ typeof(" + name + ".key) _key = " + arg0 + "; ";
txt += "typeof(" + name + ".leaf) *_leaf = " + lookup + ", &_key); ";
txt += "if (_leaf) (*_leaf)++; ";
txt += "if (_leaf) (*_leaf) += " + increment_value + ";";
if (desc->second.type == BPF_MAP_TYPE_HASH) {
txt += "else { typeof(" + name + ".leaf) _zleaf; __builtin_memset(&_zleaf, 0, sizeof(_zleaf)); ";
txt += "_zleaf++; ";
txt += "_zleaf += " + increment_value + ";";
txt += update + ", &_key, &_zleaf, BPF_NOEXIST); } ";
}
txt += "})";
......
......@@ -1212,5 +1212,18 @@ int test(struct pt_regs *ctx, struct mm_struct *mm) {
b = BPF(text=text)
fn = b.load_func("test", BPF.KPROBE)
def test_arbitrary_increment_simple(self):
b = BPF(text=b"""
#include <uapi/linux/ptrace.h>
struct bpf_map;
BPF_HASH(map);
int map_delete(struct pt_regs *ctx, struct bpf_map *bpfmap, u64 *k) {
map.increment(42, 10);
return 0;
}
""")
b.attach_kprobe(event=b"htab_map_delete_elem", fn_name=b"map_delete")
b.cleanup()
if __name__ == "__main__":
main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment