hulk inclusion category: featrue bugzilla: https://atomgit.com/openeuler/kernel/issues/8480 -------------------------------- Add local connect support for hisock. Signed-off-by: Pu Lehui <pulehui@huawei.com> --- net/core/filter.c | 4 ++ samples/bpf/hisock/bpf.c | 107 +++++++++++++++++++++++++++++++- samples/bpf/hisock/hisock_cmd.c | 49 ++++++++++++++- 3 files changed, 156 insertions(+), 4 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index 567bdb3cf0ba..37b41798d8bd 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -7806,6 +7806,10 @@ sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) #endif case BPF_FUNC_tcp_sock: return &bpf_tcp_sock_proto; +#ifdef CONFIG_HISOCK + case BPF_FUNC_sk_release: + return &bpf_sk_release_proto; +#endif #endif /* CONFIG_INET */ case BPF_FUNC_get_current_comm: return &bpf_get_current_comm_proto; diff --git a/samples/bpf/hisock/bpf.c b/samples/bpf/hisock/bpf.c index a21aebe128be..1e05acc036fd 100644 --- a/samples/bpf/hisock/bpf.c +++ b/samples/bpf/hisock/bpf.c @@ -49,6 +49,13 @@ struct { __uint(max_entries, MAX_CONN); } connmap SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_SOCKHASH); + __uint(key_size, sizeof(struct sock_tuple)); + __uint(value_size, sizeof(int)); + __uint(max_entries, MAX_CONN); +} local_connmap SEC(".maps"); + struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(key_size, sizeof(u16)); @@ -74,6 +81,28 @@ static inline bool is_speed_flow(u16 port) return false; } +static inline bool +is_local_conn(struct bpf_sock_ops *skops, u32 *laddr, u32 *raddr) +{ + struct sock_tuple key = { 0 }; + struct bpf_sock *sk; + + if (*laddr == *raddr) + return true; + + key.saddr = *laddr; + key.daddr = *raddr; + key.sport = skops->local_port; + key.dport = bpf_ntohl(skops->remote_port); + + sk = bpf_map_lookup_elem(&local_connmap, &key); + if (!sk) + return false; + + bpf_sk_release(sk); + return true; +} + static inline bool is_ipv6_addr_mapped(u32 *addr6) { return addr6[0] == 0 && addr6[1] == 0 && @@ -116,6 +145,19 @@ static void handle_listen_cb(struct bpf_sock_ops *skops) } } +static void +handle_local_estd_cb(struct bpf_sock_ops *skops, u32 *laddr, u32 *raddr) +{ + struct sock_tuple key = { 0 }; + + key.saddr = *raddr; + key.daddr = *laddr; + key.sport = bpf_ntohl(skops->remote_port); + key.dport = skops->local_port; + + bpf_sock_hash_update(skops, &local_connmap, &key, BPF_NOEXIST); +} + static void handle_remote_estd_cb(struct bpf_sock_ops *skops, u32 *laddr, u32 *raddr) { @@ -137,12 +179,28 @@ handle_remote_estd_cb(struct bpf_sock_ops *skops, u32 *laddr, u32 *raddr) static inline void handle_passive_estd_inet_cb(struct bpf_sock_ops *skops) { - handle_remote_estd_cb(skops, &skops->local_ip4, &skops->remote_ip4); + if (is_local_conn(skops, &skops->local_ip4, &skops->remote_ip4)) + handle_local_estd_cb(skops, &skops->local_ip4, &skops->remote_ip4); + else + handle_remote_estd_cb(skops, &skops->local_ip4, &skops->remote_ip4); } static inline void handle_passive_estd_inet6_cb(struct bpf_sock_ops *skops) { - handle_remote_estd_cb(skops, &skops->local_ip6[3], &skops->remote_ip6[3]); + if (is_local_conn(skops, &skops->local_ip6[3], &skops->remote_ip6[3])) + handle_local_estd_cb(skops, &skops->local_ip6[3], &skops->remote_ip6[3]); + else + handle_remote_estd_cb(skops, &skops->local_ip6[3], &skops->remote_ip6[3]); +} + +static inline void handle_active_estd_inet_cb(struct bpf_sock_ops *skops) +{ + handle_local_estd_cb(skops, &skops->local_ip4, &skops->remote_ip4); +} + +static inline void handle_active_estd_inet6_cb(struct bpf_sock_ops *skops) +{ + handle_local_estd_cb(skops, &skops->local_ip6[3], &skops->remote_ip6[3]); } static void @@ -191,6 +249,11 @@ int hisock_sockops_prog(struct bpf_sock_ops *skops) break; handle_passive_estd_inet_cb(skops); break; + case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: + if (!is_speed_flow(bpf_ntohl(skops->remote_port))) + break; + handle_active_estd_inet_cb(skops); + break; case BPF_SOCK_OPS_STATE_CB: handle_terminate_inet_cb(skops); break; @@ -205,6 +268,11 @@ int hisock_sockops_prog(struct bpf_sock_ops *skops) break; handle_passive_estd_inet6_cb(skops); break; + case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: + if (!is_speed_flow(bpf_ntohl(skops->remote_port))) + break; + handle_active_estd_inet6_cb(skops); + break; case BPF_SOCK_OPS_STATE_CB: handle_terminate_inet6_cb(skops); break; @@ -216,6 +284,41 @@ int hisock_sockops_prog(struct bpf_sock_ops *skops) return 1; } +static void +msg_redirect_cb(struct sk_msg_md *msg, u32 *laddr, u32 *raddr) +{ + struct sock_tuple key = { 0 }; + + key.daddr = *raddr; + key.saddr = *laddr; + key.dport = bpf_ntohl(msg->remote_port); + key.sport = msg->local_port; + + bpf_msg_redirect_hash(msg, &local_connmap, &key, BPF_F_INGRESS); +} + +static inline void msg_redirect_inet_cb(struct sk_msg_md *msg) +{ + msg_redirect_cb(msg, &msg->local_ip4, &msg->remote_ip4); +} + +static inline void msg_redirect_inet6_cb(struct sk_msg_md *msg) +{ + msg_redirect_cb(msg, &msg->local_ip6[3], &msg->remote_ip6[3]); +} + +SEC("hisock_skmsg") +int hisock_skmsg_prog(struct sk_msg_md *msg) +{ + if (msg->family == AF_INET) + msg_redirect_inet_cb(msg); + else if (msg->family == AF_INET6 && + is_ipv6_addr_mapped(msg->local_ip6)) + msg_redirect_inet6_cb(msg); + + return SK_PASS; +} + SEC("hisock_ingress") int hisock_ingress_prog(struct __sk_buff *skb) { diff --git a/samples/bpf/hisock/hisock_cmd.c b/samples/bpf/hisock/hisock_cmd.c index 76422d7fa7eb..874008e66732 100644 --- a/samples/bpf/hisock/hisock_cmd.c +++ b/samples/bpf/hisock/hisock_cmd.c @@ -32,6 +32,7 @@ #define TASK_COMM_LEN 16 #endif +#define HISOCK_BPFFS "/sys/fs/bpf/hisock" #define DEF_BPF_PATH "bpf.o" #define MAX_IF_NUM 8 #define MAX_PORT_NUM 8 @@ -51,9 +52,11 @@ struct { struct hisock_prog_info { const char *sec_name; + const char *pin_map; enum bpf_prog_type prog_type; enum bpf_attach_type attach_type; bool is_dev_attach; + bool is_skmsg; int prog_fd; }; @@ -63,6 +66,13 @@ static struct hisock_prog_info prog_infos[] = { .prog_type = BPF_PROG_TYPE_SOCK_OPS, .attach_type = BPF_CGROUP_SOCK_OPS, }, + { + .sec_name = "hisock_skmsg", + .prog_type = BPF_PROG_TYPE_SK_MSG, + .attach_type = BPF_SK_MSG_VERDICT, + .pin_map = "local_connmap", + .is_skmsg = true, + }, { .sec_name = "hisock_ingress", .prog_type = BPF_PROG_TYPE_HISOCK, @@ -249,6 +259,16 @@ static int detach_progs(void) continue; } + if (info->is_skmsg) { + char pin_path[64]; + + snprintf(pin_path, sizeof(pin_path), "%s/%s", + HISOCK_BPFFS, info->pin_map); + + unlink(pin_path); + continue; + } + if (bpf_prog_detach(cgrp_fd, info->attach_type)) { fprintf(stderr, "ERROR: failed to detach prog %s\n", info->sec_name); err_cnt++; @@ -259,7 +279,7 @@ static int detach_progs(void) return -err_cnt; } -static int attach_progs(void) +static int attach_progs(struct bpf_object *obj) { struct hisock_prog_info *info; int i, j, cgrp_fd; @@ -281,6 +301,31 @@ static int attach_progs(void) continue; } + if (info->is_skmsg) { + struct bpf_map *map; + char pin_path[64]; + + map = bpf_object__find_map_by_name(obj, info->pin_map); + if (!map) { + fprintf(stderr, "ERROR: failed to find pin map\n"); + goto fail; + } + + snprintf(pin_path, sizeof(pin_path), "%s/%s", + HISOCK_BPFFS, info->pin_map); + + if (bpf_map__pin(map, pin_path)) { + fprintf(stderr, "ERROR: failed to pin map\n"); + goto fail; + } + + if (bpf_prog_attach(info->prog_fd, bpf_map__fd(map), + info->attach_type, 0)) + goto fail; + + continue; + } + if (bpf_prog_attach(info->prog_fd, cgrp_fd, info->attach_type, 0)) goto fail; } @@ -337,7 +382,7 @@ static int do_hisock(void) return -1; } - if (attach_progs()) { + if (attach_progs(obj)) { fprintf(stderr, "ERROR: failed to attach progs\n"); bpf_object__close(obj); return -1; -- 2.34.1