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/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