github.com/fafucoder/cilium@v1.6.11/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 case TRACE_FROM_NETWORK: 141 return; 142 default: 143 break; 144 } 145 } 146 if (MONITOR_AGGREGATION >= TRACE_AGGREGATE_ACTIVE_CT && !monitor) 147 return; 148 149 if (!monitor) 150 monitor = TRACE_PAYLOAD_LEN; 151 uint64_t skb_len = (uint64_t)skb->len, cap_len = min((uint64_t)monitor, (uint64_t)skb_len); 152 uint32_t hash = get_hash_recalc(skb); 153 struct trace_notify msg = { 154 .type = CILIUM_NOTIFY_TRACE, 155 .subtype = obs_point, 156 .source = EVENT_SOURCE, 157 .hash = hash, 158 .len_orig = skb_len, 159 .len_cap = cap_len, 160 .src_label = src, 161 .dst_label = dst, 162 .dst_id = dst_id, 163 .reason = reason, 164 .pad = 0, 165 .ifindex = ifindex, 166 }; 167 skb_event_output(skb, &EVENTS_MAP, 168 (cap_len << 32) | BPF_F_CURRENT_CPU, 169 &msg, sizeof(msg)); 170 } 171 172 #else 173 174 static inline void send_trace_notify(struct __sk_buff *skb, __u8 obs_point, __u32 src, __u32 dst, 175 __u16 dst_id, __u32 ifindex, __u8 reason, __u32 monitor) 176 { 177 __u8 encrypted; 178 179 switch (obs_point) { 180 case TRACE_TO_LXC: 181 update_metrics(skb->len, METRIC_INGRESS, REASON_FORWARDED); 182 break; 183 184 /* TRACE_FROM_LXC, i.e endpoint-to-endpoint delivery 185 * is handled separately in ipv*_local_delivery() where we can bump 186 * an egress forward. It could still be dropped but it would show 187 * up later as an ingress drop, in that scenario. 188 * 189 * TRACE_TO_PROXY is not handled in datapath. This is because we have separate 190 * L7 proxy "forwarded" and "dropped" (ingress/egress) counters in the proxy layer 191 * to capture these metrics. 192 */ 193 case TRACE_TO_HOST: 194 case TRACE_TO_STACK: 195 case TRACE_TO_OVERLAY: 196 update_metrics(skb->len, METRIC_EGRESS, REASON_FORWARDED); 197 break; 198 case TRACE_FROM_OVERLAY: 199 case TRACE_FROM_NETWORK: 200 encrypted = reason & TRACE_REASON_ENCRYPTED; 201 if (!encrypted) 202 update_metrics(skb->len, METRIC_INGRESS, REASON_PLAINTEXT); 203 else 204 update_metrics(skb->len, METRIC_INGRESS, REASON_DECRYPT); 205 break; 206 } 207 } 208 209 #endif 210 211 #endif /* __LIB_TRACE__ */