Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.20-rc5 139 lines 3.3 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 2 * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc. 3 * 4 * Example howto extract XDP RX-queue info 5 */ 6#include <uapi/linux/bpf.h> 7#include <uapi/linux/if_ether.h> 8#include <uapi/linux/in.h> 9#include "bpf_helpers.h" 10 11/* Config setup from with userspace 12 * 13 * User-side setup ifindex in config_map, to verify that 14 * ctx->ingress_ifindex is correct (against configured ifindex) 15 */ 16struct config { 17 __u32 action; 18 int ifindex; 19 __u32 options; 20}; 21enum cfg_options_flags { 22 NO_TOUCH = 0x0U, 23 READ_MEM = 0x1U, 24 SWAP_MAC = 0x2U, 25}; 26struct bpf_map_def SEC("maps") config_map = { 27 .type = BPF_MAP_TYPE_ARRAY, 28 .key_size = sizeof(int), 29 .value_size = sizeof(struct config), 30 .max_entries = 1, 31}; 32 33/* Common stats data record (shared with userspace) */ 34struct datarec { 35 __u64 processed; 36 __u64 issue; 37}; 38 39struct bpf_map_def SEC("maps") stats_global_map = { 40 .type = BPF_MAP_TYPE_PERCPU_ARRAY, 41 .key_size = sizeof(u32), 42 .value_size = sizeof(struct datarec), 43 .max_entries = 1, 44}; 45 46#define MAX_RXQs 64 47 48/* Stats per rx_queue_index (per CPU) */ 49struct bpf_map_def SEC("maps") rx_queue_index_map = { 50 .type = BPF_MAP_TYPE_PERCPU_ARRAY, 51 .key_size = sizeof(u32), 52 .value_size = sizeof(struct datarec), 53 .max_entries = MAX_RXQs + 1, 54}; 55 56static __always_inline 57void swap_src_dst_mac(void *data) 58{ 59 unsigned short *p = data; 60 unsigned short dst[3]; 61 62 dst[0] = p[0]; 63 dst[1] = p[1]; 64 dst[2] = p[2]; 65 p[0] = p[3]; 66 p[1] = p[4]; 67 p[2] = p[5]; 68 p[3] = dst[0]; 69 p[4] = dst[1]; 70 p[5] = dst[2]; 71} 72 73SEC("xdp_prog0") 74int xdp_prognum0(struct xdp_md *ctx) 75{ 76 void *data_end = (void *)(long)ctx->data_end; 77 void *data = (void *)(long)ctx->data; 78 struct datarec *rec, *rxq_rec; 79 int ingress_ifindex; 80 struct config *config; 81 u32 key = 0; 82 83 /* Global stats record */ 84 rec = bpf_map_lookup_elem(&stats_global_map, &key); 85 if (!rec) 86 return XDP_ABORTED; 87 rec->processed++; 88 89 /* Accessing ctx->ingress_ifindex, cause BPF to rewrite BPF 90 * instructions inside kernel to access xdp_rxq->dev->ifindex 91 */ 92 ingress_ifindex = ctx->ingress_ifindex; 93 94 config = bpf_map_lookup_elem(&config_map, &key); 95 if (!config) 96 return XDP_ABORTED; 97 98 /* Simple test: check ctx provided ifindex is as expected */ 99 if (ingress_ifindex != config->ifindex) { 100 /* count this error case */ 101 rec->issue++; 102 return XDP_ABORTED; 103 } 104 105 /* Update stats per rx_queue_index. Handle if rx_queue_index 106 * is larger than stats map can contain info for. 107 */ 108 key = ctx->rx_queue_index; 109 if (key >= MAX_RXQs) 110 key = MAX_RXQs; 111 rxq_rec = bpf_map_lookup_elem(&rx_queue_index_map, &key); 112 if (!rxq_rec) 113 return XDP_ABORTED; 114 rxq_rec->processed++; 115 if (key == MAX_RXQs) 116 rxq_rec->issue++; 117 118 /* Default: Don't touch packet data, only count packets */ 119 if (unlikely(config->options & (READ_MEM|SWAP_MAC))) { 120 struct ethhdr *eth = data; 121 122 if (eth + 1 > data_end) 123 return XDP_ABORTED; 124 125 /* Avoid compiler removing this: Drop non 802.3 Ethertypes */ 126 if (ntohs(eth->h_proto) < ETH_P_802_3_MIN) 127 return XDP_ABORTED; 128 129 /* XDP_TX requires changing MAC-addrs, else HW may drop. 130 * Can also be enabled with --swapmac (for test purposes) 131 */ 132 if (unlikely(config->options & SWAP_MAC)) 133 swap_src_dst_mac(data); 134 } 135 136 return config->action; 137} 138 139char _license[] SEC("license") = "GPL";