linux/samples/bpf/lwt_len_hist_kern.c
<<
>>
Prefs
   1/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
   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
  13#include <uapi/linux/bpf.h>
  14#include <uapi/linux/if_ether.h>
  15#include <uapi/linux/ip.h>
  16#include <uapi/linux/in.h>
  17#include "bpf_helpers.h"
  18
  19# define printk(fmt, ...)                                               \
  20                ({                                                      \
  21                        char ____fmt[] = fmt;                           \
  22                        bpf_trace_printk(____fmt, sizeof(____fmt),      \
  23                                     ##__VA_ARGS__);                    \
  24                })
  25
  26struct bpf_elf_map {
  27        __u32 type;
  28        __u32 size_key;
  29        __u32 size_value;
  30        __u32 max_elem;
  31        __u32 flags;
  32        __u32 id;
  33        __u32 pinning;
  34};
  35
  36struct bpf_elf_map SEC("maps") lwt_len_hist_map = {
  37        .type = BPF_MAP_TYPE_PERCPU_HASH,
  38        .size_key = sizeof(__u64),
  39        .size_value = sizeof(__u64),
  40        .pinning = 2,
  41        .max_elem = 1024,
  42};
  43
  44static unsigned int log2(unsigned int v)
  45{
  46        unsigned int r;
  47        unsigned int shift;
  48
  49        r = (v > 0xFFFF) << 4; v >>= r;
  50        shift = (v > 0xFF) << 3; v >>= shift; r |= shift;
  51        shift = (v > 0xF) << 2; v >>= shift; r |= shift;
  52        shift = (v > 0x3) << 1; v >>= shift; r |= shift;
  53        r |= (v >> 1);
  54        return r;
  55}
  56
  57static unsigned int log2l(unsigned long v)
  58{
  59        unsigned int hi = v >> 32;
  60        if (hi)
  61                return log2(hi) + 32;
  62        else
  63                return log2(v);
  64}
  65
  66SEC("len_hist")
  67int do_len_hist(struct __sk_buff *skb)
  68{
  69        __u64 *value, key, init_val = 1;
  70
  71        key = log2l(skb->len);
  72
  73        value = bpf_map_lookup_elem(&lwt_len_hist_map, &key);
  74        if (value)
  75                __sync_fetch_and_add(value, 1);
  76        else
  77                bpf_map_update_elem(&lwt_len_hist_map, &key, &init_val, BPF_ANY);
  78
  79        return BPF_OK;
  80}
  81
  82char _license[] SEC("license") = "GPL";
  83