18c2ecf20Sopenharmony_ci/* Copyright (c) 2016 PLUMgrid 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#define KBUILD_MODNAME "foo" 88c2ecf20Sopenharmony_ci#include <uapi/linux/bpf.h> 98c2ecf20Sopenharmony_ci#include <linux/in.h> 108c2ecf20Sopenharmony_ci#include <linux/if_ether.h> 118c2ecf20Sopenharmony_ci#include <linux/if_packet.h> 128c2ecf20Sopenharmony_ci#include <linux/if_vlan.h> 138c2ecf20Sopenharmony_ci#include <linux/ip.h> 148c2ecf20Sopenharmony_ci#include <linux/ipv6.h> 158c2ecf20Sopenharmony_ci#include <bpf/bpf_helpers.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct { 188c2ecf20Sopenharmony_ci __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 198c2ecf20Sopenharmony_ci __type(key, u32); 208c2ecf20Sopenharmony_ci __type(value, long); 218c2ecf20Sopenharmony_ci __uint(max_entries, 256); 228c2ecf20Sopenharmony_ci} rxcnt SEC(".maps"); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic int parse_ipv4(void *data, u64 nh_off, void *data_end) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci struct iphdr *iph = data + nh_off; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci if (iph + 1 > data_end) 298c2ecf20Sopenharmony_ci return 0; 308c2ecf20Sopenharmony_ci return iph->protocol; 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int parse_ipv6(void *data, u64 nh_off, void *data_end) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci struct ipv6hdr *ip6h = data + nh_off; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci if (ip6h + 1 > data_end) 388c2ecf20Sopenharmony_ci return 0; 398c2ecf20Sopenharmony_ci return ip6h->nexthdr; 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ciSEC("xdp1") 438c2ecf20Sopenharmony_ciint xdp_prog1(struct xdp_md *ctx) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci void *data_end = (void *)(long)ctx->data_end; 468c2ecf20Sopenharmony_ci void *data = (void *)(long)ctx->data; 478c2ecf20Sopenharmony_ci struct ethhdr *eth = data; 488c2ecf20Sopenharmony_ci int rc = XDP_DROP; 498c2ecf20Sopenharmony_ci long *value; 508c2ecf20Sopenharmony_ci u16 h_proto; 518c2ecf20Sopenharmony_ci u64 nh_off; 528c2ecf20Sopenharmony_ci u32 ipproto; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci nh_off = sizeof(*eth); 558c2ecf20Sopenharmony_ci if (data + nh_off > data_end) 568c2ecf20Sopenharmony_ci return rc; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci h_proto = eth->h_proto; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { 618c2ecf20Sopenharmony_ci struct vlan_hdr *vhdr; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci vhdr = data + nh_off; 648c2ecf20Sopenharmony_ci nh_off += sizeof(struct vlan_hdr); 658c2ecf20Sopenharmony_ci if (data + nh_off > data_end) 668c2ecf20Sopenharmony_ci return rc; 678c2ecf20Sopenharmony_ci h_proto = vhdr->h_vlan_encapsulated_proto; 688c2ecf20Sopenharmony_ci } 698c2ecf20Sopenharmony_ci if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { 708c2ecf20Sopenharmony_ci struct vlan_hdr *vhdr; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci vhdr = data + nh_off; 738c2ecf20Sopenharmony_ci nh_off += sizeof(struct vlan_hdr); 748c2ecf20Sopenharmony_ci if (data + nh_off > data_end) 758c2ecf20Sopenharmony_ci return rc; 768c2ecf20Sopenharmony_ci h_proto = vhdr->h_vlan_encapsulated_proto; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (h_proto == htons(ETH_P_IP)) 808c2ecf20Sopenharmony_ci ipproto = parse_ipv4(data, nh_off, data_end); 818c2ecf20Sopenharmony_ci else if (h_proto == htons(ETH_P_IPV6)) 828c2ecf20Sopenharmony_ci ipproto = parse_ipv6(data, nh_off, data_end); 838c2ecf20Sopenharmony_ci else 848c2ecf20Sopenharmony_ci ipproto = 0; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci value = bpf_map_lookup_elem(&rxcnt, &ipproto); 878c2ecf20Sopenharmony_ci if (value) 888c2ecf20Sopenharmony_ci *value += 1; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci return rc; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cichar _license[] SEC("license") = "GPL"; 94