hulk inclusion category: featrue bugzilla: https://atomgit.com/openeuler/kernel/issues/7116 -------------------------------- Add local connect support for hisock. Signed-off-by: Pu Lehui <pulehui@huawei.com> --- samples/bpf/hisock/bpf.c | 67 +++++++++++++++++++++++ samples/bpf/hisock/hisock_cmd.c | 96 ++++++++++++++++++++++++++++++--- 2 files changed, 155 insertions(+), 8 deletions(-) diff --git a/samples/bpf/hisock/bpf.c b/samples/bpf/hisock/bpf.c index 777d1c19d38f..dcbd50bd6cf6 100644 --- a/samples/bpf/hisock/bpf.c +++ b/samples/bpf/hisock/bpf.c @@ -46,6 +46,10 @@ struct sock_value { u32 ingress_ifindex; }; +struct { + u32 local_mask; +} g_bss = {}; + struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(key_size, sizeof(struct sock_tuple)); @@ -53,6 +57,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)); @@ -82,6 +93,12 @@ static inline bool is_speed_flow(u16 port) return false; } +static inline bool is_local_conn(u32 laddr, u32 raddr) +{ + return (bpf_ntohl(laddr) & g_bss.local_mask) == + (bpf_ntohl(raddr) & g_bss.local_mask); +} + static inline bool is_ipv6_addr_mapped(u32 *addr6) { return addr6[0] == 0 && addr6[1] == 0 && @@ -137,6 +154,11 @@ handle_establish_cb(struct bpf_sock_ops *skops, u32 laddr, u32 raddr) key.sport = bpf_ntohl(skops->remote_port); key.dport = skops->local_port; + if (is_local_conn(laddr, raddr)) { + bpf_sock_hash_update(skops, &local_connmap, &key, BPF_NOEXIST); + return; + } + val.sk = (unsigned long)skops->sk; val.ingress_dev = parse_ingress_dev(skops); @@ -201,6 +223,11 @@ int hisock_sockops_prog(struct bpf_sock_ops *skops) break; handle_establish_inet_cb(skops); break; + case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: + if (!is_speed_flow(bpf_ntohl(skops->remote_port))) + break; + handle_establish_inet_cb(skops); + break; case BPF_SOCK_OPS_STATE_CB: handle_terminate_inet_cb(skops); break; @@ -215,6 +242,11 @@ int hisock_sockops_prog(struct bpf_sock_ops *skops) break; handle_establish_inet6_cb(skops); break; + case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: + if (!is_speed_flow(bpf_ntohl(skops->remote_port))) + break; + handle_establish_inet6_cb(skops); + break; case BPF_SOCK_OPS_STATE_CB: handle_terminate_inet6_cb(skops); break; @@ -226,6 +258,41 @@ int hisock_sockops_prog(struct bpf_sock_ops *skops) return 1; } +static inline 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 void msg_redirect_inet_cb(struct sk_msg_md *msg) +{ + msg_redirect_cb(msg, msg->local_ip4, msg->remote_ip4); +} + +static 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 xdp_md *ctx) { diff --git a/samples/bpf/hisock/hisock_cmd.c b/samples/bpf/hisock/hisock_cmd.c index f44c98d529da..64a5a63ddb05 100644 --- a/samples/bpf/hisock/hisock_cmd.c +++ b/samples/bpf/hisock/hisock_cmd.c @@ -32,6 +32,8 @@ #define TASK_COMM_LEN 16 #endif +#define HISOCK_BPFFS "/sys/fs/bpf/hisock" +#define DEF_LOCAL_MASK 0xFFFF0000 #define DEF_BPF_PATH "bpf.o" #define MAX_IF_NUM 8 #define MAX_PORT_NUM 8 @@ -44,6 +46,7 @@ struct { int port_num; char *comm[MAX_COMM_NUM]; int comm_num; + __u32 local_mask; char *cgrp_path; char *bpf_path; bool unload; @@ -51,20 +54,31 @@ struct { struct hisock_prog_info { const char *prog_name; + const char *pin_map; enum bpf_prog_type prog_type; enum bpf_attach_type attach_type; int attach_flag; int prog_fd; + bool is_skmsg; bool is_xdp; }; +struct bss { + __u32 local_mask; +}; + static struct hisock_prog_info prog_infos[] = { { .prog_name = "hisock_sockops_prog", .prog_type = BPF_PROG_TYPE_SOCK_OPS, .attach_type = BPF_CGROUP_SOCK_OPS, - .attach_flag = 0, - .is_xdp = false, + }, + { + .prog_name = "hisock_skmsg_prog", + .prog_type = BPF_PROG_TYPE_SK_MSG, + .attach_type = BPF_SK_MSG_VERDICT, + .pin_map = "local_connmap", + .is_skmsg = true, }, { .prog_name = "hisock_ingress_prog", @@ -77,8 +91,6 @@ static struct hisock_prog_info prog_infos[] = { .prog_name = "hisock_egress_prog", .prog_type = BPF_PROG_TYPE_HISOCK, .attach_type = BPF_HISOCK_EGRESS, - .attach_flag = 0, - .is_xdp = false, }, }; @@ -231,6 +243,30 @@ static int set_target_comm(struct bpf_object *obj) return 0; } +static int set_global_bss(struct bpf_object *obj) +{ + struct bpf_map *bss_map; + struct bss g_bss; + int zero = 0; + int map_fd; + + g_bss.local_mask = hisock.local_mask ?: DEF_LOCAL_MASK; + + bss_map = bpf_object__find_map_by_name(obj, ".bss"); + if (!bss_map) { + fprintf(stderr, "ERROR: failed to find bss map\n"); + return -1; + } + + map_fd = bpf_map__fd(bss_map); + if (bpf_map_update_elem(map_fd, &zero, &g_bss, BPF_ANY) < 0) { + fprintf(stderr, "ERROR: failed to update bss map\n"); + return -1; + } + + return 0; +} + static int detach_progs(void) { struct hisock_prog_info *info; @@ -258,6 +294,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->prog_name); err_cnt++; @@ -268,7 +314,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; @@ -290,6 +336,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, info->attach_flag)) + goto fail; + + continue; + } + if (bpf_prog_attach(info->prog_fd, cgrp_fd, info->attach_type, info->attach_flag)) goto fail; @@ -347,7 +418,13 @@ static int do_hisock(void) return -1; } - if (attach_progs()) { + if (set_global_bss(obj)) { + fprintf(stderr, "ERROR: failed to set global bss\n"); + bpf_object__close(obj); + return -1; + } + + if (attach_progs(obj)) { fprintf(stderr, "ERROR: failed to attach progs\n"); bpf_object__close(obj); return -1; @@ -361,7 +438,7 @@ static void do_help(void) { fprintf(stderr, "Load: hisock_cmd [-f BPF_FILE] [-c CGRP_PATH] " - "[-p PORT] [-C COMM] [-i INTERFACE]\n" + "[-p PORT] [-C COMM] [-m LOCAL_MASK] [-i INTERFACE]\n" "Unload: hisock_cmd -u [-c CGRP_PATH] [-i INTERFACE]\n"); } @@ -371,7 +448,7 @@ static int parse_args(int argc, char **argv) hisock.bpf_path = DEF_BPF_PATH; - while ((opt = getopt(argc, argv, "f:c:p:i:C:uh")) != -1) { + while ((opt = getopt(argc, argv, "f:c:p:i:C:m:uh")) != -1) { switch (opt) { case 'f': hisock.bpf_path = optarg; @@ -391,6 +468,9 @@ static int parse_args(int argc, char **argv) hisock.comm[hisock.comm_num] = optarg; hisock.comm_num++; break; + case 'm': + hisock.local_mask = (__u32)strtoul(optarg, NULL, 16); + break; case 'u': hisock.unload = true; break; -- 2.34.1