18c2ecf20Sopenharmony_ci/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch> 28c2ecf20Sopenharmony_ci * 38c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or 48c2ecf20Sopenharmony_ci * modify it under the terms of version 2 of the GNU General Public 58c2ecf20Sopenharmony_ci * License as published by the Free Software Foundation. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 88c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 98c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 108c2ecf20Sopenharmony_ci * General Public License for more details. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <uapi/linux/bpf.h> 148c2ecf20Sopenharmony_ci#include <uapi/linux/if_ether.h> 158c2ecf20Sopenharmony_ci#include <uapi/linux/ip.h> 168c2ecf20Sopenharmony_ci#include <uapi/linux/in.h> 178c2ecf20Sopenharmony_ci#include <bpf/bpf_helpers.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci# define printk(fmt, ...) \ 208c2ecf20Sopenharmony_ci ({ \ 218c2ecf20Sopenharmony_ci char ____fmt[] = fmt; \ 228c2ecf20Sopenharmony_ci bpf_trace_printk(____fmt, sizeof(____fmt), \ 238c2ecf20Sopenharmony_ci ##__VA_ARGS__); \ 248c2ecf20Sopenharmony_ci }) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistruct bpf_elf_map { 278c2ecf20Sopenharmony_ci __u32 type; 288c2ecf20Sopenharmony_ci __u32 size_key; 298c2ecf20Sopenharmony_ci __u32 size_value; 308c2ecf20Sopenharmony_ci __u32 max_elem; 318c2ecf20Sopenharmony_ci __u32 flags; 328c2ecf20Sopenharmony_ci __u32 id; 338c2ecf20Sopenharmony_ci __u32 pinning; 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistruct bpf_elf_map SEC("maps") lwt_len_hist_map = { 378c2ecf20Sopenharmony_ci .type = BPF_MAP_TYPE_PERCPU_HASH, 388c2ecf20Sopenharmony_ci .size_key = sizeof(__u64), 398c2ecf20Sopenharmony_ci .size_value = sizeof(__u64), 408c2ecf20Sopenharmony_ci .pinning = 2, 418c2ecf20Sopenharmony_ci .max_elem = 1024, 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic unsigned int log2(unsigned int v) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci unsigned int r; 478c2ecf20Sopenharmony_ci unsigned int shift; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci r = (v > 0xFFFF) << 4; v >>= r; 508c2ecf20Sopenharmony_ci shift = (v > 0xFF) << 3; v >>= shift; r |= shift; 518c2ecf20Sopenharmony_ci shift = (v > 0xF) << 2; v >>= shift; r |= shift; 528c2ecf20Sopenharmony_ci shift = (v > 0x3) << 1; v >>= shift; r |= shift; 538c2ecf20Sopenharmony_ci r |= (v >> 1); 548c2ecf20Sopenharmony_ci return r; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic unsigned int log2l(unsigned long v) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci unsigned int hi = v >> 32; 608c2ecf20Sopenharmony_ci if (hi) 618c2ecf20Sopenharmony_ci return log2(hi) + 32; 628c2ecf20Sopenharmony_ci else 638c2ecf20Sopenharmony_ci return log2(v); 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciSEC("len_hist") 678c2ecf20Sopenharmony_ciint do_len_hist(struct __sk_buff *skb) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci __u64 *value, key, init_val = 1; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci key = log2l(skb->len); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci value = bpf_map_lookup_elem(&lwt_len_hist_map, &key); 748c2ecf20Sopenharmony_ci if (value) 758c2ecf20Sopenharmony_ci __sync_fetch_and_add(value, 1); 768c2ecf20Sopenharmony_ci else 778c2ecf20Sopenharmony_ci bpf_map_update_elem(&lwt_len_hist_map, &key, &init_val, BPF_ANY); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci return BPF_OK; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cichar _license[] SEC("license") = "GPL"; 83