summaryrefslogtreecommitdiff
path: root/src/ebpf
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-12-18 17:13:13 +0100
committerChristian Poessinger <christian@poessinger.com>2020-12-19 21:56:19 +0100
commitb5c80d310527223b93e4133ac2f4c8c063c70a98 (patch)
tree48ae9e2752b4b94c07f767a019c99a8c2460c014 /src/ebpf
parent22308b05dfbcd8da0230bbd8ba3bbc2a55da7786 (diff)
downloadvyos-1x-b5c80d310527223b93e4133ac2f4c8c063c70a98.tar.gz
vyos-1x-b5c80d310527223b93e4133ac2f4c8c063c70a98.zip
xdp: T2666: switch to example code provided by xdp-tutorial
Diffstat (limited to 'src/ebpf')
-rw-r--r--src/ebpf/.gitignore1
-rw-r--r--src/ebpf/Makefile16
-rw-r--r--src/ebpf/xdp_drop_ebpf.c97
-rw-r--r--src/ebpf/xdp_router.c202
4 files changed, 0 insertions, 316 deletions
diff --git a/src/ebpf/.gitignore b/src/ebpf/.gitignore
deleted file mode 100644
index 5761abcfd..000000000
--- a/src/ebpf/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.o
diff --git a/src/ebpf/Makefile b/src/ebpf/Makefile
deleted file mode 100644
index 5b80c32d7..000000000
--- a/src/ebpf/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-#clang -target bpf -O2 -c xdp-drop-ebpf.c -o xdp-drop-ebpf.o
-
-src = $(wildcard *.c)
-obj = $(src:.c=.o)
-CLANG = clang
-CFLAGS = -Wall -Wno-unused-value -Wno-pointer-sign -Wno-compare-distinct-pointer-types -Werror -O2
-
-%.o: %.c
- $(CLANG) -target bpf $(CFLAGS) -o $@ -c $<
-
-.PHONY: all
-all: $(obj)
-
-.PHONY: clean
-clean:
- rm -f *.o
diff --git a/src/ebpf/xdp_drop_ebpf.c b/src/ebpf/xdp_drop_ebpf.c
deleted file mode 100644
index a08edf58d..000000000
--- a/src/ebpf/xdp_drop_ebpf.c
+++ /dev/null
@@ -1,97 +0,0 @@
-#include <linux/bpf.h>
-#include <linux/if_ether.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/udp.h>
-
-#include <stdint.h>
-
-/* IP flags. */
-#define IP_CE 0x8000 /* Flag: "Congestion" */
-#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
-#define IP_MF 0x2000 /* Flag: "More Fragments" */
-#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
-
-#define SEC(NAME) __attribute__((section(NAME), used))
-
-#define htons(x) ((__be16)___constant_swab16((x)))
-#define htonl(x) ((__be32)___constant_swab32((x)))
-
-struct vlan_hdr {
- __be16 h_vlan_TCI;
- __be16 h_vlan_encapsulated_proto;
-};
-
-SEC("prog")
-int xdp_drop(struct xdp_md *ctx) {
- void *data_end = (void *)(long)ctx->data_end;
- void *data = (void *)(long)ctx->data;
- struct ethhdr *eth = data;
-
- uint64_t nh_off = sizeof(*eth);
- if (data + nh_off > data_end) {
- return XDP_PASS;
- }
-
- uint16_t h_proto = eth->h_proto;
- int i;
-
- /* Handle double VLAN tagged packet. See https://en.wikipedia.org/wiki/IEEE_802.1ad */
- for (i = 0; i < 2; i++) {
- if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
- struct vlan_hdr *vhdr;
-
- vhdr = data + nh_off;
- nh_off += sizeof(struct vlan_hdr);
- if (data + nh_off > data_end) {
- return XDP_PASS;
- }
- h_proto = vhdr->h_vlan_encapsulated_proto;
- }
- }
-
- if (h_proto == htons(ETH_P_IP)) {
- struct iphdr *iph = data + nh_off;
- struct udphdr *udph = data + nh_off + sizeof(struct iphdr);
-
- uint32_t hostid = iph->daddr >> 24;
-
- if (udph + 1 > (struct udphdr *)data_end) {
- return XDP_PASS;
- }
- if (hostid == 0 || hostid == 255) {
- return XDP_DROP;
- }
- if (iph->frag_off & htons(IP_MF | IP_OFFSET)) {
- return XDP_DROP;
- }
- if (iph->protocol == IPPROTO_UDP) {
- __be16 dport = htons(udph->dest);
- __be16 sport = htons(udph->source);
-
- if (dport == 53 || sport == 53) {
- return XDP_DROP;
- }
- }
- } else if (h_proto == htons(ETH_P_IPV6)) {
- struct ipv6hdr *ip6h = data + nh_off;
- struct udphdr *udph = data + nh_off + sizeof(struct ipv6hdr);
-
- if (udph + 1 > (struct udphdr *)data_end) {
- return XDP_PASS;
- }
- if (ip6h->nexthdr == IPPROTO_UDP) {
- __be16 dport = htons(udph->dest);
- __be16 sport = htons(udph->source);
-
- if (dport == 53 || sport == 53) {
- return XDP_DROP;
- }
- }
- }
-
- return XDP_PASS;
-}
-
-char _license[] SEC("license") = "GPL";
diff --git a/src/ebpf/xdp_router.c b/src/ebpf/xdp_router.c
deleted file mode 100644
index 4fb5c7cb1..000000000
--- a/src/ebpf/xdp_router.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-// Code thankfully copied from:
-// https://medium.com/swlh/building-a-xdp-express-data-path-based-peering-router-20db4995da66
-
-#include <linux/bpf.h>
-#include <linux/if_ether.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/udp.h>
-#include <linux/socket.h>
-
-#include <bpf/bpf_endian.h>
-#include <bpf/bpf_helpers.h>
-
-#include <stdint.h>
-
-#ifndef XDP_ACTION_MAX
-#define XDP_ACTION_MAX (XDP_REDIRECT + 1)
-#endif
-
-#ifndef memcpy
-#define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))
-#endif
-
-#ifndef AF_INET
-#define AF_INET 2
-#endif
-
-#ifndef AF_INET6
-#define AF_INET6 10
-#endif
-
-#ifndef IPV6_FLOWINFO_MASK
-#define IPV6_FLOWINFO_MASK bpf_htonl(0x0FFFFFFF)
-#endif
-
-/* This is the data record stored in the map */
-struct datarec {
- __u64 rx_packets;
- __u64 rx_bytes;
-};
-
-/* Keeps stats per (enum) xdp_action */
-struct bpf_map_def SEC("maps") xdp_stats_map = {
- .type = BPF_MAP_TYPE_PERCPU_ARRAY,
- .key_size = sizeof(__u32),
- .value_size = sizeof(struct datarec),
- .max_entries = XDP_ACTION_MAX,
-};
-
-struct bpf_map_def SEC("maps") tx_port = {
- .type = BPF_MAP_TYPE_DEVMAP,
- .key_size = sizeof(int),
- .value_size = sizeof(int),
- .max_entries = 256,
-};
-
-/* from include/net/ip.h */
-static __always_inline int ip_decrease_ttl(struct iphdr *iph)
-{
- __u32 check = iph->check;
- check += bpf_htons(0x0100);
- iph->check = (__u16)(check + (check >= 0xFFFF));
- return --iph->ttl;
-}
-
-static __always_inline
-__u32 xdp_stats_record_action(struct xdp_md *ctx, __u32 action)
-{
- if (action >= XDP_ACTION_MAX)
- return XDP_ABORTED;
-
- /* Lookup in kernel BPF-side return pointer to actual data record */
- struct datarec *rec = bpf_map_lookup_elem(&xdp_stats_map, &action);
- if (!rec)
- return XDP_ABORTED;
-
- /* BPF_MAP_TYPE_PERCPU_ARRAY returns a data record specific to current
- * CPU and XDP hooks runs under Softirq, which makes it safe to update
- * without atomic operations.
- */
- rec->rx_packets++;
- rec->rx_bytes += (ctx->data_end - ctx->data);
-
- return action;
-}
-
-/* xdp_router is the name of the xdp program */
-SEC("prog")
-int xdp_router_func(struct xdp_md *ctx)
-{
- /* this is the packet context*/
- void *data_end = (void *)(long)ctx->data_end;
- void *data = (void *)(long)ctx->data;
- struct bpf_fib_lookup fib_params = {};
- struct ethhdr *eth = data;
- struct ipv6hdr *ip6h;
- struct iphdr *iph;
- __u16 h_proto;
- __u64 nh_off;
- int rc;
- /* default action is to pass */
- int action = XDP_PASS;
-
- nh_off = sizeof(*eth);
- if (data + nh_off > data_end) {
- action = XDP_DROP;
- goto out;
- }
-
- /* determine if this is IP4 or IPv6 by looking at the Ethernet protocol field */
- h_proto = eth->h_proto;
- if (h_proto == bpf_htons(ETH_P_IP)) {
- /* IPv4 part of the code */
- iph = data + nh_off;
-
- if (iph + 1 > data_end) {
- action = XDP_DROP;
- goto out;
- }
- /* as a real router, we need to check the TTL to prevent never ending loops*/
- if (iph->ttl <= 1)
- goto out;
-
- /* populate the fib_params fields to prepare for the lookup */
- fib_params.family = AF_INET;
- fib_params.tos = iph->tos;
- fib_params.l4_protocol = iph->protocol;
- fib_params.sport = 0;
- fib_params.dport = 0;
- fib_params.tot_len = bpf_ntohs(iph->tot_len);
- fib_params.ipv4_src = iph->saddr;
- fib_params.ipv4_dst = iph->daddr;
- } else if (h_proto == bpf_htons(ETH_P_IPV6)) {
- /* IPv6 part of the code */
- struct in6_addr *src = (struct in6_addr *) fib_params.ipv6_src;
- struct in6_addr *dst = (struct in6_addr *) fib_params.ipv6_dst;
-
- ip6h = data + nh_off;
- if (ip6h + 1 > data_end) {
- action = XDP_DROP;
- goto out;
- }
- /* as a real router, we need to check the TTL to prevent never ending loops*/
- if (ip6h->hop_limit <= 1)
- goto out;
-
- /* populate the fib_params fields to prepare for the lookup */
- fib_params.family = AF_INET6;
- fib_params.flowinfo = *(__be32 *) ip6h & IPV6_FLOWINFO_MASK;
- fib_params.l4_protocol = ip6h->nexthdr;
- fib_params.sport = 0;
- fib_params.dport = 0;
- fib_params.tot_len = bpf_ntohs(ip6h->payload_len);
- *src = ip6h->saddr;
- *dst = ip6h->daddr;
- } else {
- goto out;
- }
-
- fib_params.ifindex = ctx->ingress_ifindex;
-
- /* this is where the FIB lookup happens. If the lookup is successful */
- /* it will populate the fib_params.ifindex with the egress interface index */
-
- rc = bpf_fib_lookup(ctx, &fib_params, sizeof(fib_params), 0);
- switch (rc) {
- case BPF_FIB_LKUP_RET_SUCCESS: /* lookup successful */
- /* we are a router, so we need to decrease the ttl */
- if (h_proto == bpf_htons(ETH_P_IP))
- ip_decrease_ttl(iph);
- else if (h_proto == bpf_htons(ETH_P_IPV6))
- ip6h->hop_limit--;
- /* set the correct new source and destionation mac addresses */
- /* can be found in fib_params.dmac and fib_params.smac */
- memcpy(eth->h_dest, fib_params.dmac, ETH_ALEN);
- memcpy(eth->h_source, fib_params.smac, ETH_ALEN);
- /* and done, now we set the action to bpf_redirect_map with fib_params.ifindex which is the egress port as paramater */
- action = bpf_redirect_map(&tx_port, fib_params.ifindex, 0);
- break;
- case BPF_FIB_LKUP_RET_BLACKHOLE: /* dest is blackholed; can be dropped */
- case BPF_FIB_LKUP_RET_UNREACHABLE: /* dest is unreachable; can be dropped */
- case BPF_FIB_LKUP_RET_PROHIBIT: /* dest not allowed; can be dropped */
- action = XDP_DROP;
- break;
- case BPF_FIB_LKUP_RET_NOT_FWDED: /* packet is not forwarded */
- case BPF_FIB_LKUP_RET_FWD_DISABLED: /* fwding is not enabled on ingress */
- case BPF_FIB_LKUP_RET_UNSUPP_LWT: /* fwd requires encapsulation */
- case BPF_FIB_LKUP_RET_NO_NEIGH: /* no neighbor entry for nh */
- case BPF_FIB_LKUP_RET_FRAG_NEEDED: /* fragmentation required to fwd */
- /* PASS */
- break;
- }
-
-out:
- /* and done, update stats and return action */
- return xdp_stats_record_action(ctx, action);
-}
-
-char _license[] SEC("license") = "GPL";