Added helpers for BPF_PERCPU_HASH
authorLénaïc Huard <lenaic.huard@datadoghq.com>
Thu, 25 Feb 2021 14:26:46 +0000 (15:26 +0100)
committeryonghong-song <ys114321@gmail.com>
Thu, 25 Feb 2021 17:58:04 +0000 (09:58 -0800)
docs/reference_guide.md
examples/networking/xdp/xdp_macswap_count.py
src/cc/export/helpers.h
tests/cc/test_array_table.cc
tests/cc/test_bpf_table.cc
tests/cc/test_hash_table.cc
tests/python/test_percpu.py

index f430a57395579e8d4e07a41ed30cefcc2ff91bd3..715bc5c132dee4b5b98cf2d09d7a9159ab1c484e 100644 (file)
@@ -51,29 +51,30 @@ This guide is incomplete. If something feels missing, check the bcc and kernel s
         - [4. BPF_HISTOGRAM](#4-bpf_histogram)
         - [5. BPF_STACK_TRACE](#5-bpf_stack_trace)
         - [6. BPF_PERF_ARRAY](#6-bpf_perf_array)
-        - [7. BPF_PERCPU_ARRAY](#7-bpf_percpu_array)
-        - [8. BPF_LPM_TRIE](#8-bpf_lpm_trie)
-        - [9. BPF_PROG_ARRAY](#9-bpf_prog_array)
-        - [10. BPF_DEVMAP](#10-bpf_devmap)
-        - [11. BPF_CPUMAP](#11-bpf_cpumap)
-        - [12. BPF_XSKMAP](#12-bpf_xskmap)
-        - [13. BPF_ARRAY_OF_MAPS](#13-bpf_array_of_maps)
-        - [14. BPF_HASH_OF_MAPS](#14-bpf_hash_of_maps)
-        - [15. BPF_STACK](#15-bpf_stack)
-        - [16. BPF_QUEUE](#16-bpf_queue)
-        - [17. map.lookup()](#17-maplookup)
-        - [18. map.lookup_or_try_init()](#18-maplookup_or_try_init)
-        - [19. map.delete()](#19-mapdelete)
-        - [20. map.update()](#20-mapupdate)
-        - [21. map.insert()](#21-mapinsert)
-        - [22. map.increment()](#22-mapincrement)
-        - [23. map.get_stackid()](#23-mapget_stackid)
-        - [24. map.perf_read()](#24-mapperf_read)
-        - [25. map.call()](#25-mapcall)
-        - [26. map.redirect_map()](#26-mapredirect_map)
-        - [27. map.push()](#27-mappush)
-        - [28. map.pop()](#28-mappop)
-        - [29. map.peek()](#29-mappeek)
+        - [7. BPF_PERCPU_HASH](#7-bpf_percpu_hash)
+        - [8. BPF_PERCPU_ARRAY](#8-bpf_percpu_array)
+        - [9. BPF_LPM_TRIE](#9-bpf_lpm_trie)
+        - [10. BPF_PROG_ARRAY](#10-bpf_prog_array)
+        - [11. BPF_DEVMAP](#11-bpf_devmap)
+        - [12. BPF_CPUMAP](#12-bpf_cpumap)
+        - [13. BPF_XSKMAP](#13-bpf_xskmap)
+        - [14. BPF_ARRAY_OF_MAPS](#14-bpf_array_of_maps)
+        - [15. BPF_HASH_OF_MAPS](#15-bpf_hash_of_maps)
+        - [16. BPF_STACK](#16-bpf_stack)
+        - [17. BPF_QUEUE](#17-bpf_queue)
+        - [18. map.lookup()](#18-maplookup)
+        - [19. map.lookup_or_try_init()](#19-maplookup_or_try_init)
+        - [20. map.delete()](#20-mapdelete)
+        - [21. map.update()](#21-mapupdate)
+        - [22. map.insert()](#22-mapinsert)
+        - [23. map.increment()](#23-mapincrement)
+        - [24. map.get_stackid()](#24-mapget_stackid)
+        - [25. map.perf_read()](#25-mapperf_read)
+        - [26. map.call()](#26-mapcall)
+        - [27. map.redirect_map()](#27-mapredirect_map)
+        - [28. map.push()](#28-mappush)
+        - [29. map.pop()](#29-mappop)
+        - [30. map.peek()](#30-mappeek)
     - [Licensing](#licensing)
     - [Rewriter](#rewriter)
 
@@ -980,7 +981,36 @@ Methods (covered later): map.perf_read().
 Examples in situ:
 [search /tests](https://github.com/iovisor/bcc/search?q=BPF_PERF_ARRAY+path%3Atests&type=Code)
 
-### 7. BPF_PERCPU_ARRAY
+### 7. BPF_PERCPU_HASH
+
+Syntax: ```BPF_PERCPU_HASH(name [, key_type [, leaf_type [, size]]])```
+
+Creates NUM_CPU int-indexed hash maps (associative arrays) named ```name```, with optional parameters. Each CPU will have a separate copy of this array. The copies are not kept synchronized in any way.
+
+Note that due to limits defined in the kernel (in linux/mm/percpu.c), the ```leaf_type``` cannot have a size of more than 32KB.
+In other words, ```BPF_PERCPU_HASH``` elements cannot be larger than 32KB in size.
+
+
+Defaults: ```BPF_PERCPU_HASH(name, key_type=u64, leaf_type=u64, size=10240)```
+
+For example:
+
+```C
+BPF_PERCPU_HASH(start, struct request *);
+```
+
+This creates NUM_CPU hashes named ```start``` where the key is a ```struct request *```, and the value defaults to u64.
+
+This is a wrapper macro for `BPF_TABLE("percpu_hash", ...)`.
+
+Methods (covered later): map.lookup(), map.lookup_or_try_init(), map.delete(), map.update(), map.insert(), map.increment().
+
+Examples in situ:
+[search /examples](https://github.com/iovisor/bcc/search?q=BPF_PERCPU_HASH+path%3Aexamples&type=Code),
+[search /tools](https://github.com/iovisor/bcc/search?q=BPF_PERCPU_HASH+path%3Atools&type=Code)
+
+
+### 8. BPF_PERCPU_ARRAY
 
 Syntax: ```BPF_PERCPU_ARRAY(name [, leaf_type [, size]])```
 
@@ -1008,7 +1038,7 @@ Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=BPF_PERCPU_ARRAY+path%3Aexamples&type=Code),
 [search /tools](https://github.com/iovisor/bcc/search?q=BPF_PERCPU_ARRAY+path%3Atools&type=Code)
 
-### 8. BPF_LPM_TRIE
+### 9. BPF_LPM_TRIE
 
 Syntax: `BPF_LPM_TRIE(name [, key_type [, leaf_type [, size]]])`
 
@@ -1032,7 +1062,7 @@ Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=BPF_LPM_TRIE+path%3Aexamples&type=Code),
 [search /tools](https://github.com/iovisor/bcc/search?q=BPF_LPM_TRIE+path%3Atools&type=Code)
 
-### 9. BPF_PROG_ARRAY
+### 10. BPF_PROG_ARRAY
 
 Syntax: ```BPF_PROG_ARRAY(name, size)```
 
@@ -1047,7 +1077,7 @@ Examples in situ:
 [search /tests](https://github.com/iovisor/bcc/search?q=BPF_PROG_ARRAY+path%3Atests&type=Code),
 [assign fd](https://github.com/iovisor/bcc/blob/master/examples/networking/tunnel_monitor/monitor.py#L24-L26)
 
-### 10. BPF_DEVMAP
+### 11. BPF_DEVMAP
 
 Syntax: ```BPF_DEVMAP(name, size)```
 
@@ -1063,7 +1093,7 @@ Methods (covered later): map.redirect_map().
 Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=BPF_DEVMAP+path%3Aexamples&type=Code),
 
-### 11. BPF_CPUMAP
+### 12. BPF_CPUMAP
 
 Syntax: ```BPF_CPUMAP(name, size)```
 
@@ -1079,7 +1109,7 @@ Methods (covered later): map.redirect_map().
 Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=BPF_CPUMAP+path%3Aexamples&type=Code),
 
-### 12. BPF_XSKMAP
+### 13. BPF_XSKMAP
 
 Syntax: ```BPF_XSKMAP(name, size)```
 
@@ -1095,7 +1125,7 @@ Methods (covered later): map.redirect_map(). map.lookup()
 Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=BPF_XSKMAP+path%3Aexamples&type=Code),
 
-### 13. BPF_ARRAY_OF_MAPS
+### 14. BPF_ARRAY_OF_MAPS
 
 Syntax: ```BPF_ARRAY_OF_MAPS(name, inner_map_name, size)```
 
@@ -1108,7 +1138,7 @@ BPF_TABLE("hash", int, int, ex2, 1024);
 BPF_ARRAY_OF_MAPS(maps_array, "ex1", 10);
 ```
 
-### 14. BPF_HASH_OF_MAPS
+### 15. BPF_HASH_OF_MAPS
 
 Syntax: ```BPF_HASH_OF_MAPS(name, inner_map_name, size)```
 
@@ -1121,7 +1151,7 @@ BPF_ARRAY(ex2, int, 1024);
 BPF_HASH_OF_MAPS(maps_hash, "ex1", 10);
 ```
 
-### 15. BPF_STACK
+### 16. BPF_STACK
 
 Syntax: ```BPF_STACK(name, leaf_type, max_entries[, flags])```
 
@@ -1141,7 +1171,7 @@ Methods (covered later): map.push(), map.pop(), map.peek().
 Examples in situ:
 [search /tests](https://github.com/iovisor/bcc/search?q=BPF_STACK+path%3Atests&type=Code),
 
-### 16. BPF_QUEUE
+### 17. BPF_QUEUE
 
 Syntax: ```BPF_QUEUE(name, leaf_type, max_entries[, flags])```
 
@@ -1161,7 +1191,7 @@ Methods (covered later): map.push(), map.pop(), map.peek().
 Examples in situ:
 [search /tests](https://github.com/iovisor/bcc/search?q=BPF_QUEUE+path%3Atests&type=Code),
 
-### 17. map.lookup()
+### 18. map.lookup()
 
 Syntax: ```*val map.lookup(&key)```
 
@@ -1171,7 +1201,7 @@ Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=lookup+path%3Aexamples&type=Code),
 [search /tools](https://github.com/iovisor/bcc/search?q=lookup+path%3Atools&type=Code)
 
-### 18. map.lookup_or_try_init()
+### 19. map.lookup_or_try_init()
 
 Syntax: ```*val map.lookup_or_try_init(&key, &zero)```
 
@@ -1184,7 +1214,7 @@ Examples in situ:
 Note: The old map.lookup_or_init() may cause return from the function, so lookup_or_try_init() is recommended as it
 does not have this side effect.
 
-### 19. map.delete()
+### 20. map.delete()
 
 Syntax: ```map.delete(&key)```
 
@@ -1194,7 +1224,7 @@ Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=delete+path%3Aexamples&type=Code),
 [search /tools](https://github.com/iovisor/bcc/search?q=delete+path%3Atools&type=Code)
 
-### 20. map.update()
+### 21. map.update()
 
 Syntax: ```map.update(&key, &val)```
 
@@ -1204,7 +1234,7 @@ Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=update+path%3Aexamples&type=Code),
 [search /tools](https://github.com/iovisor/bcc/search?q=update+path%3Atools&type=Code)
 
-### 21. map.insert()
+### 22. map.insert()
 
 Syntax: ```map.insert(&key, &val)```
 
@@ -1214,7 +1244,7 @@ Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=insert+path%3Aexamples&type=Code),
 [search /tools](https://github.com/iovisor/bcc/search?q=insert+path%3Atools&type=Code)
 
-### 22. map.increment()
+### 23. map.increment()
 
 Syntax: ```map.increment(key[, increment_amount])```
 
@@ -1224,7 +1254,7 @@ Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=increment+path%3Aexamples&type=Code),
 [search /tools](https://github.com/iovisor/bcc/search?q=increment+path%3Atools&type=Code)
 
-### 23. map.get_stackid()
+### 24. map.get_stackid()
 
 Syntax: ```int map.get_stackid(void *ctx, u64 flags)```
 
@@ -1234,7 +1264,7 @@ Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?q=get_stackid+path%3Aexamples&type=Code),
 [search /tools](https://github.com/iovisor/bcc/search?q=get_stackid+path%3Atools&type=Code)
 
-### 24. map.perf_read()
+### 25. map.perf_read()
 
 Syntax: ```u64 map.perf_read(u32 cpu)```
 
@@ -1243,7 +1273,7 @@ This returns the hardware performance counter as configured in [5. BPF_PERF_ARRA
 Examples in situ:
 [search /tests](https://github.com/iovisor/bcc/search?q=perf_read+path%3Atests&type=Code)
 
-### 25. map.call()
+### 26. map.call()
 
 Syntax: ```void map.call(void *ctx, int index)```
 
@@ -1282,7 +1312,7 @@ Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?l=C&q=call+path%3Aexamples&type=Code),
 [search /tests](https://github.com/iovisor/bcc/search?l=C&q=call+path%3Atests&type=Code)
 
-### 26. map.redirect_map()
+### 27. map.redirect_map()
 
 Syntax: ```int map.redirect_map(int index, int flags)```
 
@@ -1320,7 +1350,7 @@ b.attach_xdp("eth1", out_fn, 0)
 Examples in situ:
 [search /examples](https://github.com/iovisor/bcc/search?l=C&q=redirect_map+path%3Aexamples&type=Code),
 
-### 27. map.push()
+### 28. map.push()
 
 Syntax: ```int map.push(&val, int flags)```
 
@@ -1331,7 +1361,7 @@ Returns 0 on success, negative error on failure.
 Examples in situ:
 [search /tests](https://github.com/iovisor/bcc/search?q=push+path%3Atests&type=Code),
 
-### 28. map.pop()
+### 29. map.pop()
 
 Syntax: ```int map.pop(&val)```
 
@@ -1342,7 +1372,7 @@ Returns 0 on success, negative error on failure.
 Examples in situ:
 [search /tests](https://github.com/iovisor/bcc/search?q=pop+path%3Atests&type=Code),
 
-### 29. map.peek()
+### 30. map.peek()
 
 Syntax: ```int map.peek(&val)```
 
index 770ce8ca0b2050e737505a695458179d25d73fc7..99a84f9a5c827350209dddedb2b37face1e9965a 100755 (executable)
@@ -59,7 +59,7 @@ b = BPF(text = """
 #include <linux/ipv6.h>
 
 
-BPF_TABLE("percpu_array", uint32_t, long, dropcnt, 256);
+BPF_PERCPU_ARRAY(dropcnt, long, 256);
 
 static inline int parse_ipv4(void *data, u64 nh_off, void *data_end) {
     struct iphdr *iph = data + nh_off;
index 0447a956e35690a0279f87e1918371d1cdb98e82..ce8c00e3c6fa23bda5c17e2a40caed456878aefb 100644 (file)
@@ -255,6 +255,25 @@ struct _name##_table_t _name = { .max_entries = (_max_entries) }
 #define BPF_HASH(...) \
   BPF_HASHX(__VA_ARGS__, BPF_HASH4, BPF_HASH3, BPF_HASH2, BPF_HASH1)(__VA_ARGS__)
 
+#define BPF_PERCPU_HASH1(_name) \
+  BPF_TABLE("percpu_hash", u64, u64, _name, 10240)
+#define BPF_PERCPU_HASH2(_name, _key_type) \
+  BPF_TABLE("percpu_hash", _key_type, u64, _name, 10240)
+#define BPF_PERCPU_HASH3(_name, _key_type, _leaf_type) \
+  BPF_TABLE("percpu_hash", _key_type, _leaf_type, _name, 10240)
+#define BPF_PERCPU_HASH4(_name, _key_type, _leaf_type, _size) \
+  BPF_TABLE("percpu_hash", _key_type, _leaf_type, _name, _size)
+
+// helper for default-variable macro function
+#define BPF_PERCPU_HASHX(_1, _2, _3, _4, NAME, ...) NAME
+
+// Define a hash function, some arguments optional
+// BPF_PERCPU_HASH(name, key_type=u64, leaf_type=u64, size=10240)
+#define BPF_PERCPU_HASH(...)                                            \
+  BPF_PERCPU_HASHX(                                                     \
+    __VA_ARGS__, BPF_PERCPU_HASH4, BPF_PERCPU_HASH3, BPF_PERCPU_HASH2, BPF_PERCPU_HASH1) \
+           (__VA_ARGS__)
+
 #define BPF_ARRAY1(_name) \
   BPF_TABLE("array", int, u64, _name, 10240)
 #define BPF_ARRAY2(_name, _leaf_type) \
index 190f92725d8ef2419cda35b8ea2091c9ec2cfc22..c941f0f9aa02fd32975d8947efb39362607341e9 100644 (file)
@@ -98,8 +98,8 @@ TEST_CASE("test array table", "[array_table]") {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
 TEST_CASE("percpu array table", "[percpu_array_table]") {
   const std::string BPF_PROGRAM = R"(
-    BPF_TABLE("percpu_hash", int, u64, myhash, 128);
-    BPF_TABLE("percpu_array", int, u64, myarray, 64);
+    BPF_PERCPU_HASH(myhash, int, u64, 128);
+    BPF_PERCPU_ARRAY(myarray, u64, 64);
   )";
 
   ebpf::BPF bpf;
index 5d4ea3c5c7c659ca38602794399c16e2454e8335..d61b9b5e27e8f638d73cb58b28b380a8c773c659 100644 (file)
@@ -94,7 +94,7 @@ TEST_CASE("test bpf table", "[bpf_table]") {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
 TEST_CASE("test bpf percpu tables", "[bpf_percpu_table]") {
   const std::string BPF_PROGRAM = R"(
-    BPF_TABLE("percpu_hash", int, u64, myhash, 128);
+    BPF_PERCPU_HASH(myhash, int, u64, 128);
   )";
 
   ebpf::BPF bpf;
index 1bcc30632e4f4a31569a19caa0a51cc7e98ab638..38e08b7cb82b8ee92808a87ee499a07d8a0defbe 100644 (file)
@@ -94,8 +94,8 @@ TEST_CASE("test hash table", "[hash_table]") {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0)
 TEST_CASE("percpu hash table", "[percpu_hash_table]") {
   const std::string BPF_PROGRAM = R"(
-    BPF_TABLE("percpu_hash", int, u64, myhash, 128);
-    BPF_TABLE("percpu_array", int, u64, myarray, 64);
+    BPF_PERCPU_HASH(myhash, int, u64, 128);
+    BPF_PERCPU_ARRAY(myarray, u64, 64);
   )";
 
   ebpf::BPF bpf;
index 9469b1a755002e99b9bd31a3d31afff76b6e08ba..b493752eeac23b1567ffefb3380f112a990f4bf9 100755 (executable)
@@ -11,7 +11,7 @@ class TestPercpu(unittest.TestCase):
 
     def setUp(self):
         try:
-            b = BPF(text='BPF_TABLE("percpu_array", u32, u32, stub, 1);')
+            b = BPF(text='BPF_PERCPU_ARRAY(stub, u32, 1);')
         except:
             raise unittest.SkipTest("PerCpu unsupported on this kernel")
 
@@ -25,7 +25,7 @@ class TestPercpu(unittest.TestCase):
 
     def test_u64(self):
         test_prog1 = """
-        BPF_TABLE("percpu_hash", u32, u64, stats, 1);
+        BPF_PERCPU_HASH(stats, u32, u64, 1);
         int hello_world(void *ctx) {
             u32 key=0;
             u64 value = 0, *val;
@@ -57,7 +57,7 @@ class TestPercpu(unittest.TestCase):
 
     def test_u32(self):
         test_prog1 = """
-        BPF_TABLE("percpu_array", u32, u32, stats, 1);
+        BPF_PERCPU_ARRAY(stats, u32, 1);
         int hello_world(void *ctx) {
             u32 key=0;
             u32 value = 0, *val;
@@ -93,7 +93,7 @@ class TestPercpu(unittest.TestCase):
         u32 c1;
         u32 c2;
         } counter;
-        BPF_TABLE("percpu_hash", u32, counter, stats, 1);
+        BPF_PERCPU_HASH(stats, u32, counter, 1);
         int hello_world(void *ctx) {
             u32 key=0;
             counter value = {0,0}, *val;