From 1aeec1ffc5517ed47b249ba74a3e2870af36f865 Mon Sep 17 00:00:00 2001 From: chenyuezhou Date: Tue, 8 Jun 2021 12:09:31 -0400 Subject: [PATCH] libbcc: add msg_redirect_hash() and sk_redirect_hash() for sockhash --- docs/reference_guide.md | 30 ++++++++++++++++++--- src/cc/export/helpers.h | 2 ++ src/cc/frontends/clang/b_frontend_action.cc | 7 +++++ tests/cc/test_sock_table.cc | 4 +++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/docs/reference_guide.md b/docs/reference_guide.md index 954ad7d1..63c82d22 100644 --- a/docs/reference_guide.md +++ b/docs/reference_guide.md @@ -78,6 +78,8 @@ This guide is incomplete. If something feels missing, check the bcc and kernel s - [30. map.pop()](#30-mappop) - [31. map.peek()](#31-mappeek) - [32. map.sock_hash_update()](#32-mapsock_hash_update) + - [33. map.msg_redirect_hash()](#33-mapmsg_redirect_hash) + - [34. map.sk_redirect_hash()](#34-mapsk_redirect_hash) - [Licensing](#licensing) - [Rewriter](#rewriter) @@ -1234,11 +1236,11 @@ BPF_HASH(skh, struct sock_key, 65535); This creates a hash named ```skh``` where the key is a ```struct sock_key```. -A sockhash is a BPF map type that holds references to sock structs. Then with a new sk/msg redirect bpf helper BPF programs can use the map to redirect skbs/msgs between sockets (```bpf_sk_redirect_hash/bpf_msg_redirect_hash```). +A sockhash is a BPF map type that holds references to sock structs. Then with a new sk/msg redirect bpf helper BPF programs can use the map to redirect skbs/msgs between sockets (```map.sk_redirect_hash()/map.msg_redirect_hash()```). The difference between ```BPF_SOCKHASH``` and ```BPF_SOCKMAP``` is that ```BPF_SOCKMAP``` is implemented based on an array, and enforces keys to be four bytes. While ```BPF_SOCKHASH``` is implemented based on hash table, and the type of key can be specified freely. -Methods (covered later): map.sock_hash_update(). +Methods (covered later): map.sock_hash_update(), map.msg_redirect_hash(), map.sk_redirect_hash(). [search /tests](https://github.com/iovisor/bcc/search?q=BPF_SOCKHASH+path%3Atests&type=Code) @@ -1436,7 +1438,7 @@ Examples in situ: ### 32. map.sock_hash_update() -Syntax: ```int map.sock_hash_update(struct bpf_sock_ops *, &key, int flags)``` +Syntax: ```int map.sock_hash_update(struct bpf_sock_ops *skops, &key, int flags)``` Add an entry to, or update a sockhash map referencing sockets. The skops is used as a new value for the entry associated to key. flags is one of: @@ -1453,6 +1455,28 @@ Return 0 on success, or a negative error in case of failure. Examples in situ: [search /tests](https://github.com/iovisor/bcc/search?q=sock_hash_update+path%3Atests&type=Code), +### 33. map.msg_redirect_hash() + +Syntax: ```int map.msg_redirect_hash(struct sk_msg_buff *msg, void *key, u64 flags)``` + +This helper is used in programs implementing policies at the socket level. If the message msg is allowed to pass (i.e. if the verdict eBPF program returns SK_PASS), redirect it to the socket referenced by map (of type BPF_MAP_TYPE_SOCKHASH) using hash key. Both ingress and egress interfaces can be used for redirection. The BPF_F_INGRESS value in flags is used to make the distinction (ingress path is selected if the flag is present, egress path otherwise). This is the only flag supported for now. + +Return SK_PASS on success, or SK_DROP on error. + +Examples in situ: +[search /tests](https://github.com/iovisor/bcc/search?q=msg_redirect_hash+path%3Atests&type=Code), + +### 34. map.sk_redirect_hash() + +Syntax: ```int map.sk_redirect_hash(struct sk_buff *skb, void *key, u64 flags)``` + +This helper is used in programs implementing policies at the skb socket level. If the sk_buff skb is allowed to pass (i.e. if the verdict eBPF program returns SK_PASS), redirect it to the socket referenced by map (of type BPF_MAP_TYPE_SOCKHASH) using hash key. Both ingress and egress interfaces can be used for redirection. The BPF_F_INGRESS value in flags is used to make the distinction (ingress path is selected if the flag is present, egress otherwise). This is the only flag supported for now. + +Return SK_PASS on success, or SK_DROP on error. + +Examples in situ: +[search /tests](https://github.com/iovisor/bcc/search?q=sk_redirect_hash+path%3Atests&type=Code), + ## Licensing Depending on which [BPF helpers](kernel-versions.md#helpers) are used, a GPL-compatible license is required. diff --git a/src/cc/export/helpers.h b/src/cc/export/helpers.h index e447486b..0be3572b 100644 --- a/src/cc/export/helpers.h +++ b/src/cc/export/helpers.h @@ -422,6 +422,8 @@ struct _name##_table_t {\ int (*update) (_key_type *, int *); \ int (*delete) (_key_type *); \ int (*sock_hash_update) (void *, void *, u64); \ + int (*msg_redirect_hash) (void *, void *, u64); \ + int (*sk_redirect_hash) (void *, void *, u64); \ u32 max_entries; \ }; \ __attribute__((section("maps/sockhash"))) \ diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc index 1c673226..e78ceb3c 100644 --- a/src/cc/frontends/clang/b_frontend_action.cc +++ b/src/cc/frontends/clang/b_frontend_action.cc @@ -1029,6 +1029,13 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) { } fe_.perf_events_[name] = perf_event; } + } else if (memb_name == "msg_redirect_hash" || memb_name == "sk_redirect_hash") { + string arg0 = rewriter_.getRewrittenText(expansionRange(Call->getArg(0)->getSourceRange())); + string args_other = rewriter_.getRewrittenText(expansionRange(SourceRange(GET_BEGINLOC(Call->getArg(1)), + GET_ENDLOC(Call->getArg(2))))); + + txt = "bpf_" + string(memb_name) + "(" + arg0 + ", (void *)bpf_pseudo_fd(1, " + fd + "), "; + txt += args_other + ")"; } else { if (memb_name == "lookup") { prefix = "bpf_map_lookup_elem"; diff --git a/tests/cc/test_sock_table.cc b/tests/cc/test_sock_table.cc index db5ce525..6db184ef 100644 --- a/tests/cc/test_sock_table.cc +++ b/tests/cc/test_sock_table.cc @@ -72,10 +72,14 @@ BPF_SOCKHASH(sk_hash2, u32, 10); int test(struct bpf_sock_ops *skops) { u32 key = 0, val = 0; + struct sk_msg_buff *msg; + struct sk_buff *skb; sk_hash2.update(&key, &val); sk_hash2.delete(&key); sk_hash2.sock_hash_update(skops, &key, 0); + sk_hash2.msg_redirect_hash(msg, &key, 0); + sk_hash2.sk_redirect_hash(skb, &key, 0); return 0; } -- 2.34.1