Merge tag 'fbdev-v4.17' of git://github.com/bzolnier/linux
[sfrench/cifs-2.6.git] / samples / bpf / xdp_rxq_info_kern.c
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 "bpf_helpers.h"
8
9 /* Config setup from with userspace
10  *
11  * User-side setup ifindex in config_map, to verify that
12  * ctx->ingress_ifindex is correct (against configured ifindex)
13  */
14 struct config {
15         __u32 action;
16         int ifindex;
17 };
18 struct bpf_map_def SEC("maps") config_map = {
19         .type           = BPF_MAP_TYPE_ARRAY,
20         .key_size       = sizeof(int),
21         .value_size     = sizeof(struct config),
22         .max_entries    = 1,
23 };
24
25 /* Common stats data record (shared with userspace) */
26 struct datarec {
27         __u64 processed;
28         __u64 issue;
29 };
30
31 struct bpf_map_def SEC("maps") stats_global_map = {
32         .type           = BPF_MAP_TYPE_PERCPU_ARRAY,
33         .key_size       = sizeof(u32),
34         .value_size     = sizeof(struct datarec),
35         .max_entries    = 1,
36 };
37
38 #define MAX_RXQs 64
39
40 /* Stats per rx_queue_index (per CPU) */
41 struct bpf_map_def SEC("maps") rx_queue_index_map = {
42         .type           = BPF_MAP_TYPE_PERCPU_ARRAY,
43         .key_size       = sizeof(u32),
44         .value_size     = sizeof(struct datarec),
45         .max_entries    = MAX_RXQs + 1,
46 };
47
48 SEC("xdp_prog0")
49 int  xdp_prognum0(struct xdp_md *ctx)
50 {
51         void *data_end = (void *)(long)ctx->data_end;
52         void *data     = (void *)(long)ctx->data;
53         struct datarec *rec, *rxq_rec;
54         int ingress_ifindex;
55         struct config *config;
56         u32 key = 0;
57
58         /* Global stats record */
59         rec = bpf_map_lookup_elem(&stats_global_map, &key);
60         if (!rec)
61                 return XDP_ABORTED;
62         rec->processed++;
63
64         /* Accessing ctx->ingress_ifindex, cause BPF to rewrite BPF
65          * instructions inside kernel to access xdp_rxq->dev->ifindex
66          */
67         ingress_ifindex = ctx->ingress_ifindex;
68
69         config = bpf_map_lookup_elem(&config_map, &key);
70         if (!config)
71                 return XDP_ABORTED;
72
73         /* Simple test: check ctx provided ifindex is as expected */
74         if (ingress_ifindex != config->ifindex) {
75                 /* count this error case */
76                 rec->issue++;
77                 return XDP_ABORTED;
78         }
79
80         /* Update stats per rx_queue_index. Handle if rx_queue_index
81          * is larger than stats map can contain info for.
82          */
83         key = ctx->rx_queue_index;
84         if (key >= MAX_RXQs)
85                 key = MAX_RXQs;
86         rxq_rec = bpf_map_lookup_elem(&rx_queue_index_map, &key);
87         if (!rxq_rec)
88                 return XDP_ABORTED;
89         rxq_rec->processed++;
90         if (key == MAX_RXQs)
91                 rxq_rec->issue++;
92
93         return config->action;
94 }
95
96 char _license[] SEC("license") = "GPL";