github.com/cilium/cilium@v1.16.2/bpf/lib/drop.h (about) 1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 /* Copyright Authors of Cilium */ 3 4 /* 5 * Drop & error notification via perf event ring buffer 6 * 7 * API: 8 * int send_drop_notify(ctx, src, dst, dst_id, reason, exitcode, enum metric_dir direction) 9 * int send_drop_notify_error(ctx, error, exitcode, enum metric_dir direction) 10 * 11 * If DROP_NOTIFY is not defined, the API will be compiled in as a NOP. 12 */ 13 14 #pragma once 15 16 #include "dbg.h" 17 #include "events.h" 18 #include "common.h" 19 #include "utils.h" 20 #include "metrics.h" 21 22 #ifdef DROP_NOTIFY 23 struct drop_notify { 24 NOTIFY_CAPTURE_HDR 25 __u32 src_label; 26 __u32 dst_label; 27 __u32 dst_id; /* 0 for egress */ 28 __u16 line; 29 __u8 file; 30 __s8 ext_error; 31 __u32 ifindex; 32 }; 33 34 /* 35 * We pass information in the meta area as follows: 36 * 37 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 38 * | Source Label | 39 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 40 * | Destination Label | 41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 42 * | Error Code | Extended Error| Unused | 43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44 * | Designated Destination Endpoint ID | 45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 46 * | Exit Code | Source File | Source Line | 47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 48 * 49 */ 50 51 __section_tail(CILIUM_MAP_CALLS, CILIUM_CALL_DROP_NOTIFY) 52 int __send_drop_notify(struct __ctx_buff *ctx) 53 { 54 /* Mask needed to calm verifier. */ 55 __u32 error = ctx_load_meta(ctx, 2) & 0xFFFFFFFF; 56 __u64 ctx_len = ctx_full_len(ctx); 57 __u64 cap_len = min_t(__u64, TRACE_PAYLOAD_LEN, ctx_len); 58 __u32 meta4 = ctx_load_meta(ctx, 4); 59 __u16 line = (__u16)(meta4 >> 16); 60 __u8 file = (__u8)(meta4 >> 8); 61 __u8 exitcode = (__u8)meta4; 62 struct drop_notify msg; 63 64 msg = (typeof(msg)) { 65 __notify_common_hdr(CILIUM_NOTIFY_DROP, (__u8)error), 66 __notify_pktcap_hdr(ctx_len, (__u16)cap_len), 67 .src_label = ctx_load_meta(ctx, 0), 68 .dst_label = ctx_load_meta(ctx, 1), 69 .dst_id = ctx_load_meta(ctx, 3), 70 .line = line, 71 .file = file, 72 .ext_error = (__s8)(__u8)(error >> 8), 73 .ifindex = ctx_get_ifindex(ctx), 74 }; 75 76 ctx_event_output(ctx, &EVENTS_MAP, 77 (cap_len << 32) | BPF_F_CURRENT_CPU, 78 &msg, sizeof(msg)); 79 80 return exitcode; 81 } 82 83 /** 84 * send_drop_notify 85 * @ctx: socket buffer 86 * @src: source identity 87 * @dst: destination identity 88 * @dst_id: designated destination endpoint ID, if ingress, otherwise 0 89 * @reason: Reason for drop 90 * @exitcode: error code to return to the kernel 91 * 92 * Generate a notification to indicate a packet was dropped. 93 * 94 * NOTE: This is terminal function and will cause the BPF program to exit 95 */ 96 static __always_inline int 97 _send_drop_notify(__u8 file, __u16 line, struct __ctx_buff *ctx, 98 __u32 src, __u32 dst, __u32 dst_id, 99 __u32 reason, __u32 exitcode, enum metric_dir direction) 100 { 101 int ret __maybe_unused; 102 103 /* These fields should be constants and fit (together) in 32 bits */ 104 if (!__builtin_constant_p(exitcode) || exitcode > 0xff || 105 !__builtin_constant_p(file) || file > 0xff || 106 !__builtin_constant_p(line) || line > 0xffff) 107 __throw_build_bug(); 108 109 /* Non-zero 'dst_id' is only to be used for ingress. */ 110 if (dst_id != 0 && (!__builtin_constant_p(direction) || direction != METRIC_INGRESS)) 111 __throw_build_bug(); 112 113 ctx_store_meta(ctx, 0, src); 114 ctx_store_meta(ctx, 1, dst); 115 ctx_store_meta(ctx, 2, reason); 116 ctx_store_meta(ctx, 3, dst_id); 117 ctx_store_meta(ctx, 4, exitcode | file << 8 | line << 16); 118 119 _update_metrics(ctx_full_len(ctx), direction, (__u8)reason, line, file); 120 ret = tail_call_internal(ctx, CILIUM_CALL_DROP_NOTIFY, NULL); 121 /* ignore the returned error, use caller-provided exitcode */ 122 123 return exitcode; 124 } 125 #else 126 static __always_inline 127 int _send_drop_notify(__u8 file __maybe_unused, __u16 line __maybe_unused, 128 struct __ctx_buff *ctx, __u32 src __maybe_unused, 129 __u32 dst __maybe_unused, __u32 dst_id __maybe_unused, 130 __u32 reason, __u32 exitcode, enum metric_dir direction) 131 { 132 _update_metrics(ctx_full_len(ctx), direction, (__u8)reason, line, file); 133 return exitcode; 134 } 135 #endif /* DROP_NOTIFY */ 136 137 /* 138 * The following macros are required in order to pass source file/line 139 * information. The *_ext versions take an additional parameter ext_err 140 * which can be used to pass additional information, e.g., this could be an 141 * original error returned by fib_lookup (if reason == DROP_NO_FIB). 142 */ 143 144 /* 145 * Cilium errors are greater than absolute errno values, so we just pass 146 * a positive value here 147 */ 148 #define __DROP_REASON(err) ({ \ 149 typeof(err) __err = (err); \ 150 (__u8)(__err > 0 ? __err : -__err); \ 151 }) 152 153 /* 154 * We only have 8 bits here to pass either a small positive value or an errno 155 * (this can be fixed by changing the layout of struct drop_notify, but for now 156 * we can hack this as follows). So we pass a negative errno value as is if it 157 * is >= -128, and set it 0 if it is < -128 (which actually shoudn't happen in 158 * our case) 159 */ 160 #define __DROP_REASON_EXT(err, ext_err) ({ \ 161 typeof(ext_err) __ext_err = (ext_err); \ 162 __DROP_REASON(err) | ((__u8)(__ext_err < -128 ? 0 : __ext_err) << 8); \ 163 }) 164 165 #define send_drop_notify(ctx, src, dst, dst_id, reason, exitcode, direction) \ 166 _send_drop_notify(__MAGIC_FILE__, __MAGIC_LINE__, ctx, src, dst, dst_id, \ 167 __DROP_REASON(reason), exitcode, direction) 168 169 #define send_drop_notify_error(ctx, src, reason, exitcode, direction) \ 170 _send_drop_notify(__MAGIC_FILE__, __MAGIC_LINE__, ctx, src, 0, 0, \ 171 __DROP_REASON(reason), exitcode, direction) 172 173 #define send_drop_notify_ext(ctx, src, dst, dst_id, reason, ext_err, exitcode, direction) \ 174 _send_drop_notify(__MAGIC_FILE__, __MAGIC_LINE__, ctx, src, dst, dst_id, \ 175 __DROP_REASON_EXT(reason, ext_err), exitcode, direction) 176 177 #define send_drop_notify_error_ext(ctx, src, reason, ext_err, exitcode, direction) \ 178 _send_drop_notify(__MAGIC_FILE__, __MAGIC_LINE__, ctx, src, 0, 0, \ 179 __DROP_REASON_EXT(reason, ext_err), exitcode, direction)