diff --git a/bpf/Makefile b/bpf/Makefile index 696878cacb39..018aafe0f852 100644 --- a/bpf/Makefile +++ b/bpf/Makefile @@ -60,6 +60,8 @@ LB_OPTIONS = \ -DENABLE_IPV4:-DENABLE_IPV6:-DENABLE_IPSEC:-DLB_L3:-DLB_L4:-DENABLE_HOST_SERVICES_UDP:-DENABLE_HOST_SERVICES_TCP:-DENABLE_NODEPORT:-DENABLE_EXTERNAL_IP \ -DENABLE_IPV4:-DENABLE_IPV6:-DENABLE_IPSEC:-DLB_L3:-DLB_L4:-DENABLE_HOST_SERVICES_UDP:-DENABLE_HOST_SERVICES_TCP:-DENABLE_NODEPORT:-DENABLE_EXTERNAL_IP:-DENABLE_NODEPORT_ACCELERATION \ -DENABLE_IPV4:-DENABLE_IPV6:-DENABLE_IPSEC:-DLB_L3:-DLB_L4:-DENABLE_HOST_SERVICES_UDP:-DENABLE_HOST_SERVICES_TCP:-DENABLE_NODEPORT:-DENABLE_EXTERNAL_IP:-DENABLE_NODEPORT_ACCELERATION:-DENABLE_SESSION_AFFINITY \ + -DENABLE_IPV4:-DENABLE_IPSEC:-DLB_L3:-DLB_L4:-DENABLE_HOST_SERVICES_UDP:-DENABLE_HOST_SERVICES_TCP:-DENABLE_NODEPORT:-DENABLE_EXTERNAL_IP:-DENABLE_NODEPORT_ACCELERATION:-DENABLE_SESSION_AFFINITY \ + -DENABLE_IPV6:-DENABLE_IPSEC:-DLB_L3:-DLB_L4:-DENABLE_HOST_SERVICES_UDP:-DENABLE_HOST_SERVICES_TCP:-DENABLE_NODEPORT:-DENABLE_EXTERNAL_IP:-DENABLE_NODEPORT_ACCELERATION:-DENABLE_SESSION_AFFINITY \ # These options are intended to max out the BPF program complexity. it is load # tested as well. @@ -82,25 +84,16 @@ bpf_sock.o: bpf_sock.ll @$(ECHO_CC) $(QUIET) ${LLC} ${LLC_FLAGS} -filetype=obj -o $@ $(patsubst %.o,%.ll,$@) -# The following option combinations are compile tested -OVERLAY_OPTIONS = \ - -DENABLE_IPV4 \ - -DENABLE_IPV6 - -# These options are intended to max out the BPF program complexity. it is load -# tested as well. -MAX_OVERLAY_OPTIONS = -DENABLE_IPV4 -DENABLE_IPV6 -DENABLE_IPSEC - bpf_overlay.ll: bpf_overlay.c $(LIB) $(QUIET) set -e; \ if [ $(BUILD_PERMUTATIONS) != "" ]; then \ - $(foreach OPTS,$(OVERLAY_OPTIONS), \ + $(foreach OPTS,$(LB_OPTIONS), \ $(ECHO_CC) " [$(subst :,$(space),$(OPTS))]"; \ ${CLANG} $(subst :,$(space),$(OPTS)) ${CLANG_FLAGS} -c $< -o $@; \ ${LLC} ${LLC_FLAGS} -o /dev/null $@; ) \ fi @$(ECHO_CC) - $(QUIET) ${CLANG} ${MAX_OVERLAY_OPTIONS} ${CLANG_FLAGS} -c $< -o $@ + $(QUIET) ${CLANG} ${MAX_LB_OPTIONS} ${CLANG_FLAGS} -c $< -o $@ bpf_overlay.o: bpf_overlay.ll @$(ECHO_CC) diff --git a/bpf/Makefile.bpf b/bpf/Makefile.bpf index 14f25bb1113c..d88a3ec23228 100644 --- a/bpf/Makefile.bpf +++ b/bpf/Makefile.bpf @@ -3,11 +3,14 @@ FLAGS := -I$(ROOT_DIR)/bpf/include -I$(ROOT_DIR)/bpf -D__NR_CPUS__=$(shell nproc) -O2 -g -CLANG_FLAGS := ${FLAGS} -target bpf -emit-llvm +CLANG_FLAGS := ${FLAGS} -target bpf -std=gnu89 -nostdinc -emit-llvm # eBPF verifier enforces unaligned access checks where necessary, so don't # let clang complain too early. -CLANG_FLAGS += -Wall -Wextra -Werror -CLANG_FLAGS += -Wno-address-of-packed-member -Wno-unknown-warning-option -Wno-gnu-variable-sized-type-not-at-end +CLANG_FLAGS += -Wall -Wextra -Werror -Wshadow +CLANG_FLAGS += -Wno-address-of-packed-member +CLANG_FLAGS += -Wno-unknown-warning-option +CLANG_FLAGS += -Wno-gnu-variable-sized-type-not-at-end +CLANG_FLAGS += -Wdeclaration-after-statement LLC_FLAGS := -march=bpf -mcpu=probe -mattr=dwarfris # BUILD_PERMUTATIONS_DEP is a dummy file dependency that ensures all targets diff --git a/bpf/bpf_lxc.c b/bpf/bpf_lxc.c index 9d79fb1308a3..4dbd13314511 100644 --- a/bpf/bpf_lxc.c +++ b/bpf/bpf_lxc.c @@ -884,6 +884,7 @@ ipv6_policy(struct __ctx_buff *ctx, int ifindex, __u32 src_label, __u8 *reason, send_policy_verdict_notify(ctx, src_label, tuple.dport, tuple.nexthdr, POLICY_INGRESS, 1, verdict, policy_match_type); #ifdef ENABLE_DSR + { bool dsr = false; ret = handle_dsr_v6(ctx, &dsr); @@ -891,6 +892,7 @@ ipv6_policy(struct __ctx_buff *ctx, int ifindex, __u32 src_label, __u8 *reason, return ret; ct_state_new.dsr = dsr; + } #endif /* ENABLE_DSR */ ct_state_new.src_sec_id = src_label; @@ -1099,6 +1101,7 @@ ipv4_policy(struct __ctx_buff *ctx, int ifindex, __u32 src_label, __u8 *reason, send_policy_verdict_notify(ctx, src_label, tuple.dport, tuple.nexthdr, POLICY_INGRESS, 0, verdict, policy_match_type); #ifdef ENABLE_DSR + { bool dsr = false; ret = handle_dsr_v4(ctx, &dsr); @@ -1106,6 +1109,7 @@ ipv4_policy(struct __ctx_buff *ctx, int ifindex, __u32 src_label, __u8 *reason, return ret; ct_state_new.dsr = dsr; + } #endif /* ENABLE_DSR */ ct_state_new.src_sec_id = src_label; diff --git a/bpf/bpf_overlay.c b/bpf/bpf_overlay.c index 0980a0f6b40e..f38a5a5629cd 100644 --- a/bpf/bpf_overlay.c +++ b/bpf/bpf_overlay.c @@ -36,7 +36,7 @@ static __always_inline int handle_ipv6(struct __ctx_buff *ctx, return DROP_INVALID; #ifdef ENABLE_NODEPORT if (!bpf_skip_nodeport(ctx)) { - int ret = nodeport_lb6(ctx, *identity); + ret = nodeport_lb6(ctx, *identity); if (ret < 0) return ret; } @@ -95,12 +95,14 @@ static __always_inline int handle_ipv6(struct __ctx_buff *ctx, /* Lookup IPv6 address in list of local endpoints */ if ((ep = lookup_ip6_endpoint(ip6)) != NULL) { + __u8 nexthdr; + /* Let through packets to the node-ip so they are * processed by the local ip stack */ if (ep->flags & ENDPOINT_F_HOST) goto to_host; - __u8 nexthdr = ip6->nexthdr; + nexthdr = ip6->nexthdr; hdrlen = ipv6_hdrlen(ctx, l3_off, &nexthdr); if (hdrlen < 0) return hdrlen; @@ -113,7 +115,6 @@ static __always_inline int handle_ipv6(struct __ctx_buff *ctx, if (1) { union macaddr host_mac = HOST_IFINDEX_MAC; union macaddr router_mac = NODE_MAC; - int ret; ret = ipv6_l3(ctx, ETH_HLEN, (__u8 *) &router_mac.addr, (__u8 *) &host_mac.addr, METRIC_INGRESS); if (ret != CTX_ACT_OK) diff --git a/bpf/bpf_sock.c b/bpf/bpf_sock.c index 2c52e515665d..ed667d0a4332 100644 --- a/bpf/bpf_sock.c +++ b/bpf/bpf_sock.c @@ -77,11 +77,17 @@ void ctx_set_port(struct bpf_sock_addr *ctx, __be16 dport) } static __always_inline __maybe_unused bool -ctx_in_hostns(void *ctx __maybe_unused) +ctx_in_hostns(void *ctx __maybe_unused, __u64 *cookie) { #ifdef BPF_HAVE_NETNS_COOKIE - return get_netns_cookie(ctx) == get_netns_cookie(NULL); + __u64 own_cookie = get_netns_cookie(ctx); + + if (cookie) + *cookie = own_cookie; + return own_cookie == get_netns_cookie(NULL); #else + if (cookie) + *cookie = 0; return true; #endif } @@ -237,7 +243,8 @@ static __always_inline int __sock4_xlate(struct bpf_sock_addr *ctx, struct bpf_sock_addr *ctx_full, const bool udp_only) { - const bool in_hostns = ctx_in_hostns(ctx_full); + union lb4_affinity_client_id id; + const bool in_hostns = ctx_in_hostns(ctx_full, &id.client_cookie); struct lb4_backend *backend; struct lb4_service *svc; struct lb4_key key = { @@ -245,9 +252,8 @@ static __always_inline int __sock4_xlate(struct bpf_sock_addr *ctx, .dport = ctx_dst_port(ctx), }; struct lb4_service *slave_svc; - __u32 backend_id = 0; - /* Indicates whether a backend was selected from session affinity */ bool backend_from_affinity = false; + __u32 backend_id = 0; if (!udp_only && !sock_proto_enabled(ctx->protocol)) return -ENOTSUP; @@ -276,56 +282,48 @@ static __always_inline int __sock4_xlate(struct bpf_sock_addr *ctx, if (sock4_skip_xlate(svc, in_hostns, ctx->user_ip4)) return -EPERM; -#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) - /* Session affinity id (a netns cookie) */ - union lb4_affinity_client_id client_id = { .client_cookie = 0 }; if (svc->affinity) { - client_id.client_cookie = get_netns_cookie(ctx_full); - backend_id = lb4_affinity_backend_id(svc->rev_nat_index, - svc->affinity_timeout, - true, client_id); + backend_id = lb4_affinity_backend_id_by_netns(svc, &id); backend_from_affinity = true; } -#endif if (backend_id == 0) { -reselect_backend: __maybe_unused +reselect_backend: backend_from_affinity = false; + key.slave = (sock_local_cookie(ctx_full) % svc->count) + 1; slave_svc = __lb4_lookup_slave(&key); if (!slave_svc) { update_metrics(0, METRIC_EGRESS, REASON_LB_NO_SLAVE); return -ENOENT; } + backend_id = slave_svc->backend_id; } backend = __lb4_lookup_backend(backend_id); if (!backend) { -#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) if (backend_from_affinity) { /* Backend from the session affinity no longer exists, * thus select a new one. Also, remove the affinity, - * so that if the svc doesn't have any backend, - * a subsequent request to the svc doesn't hit - * the reselection again. */ - lb4_delete_affinity(svc->rev_nat_index, true, client_id); + * so that if the svc doesn't have any backend, a + * subsequent request to the svc doesn't hit the + * reselection again. + */ + lb4_delete_affinity_by_netns(svc, &id); goto reselect_backend; } -#endif + update_metrics(0, METRIC_EGRESS, REASON_LB_NO_BACKEND); return -ENOENT; } -#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) if (svc->affinity) - lb4_update_affinity(svc->rev_nat_index, true, client_id, backend_id); -#endif + lb4_update_affinity_by_netns(svc, &id, backend_id); /* revnat entry is not required for TCP protocol */ - if (!udp_only && ctx->protocol == IPPROTO_TCP) { + if (!udp_only && ctx->protocol == IPPROTO_TCP) goto update_dst; - } if (sock4_update_revnat(ctx_full, backend, &key, svc->rev_nat_index) < 0) { @@ -357,7 +355,8 @@ static __always_inline int __sock4_post_bind(struct bpf_sock *ctx, .dport = ctx_src_port(ctx), }; - if (!sock_proto_enabled(ctx->protocol) || !ctx_in_hostns(ctx_full)) + if (!sock_proto_enabled(ctx->protocol) || + !ctx_in_hostns(ctx_full, NULL)) return 0; svc = lb4_lookup_service(&key); @@ -602,7 +601,8 @@ int sock6_xlate_v4_in_v6(struct bpf_sock_addr *ctx __maybe_unused, } #if defined(ENABLE_NODEPORT) || defined(ENABLE_EXTERNAL_IP) -static __always_inline int sock6_post_bind_v4_in_v6(struct bpf_sock *ctx) +static __always_inline int +sock6_post_bind_v4_in_v6(struct bpf_sock *ctx __maybe_unused) { #ifdef ENABLE_IPV4 struct bpf_sock fake_ctx; @@ -629,7 +629,8 @@ static __always_inline int __sock6_post_bind(struct bpf_sock *ctx) .dport = ctx_src_port(ctx), }; - if (!sock_proto_enabled(ctx->protocol) || !ctx_in_hostns(ctx)) + if (!sock_proto_enabled(ctx->protocol) || + !ctx_in_hostns(ctx, NULL)) return 0; ctx_get_v6_src_address(ctx, &key.address); @@ -662,7 +663,8 @@ static __always_inline int __sock6_xlate(struct bpf_sock_addr *ctx, const bool udp_only) { #ifdef ENABLE_IPV6 - const bool in_hostns = ctx_in_hostns(ctx); + union lb6_affinity_client_id id; + const bool in_hostns = ctx_in_hostns(ctx, &id.client_cookie); struct lb6_backend *backend; struct lb6_service *svc; struct lb6_key key = { @@ -694,49 +696,41 @@ static __always_inline int __sock6_xlate(struct bpf_sock_addr *ctx, if (sock6_skip_xlate(svc, in_hostns, &v6_orig)) return -EPERM; -#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) - union lb6_affinity_client_id client_id = { .client_cookie = 0 }; if (svc->affinity) { - client_id.client_cookie = get_netns_cookie(ctx); - backend_id = lb6_affinity_backend_id(svc->rev_nat_index, - svc->affinity_timeout, - true, &client_id); + backend_id = lb6_affinity_backend_id_by_netns(svc, &id); backend_from_affinity = true; } -#endif if (backend_id == 0) { -reselect_backend: __maybe_unused +reselect_backend: backend_from_affinity = false; + key.slave = (sock_local_cookie(ctx) % svc->count) + 1; slave_svc = __lb6_lookup_slave(&key); if (!slave_svc) { update_metrics(0, METRIC_EGRESS, REASON_LB_NO_SLAVE); return -ENOENT; } + backend_id = slave_svc->backend_id; } backend = __lb6_lookup_backend(backend_id); if (!backend) { -#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) if (backend_from_affinity) { - lb6_delete_affinity(svc->rev_nat_index, true, &client_id); + lb6_delete_affinity_by_netns(svc, &id); goto reselect_backend; } -#endif + update_metrics(0, METRIC_EGRESS, REASON_LB_NO_BACKEND); return -ENOENT; } -#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) if (svc->affinity) - lb6_update_affinity(svc->rev_nat_index, true, &client_id, backend_id); -#endif + lb6_update_affinity_by_netns(svc, &id, backend_id); - if (!udp_only && ctx->protocol == IPPROTO_TCP) { + if (!udp_only && ctx->protocol == IPPROTO_TCP) goto update_dst; - } if (sock6_update_revnat(ctx, backend, &key, svc->rev_nat_index) < 0) { diff --git a/bpf/include/bpf/ctx/skb.h b/bpf/include/bpf/ctx/skb.h index b3d20ef240ca..c821347d4515 100644 --- a/bpf/include/bpf/ctx/skb.h +++ b/bpf/include/bpf/ctx/skb.h @@ -49,6 +49,13 @@ #define ctx_adjust_meta ({ -ENOTSUPP; }) +/* Avoid expensive calls into the kernel flow dissector if it's not an L4 + * hash. We currently only use the hash for debugging. If needed later, we + * can map it to BPF_FUNC(get_hash_recalc) to get the L4 hash. + */ +#define get_hash(ctx) ctx->hash +#define get_hash_recalc(ctx) get_hash(ctx) + static __always_inline __maybe_unused int ctx_redirect(struct __sk_buff *ctx __maybe_unused, int ifindex, __u32 flags) { diff --git a/bpf/include/bpf/ctx/xdp.h b/bpf/include/bpf/ctx/xdp.h index f18126290d42..80de26699c3c 100644 --- a/bpf/include/bpf/ctx/xdp.h +++ b/bpf/include/bpf/ctx/xdp.h @@ -100,7 +100,8 @@ xdp_store_bytes(const struct xdp_md *ctx, __u64 off, const void *from, #define ctx_adjust_meta xdp_adjust_meta -#define get_hash_recalc(ctx) ({ 0; }) +#define get_hash(ctx) ({ 0; }) +#define get_hash_recalc(ctx) get_hash(ctx) /* Checksum pieces from Linux kernel. */ static inline __sum16 csum_fold(__wsum csum) diff --git a/bpf/include/bpf/helpers_skb.h b/bpf/include/bpf/helpers_skb.h index 02cda4a10fec..254ffc498a83 100644 --- a/bpf/include/bpf/helpers_skb.h +++ b/bpf/include/bpf/helpers_skb.h @@ -12,9 +12,6 @@ /* Only used helpers in Cilium go below. */ -/* Packet misc meta data */ -static __u32 BPF_FUNC(get_hash_recalc, struct __sk_buff *skb); - /* Packet redirection */ static int BPF_FUNC(redirect, int ifindex, __u32 flags); diff --git a/bpf/init.sh b/bpf/init.sh index 7926679299e3..4c69190d885c 100755 --- a/bpf/init.sh +++ b/bpf/init.sh @@ -268,11 +268,12 @@ function bpf_compile() TYPE=$3 EXTRA_OPTS=$4 - clang -O2 -target bpf -emit-llvm \ - -Wall -Wextra -Werror \ + clang -O2 -target bpf -std=gnu89 -nostdinc -emit-llvm \ + -Wall -Wextra -Werror -Wshadow \ -Wno-address-of-packed-member \ -Wno-unknown-warning-option \ -Wno-gnu-variable-sized-type-not-at-end \ + -Wdeclaration-after-statement \ -I. -I$DIR -I$LIB -I$LIB/include \ -D__NR_CPUS__=$(nproc) \ -DENABLE_ARP_RESPONDER=1 \ diff --git a/bpf/lib/common.h b/bpf/lib/common.h index dc85a5e644a4..813f4b6cf43f 100644 --- a/bpf/lib/common.h +++ b/bpf/lib/common.h @@ -95,16 +95,13 @@ static __always_inline bool validate_ethertype(struct __ctx_buff *ctx, { void *data = ctx_data(ctx); void *data_end = ctx_data_end(ctx); + struct ethhdr *eth = data; if (data + ETH_HLEN > data_end) return false; - - struct ethhdr *eth = data; *proto = eth->h_proto; - if (bpf_ntohs(*proto) < ETH_P_802_3_MIN) return false; // non-Ethernet II unsupported - return true; } @@ -265,6 +262,17 @@ enum { __u16 len_cap; /* Length of captured bytes */ \ __u16 version; /* Capture header version */ +#define __notify_common_hdr(t, s) \ + .type = (t), \ + .subtype = (s), \ + .source = EVENT_SOURCE, \ + .hash = get_hash_recalc(ctx) + +#define __notify_pktcap_hdr(o, c) \ + .len_orig = (o), \ + .len_cap = (c), \ + .version = NOTIFY_CAPTURE_VER + /* Capture notifications version. Must be incremented when format changes. */ #define NOTIFY_CAPTURE_VER 1 diff --git a/bpf/lib/dbg.h b/bpf/lib/dbg.h index bf702302bf43..82dbbd63cbc4 100644 --- a/bpf/lib/dbg.h +++ b/bpf/lib/dbg.h @@ -129,6 +129,7 @@ enum { #endif #ifdef DEBUG +#include "common.h" #include "utils.h" # define printk(fmt, ...) \ @@ -148,34 +149,28 @@ struct debug_msg { static __always_inline void cilium_dbg(struct __ctx_buff *ctx, __u8 type, __u32 arg1, __u32 arg2) { - __u32 hash = get_hash_recalc(ctx); struct debug_msg msg = { - .type = CILIUM_NOTIFY_DBG_MSG, - .subtype = type, - .source = EVENT_SOURCE, - .hash = hash, - .arg1 = arg1, - .arg2 = arg2, + __notify_common_hdr(CILIUM_NOTIFY_DBG_MSG, type), + .arg1 = arg1, + .arg2 = arg2, }; - ctx_event_output(ctx, &EVENTS_MAP, BPF_F_CURRENT_CPU, &msg, sizeof(msg)); + ctx_event_output(ctx, &EVENTS_MAP, BPF_F_CURRENT_CPU, + &msg, sizeof(msg)); } static __always_inline void cilium_dbg3(struct __ctx_buff *ctx, __u8 type, __u32 arg1, __u32 arg2, __u32 arg3) { - __u32 hash = get_hash_recalc(ctx); struct debug_msg msg = { - .type = CILIUM_NOTIFY_DBG_MSG, - .subtype = type, - .source = EVENT_SOURCE, - .hash = hash, - .arg1 = arg1, - .arg2 = arg2, - .arg3 = arg3, + __notify_common_hdr(CILIUM_NOTIFY_DBG_MSG, type), + .arg1 = arg1, + .arg2 = arg2, + .arg3 = arg3, }; - ctx_event_output(ctx, &EVENTS_MAP, BPF_F_CURRENT_CPU, &msg, sizeof(msg)); + ctx_event_output(ctx, &EVENTS_MAP, BPF_F_CURRENT_CPU, + &msg, sizeof(msg)); } struct debug_capture_msg { @@ -187,19 +182,13 @@ struct debug_capture_msg { static __always_inline void cilium_dbg_capture2(struct __ctx_buff *ctx, __u8 type, __u32 arg1, __u32 arg2) { - __u64 ctx_len = (__u64)ctx_full_len(ctx); - __u64 cap_len = min((__u64)TRACE_PAYLOAD_LEN, (__u64)ctx_len); - __u32 hash = get_hash_recalc(ctx); + __u64 ctx_len = ctx_full_len(ctx); + __u64 cap_len = min_t(__u64, TRACE_PAYLOAD_LEN, ctx_len); struct debug_capture_msg msg = { - .type = CILIUM_NOTIFY_DBG_CAPTURE, - .subtype = type, - .source = EVENT_SOURCE, - .hash = hash, - .len_orig = ctx_len, - .len_cap = cap_len, - .version = NOTIFY_CAPTURE_VER, - .arg1 = arg1, - .arg2 = arg2, + __notify_common_hdr(CILIUM_NOTIFY_DBG_CAPTURE, type), + __notify_pktcap_hdr(ctx_len, cap_len), + .arg1 = arg1, + .arg2 = arg2, }; ctx_event_output(ctx, &EVENTS_MAP, diff --git a/bpf/lib/drop.h b/bpf/lib/drop.h index 7b65f292c269..74503e19a619 100644 --- a/bpf/lib/drop.h +++ b/bpf/lib/drop.h @@ -32,31 +32,27 @@ struct drop_notify { __section_tail(CILIUM_MAP_CALLS, CILIUM_CALL_DROP_NOTIFY) int __send_drop_notify(struct __ctx_buff *ctx) { - __u64 ctx_len = (__u64)ctx_full_len(ctx); - __u64 cap_len = min((__u64)TRACE_PAYLOAD_LEN, (__u64)ctx_len); - __u32 hash = get_hash_recalc(ctx); - struct drop_notify msg = { - .type = CILIUM_NOTIFY_DROP, - .source = EVENT_SOURCE, - .hash = hash, - .len_orig = ctx_len, - .len_cap = cap_len, - .version = NOTIFY_CAPTURE_VER, - .src_label = ctx_load_meta(ctx, 0), - .dst_label = ctx_load_meta(ctx, 1), - .dst_id = ctx_load_meta(ctx, 3), - .unused = 0, - }; /* Mask needed to calm verifier. */ int error = ctx_load_meta(ctx, 2) & 0xFFFFFFFF; + __u64 ctx_len = ctx_full_len(ctx); + __u64 cap_len = min_t(__u64, TRACE_PAYLOAD_LEN, ctx_len); + struct drop_notify msg; if (error < 0) error = -error; - msg.subtype = error; + + msg = (typeof(msg)) { + __notify_common_hdr(CILIUM_NOTIFY_DROP, error), + __notify_pktcap_hdr(ctx_len, cap_len), + .src_label = ctx_load_meta(ctx, 0), + .dst_label = ctx_load_meta(ctx, 1), + .dst_id = ctx_load_meta(ctx, 3), + }; ctx_event_output(ctx, &EVENTS_MAP, (cap_len << 32) | BPF_F_CURRENT_CPU, &msg, sizeof(msg)); + return ctx_load_meta(ctx, 4); } diff --git a/bpf/lib/l3.h b/bpf/lib/l3.h index 34d7df69cb39..d1ac0e4e0eed 100644 --- a/bpf/lib/l3.h +++ b/bpf/lib/l3.h @@ -63,13 +63,12 @@ static __always_inline int ipv6_local_delivery(struct __ctx_buff *ctx, int l3_of const struct endpoint_info *ep, __u8 direction) { + mac_t router_mac = ep->node_mac; + mac_t lxc_mac = ep->mac; int ret; cilium_dbg(ctx, DBG_LOCAL_DELIVERY, ep->lxc_id, seclabel); - mac_t lxc_mac = ep->mac; - mac_t router_mac = ep->node_mac; - /* This will invalidate the size check */ ret = ipv6_l3(ctx, l3_off, (__u8 *) &router_mac, (__u8 *) &lxc_mac, direction); if (ret != CTX_ACT_OK) @@ -102,13 +101,12 @@ static __always_inline int ipv4_local_delivery(struct __ctx_buff *ctx, int l3_of const struct endpoint_info *ep, __u8 direction __maybe_unused) { + mac_t router_mac = ep->node_mac; + mac_t lxc_mac = ep->mac; int ret; cilium_dbg(ctx, DBG_LOCAL_DELIVERY, ep->lxc_id, seclabel); - mac_t lxc_mac = ep->mac; - mac_t router_mac = ep->node_mac; - ret = ipv4_l3(ctx, l3_off, (__u8 *) &router_mac, (__u8 *) &lxc_mac, ip4); if (ret != CTX_ACT_OK) return ret; diff --git a/bpf/lib/lb.h b/bpf/lib/lb.h index e14e2606ed27..d9f8e6861c88 100644 --- a/bpf/lib/lb.h +++ b/bpf/lib/lb.h @@ -201,7 +201,6 @@ static __always_inline int extract_l4_port(struct __ctx_buff *ctx, __u8 nexthdr, #ifdef ENABLE_IPV4_FRAGMENTS if (ip4) { struct ipv4_frag_l4ports ports = { }; - int ret; if (unlikely(ipv4_is_fragment(ip4))) { ret = ipv4_handle_fragment(ctx, ip4, l4_off, @@ -476,22 +475,25 @@ static __always_inline int lb6_xlate(struct __ctx_buff *ctx, } #ifdef ENABLE_SESSION_AFFINITY -static __always_inline -__u32 lb6_affinity_backend_id(__u16 rev_nat_id, - __u32 svc_affinity_timeout, - bool netns_cookie, - union lb6_affinity_client_id *client_id) +static __always_inline __u32 +__lb6_affinity_backend_id(const struct lb6_service *svc, bool netns_cookie, + union lb6_affinity_client_id *id) { __u32 now = bpf_ktime_get_sec(); - struct lb_affinity_match match = { .rev_nat_id = rev_nat_id }; + struct lb_affinity_match match = { + .rev_nat_id = svc->rev_nat_index, + }; + struct lb6_affinity_key key = { + .rev_nat_id = svc->rev_nat_index, + .netns_cookie = netns_cookie, + }; struct lb_affinity_val *val; - struct lb6_affinity_key key = { .netns_cookie = netns_cookie, - .rev_nat_id = rev_nat_id }; - ipv6_addr_copy(&key.client_id.client_ip, &client_id->client_ip); + ipv6_addr_copy(&key.client_id.client_ip, &id->client_ip); + val = map_lookup_elem(&LB6_AFFINITY_MAP, &key); if (val != NULL) { - if ((val->last_used + svc_affinity_timeout) < now) { + if (val->last_used + svc->affinity_timeout < now) { map_delete_elem(&LB6_AFFINITY_MAP, &key); return 0; } @@ -508,33 +510,91 @@ __u32 lb6_affinity_backend_id(__u16 rev_nat_id, return 0; } -static __always_inline -void lb6_update_affinity(__u16 rev_nat_id, bool netns_cookie, - union lb6_affinity_client_id *client_id, - __u32 backend_id) +static __always_inline __u32 +lb6_affinity_backend_id_by_addr(const struct lb6_service *svc, + union lb6_affinity_client_id *id) +{ + return __lb6_affinity_backend_id(svc, false, id); +} + +static __always_inline void +__lb6_update_affinity(const struct lb6_service *svc, bool netns_cookie, + union lb6_affinity_client_id *id, __u32 backend_id) { __u32 now = bpf_ktime_get_sec(); - struct lb6_affinity_key key = { .rev_nat_id = rev_nat_id, - .netns_cookie = netns_cookie }; - struct lb_affinity_val val = { .last_used = now, - .backend_id = backend_id }; + struct lb6_affinity_key key = { + .rev_nat_id = svc->rev_nat_index, + .netns_cookie = netns_cookie, + }; + struct lb_affinity_val val = { + .backend_id = backend_id, + .last_used = now, + }; + + ipv6_addr_copy(&key.client_id.client_ip, &id->client_ip); - ipv6_addr_copy(&key.client_id.client_ip, &client_id->client_ip); map_update_elem(&LB6_AFFINITY_MAP, &key, &val, 0); } -static __always_inline -void lb6_delete_affinity(__u16 rev_nat_id, bool netns_cookie, - union lb6_affinity_client_id *client_id) +static __always_inline void +lb6_update_affinity_by_addr(const struct lb6_service *svc, + union lb6_affinity_client_id *id, __u32 backend_id) { - struct lb6_affinity_key key = { .rev_nat_id = rev_nat_id, - .netns_cookie = netns_cookie }; + __lb6_update_affinity(svc, false, id, backend_id); +} + +static __always_inline void +__lb6_delete_affinity(const struct lb6_service *svc, bool netns_cookie, + union lb6_affinity_client_id *id) +{ + struct lb6_affinity_key key = { + .rev_nat_id = svc->rev_nat_index, + .netns_cookie = netns_cookie, + }; + + ipv6_addr_copy(&key.client_id.client_ip, &id->client_ip); - ipv6_addr_copy(&key.client_id.client_ip, &client_id->client_ip); map_delete_elem(&LB6_AFFINITY_MAP, &key); } + +static __always_inline void +lb6_delete_affinity_by_addr(const struct lb6_service *svc, + union lb6_affinity_client_id *id) +{ + __lb6_delete_affinity(svc, false, id); +} #endif /* ENABLE_SESSION_AFFINITY */ +static __always_inline __u32 +lb6_affinity_backend_id_by_netns(const struct lb6_service *svc __maybe_unused, + union lb6_affinity_client_id *id __maybe_unused) +{ +#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) + return __lb6_affinity_backend_id(svc, true, id); +#else + return 0; +#endif +} + +static __always_inline void +lb6_update_affinity_by_netns(const struct lb6_service *svc __maybe_unused, + union lb6_affinity_client_id *id __maybe_unused, + __u32 backend_id __maybe_unused) +{ +#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) + __lb6_update_affinity(svc, true, id, backend_id); +#endif +} + +static __always_inline void +lb6_delete_affinity_by_netns(const struct lb6_service *svc __maybe_unused, + union lb6_affinity_client_id *id __maybe_unused) +{ +#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) + __lb6_delete_affinity(svc, true, id); +#endif +} + static __always_inline int lb6_local(const void *map, struct __ctx_buff *ctx, int l3_off, int l4_off, struct csum_offset *csum_off, @@ -558,20 +618,18 @@ static __always_inline int lb6_local(const void *map, struct __ctx_buff *ctx, #endif /* See lb4_local comments re svc endpoint lookup process */ - ret = ct_lookup6(map, tuple, ctx, l4_off, CT_SERVICE, state, &monitor); switch(ret) { case CT_NEW: #ifdef ENABLE_SESSION_AFFINITY if (svc->affinity) { - backend_id = lb6_affinity_backend_id(svc->rev_nat_index, - svc->affinity_timeout, - false, &client_id); + backend_id = lb6_affinity_backend_id_by_addr(svc, &client_id); if (backend_id != 0) { backend_from_affinity = true; + backend = lb6_lookup_backend(ctx, backend_id); if (backend == NULL) { - lb6_delete_affinity(svc->rev_nat_index, false, &client_id); + lb6_delete_affinity_by_addr(svc, &client_id); backend_id = 0; } } @@ -579,11 +637,13 @@ static __always_inline int lb6_local(const void *map, struct __ctx_buff *ctx, #endif if (backend_id == 0) { backend_from_affinity = false; + slave = lb6_select_slave(svc->count); - if ((slave_svc = lb6_lookup_slave(ctx, key, slave)) == NULL) { + if ((slave_svc = lb6_lookup_slave(ctx, key, slave)) == NULL) goto drop_no_service; - } + backend_id = slave_svc->backend_id; + backend = lb6_lookup_backend(ctx, slave_svc->backend_id); if (backend == NULL) goto drop_no_service; @@ -591,6 +651,7 @@ static __always_inline int lb6_local(const void *map, struct __ctx_buff *ctx, state->backend_id = backend_id; state->rev_nat_index = svc->rev_nat_index; + ret = ct_create6(map, NULL, tuple, ctx, CT_SERVICE, state, false); /* Fail closed, if the conntrack entry create fails drop * service lookup. @@ -616,17 +677,15 @@ static __always_inline int lb6_local(const void *map, struct __ctx_buff *ctx, if (state->rev_nat_index != svc->rev_nat_index) { #ifdef ENABLE_SESSION_AFFINITY if (svc->affinity) { - backend_id = lb6_affinity_backend_id(svc->rev_nat_index, - svc->affinity_timeout, - false, &client_id); + backend_id = lb6_affinity_backend_id_by_addr(svc, + &client_id); backend_from_affinity = true; } #endif if (backend_id == 0) { slave = lb6_select_slave(svc->count); - if (!(slave_svc = lb6_lookup_slave(ctx, key, slave))) { + if (!(slave_svc = lb6_lookup_slave(ctx, key, slave))) goto drop_no_service; - } backend_id = slave_svc->backend_id; } @@ -645,7 +704,7 @@ static __always_inline int lb6_local(const void *map, struct __ctx_buff *ctx, * in this case is just an optimization. */ #if defined(ENABLE_SESSION_AFFINITY) && !defined(HAVE_LARGE_INSN_LIMIT) if (backend_from_affinity) - lb6_delete_affinity(svc->rev_nat_index, false, &client_id); + lb6_delete_affinity_by_addr(svc, &client_id); #endif key->slave = 0; if (!(svc = lb6_lookup_service(key))) { @@ -673,12 +732,10 @@ static __always_inline int lb6_local(const void *map, struct __ctx_buff *ctx, state->rev_nat_index = svc->rev_nat_index; #ifdef ENABLE_SESSION_AFFINITY - if (svc->affinity) { - lb6_update_affinity(svc->rev_nat_index, false, &client_id, - state->backend_id); - } + if (svc->affinity) + lb6_update_affinity_by_addr(svc, &client_id, + state->backend_id); #endif - return lb6_xlate(ctx, addr, tuple->nexthdr, l3_off, l4_off, csum_off, key, backend); @@ -957,22 +1014,24 @@ lb4_xlate(struct __ctx_buff *ctx, __be32 *new_daddr, __be32 *new_saddr, } #ifdef ENABLE_SESSION_AFFINITY -static __always_inline -__u32 lb4_affinity_backend_id(__u16 rev_nat_id, - __u32 svc_affinity_timeout, - bool netns_cookie, - union lb4_affinity_client_id client_id) +static __always_inline __u32 +__lb4_affinity_backend_id(const struct lb4_service *svc, bool netns_cookie, + union lb4_affinity_client_id *id) { __u32 now = bpf_ktime_get_sec(); - struct lb_affinity_match match = { .rev_nat_id = rev_nat_id }; + struct lb_affinity_match match = { + .rev_nat_id = svc->rev_nat_index, + }; + struct lb4_affinity_key key = { + .rev_nat_id = svc->rev_nat_index, + .netns_cookie = netns_cookie, + .client_id = *id, + }; struct lb_affinity_val *val; - struct lb4_affinity_key key = { .client_id = client_id, - .netns_cookie = netns_cookie, - .rev_nat_id = rev_nat_id }; val = map_lookup_elem(&LB4_AFFINITY_MAP, &key); if (val != NULL) { - if ((val->last_used + svc_affinity_timeout) < now) { + if (val->last_used + svc->affinity_timeout < now) { map_delete_elem(&LB4_AFFINITY_MAP, &key); return 0; } @@ -989,33 +1048,89 @@ __u32 lb4_affinity_backend_id(__u16 rev_nat_id, return 0; } -static __always_inline -void lb4_update_affinity(__u16 rev_nat_id, bool netns_cookie, - union lb4_affinity_client_id client_id, - __u32 backend_id) +static __always_inline __u32 +lb4_affinity_backend_id_by_addr(const struct lb4_service *svc, + union lb4_affinity_client_id *id) +{ + return __lb4_affinity_backend_id(svc, false, id); +} + +static __always_inline void +__lb4_update_affinity(const struct lb4_service *svc, bool netns_cookie, + union lb4_affinity_client_id *id, __u32 backend_id) { __u32 now = bpf_ktime_get_sec(); - struct lb4_affinity_key key = { .rev_nat_id = rev_nat_id, - .netns_cookie = netns_cookie, - .client_id = client_id }; - struct lb_affinity_val val = { .last_used = now, - .backend_id = backend_id }; + struct lb4_affinity_key key = { + .rev_nat_id = svc->rev_nat_index, + .netns_cookie = netns_cookie, + .client_id = *id, + }; + struct lb_affinity_val val = { + .backend_id = backend_id, + .last_used = now, + }; map_update_elem(&LB4_AFFINITY_MAP, &key, &val, 0); } -static __always_inline -void lb4_delete_affinity(__u16 rev_nat_id, bool netns_cookie, - union lb4_affinity_client_id client_id) +static __always_inline void +lb4_update_affinity_by_addr(const struct lb4_service *svc, + union lb4_affinity_client_id *id, __u32 backend_id) { - struct lb4_affinity_key key = { .rev_nat_id = rev_nat_id, - .netns_cookie = netns_cookie, - .client_id = client_id }; + __lb4_update_affinity(svc, false, id, backend_id); +} + +static __always_inline void +__lb4_delete_affinity(const struct lb4_service *svc, bool netns_cookie, + union lb4_affinity_client_id *id) +{ + struct lb4_affinity_key key = { + .rev_nat_id = svc->rev_nat_index, + .netns_cookie = netns_cookie, + .client_id = *id, + }; map_delete_elem(&LB4_AFFINITY_MAP, &key); } + +static __always_inline void +lb4_delete_affinity_by_addr(const struct lb4_service *svc, + union lb4_affinity_client_id *id) +{ + __lb4_delete_affinity(svc, false, id); +} #endif /* ENABLE_SESSION_AFFINITY */ +static __always_inline __u32 +lb4_affinity_backend_id_by_netns(const struct lb4_service *svc __maybe_unused, + union lb4_affinity_client_id *id __maybe_unused) +{ +#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) + return __lb4_affinity_backend_id(svc, true, id); +#else + return 0; +#endif +} + +static __always_inline void +lb4_update_affinity_by_netns(const struct lb4_service *svc __maybe_unused, + union lb4_affinity_client_id *id __maybe_unused, + __u32 backend_id __maybe_unused) +{ +#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) + __lb4_update_affinity(svc, true, id, backend_id); +#endif +} + +static __always_inline void +lb4_delete_affinity_by_netns(const struct lb4_service *svc __maybe_unused, + union lb4_affinity_client_id *id __maybe_unused) +{ +#if defined(ENABLE_SESSION_AFFINITY) && defined(BPF_HAVE_NETNS_COOKIE) + __lb4_delete_affinity(svc, true, id); +#endif +} + static __always_inline int lb4_local(const void *map, struct __ctx_buff *ctx, int l3_off, int l4_off, struct csum_offset *csum_off, @@ -1034,36 +1149,37 @@ static __always_inline int lb4_local(const void *map, struct __ctx_buff *ctx, bool backend_from_affinity = false; int ret; #ifdef ENABLE_SESSION_AFFINITY - union lb4_affinity_client_id client_id = { .client_ip = saddr }; + union lb4_affinity_client_id client_id = { + .client_ip = saddr, + }; #endif - ret = ct_lookup4(map, tuple, ctx, l4_off, CT_SERVICE, state, &monitor); switch(ret) { case CT_NEW: #ifdef ENABLE_SESSION_AFFINITY if (svc->affinity) { - backend_id = lb4_affinity_backend_id(svc->rev_nat_index, - svc->affinity_timeout, - false, client_id); + backend_id = lb4_affinity_backend_id_by_addr(svc, &client_id); if (backend_id != 0) { backend_from_affinity = true; + backend = lb4_lookup_backend(ctx, backend_id); if (backend == NULL) { - lb4_delete_affinity(svc->rev_nat_index, false, client_id); + lb4_delete_affinity_by_addr(svc, &client_id); backend_id = 0; } } } #endif - if (backend_id == 0) { backend_from_affinity = false; + /* No CT entry has been found, so select a svc endpoint */ slave = lb4_select_slave(svc->count); - if ((slave_svc = lb4_lookup_slave(ctx, key, slave)) == NULL) { + if ((slave_svc = lb4_lookup_slave(ctx, key, slave)) == NULL) goto drop_no_service; - } + backend_id = slave_svc->backend_id; + backend = lb4_lookup_backend(ctx, backend_id); if (backend == NULL) goto drop_no_service; @@ -1071,13 +1187,13 @@ static __always_inline int lb4_local(const void *map, struct __ctx_buff *ctx, state->backend_id = backend_id; state->rev_nat_index = svc->rev_nat_index; + ret = ct_create4(map, NULL, tuple, ctx, CT_SERVICE, state, false); /* Fail closed, if the conntrack entry create fails drop * service lookup. */ - if (IS_ERR(ret)) { + if (IS_ERR(ret)) goto drop_no_service; - } goto update_state; case CT_ESTABLISHED: case CT_RELATED: @@ -1105,18 +1221,16 @@ static __always_inline int lb4_local(const void *map, struct __ctx_buff *ctx, if (state->rev_nat_index != svc->rev_nat_index) { #ifdef ENABLE_SESSION_AFFINITY if (svc->affinity) { - backend_id = lb4_affinity_backend_id(svc->rev_nat_index, - svc->affinity_timeout, - false, client_id); + backend_id = lb4_affinity_backend_id_by_addr(svc, + &client_id); backend_from_affinity = true; } #endif - if (backend_id == 0) { slave = lb4_select_slave(svc->count); - if (!(slave_svc = lb4_lookup_slave(ctx, key, slave))) { + if (!(slave_svc = lb4_lookup_slave(ctx, key, slave))) goto drop_no_service; - } + backend_id = slave_svc->backend_id; } @@ -1132,7 +1246,7 @@ static __always_inline int lb4_local(const void *map, struct __ctx_buff *ctx, if (!(backend = lb4_lookup_backend(ctx, state->backend_id))) { #ifdef ENABLE_SESSION_AFFINITY if (backend_from_affinity) - lb4_delete_affinity(svc->rev_nat_index, false, client_id); + lb4_delete_affinity_by_addr(svc, &client_id); #endif key->slave = 0; if (!(svc = lb4_lookup_service(key))) { @@ -1159,10 +1273,9 @@ static __always_inline int lb4_local(const void *map, struct __ctx_buff *ctx, state->addr = new_daddr = backend->address; #ifdef ENABLE_SESSION_AFFINITY - if (svc->affinity) { - lb4_update_affinity(svc->rev_nat_index, false, client_id, - state->backend_id); - } + if (svc->affinity) + lb4_update_affinity_by_addr(svc, &client_id, + state->backend_id); #endif #ifndef DISABLE_LOOPBACK_LB @@ -1180,18 +1293,15 @@ static __always_inline int lb4_local(const void *map, struct __ctx_buff *ctx, state->svc_addr = saddr; } #endif - if (!state->loopback) tuple->daddr = backend->address; return lb4_xlate(ctx, &new_daddr, &new_saddr, &saddr, tuple->nexthdr, l3_off, l4_off, csum_off, key, backend); - drop_no_service: tuple->flags = flags; return DROP_NO_SERVICE; } #endif /* ENABLE_IPV4 */ - #endif /* __LB_H_ */ diff --git a/bpf/lib/nat.h b/bpf/lib/nat.h index 4bbb4815685b..7bbca989d6a0 100644 --- a/bpf/lib/nat.h +++ b/bpf/lib/nat.h @@ -460,6 +460,7 @@ static __always_inline __maybe_unused int snat_v4_create_dsr(struct __ctx_buff * __be16 dport; } l4hdr; __u32 off; + int ret; build_bug_on(sizeof(struct ipv4_nat_entry) > 64); @@ -470,7 +471,9 @@ static __always_inline __maybe_unused int snat_v4_create_dsr(struct __ctx_buff * tuple.daddr = ip4->saddr; tuple.saddr = ip4->daddr; tuple.flags = NAT_DIR_EGRESS; + off = ((void *)ip4 - data) + ipv4_hdrlen(ip4); + switch (tuple.nexthdr) { case IPPROTO_TCP: case IPPROTO_UDP: @@ -489,7 +492,7 @@ static __always_inline __maybe_unused int snat_v4_create_dsr(struct __ctx_buff * state.to_saddr = to_saddr; state.to_sport = to_sport; - int ret = map_update_elem(&SNAT_MAPPING_IPV4, &tuple, &state, 0); + ret = map_update_elem(&SNAT_MAPPING_IPV4, &tuple, &state, 0); if (ret) return ret; @@ -917,8 +920,8 @@ static __always_inline __maybe_unused int snat_v6_create_dsr(struct __ctx_buff * __be16 sport; __be16 dport; } l4hdr; + int ret, hdrlen; __u32 off; - int hdrlen; build_bug_on(sizeof(struct ipv6_nat_entry) > 64); @@ -933,7 +936,9 @@ static __always_inline __maybe_unused int snat_v6_create_dsr(struct __ctx_buff * ipv6_addr_copy(&tuple.daddr, (union v6addr *)&ip6->saddr); ipv6_addr_copy(&tuple.saddr, (union v6addr *)&ip6->daddr); tuple.flags = NAT_DIR_EGRESS; + off = ((void *)ip6 - data) + hdrlen; + switch (tuple.nexthdr) { case IPPROTO_TCP: case IPPROTO_UDP: @@ -943,8 +948,9 @@ static __always_inline __maybe_unused int snat_v6_create_dsr(struct __ctx_buff * tuple.sport = l4hdr.dport; break; default: - // NodePort svc can be reached only via TCP or UDP, so - // drop the rest + /* NodePort svc can be reached only via TCP or UDP, so + * drop the rest. + */ return DROP_NAT_UNSUPP_PROTO; } @@ -952,7 +958,7 @@ static __always_inline __maybe_unused int snat_v6_create_dsr(struct __ctx_buff * ipv6_addr_copy(&state.to_saddr, to_saddr); state.to_sport = to_sport; - int ret = map_update_elem(&SNAT_MAPPING_IPV6, &tuple, &state, 0); + ret = map_update_elem(&SNAT_MAPPING_IPV6, &tuple, &state, 0); if (ret) return ret; diff --git a/bpf/lib/nodeport.h b/bpf/lib/nodeport.h index fde7e2a47e37..5d2e74091067 100644 --- a/bpf/lib/nodeport.h +++ b/bpf/lib/nodeport.h @@ -162,9 +162,12 @@ static __always_inline int nodeport_nat_ipv6_fwd(struct __ctx_buff *ctx, .min_port = NODEPORT_PORT_MIN_NAT, .max_port = 65535, }; + int ret; + ipv6_addr_copy(&target.addr, addr); - int ret = nodeport_nat_ipv6_needed(ctx, addr, NAT_DIR_EGRESS) ? - snat_v6_process(ctx, NAT_DIR_EGRESS, &target) : CTX_ACT_OK; + + ret = nodeport_nat_ipv6_needed(ctx, addr, NAT_DIR_EGRESS) ? + snat_v6_process(ctx, NAT_DIR_EGRESS, &target) : CTX_ACT_OK; if (ret == NAT_PUNT_TO_STACK) ret = CTX_ACT_OK; return ret; @@ -356,8 +359,8 @@ int tail_nodeport_nat_ipv6(struct __ctx_buff *ctx) dst = (union v6addr *)&ip6->daddr; info = ipcache_lookup6(&IPCACHE_MAP, dst, V6_CACHE_KEY_LEN); if (info != NULL && info->tunnel_endpoint != 0) { - int ret = __encap_with_nodeid(ctx, info->tunnel_endpoint, - SECLABEL, TRACE_PAYLOAD_LEN); + ret = __encap_with_nodeid(ctx, info->tunnel_endpoint, + SECLABEL, TRACE_PAYLOAD_LEN); if (ret) return ret; @@ -625,8 +628,8 @@ static __always_inline int rev_nodeport_lb6(struct __ctx_buff *ctx, int *ifindex info = ipcache_lookup6(&IPCACHE_MAP, dst, V6_CACHE_KEY_LEN); if (info != NULL && info->tunnel_endpoint != 0) { - int ret = __encap_with_nodeid(ctx, info->tunnel_endpoint, - SECLABEL, TRACE_PAYLOAD_LEN); + ret = __encap_with_nodeid(ctx, info->tunnel_endpoint, + SECLABEL, TRACE_PAYLOAD_LEN); if (ret) return ret; @@ -656,9 +659,9 @@ static __always_inline int rev_nodeport_lb6(struct __ctx_buff *ctx, int *ifindex ipv6_addr_copy((union v6addr *) &fib_params.ipv6_src, &tuple.saddr); ipv6_addr_copy((union v6addr *) &fib_params.ipv6_dst, &tuple.daddr); - int rc = fib_lookup(ctx, &fib_params, sizeof(fib_params), - BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT); - if (rc != 0) + ret = fib_lookup(ctx, &fib_params, sizeof(fib_params), + BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT); + if (ret != 0) return DROP_NO_FIB; if (eth_store_daddr(ctx, fib_params.dmac, 0) < 0) @@ -702,6 +705,7 @@ static __always_inline bool nodeport_nat_ipv4_needed(struct __ctx_buff *ctx, bool *from_endpoint __maybe_unused, const bool encap __maybe_unused) { + struct endpoint_info *ep __maybe_unused; void *data, *data_end; struct iphdr *ip4; @@ -716,8 +720,6 @@ static __always_inline bool nodeport_nat_ipv4_needed(struct __ctx_buff *ctx, return true; } #ifdef ENABLE_MASQUERADE - struct endpoint_info *ep; - /* Do not MASQ when this function is executed from bpf_overlay * (encap=true denotes this fact). Otherwise, a packet will be * SNAT'd to cilium_host IP addr. */ @@ -794,27 +796,30 @@ static __always_inline int set_dsr_opt4(struct __ctx_buff *ctx, __be32 svc_addr, __be32 svc_port) { union tcp_flags tcp_flags = { .value = 0 }; + __u32 iph_old, iph_new, opt1, opt2; __be32 sum; - __u32 iph_old, iph_new; if (ip4->protocol == IPPROTO_TCP) { if (ctx_load_bytes(ctx, ETH_HLEN + sizeof(*ip4) + 12, &tcp_flags, 2) < 0) return DROP_CT_INVALID_HDR; - // Setting the option is required only for the first packet - // (SYN), in the case of TCP, as for further packets of the - // same connection a remote node will use a NAT entry to - // reverse xlate a reply. + + /* Setting the option is required only for the first packet + * (SYN), in the case of TCP, as for further packets of the + * same connection a remote node will use a NAT entry to + * reverse xlate a reply. + */ if (!(tcp_flags.value & (TCP_FLAG_SYN))) return 0; } iph_old = *(__u32 *)ip4; - ip4->ihl += 0x2; // To accommodate u64 option + ip4->ihl += 0x2; /* To accommodate u64 option. */ ip4->tot_len = bpf_htons(bpf_ntohs(ip4->tot_len) + 0x8); iph_new = *(__u32 *)ip4; - __u32 opt1 = bpf_htonl(DSR_IPV4_OPT_32 | svc_port); - __u32 opt2 = bpf_htonl(svc_addr); + + opt1 = bpf_htonl(DSR_IPV4_OPT_32 | svc_port); + opt2 = bpf_htonl(svc_addr); sum = csum_diff(&iph_old, 4, &iph_new, 4, 0); sum = csum_diff(NULL, 0, &opt1, sizeof(opt1), sum); @@ -829,11 +834,9 @@ static __always_inline int set_dsr_opt4(struct __ctx_buff *ctx, if (ctx_store_bytes(ctx, ETH_HLEN + sizeof(*ip4) + sizeof(opt1), &opt2, sizeof(opt2), 0) < 0) return DROP_INVALID; - if (l3_csum_replace(ctx, ETH_HLEN + offsetof(struct iphdr, check), - 0, sum, 0) < 0) { + 0, sum, 0) < 0) return DROP_CSUM_L3; - } return 0; } @@ -846,11 +849,12 @@ static __always_inline int handle_dsr_v4(struct __ctx_buff *ctx, bool *dsr) if (!revalidate_data(ctx, &data, &data_end, &ip4)) return DROP_INVALID; - // Check whether IPv4 header contains a 64-bit option (IPv4 header - // w/o option (5 x 32-bit words) + the DSR option (2 x 32-bit words)) + /* Check whether IPv4 header contains a 64-bit option (IPv4 header + * w/o option (5 x 32-bit words) + the DSR option (2 x 32-bit words)). + */ if (ip4->ihl == 0x7) { - __u32 opt1 = 0; - __u32 opt2 = 0; + __u32 opt1 = 0, opt2 = 0; + __be32 address, dport; if (ctx_load_bytes(ctx, ETH_HLEN + sizeof(struct iphdr), &opt1, sizeof(opt1)) < 0) @@ -865,9 +869,8 @@ static __always_inline int handle_dsr_v4(struct __ctx_buff *ctx, bool *dsr) return DROP_INVALID; opt2 = bpf_ntohl(opt2); - - __be32 dport = opt1 & DSR_IPV4_DPORT_MASK; - __be32 address = opt2; + dport = opt1 & DSR_IPV4_DPORT_MASK; + address = opt2; *dsr = true; if (snat_v4_create_dsr(ctx, address, dport) < 0) @@ -961,8 +964,8 @@ int tail_nodeport_nat_ipv4(struct __ctx_buff *ctx) info = ipcache_lookup4(&IPCACHE_MAP, ip4->daddr, V4_CACHE_KEY_LEN); if (info != NULL && info->tunnel_endpoint != 0) { - int ret = __encap_with_nodeid(ctx, info->tunnel_endpoint, - SECLABEL, TRACE_PAYLOAD_LEN); + ret = __encap_with_nodeid(ctx, info->tunnel_endpoint, + SECLABEL, TRACE_PAYLOAD_LEN); if (ret) return ret; @@ -1234,8 +1237,8 @@ static __always_inline int rev_nodeport_lb4(struct __ctx_buff *ctx, int *ifindex info = ipcache_lookup4(&IPCACHE_MAP, ip4->daddr, V4_CACHE_KEY_LEN); if (info != NULL && info->tunnel_endpoint != 0) { - int ret = __encap_with_nodeid(ctx, info->tunnel_endpoint, - SECLABEL, TRACE_PAYLOAD_LEN); + ret = __encap_with_nodeid(ctx, info->tunnel_endpoint, + SECLABEL, TRACE_PAYLOAD_LEN); if (ret) return ret; @@ -1254,26 +1257,27 @@ static __always_inline int rev_nodeport_lb4(struct __ctx_buff *ctx, int *ifindex dmac = map_lookup_elem(&NODEPORT_NEIGH4, &ip4->daddr); if (dmac) { - if (eth_store_daddr(ctx, dmac->addr, 0) < 0) - return DROP_WRITE_ERROR; - if (eth_store_saddr(ctx, mac->addr, 0) < 0) - return DROP_WRITE_ERROR; + if (eth_store_daddr(ctx, dmac->addr, 0) < 0) + return DROP_WRITE_ERROR; + if (eth_store_saddr(ctx, mac->addr, 0) < 0) + return DROP_WRITE_ERROR; } else { - fib_params.family = AF_INET; - fib_params.ifindex = *ifindex; + fib_params.family = AF_INET; + fib_params.ifindex = *ifindex; - fib_params.ipv4_src = ip4->saddr; - fib_params.ipv4_dst = ip4->daddr; + fib_params.ipv4_src = ip4->saddr; + fib_params.ipv4_dst = ip4->daddr; - int rc = fib_lookup(ctx, &fib_params, sizeof(fib_params), - BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT); - if (rc != 0) - return DROP_NO_FIB; + ret = fib_lookup(ctx, &fib_params, sizeof(fib_params), + BPF_FIB_LOOKUP_DIRECT | + BPF_FIB_LOOKUP_OUTPUT); + if (ret != 0) + return DROP_NO_FIB; - if (eth_store_daddr(ctx, fib_params.dmac, 0) < 0) - return DROP_WRITE_ERROR; - if (eth_store_saddr(ctx, fib_params.smac, 0) < 0) - return DROP_WRITE_ERROR; + if (eth_store_daddr(ctx, fib_params.dmac, 0) < 0) + return DROP_WRITE_ERROR; + if (eth_store_saddr(ctx, fib_params.smac, 0) < 0) + return DROP_WRITE_ERROR; } } else { if (!bpf_skip_recirculation(ctx)) { diff --git a/bpf/lib/policy.h b/bpf/lib/policy.h index aa2c884ef398..fa7a37b452ab 100644 --- a/bpf/lib/policy.h +++ b/bpf/lib/policy.h @@ -83,19 +83,29 @@ __policy_can_access(const void *map, struct __ctx_buff *ctx, __u32 identity, __u16 dport, __u8 proto, int dir, bool is_untracked_fragment, __u8 *match_type) { + struct policy_entry *policy; + struct policy_key key = { + .sec_label = identity, + .dport = dport, + .protocol = proto, + .egress = !dir, + .pad = 0, + }; + #ifdef ALLOW_ICMP_FRAG_NEEDED - // When ALLOW_ICMP_FRAG_NEEDED is defined we allow all packets - // of ICMP type 3 code 4 - Fragmentation Needed + /* When ALLOW_ICMP_FRAG_NEEDED is defined we allow all packets + * of ICMP type 3 code 4 - Fragmentation Needed. + */ if (proto == IPPROTO_ICMP) { void *data, *data_end; struct icmphdr icmphdr __align_stack_8; struct iphdr *ip4; + __u32 off; if (!revalidate_data(ctx, &data, &data_end, &ip4)) return DROP_INVALID; - __u32 off = ((void *)ip4 - data) + ipv4_hdrlen(ip4); - + off = ((void *)ip4 - data) + ipv4_hdrlen(ip4); if (ctx_load_bytes(ctx, off, &icmphdr, sizeof(icmphdr)) < 0) return DROP_INVALID; @@ -104,16 +114,6 @@ __policy_can_access(const void *map, struct __ctx_buff *ctx, __u32 identity, } #endif /* ALLOW_ICMP_FRAG_NEEDED */ - struct policy_entry *policy; - - struct policy_key key = { - .sec_label = identity, - .dport = dport, - .protocol = proto, - .egress = !dir, - .pad = 0, - }; - /* L4 lookup can't be done on untracked fragments. */ if (!is_untracked_fragment) { /* Start with L3/L4 lookup. */ @@ -219,24 +219,22 @@ static __always_inline int policy_can_egress(struct __ctx_buff *ctx, __u32 identity, __u16 dport, __u8 proto, __u8 *match_type) { + int ret; + #ifdef ENCAP_IFINDEX if (is_encap(dport, proto)) return DROP_ENCAP_PROHIBITED; #endif - - int ret = __policy_can_access(&POLICY_MAP, ctx, identity, dport, proto, - CT_EGRESS, false, match_type); + ret = __policy_can_access(&POLICY_MAP, ctx, identity, dport, proto, + CT_EGRESS, false, match_type); if (ret >= 0) return ret; - cilium_dbg(ctx, DBG_POLICY_DENIED, SECLABEL, identity); - #ifdef POLICY_AUDIT_MODE if (IS_ERR(ret)) { ret = CTX_ACT_OK; } #endif - return ret; } diff --git a/bpf/lib/policy_log.h b/bpf/lib/policy_log.h index 711bdfabf4a0..406fecafbd9e 100644 --- a/bpf/lib/policy_log.h +++ b/bpf/lib/policy_log.h @@ -31,13 +31,14 @@ struct policy_verdict_notify { ipv6:1, match_type:3, pad0:2; - __u32 pad1; // align with 64 bits + __u32 pad1; /* align with 64 bits */ }; static __always_inline bool policy_verdict_filter_allow(__u32 filter, __u8 dir) { - // Make dir being volatile to avoid compiler optimizing out filter (thinking - // it to be zero). + /* Make dir being volatile to avoid compiler optimizing out + * filter (thinking it to be zero). + */ volatile __u8 d = dir; return ((filter & d) > 0); } @@ -47,29 +48,23 @@ send_policy_verdict_notify(struct __ctx_buff *ctx, __u32 remote_label, __u16 dst __u8 proto, __u8 dir, __u8 is_ipv6, int verdict, __u8 match_type) { - if (!policy_verdict_filter_allow(POLICY_VERDICT_LOG_FILTER, dir)) { + __u64 ctx_len = ctx_full_len(ctx); + __u64 cap_len = min_t(__u64, TRACE_PAYLOAD_LEN, ctx_len); + struct policy_verdict_notify msg; + + if (!policy_verdict_filter_allow(POLICY_VERDICT_LOG_FILTER, dir)) return; - } - __u64 ctx_len = (__u64)ctx_full_len(ctx); - __u64 cap_len = min((__u64)TRACE_PAYLOAD_LEN, (__u64)ctx_len); - __u32 hash = get_hash_recalc(ctx); - struct policy_verdict_notify msg = { - .type = CILIUM_NOTIFY_POLICY_VERDICT, - .source = EVENT_SOURCE, - .hash = hash, - .len_orig = ctx_len, - .len_cap = cap_len, - .version = NOTIFY_CAPTURE_VER, - .remote_label = remote_label, - .verdict = verdict, - .dst_port = bpf_ntohs(dst_port), - .proto = proto, - .dir = dir, - .ipv6 = is_ipv6, - .match_type = match_type, - .pad0 = 0, - .pad1 = 0, + msg = (typeof(msg)) { + __notify_common_hdr(CILIUM_NOTIFY_POLICY_VERDICT, 0), + __notify_pktcap_hdr(ctx_len, cap_len), + .remote_label = remote_label, + .verdict = verdict, + .dst_port = bpf_ntohs(dst_port), + .match_type = match_type, + .proto = proto, + .dir = dir, + .ipv6 = is_ipv6, }; ctx_event_output(ctx, &EVENTS_MAP, diff --git a/bpf/lib/trace.h b/bpf/lib/trace.h index 9732ad28e214..c9f7ab74c9e8 100644 --- a/bpf/lib/trace.h +++ b/bpf/lib/trace.h @@ -143,112 +143,87 @@ static __always_inline void send_trace_notify(struct __ctx_buff *ctx, __u8 obs_point, __u32 src, __u32 dst, __u16 dst_id, __u32 ifindex, __u8 reason, __u32 monitor) { + __u64 ctx_len = ctx_full_len(ctx); + __u64 cap_len = min_t(__u64, monitor ? : TRACE_PAYLOAD_LEN, + ctx_len); + struct trace_notify msg; + update_trace_metrics(ctx, obs_point, reason); if (!emit_trace_notify(obs_point, monitor)) return; - if (!monitor) - monitor = TRACE_PAYLOAD_LEN; - - __u64 ctx_len = (__u64)ctx_full_len(ctx); - __u64 cap_len = min((__u64)monitor, (__u64)ctx_len); - __u32 hash = get_hash_recalc(ctx); - struct trace_notify msg = { - .type = CILIUM_NOTIFY_TRACE, - .subtype = obs_point, - .source = EVENT_SOURCE, - .hash = hash, - .len_orig = ctx_len, - .len_cap = cap_len, - .version = NOTIFY_CAPTURE_VER, - .src_label = src, - .dst_label = dst, - .dst_id = dst_id, - .reason = reason, - .ipv6 = 0, - .pad = 0, - .ifindex = ifindex, - .orig_ip4 = 0, - .orig_pad1 = 0, - .orig_pad2 = 0, - .orig_pad3 = 0, + msg = (typeof(msg)) { + __notify_common_hdr(CILIUM_NOTIFY_TRACE, obs_point), + __notify_pktcap_hdr(ctx_len, cap_len), + .src_label = src, + .dst_label = dst, + .dst_id = dst_id, + .reason = reason, + .ifindex = ifindex, }; + ctx_event_output(ctx, &EVENTS_MAP, (cap_len << 32) | BPF_F_CURRENT_CPU, &msg, sizeof(msg)); } static __always_inline void -send_trace_notify4(struct __ctx_buff *ctx, __u8 obs_point, __u32 src, __u32 dst, __be32 orig_addr, - __u16 dst_id, __u32 ifindex, __u8 reason, __u32 monitor) +send_trace_notify4(struct __ctx_buff *ctx, __u8 obs_point, __u32 src, __u32 dst, + __be32 orig_addr, __u16 dst_id, __u32 ifindex, __u8 reason, + __u32 monitor) { + __u64 ctx_len = ctx_full_len(ctx); + __u64 cap_len = min_t(__u64, monitor ? : TRACE_PAYLOAD_LEN, + ctx_len); + struct trace_notify msg; + update_trace_metrics(ctx, obs_point, reason); if (!emit_trace_notify(obs_point, monitor)) return; - if (!monitor) - monitor = TRACE_PAYLOAD_LEN; - - __u64 ctx_len = (__u64)ctx_full_len(ctx); - __u64 cap_len = min((__u64)monitor, (__u64)ctx_len); - __u32 hash = get_hash_recalc(ctx); - struct trace_notify msg = { - .type = CILIUM_NOTIFY_TRACE, - .subtype = obs_point, - .source = EVENT_SOURCE, - .hash = hash, - .len_orig = ctx_len, - .len_cap = cap_len, - .version = NOTIFY_CAPTURE_VER, - .src_label = src, - .dst_label = dst, - .dst_id = dst_id, - .reason = reason, - .ipv6 = 0, - .pad = 0, - .ifindex = ifindex, - .orig_ip4 = orig_addr, - .orig_pad1 = 0, - .orig_pad2 = 0, - .orig_pad3 = 0, + msg = (typeof(msg)) { + __notify_common_hdr(CILIUM_NOTIFY_TRACE, obs_point), + __notify_pktcap_hdr(ctx_len, cap_len), + .src_label = src, + .dst_label = dst, + .dst_id = dst_id, + .reason = reason, + .ifindex = ifindex, + .ipv6 = 0, + .orig_ip4 = orig_addr, }; + ctx_event_output(ctx, &EVENTS_MAP, (cap_len << 32) | BPF_F_CURRENT_CPU, &msg, sizeof(msg)); } static __always_inline void -send_trace_notify6(struct __ctx_buff *ctx, __u8 obs_point, __u32 src, __u32 dst, union v6addr *orig_addr, - __u16 dst_id, __u32 ifindex, __u8 reason, __u32 monitor) +send_trace_notify6(struct __ctx_buff *ctx, __u8 obs_point, __u32 src, __u32 dst, + union v6addr *orig_addr, __u16 dst_id, __u32 ifindex, + __u8 reason, __u32 monitor) { + __u64 ctx_len = ctx_full_len(ctx); + __u64 cap_len = min_t(__u64, monitor ? : TRACE_PAYLOAD_LEN, + ctx_len); + struct trace_notify msg; + update_trace_metrics(ctx, obs_point, reason); if (!emit_trace_notify(obs_point, monitor)) return; - if (!monitor) - monitor = TRACE_PAYLOAD_LEN; - - __u64 ctx_len = (__u64)ctx_full_len(ctx); - __u64 cap_len = min((__u64)monitor, (__u64)ctx_len); - __u32 hash = get_hash_recalc(ctx); - struct trace_notify msg = { - .type = CILIUM_NOTIFY_TRACE, - .subtype = obs_point, - .source = EVENT_SOURCE, - .hash = hash, - .len_orig = ctx_len, - .len_cap = cap_len, - .version = NOTIFY_CAPTURE_VER, - .src_label = src, - .dst_label = dst, - .dst_id = dst_id, - .reason = reason, - .ipv6 = 1, - .pad = 0, - .ifindex = ifindex, + msg = (typeof(msg)) { + __notify_common_hdr(CILIUM_NOTIFY_TRACE, obs_point), + __notify_pktcap_hdr(ctx_len, cap_len), + .src_label = src, + .dst_label = dst, + .dst_id = dst_id, + .reason = reason, + .ifindex = ifindex, + .ipv6 = 1, }; ipv6_addr_copy(&msg.orig_ip6, orig_addr); diff --git a/bpf/lib/utils.h b/bpf/lib/utils.h index 3270b708c1be..4d4303d28084 100644 --- a/bpf/lib/utils.h +++ b/bpf/lib/utils.h @@ -11,20 +11,32 @@ #include "time.h" #include "static_data.h" -#define min(x, y) \ -({ \ - typeof(x) _x = (x); \ - typeof(y) _y = (y); \ - (void) (&_x == &_y); \ - _x < _y ? _x : _y; \ +#define __min(t_x, t_y, x, y) \ +({ \ + t_x _x = (x); \ + t_y _y = (y); \ + (void) (&_x == &_y); \ + _x < _y ? _x : _y; \ }) -#define max(x, y) \ -({ \ - typeof(x) _x = (x); \ - typeof(y) _y = (y); \ - (void) (&_x == &_y); \ - _x > _y ? _x : _y; \ +#define __max(t_x, t_y, x, y) \ +({ \ + t_x _x = (x); \ + t_y _y = (y); \ + (void) (&_x == &_y); \ + _x > _y ? _x : _y; \ }) +#define min(x, y) \ + __min(typeof(x), typeof(y), x, y) + +#define max(x, y) \ + __max(typeof(x), typeof(y), x, y) + +#define min_t(t, x, y) \ + __min(t, t, x, y) + +#define max_t(t, x, y) \ + __max(t, t, x, y) + #endif /* __LIB_UTILS_H_ */ diff --git a/pkg/datapath/loader/compile.go b/pkg/datapath/loader/compile.go index 56faea952056..5d1d298cc549 100644 --- a/pkg/datapath/loader/compile.go +++ b/pkg/datapath/loader/compile.go @@ -82,12 +82,13 @@ type directoryInfo struct { } var ( - standardCFlags = []string{"-O2", "-target", "bpf", - fmt.Sprintf("-D__NR_CPUS__=%d", runtime.NumCPU()), - "-Wall", "-Wextra", "-Werror", + standardCFlags = []string{"-O2", "-target", "bpf", "-std=gnu89", + "-nostdinc", fmt.Sprintf("-D__NR_CPUS__=%d", runtime.NumCPU()), + "-Wall", "-Wextra", "-Werror", "-Wshadow", "-Wno-address-of-packed-member", "-Wno-unknown-warning-option", - "-Wno-gnu-variable-sized-type-not-at-end"} + "-Wno-gnu-variable-sized-type-not-at-end", + "-Wdeclaration-after-statement"} standardLDFlags = []string{"-march=bpf"} // testIncludes allows the unit tests to inject additional include diff --git a/test/bpf/Makefile b/test/bpf/Makefile index 64cae73537d7..d291ac635118 100644 --- a/test/bpf/Makefile +++ b/test/bpf/Makefile @@ -4,9 +4,13 @@ include ../../Makefile.defs FLAGS := -I../../bpf/ -I../../bpf/include -I. -D__NR_CPUS__=$(shell nproc) -O2 -FLAGS_CLANG := -Wno-gnu-variable-sized-type-not-at-end +FLAGS_CLANG := -Wall -Wextra -Werror -Wshadow -Wno-unused-parameter +FLAGS_CLANG += -Wno-address-of-packed-member +FLAGS_CLANG += -Wno-unknown-warning-option +FLAGS_CLANG += -Wno-gnu-variable-sized-type-not-at-end +FLAGS_CLANG += -Wdeclaration-after-statement -BPF_CC_FLAGS := ${FLAGS} -target bpf -emit-llvm +BPF_CC_FLAGS := ${FLAGS} -target bpf -std=gnu89 -nostdinc -emit-llvm BPF_LLC_FLAGS := -march=bpf -mcpu=probe -filetype=obj LIB := $(shell find ../../bpf/ -name '*.h')