hulk inclusion category: featrue bugzilla: https://atomgit.com/openeuler/kernel/issues/8480 -------------------------------- Apply BPF_HISOCK_INGRESS to hisock ingress. Signed-off-by: Pu Lehui <pulehui@huawei.com> --- samples/bpf/hisock/bpf.c | 133 +++++++++++++++++++------------- samples/bpf/hisock/hisock_cmd.c | 28 +++---- 2 files changed, 89 insertions(+), 72 deletions(-) diff --git a/samples/bpf/hisock/bpf.c b/samples/bpf/hisock/bpf.c index 46159c96cb18..e6a70bad5245 100644 --- a/samples/bpf/hisock/bpf.c +++ b/samples/bpf/hisock/bpf.c @@ -4,8 +4,9 @@ * * Description: End-to-End HiSock Redirect sample. */ +#define KBUILD_MODNAME "foo" #include <linux/if_vlan.h> -#include <net/dst.h> +#include <linux/filter.h> #include <uapi/linux/in.h> #include <uapi/linux/if_ether.h> @@ -15,14 +16,12 @@ #include <bpf/bpf_endian.h> #include <bpf/bpf_helpers.h> +#include <bpf/bpf_core_read.h> #define IP_MF 0x2000 #define IP_OFFSET 0x1FFF #define CSUM_SHIFT_BITS 16 -#define SOCKOPS_SUCC 1 -#define SOCKOPS_FAIL 0 - #define PORT_LOCAL 1 #define PORT_REMOTE 2 @@ -38,10 +37,11 @@ struct sock_tuple { }; struct sock_value { - struct dst_entry *ingress_dst; + unsigned long sk; + unsigned long egress_dev; + unsigned long ingress_dev; struct ethhdr ingress_eth; bool eth_updated; - u32 ingress_ifindex; }; struct { @@ -58,9 +58,12 @@ struct { __uint(max_entries, 128); } speed_port SEC(".maps"); -struct dst_entry *bpf_skops_get_ingress_dst(struct bpf_sock_ops *skops) __ksym; -int bpf_xdp_set_ingress_dst(struct xdp_md *xdp, void *dst) __ksym; -int bpf_skb_change_dev(struct __sk_buff *skb, u32 ifindex) __ksym; +int bpf_set_ingress_dst(struct __sk_buff *skb, unsigned long sk) __ksym; +int bpf_get_skb_ethhdr(struct __sk_buff *skb, struct ethhdr *peth, int size) __ksym; +int bpf_set_ingress_dev(struct __sk_buff *skb, unsigned long dev) __ksym; +int bpf_set_egress_dev(struct __sk_buff *skb, unsigned long dev) __ksym; +void bpf_handle_ingress_ptype(struct __sk_buff *skb) __ksym; +void bpf_handle_egress_ptype(struct __sk_buff *skb) __ksym; static inline bool is_speed_flow(u32 local, u32 remote) { @@ -77,29 +80,46 @@ static inline bool is_speed_flow(u32 local, u32 remote) return false; } +static inline unsigned long parse_ingress_dev(struct bpf_sock_ops *skops) +{ + struct sk_buff *skb; + struct net_device *dev; + + skb = BPF_CORE_READ((struct bpf_sock_ops_kern *)skops, skb); + dev = BPF_CORE_READ(skb, dev); + + return (unsigned long)dev; +} + +static inline unsigned long parse_egress_dev(struct __sk_buff *skb) +{ + struct net_device *dev; + + dev = BPF_CORE_READ((struct sk_buff *)skb, dev); + + return (unsigned long)dev; +} + SEC("hisock_sockops") int hisock_sockops_prog(struct bpf_sock_ops *skops) { struct sock_tuple key = { 0 }; struct sock_value val = { 0 }; - struct dst_entry *dst; if (!is_speed_flow(skops->local_port, bpf_ntohl(skops->remote_port))) - return SOCKOPS_SUCC; + return 1; switch (skops->op) { case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: - dst = bpf_skops_get_ingress_dst(skops); - if (!dst) - return SOCKOPS_FAIL; - key.saddr = skops->remote_ip4; key.sport = bpf_ntohl(skops->remote_port); key.daddr = skops->local_ip4; key.dport = skops->local_port; - val.ingress_dst = dst; + val.sk = (unsigned long)skops->sk; + val.ingress_dev = parse_ingress_dev(skops); + bpf_map_update_elem(&connmap, &key, &val, BPF_ANY); bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG); @@ -124,43 +144,39 @@ int hisock_sockops_prog(struct bpf_sock_ops *skops) break; } - return SOCKOPS_SUCC; + return 1; } SEC("hisock_ingress") -int hisock_ingress_prog(struct xdp_md *ctx) +int hisock_ingress_prog(struct __sk_buff *skb) { - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; + void *data_end = (void *)(long)skb->data_end; + void *data = (void *)(long)skb->data; struct sock_tuple key = { 0 }; struct sock_value *val; - struct ethhdr *ehdr; struct tcphdr *thdr; struct iphdr *ihdr; + struct ethhdr ehdr; - ehdr = (struct ethhdr *)data; - if (ehdr + 1 > data_end) - return XDP_PASS; - - if (ehdr->h_proto != bpf_htons(ETH_P_IP)) - return XDP_PASS; + if (skb->protocol != bpf_htons(ETH_P_IP)) + return HISOCK_PASS; - ihdr = (struct iphdr *)(ehdr + 1); + ihdr = (struct iphdr *)data; if (ihdr + 1 > data_end) - return XDP_PASS; + return HISOCK_PASS; if (ihdr->ihl != 5 || ihdr->protocol != IPPROTO_TCP) - return XDP_PASS; + return HISOCK_PASS; if (ihdr->frag_off & bpf_htons(IP_MF | IP_OFFSET)) - return XDP_PASS; + return HISOCK_PASS; thdr = (struct tcphdr *)(ihdr + 1); if (thdr + 1 > data_end) - return XDP_PASS; + return HISOCK_PASS; if (thdr->syn || thdr->fin || thdr->rst) - return XDP_PASS; + return HISOCK_PASS; key.saddr = ihdr->saddr; key.sport = bpf_ntohs(thdr->source); @@ -169,22 +185,25 @@ int hisock_ingress_prog(struct xdp_md *ctx) val = bpf_map_lookup_elem(&connmap, &key); if (!val) - return XDP_PASS; + return HISOCK_PASS; - if (unlikely(!val->eth_updated)) { - memcpy(val->ingress_eth.h_source, ehdr->h_dest, ETH_ALEN); - memcpy(val->ingress_eth.h_dest, ehdr->h_source, ETH_ALEN); - val->ingress_eth.h_proto = ehdr->h_proto; - val->eth_updated = true; + if (!val->eth_updated) { + if (!(bpf_get_skb_ethhdr(skb, &ehdr, sizeof(ehdr)))) { + memcpy(val->ingress_eth.h_source, ehdr.h_dest, ETH_ALEN); + memcpy(val->ingress_eth.h_dest, ehdr.h_source, ETH_ALEN); + val->ingress_eth.h_proto = ehdr.h_proto; + val->eth_updated = true; + } } - if (unlikely(!val->ingress_ifindex)) - val->ingress_ifindex = ctx->ingress_ifindex; + if (!val->egress_dev) + val->egress_dev = parse_egress_dev(skb); - if (likely(val->ingress_dst)) - bpf_xdp_set_ingress_dst(ctx, val->ingress_dst); + bpf_set_ingress_dev(skb, val->ingress_dev); + bpf_handle_ingress_ptype(skb); + bpf_set_ingress_dst(skb, val->sk); - return XDP_HISOCK_REDIRECT; + return HISOCK_REDIRECT; } static inline void ipv4_csum(struct iphdr *ihdr) @@ -207,8 +226,19 @@ int hisock_egress_prog(struct __sk_buff *skb) struct sock_tuple key = { 0 }; struct sock_value *val; struct ethhdr *ehdr; + struct tcphdr *thdr; struct iphdr *ihdr; - int ret; + + ihdr = (struct iphdr *)data; + if (ihdr + 1 > data_end) + return HISOCK_PASS; + + thdr = (struct tcphdr *)(ihdr + 1); + if (thdr + 1 > data_end) + return HISOCK_PASS; + + if (thdr->syn || thdr->fin || thdr->rst) + return HISOCK_PASS; key.saddr = skb->remote_ip4; key.sport = bpf_ntohl(skb->remote_port); @@ -219,18 +249,13 @@ int hisock_egress_prog(struct __sk_buff *skb) if (!val) return HISOCK_PASS; - if (unlikely(!val->eth_updated)) + if (!val->eth_updated) goto redirect; - ihdr = (struct iphdr *)data; - if (ihdr + 1 > data_end) - return HISOCK_PASS; - ihdr->tot_len = bpf_htons(skb->len); ipv4_csum(ihdr); - ret = bpf_skb_change_head(skb, ETH_HLEN, 0); - if (ret < 0) + if (bpf_skb_change_head(skb, ETH_HLEN, 0) < 0) goto redirect; data = (void *)(long)skb->data; @@ -241,9 +266,9 @@ int hisock_egress_prog(struct __sk_buff *skb) return HISOCK_DROP; memcpy(ehdr, &val->ingress_eth, ETH_HLEN); + bpf_handle_egress_ptype(skb); redirect: - if (likely(val->ingress_ifindex)) - bpf_skb_change_dev(skb, val->ingress_ifindex); + bpf_set_egress_dev(skb, val->egress_dev); return HISOCK_REDIRECT; } diff --git a/samples/bpf/hisock/hisock_cmd.c b/samples/bpf/hisock/hisock_cmd.c index 6b64c008b6c7..ae114ccb6c24 100644 --- a/samples/bpf/hisock/hisock_cmd.c +++ b/samples/bpf/hisock/hisock_cmd.c @@ -48,9 +48,8 @@ struct hisock_prog_info { const char *prog_name; enum bpf_prog_type prog_type; enum bpf_attach_type attach_type; - int attach_flag; + bool is_dev_attach; int prog_fd; - bool is_xdp; }; static struct hisock_prog_info prog_infos[] = { @@ -58,22 +57,17 @@ 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_ingress_prog", - .prog_type = BPF_PROG_TYPE_XDP, - .attach_type = BPF_XDP, - .attach_flag = XDP_FLAGS_SKB_MODE, - .is_xdp = true, + .prog_type = BPF_PROG_TYPE_HISOCK, + .attach_type = BPF_HISOCK_INGRESS, + .is_dev_attach = true, }, { .prog_name = "hisock_egress_prog", .prog_type = BPF_PROG_TYPE_HISOCK, .attach_type = BPF_HISOCK_EGRESS, - .attach_flag = 0, - .is_xdp = false, }, }; @@ -208,10 +202,9 @@ static int detach_progs(void) for (i = 0; i < ARRAY_SIZE(prog_infos); i++) { info = &prog_infos[i]; - if (info->is_xdp) { + if (info->is_dev_attach) { for (j = 0; j < hisock.if_num; j++) { - if (bpf_xdp_detach(hisock.ifindex[j], - info->attach_flag, NULL)) { + if (bpf_prog_detach(hisock.ifindex[j], info->attach_type)) { fprintf(stderr, "ERROR: failed to detach prog %s\n", info->prog_name); @@ -244,17 +237,16 @@ static int attach_progs(void) for (i = 0; i < ARRAY_SIZE(prog_infos); i++) { info = &prog_infos[i]; - if (info->is_xdp) { + if (info->is_dev_attach) { for (j = 0; j < hisock.if_num; j++) { - if (bpf_xdp_attach(hisock.ifindex[j], info->prog_fd, - info->attach_flag, NULL)) + if (bpf_prog_attach(info->prog_fd, hisock.ifindex[j], + info->attach_type, 0)) goto fail; } continue; } - if (bpf_prog_attach(info->prog_fd, cgrp_fd, info->attach_type, - info->attach_flag)) + if (bpf_prog_attach(info->prog_fd, cgrp_fd, info->attach_type, 0)) goto fail; } -- 2.34.1