root/samples/bpf/xdp_rxq_info_kern.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. swap_src_dst_mac
  2. SEC

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

/* [<][>][^][v][top][bottom][index][help] */