|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | +/* Copyright (c) 2022 Freysteinn Alfredsson <[email protected]> */ |
| 3 | + |
| 4 | +#include <vmlinux_local.h> |
| 5 | +#include <linux/bpf.h> |
| 6 | +#include <bpf/bpf_endian.h> |
| 7 | +#include <bpf/bpf_helpers.h> |
| 8 | +#include <xdp/parsing_helpers.h> |
| 9 | + |
| 10 | +#include "bpf_local_helpers.h" |
| 11 | + |
| 12 | +struct { |
| 13 | + __uint(type, BPF_MAP_TYPE_PIFO); |
| 14 | + __uint(key_size, sizeof(__u32)); |
| 15 | + __uint(value_size, sizeof(__u32)); |
| 16 | + __uint(max_entries, 1024); |
| 17 | +} pifo_map SEC(".maps"); |
| 18 | + |
| 19 | + |
| 20 | +/* Simple PIFO strict priority */ |
| 21 | +SEC("xdp") |
| 22 | +int enqueue_prog(struct xdp_md *xdp) |
| 23 | +{ |
| 24 | + void *data_end = (void *)(long)xdp->data_end; |
| 25 | + void *data = (void *)(long)xdp->data; |
| 26 | + struct hdr_cursor nh = { .pos = data }; |
| 27 | + struct ethhdr *eth; |
| 28 | + int eth_type; |
| 29 | + struct iphdr *iphdr; |
| 30 | + struct ipv6hdr *ipv6hdr; |
| 31 | + int ip_type; |
| 32 | + struct udphdr *udphdr; |
| 33 | + int udp_dst_port; |
| 34 | + __u16 prio = 0; |
| 35 | + |
| 36 | + /* Parse Ethernet and IP/IPv6 headers */ |
| 37 | + eth_type = parse_ethhdr(&nh, data_end, ð); |
| 38 | + if (eth_type == bpf_htons(ETH_P_IP)) { |
| 39 | + ip_type = parse_iphdr(&nh, data_end, &iphdr); |
| 40 | + if (ip_type != IPPROTO_UDP) |
| 41 | + goto err; |
| 42 | + } else if (eth_type == bpf_htons(ETH_P_IPV6)) { |
| 43 | + ip_type = parse_ip6hdr(&nh, data_end, &ipv6hdr); |
| 44 | + if (ip_type != IPPROTO_UDP) |
| 45 | + goto err; |
| 46 | + } else { |
| 47 | + goto err; |
| 48 | + } |
| 49 | + |
| 50 | + /* Parse UDP header */ |
| 51 | + if (parse_udphdr(&nh, data_end, &udphdr) < 0) |
| 52 | + goto err; |
| 53 | + udp_dst_port = bpf_htons(udphdr->dest); |
| 54 | + |
| 55 | + /* Calculate scheduling priority */ |
| 56 | + prio = 0; |
| 57 | + if (udp_dst_port == 8001) |
| 58 | + prio = 1; |
| 59 | + else if (udp_dst_port > 8001) |
| 60 | + prio = 2; |
| 61 | + |
| 62 | + |
| 63 | + bpf_printk("XDP PIFO scheduled with priority %d", prio); |
| 64 | + return bpf_redirect_map(&pifo_map, prio, 0); |
| 65 | +err: |
| 66 | + bpf_printk("XDP PIFO failed"); |
| 67 | + return XDP_DROP; |
| 68 | +} |
| 69 | + |
| 70 | +SEC("dequeue") |
| 71 | +void *dequeue_prog(struct dequeue_ctx *ctx) |
| 72 | +{ |
| 73 | + __u64 prio = 0; |
| 74 | + void *pkt = (void *) bpf_packet_dequeue(ctx, &pifo_map, 0, &prio); |
| 75 | + if (!pkt) |
| 76 | + return 0; |
| 77 | + return pkt; |
| 78 | +} |
| 79 | + |
| 80 | +char _license[] SEC("license") = "GPL"; |
0 commit comments