github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/bpf/lib/trace.h (about) 1 /* 2 * Copyright (C) 2016-2018 Authors of Cilium 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 /* 19 * Packet forwarding notification via perf event ring buffer. 20 * 21 * API: 22 * void send_trace_notify(skb, obs_point, src, dst, dst_id, ifindex, reason, monitor) 23 * 24 * If TRACE_NOTIFY is not defined, the API will be compiled in as a NOP. 25 */ 26 27 #ifndef __LIB_TRACE__ 28 #define __LIB_TRACE__ 29 30 #include "dbg.h" 31 #include "events.h" 32 #include "common.h" 33 #include "utils.h" 34 #include "metrics.h" 35 36 /* Available observation points. */ 37 enum { 38 TRACE_TO_LXC, 39 TRACE_TO_PROXY, 40 TRACE_TO_HOST, 41 TRACE_TO_STACK, 42 TRACE_TO_OVERLAY, 43 TRACE_FROM_LXC, 44 TRACE_FROM_PROXY, 45 TRACE_FROM_HOST, 46 TRACE_FROM_STACK, 47 TRACE_FROM_OVERLAY, 48 TRACE_FROM_NETWORK, 49 }; 50 51 /* Reasons for forwarding a packet. */ 52 enum { 53 TRACE_REASON_POLICY = CT_NEW, 54 TRACE_REASON_CT_ESTABLISHED = CT_ESTABLISHED, 55 TRACE_REASON_CT_REPLY = CT_REPLY, 56 TRACE_REASON_CT_RELATED = CT_RELATED, 57 }; 58 59 #define TRACE_REASON_ENCRYPTED 0x80 60 61 /* Trace aggregation levels. */ 62 enum { 63 TRACE_AGGREGATE_NONE = 0, /* Trace every packet on rx & tx */ 64 TRACE_AGGREGATE_RX = 1, /* Hide trace on packet receive */ 65 TRACE_AGGREGATE_ACTIVE_CT = 3, /* Ratelimit active connection traces */ 66 }; 67 68 #ifndef MONITOR_AGGREGATION 69 #define MONITOR_AGGREGATION TRACE_AGGREGATE_NONE 70 #endif 71 72 #ifdef TRACE_NOTIFY 73 74 struct trace_notify { 75 NOTIFY_COMMON_HDR 76 __u32 len_orig; 77 __u32 len_cap; 78 __u32 src_label; 79 __u32 dst_label; 80 __u16 dst_id; 81 __u8 reason; 82 __u8 pad; 83 __u32 ifindex; 84 }; 85 86 /** 87 * send_trace_notify 88 * @skb: socket buffer 89 * @obs_point: observation point (TRACE_*) 90 * @src: source identity 91 * @dst: destination identity 92 * @dst_id: designated destination endpoint ID 93 * @ifindex: designated destination ifindex 94 * @reason: reason for forwarding the packet (TRACE_REASON_*) 95 * @monitor: length of notification to send (0 means don't send) 96 * 97 * Generate a notification to indicate a packet was forwarded at an observation point. 98 */ 99 static inline void 100 send_trace_notify(struct __sk_buff *skb, __u8 obs_point, __u32 src, __u32 dst, 101 __u16 dst_id, __u32 ifindex, __u8 reason, __u32 monitor) 102 { 103 __u8 encrypted; 104 105 switch (obs_point) { 106 case TRACE_TO_LXC: 107 update_metrics(skb->len, METRIC_INGRESS, REASON_FORWARDED); 108 break; 109 110 /* TRACE_FROM_LXC, i.e endpoint-to-endpoint delivery 111 * is handled separately in ipv*_local_delivery() where we can bump 112 * an egress forward. It could still be dropped but it would show 113 * up later as an ingress drop, in that scenario. 114 * 115 * TRACE_TO_PROXY is not handled in datapath. This is because we have separate 116 * L7 proxy "forwarded" and "dropped" (ingress/egress) counters in the proxy layer 117 * to capture these metrics. 118 */ 119 case TRACE_TO_HOST: 120 case TRACE_TO_STACK: 121 case TRACE_TO_OVERLAY: 122 update_metrics(skb->len, METRIC_EGRESS, REASON_FORWARDED); 123 break; 124 case TRACE_FROM_OVERLAY: 125 case TRACE_FROM_NETWORK: 126 encrypted = reason & TRACE_REASON_ENCRYPTED; 127 if (!encrypted) 128 update_metrics(skb->len, METRIC_INGRESS, REASON_PLAINTEXT); 129 else 130 update_metrics(skb->len, METRIC_INGRESS, REASON_DECRYPT); 131 break; 132 } 133 if (MONITOR_AGGREGATION >= TRACE_AGGREGATE_RX) { 134 switch (obs_point) { 135 case TRACE_FROM_LXC: 136 case TRACE_FROM_PROXY: 137 case TRACE_FROM_HOST: 138 case TRACE_FROM_STACK: 139 case TRACE_FROM_OVERLAY: 140 return; 141 default: 142 break; 143 } 144 } 145 if (MONITOR_AGGREGATION >= TRACE_AGGREGATE_ACTIVE_CT && !monitor) 146 return; 147 148 if (!monitor) 149 monitor = TRACE_PAYLOAD_LEN; 150 uint64_t skb_len = (uint64_t)skb->len, cap_len = min((uint64_t)monitor, (uint64_t)skb_len); 151 uint32_t hash = get_hash_recalc(skb); 152 struct trace_notify msg = { 153 .type = CILIUM_NOTIFY_TRACE, 154 .subtype = obs_point, 155 .source = EVENT_SOURCE, 156 .hash = hash, 157 .len_orig = skb_len, 158 .len_cap = cap_len, 159 .src_label = src, 160 .dst_label = dst, 161 .dst_id = dst_id, 162 .reason = reason, 163 .pad = 0, 164 .ifindex = ifindex, 165 }; 166 skb_event_output(skb, &EVENTS_MAP, 167 (cap_len << 32) | BPF_F_CURRENT_CPU, 168 &msg, sizeof(msg)); 169 } 170 171 #else 172 173 static inline void send_trace_notify(struct __sk_buff *skb, __u8 obs_point, __u32 src, __u32 dst, 174 __u16 dst_id, __u32 ifindex, __u8 reason, __u32 monitor) 175 { 176 __u8 encrypted; 177 178 switch (obs_point) { 179 case TRACE_TO_LXC: 180 update_metrics(skb->len, METRIC_INGRESS, REASON_FORWARDED); 181 break; 182 183 /* TRACE_FROM_LXC, i.e endpoint-to-endpoint delivery 184 * is handled separately in ipv*_local_delivery() where we can bump 185 * an egress forward. It could still be dropped but it would show 186 * up later as an ingress drop, in that scenario. 187 * 188 * TRACE_TO_PROXY is not handled in datapath. This is because we have separate 189 * L7 proxy "forwarded" and "dropped" (ingress/egress) counters in the proxy layer 190 * to capture these metrics. 191 */ 192 case TRACE_TO_HOST: 193 case TRACE_TO_STACK: 194 case TRACE_TO_OVERLAY: 195 update_metrics(skb->len, METRIC_EGRESS, REASON_FORWARDED); 196 break; 197 case TRACE_FROM_OVERLAY: 198 case TRACE_FROM_NETWORK: 199 encrypted = reason & TRACE_REASON_ENCRYPTED; 200 if (!encrypted) 201 update_metrics(skb->len, METRIC_INGRESS, REASON_PLAINTEXT); 202 else 203 update_metrics(skb->len, METRIC_INGRESS, REASON_DECRYPT); 204 break; 205 } 206 } 207 208 #endif 209 210 #endif /* __LIB_TRACE__ */