root/samples/bpf/xdp2_kern.c

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

DEFINITIONS

This source file includes following definitions.
  1. swap_src_dst_mac
  2. parse_ipv4
  3. parse_ipv6
  4. SEC

   1 /* Copyright (c) 2016 PLUMgrid
   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 #define KBUILD_MODNAME "foo"
   8 #include <uapi/linux/bpf.h>
   9 #include <linux/in.h>
  10 #include <linux/if_ether.h>
  11 #include <linux/if_packet.h>
  12 #include <linux/if_vlan.h>
  13 #include <linux/ip.h>
  14 #include <linux/ipv6.h>
  15 #include "bpf_helpers.h"
  16 
  17 struct {
  18         __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  19         __type(key, u32);
  20         __type(value, long);
  21         __uint(max_entries, 256);
  22 } rxcnt SEC(".maps");
  23 
  24 static void swap_src_dst_mac(void *data)
  25 {
  26         unsigned short *p = data;
  27         unsigned short dst[3];
  28 
  29         dst[0] = p[0];
  30         dst[1] = p[1];
  31         dst[2] = p[2];
  32         p[0] = p[3];
  33         p[1] = p[4];
  34         p[2] = p[5];
  35         p[3] = dst[0];
  36         p[4] = dst[1];
  37         p[5] = dst[2];
  38 }
  39 
  40 static int parse_ipv4(void *data, u64 nh_off, void *data_end)
  41 {
  42         struct iphdr *iph = data + nh_off;
  43 
  44         if (iph + 1 > data_end)
  45                 return 0;
  46         return iph->protocol;
  47 }
  48 
  49 static int parse_ipv6(void *data, u64 nh_off, void *data_end)
  50 {
  51         struct ipv6hdr *ip6h = data + nh_off;
  52 
  53         if (ip6h + 1 > data_end)
  54                 return 0;
  55         return ip6h->nexthdr;
  56 }
  57 
  58 SEC("xdp1")
  59 int xdp_prog1(struct xdp_md *ctx)
  60 {
  61         void *data_end = (void *)(long)ctx->data_end;
  62         void *data = (void *)(long)ctx->data;
  63         struct ethhdr *eth = data;
  64         int rc = XDP_DROP;
  65         long *value;
  66         u16 h_proto;
  67         u64 nh_off;
  68         u32 ipproto;
  69 
  70         nh_off = sizeof(*eth);
  71         if (data + nh_off > data_end)
  72                 return rc;
  73 
  74         h_proto = eth->h_proto;
  75 
  76         if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
  77                 struct vlan_hdr *vhdr;
  78 
  79                 vhdr = data + nh_off;
  80                 nh_off += sizeof(struct vlan_hdr);
  81                 if (data + nh_off > data_end)
  82                         return rc;
  83                 h_proto = vhdr->h_vlan_encapsulated_proto;
  84         }
  85         if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
  86                 struct vlan_hdr *vhdr;
  87 
  88                 vhdr = data + nh_off;
  89                 nh_off += sizeof(struct vlan_hdr);
  90                 if (data + nh_off > data_end)
  91                         return rc;
  92                 h_proto = vhdr->h_vlan_encapsulated_proto;
  93         }
  94 
  95         if (h_proto == htons(ETH_P_IP))
  96                 ipproto = parse_ipv4(data, nh_off, data_end);
  97         else if (h_proto == htons(ETH_P_IPV6))
  98                 ipproto = parse_ipv6(data, nh_off, data_end);
  99         else
 100                 ipproto = 0;
 101 
 102         value = bpf_map_lookup_elem(&rxcnt, &ipproto);
 103         if (value)
 104                 *value += 1;
 105 
 106         if (ipproto == IPPROTO_UDP) {
 107                 swap_src_dst_mac(data);
 108                 rc = XDP_TX;
 109         }
 110 
 111         return rc;
 112 }
 113 
 114 char _license[] SEC("license") = "GPL";

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