katran/lib/bpf/balancer_helpers.h (80 lines of code) (raw):

/* Copyright (C) 2018-present, Facebook, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __BALANCER_HELPERS #define __BALANCER_HELPERS /* * This file contains common used routines. such as csum helpers etc */ #include <linux/in.h> #include <linux/ip.h> #include <linux/ipv6.h> #include <stdbool.h> #include "balancer_consts.h" #include "balancer_structs.h" #include "bpf.h" #include "bpf_helpers.h" #include "control_data_maps.h" #include "csum_helpers.h" #include "introspection.h" #define bpf_printk(fmt, ...) \ ({ \ char ____fmt[] = fmt; \ bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \ }) #ifdef KATRAN_INTROSPECTION /** * helper to print blob of data into perf pipe */ __attribute__((__always_inline__)) static inline void submit_event( struct xdp_md* ctx, void* map, __u32 event_id, void* data, __u32 size, bool metadata_only) { struct ctl_value* gk; __u32 introspection_gk_pos = 5; gk = bpf_map_lookup_elem(&ctl_array, &introspection_gk_pos); if (!gk || gk->value == 0) { return; } struct event_metadata md = {}; __u64 flags = BPF_F_CURRENT_CPU; md.event = event_id; md.pkt_size = size; if (metadata_only) { md.data_len = 0; } else { md.data_len = min_helper(size, MAX_EVENT_SIZE); flags |= (__u64)md.data_len << 32; } bpf_perf_event_output(ctx, map, flags, &md, sizeof(struct event_metadata)); } #endif #ifdef INLINE_DECAP_GENERIC __attribute__((__always_inline__)) static inline int recirculate( struct xdp_md* ctx) { int i = RECIRCULATION_INDEX; bpf_tail_call(ctx, &subprograms, i); // we should never hit this return XDP_PASS; } #endif // of INLINE_DECAP_GENERIC __attribute__((__always_inline__)) static inline int decrement_ttl(void* data, void* data_end, int offset, bool is_ipv6) { struct iphdr* iph; struct ipv6hdr* ip6h; if (is_ipv6) { if ((data + offset + sizeof(struct ipv6hdr)) > data_end) { return XDP_DROP; } ip6h = (struct ipv6hdr*)(data + offset); if (!--ip6h->hop_limit) { // ttl 0 return XDP_DROP; } } else { if ((data + offset + sizeof(struct iphdr)) > data_end) { return XDP_DROP; } iph = (struct iphdr*)(data + offset); __u32 csum; if (!--iph->ttl) { // ttl 0 return XDP_DROP; } csum = iph->check + 0x0001; iph->check = (csum & 0xffff) + (csum >> 16); } return FURTHER_PROCESSING; } #endif