linux/samples/bpf/xdp_redirect_kern.c
<<
>>
Prefs
   1/* Copyright (c) 2016 John Fastabend <john.r.fastabend@intel.com>
   2 *
   3 * This program is free software; you can redistribute it and/or
   4 * modify it under the terms of version 2 of the GNU General Public
   5 * License as published by the Free Software Foundation.
   6 *
   7 * This program is distributed in the hope that it will be useful, but
   8 * WITHOUT ANY WARRANTY; without even the implied warranty of
   9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10 * General Public License for more details.
  11 */
  12#define KBUILD_MODNAME "foo"
  13#include <uapi/linux/bpf.h>
  14#include <linux/in.h>
  15#include <linux/if_ether.h>
  16#include <linux/if_packet.h>
  17#include <linux/if_vlan.h>
  18#include <linux/ip.h>
  19#include <linux/ipv6.h>
  20#include "bpf_helpers.h"
  21
  22struct bpf_map_def SEC("maps") tx_port = {
  23        .type = BPF_MAP_TYPE_ARRAY,
  24        .key_size = sizeof(int),
  25        .value_size = sizeof(int),
  26        .max_entries = 1,
  27};
  28
  29/* Count RX packets, as XDP bpf_prog doesn't get direct TX-success
  30 * feedback.  Redirect TX errors can be caught via a tracepoint.
  31 */
  32struct bpf_map_def SEC("maps") rxcnt = {
  33        .type = BPF_MAP_TYPE_PERCPU_ARRAY,
  34        .key_size = sizeof(u32),
  35        .value_size = sizeof(long),
  36        .max_entries = 1,
  37};
  38
  39static void swap_src_dst_mac(void *data)
  40{
  41        unsigned short *p = data;
  42        unsigned short dst[3];
  43
  44        dst[0] = p[0];
  45        dst[1] = p[1];
  46        dst[2] = p[2];
  47        p[0] = p[3];
  48        p[1] = p[4];
  49        p[2] = p[5];
  50        p[3] = dst[0];
  51        p[4] = dst[1];
  52        p[5] = dst[2];
  53}
  54
  55SEC("xdp_redirect")
  56int xdp_redirect_prog(struct xdp_md *ctx)
  57{
  58        void *data_end = (void *)(long)ctx->data_end;
  59        void *data = (void *)(long)ctx->data;
  60        struct ethhdr *eth = data;
  61        int rc = XDP_DROP;
  62        int *ifindex, port = 0;
  63        long *value;
  64        u32 key = 0;
  65        u64 nh_off;
  66
  67        nh_off = sizeof(*eth);
  68        if (data + nh_off > data_end)
  69                return rc;
  70
  71        ifindex = bpf_map_lookup_elem(&tx_port, &port);
  72        if (!ifindex)
  73                return rc;
  74
  75        value = bpf_map_lookup_elem(&rxcnt, &key);
  76        if (value)
  77                *value += 1;
  78
  79        swap_src_dst_mac(data);
  80        return bpf_redirect(*ifindex, 0);
  81}
  82
  83/* Redirect require an XDP bpf_prog loaded on the TX device */
  84SEC("xdp_redirect_dummy")
  85int xdp_redirect_dummy_prog(struct xdp_md *ctx)
  86{
  87        return XDP_PASS;
  88}
  89
  90char _license[] SEC("license") = "GPL";
  91