162306a36Sopenharmony_ci/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or
462306a36Sopenharmony_ci * modify it under the terms of version 2 of the GNU General Public
562306a36Sopenharmony_ci * License as published by the Free Software Foundation.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * This program is distributed in the hope that it will be useful, but
862306a36Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
962306a36Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1062306a36Sopenharmony_ci * General Public License for more details.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "vmlinux.h"
1462306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistruct {
1762306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
1862306a36Sopenharmony_ci	__type(key, u64);
1962306a36Sopenharmony_ci	__type(value, u64);
2062306a36Sopenharmony_ci	__uint(pinning, LIBBPF_PIN_BY_NAME);
2162306a36Sopenharmony_ci	__uint(max_entries, 1024);
2262306a36Sopenharmony_ci} lwt_len_hist_map SEC(".maps");
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistatic unsigned int log2(unsigned int v)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	unsigned int r;
2762306a36Sopenharmony_ci	unsigned int shift;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	r = (v > 0xFFFF) << 4; v >>= r;
3062306a36Sopenharmony_ci	shift = (v > 0xFF) << 3; v >>= shift; r |= shift;
3162306a36Sopenharmony_ci	shift = (v > 0xF) << 2; v >>= shift; r |= shift;
3262306a36Sopenharmony_ci	shift = (v > 0x3) << 1; v >>= shift; r |= shift;
3362306a36Sopenharmony_ci	r |= (v >> 1);
3462306a36Sopenharmony_ci	return r;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic unsigned int log2l(unsigned long v)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	unsigned int hi = v >> 32;
4062306a36Sopenharmony_ci	if (hi)
4162306a36Sopenharmony_ci		return log2(hi) + 32;
4262306a36Sopenharmony_ci	else
4362306a36Sopenharmony_ci		return log2(v);
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ciSEC("len_hist")
4762306a36Sopenharmony_ciint do_len_hist(struct __sk_buff *skb)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	__u64 *value, key, init_val = 1;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	key = log2l(skb->len);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	value = bpf_map_lookup_elem(&lwt_len_hist_map, &key);
5462306a36Sopenharmony_ci	if (value)
5562306a36Sopenharmony_ci		__sync_fetch_and_add(value, 1);
5662306a36Sopenharmony_ci	else
5762306a36Sopenharmony_ci		bpf_map_update_elem(&lwt_len_hist_map, &key, &init_val, BPF_ANY);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	return BPF_OK;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cichar _license[] SEC("license") = "GPL";
63