bpf/flow.c (47 lines of code) (raw):

#include <vmlinux.h> #include <bpf_helpers.h> #include <bpf_tracing.h> #include <bpf_core_read.h> #include <inspector.h> #include <feature-switch.h> #define TC_ACT_OK 0 //todo aggregate all flow based metrics in one map to save memory. struct flow_metrics { u64 packets; u64 bytes; u32 drops; u32 retrans; }; struct { __uint(type, BPF_MAP_TYPE_LRU_PERCPU_HASH); __type(key, struct flow_tuple_4); __type(value, struct flow_metrics); __uint(max_entries, 65535); } insp_flow4_metrics SEC(".maps"); FEATURE_SWITCH(flow) static inline int __do_flow(struct __sk_buff *skb){ struct flow_tuple_4 tuple = {0}; int flow_port_key = 0; bool enable_flow_port = is_enable(flow_port_key); if(set_flow_tuple4(skb, &tuple, enable_flow_port) < 0){ goto out; } struct flow_metrics *metric = bpf_map_lookup_elem(&insp_flow4_metrics, &tuple); if(metric){ __sync_fetch_and_add(&metric->packets, 1); __sync_fetch_and_add(&metric->bytes, skb->len); }else { struct flow_metrics m = {1, skb->len, 0, 0}; bpf_map_update_elem(&insp_flow4_metrics, &tuple, &m, BPF_ANY); } out: return TC_ACT_OK; } SEC("tc/ingress") int tc_ingress(struct __sk_buff *skb){ return __do_flow(skb); } SEC("tc/egress") int tc_egress(struct __sk_buff *skb){ return __do_flow(skb); } char LICENSE[] SEC("license") = "Dual BSD/GPL";