cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xdp_router_ipv4.bpf.c (3886B)


      1/* Copyright (C) 2017 Cavium, Inc.
      2 *
      3 * This program is free software; you can redistribute it and/or modify it
      4 * under the terms of version 2 of the GNU General Public License
      5 * as published by the Free Software Foundation.
      6 */
      7
      8#include "vmlinux.h"
      9#include "xdp_sample.bpf.h"
     10#include "xdp_sample_shared.h"
     11
     12#define ETH_ALEN	6
     13#define ETH_P_8021Q	0x8100
     14#define ETH_P_8021AD	0x88A8
     15
     16struct trie_value {
     17	__u8 prefix[4];
     18	__be64 value;
     19	int ifindex;
     20	int metric;
     21	__be32 gw;
     22};
     23
     24/* Key for lpm_trie */
     25union key_4 {
     26	u32 b32[2];
     27	u8 b8[8];
     28};
     29
     30struct arp_entry {
     31	__be64 mac;
     32	__be32 dst;
     33};
     34
     35struct direct_map {
     36	struct arp_entry arp;
     37	int ifindex;
     38	__be64 mac;
     39};
     40
     41/* Map for trie implementation */
     42struct {
     43	__uint(type, BPF_MAP_TYPE_LPM_TRIE);
     44	__uint(key_size, 8);
     45	__uint(value_size, sizeof(struct trie_value));
     46	__uint(max_entries, 50);
     47	__uint(map_flags, BPF_F_NO_PREALLOC);
     48} lpm_map SEC(".maps");
     49
     50/* Map for ARP table */
     51struct {
     52	__uint(type, BPF_MAP_TYPE_HASH);
     53	__type(key, __be32);
     54	__type(value, __be64);
     55	__uint(max_entries, 50);
     56} arp_table SEC(".maps");
     57
     58/* Map to keep the exact match entries in the route table */
     59struct {
     60	__uint(type, BPF_MAP_TYPE_HASH);
     61	__type(key, __be32);
     62	__type(value, struct direct_map);
     63	__uint(max_entries, 50);
     64} exact_match SEC(".maps");
     65
     66struct {
     67	__uint(type, BPF_MAP_TYPE_DEVMAP);
     68	__uint(key_size, sizeof(int));
     69	__uint(value_size, sizeof(int));
     70	__uint(max_entries, 100);
     71} tx_port SEC(".maps");
     72
     73SEC("xdp")
     74int xdp_router_ipv4_prog(struct xdp_md *ctx)
     75{
     76	void *data_end = (void *)(long)ctx->data_end;
     77	void *data = (void *)(long)ctx->data;
     78	struct ethhdr *eth = data;
     79	u64 nh_off = sizeof(*eth);
     80	struct datarec *rec;
     81	__be16 h_proto;
     82	u32 key = 0;
     83
     84	rec = bpf_map_lookup_elem(&rx_cnt, &key);
     85	if (rec)
     86		NO_TEAR_INC(rec->processed);
     87
     88	if (data + nh_off > data_end)
     89		goto drop;
     90
     91	h_proto = eth->h_proto;
     92	if (h_proto == bpf_htons(ETH_P_8021Q) ||
     93	    h_proto == bpf_htons(ETH_P_8021AD)) {
     94		struct vlan_hdr *vhdr;
     95
     96		vhdr = data + nh_off;
     97		nh_off += sizeof(struct vlan_hdr);
     98		if (data + nh_off > data_end)
     99			goto drop;
    100
    101		h_proto = vhdr->h_vlan_encapsulated_proto;
    102	}
    103
    104	switch (bpf_ntohs(h_proto)) {
    105	case ETH_P_ARP:
    106		if (rec)
    107			NO_TEAR_INC(rec->xdp_pass);
    108		return XDP_PASS;
    109	case ETH_P_IP: {
    110		struct iphdr *iph = data + nh_off;
    111		struct direct_map *direct_entry;
    112		__be64 *dest_mac, *src_mac;
    113		int forward_to;
    114
    115		if (iph + 1 > data_end)
    116			goto drop;
    117
    118		direct_entry = bpf_map_lookup_elem(&exact_match, &iph->daddr);
    119
    120		/* Check for exact match, this would give a faster lookup */
    121		if (direct_entry && direct_entry->mac &&
    122		    direct_entry->arp.mac) {
    123			src_mac = &direct_entry->mac;
    124			dest_mac = &direct_entry->arp.mac;
    125			forward_to = direct_entry->ifindex;
    126		} else {
    127			struct trie_value *prefix_value;
    128			union key_4 key4;
    129
    130			/* Look up in the trie for lpm */
    131			key4.b32[0] = 32;
    132			key4.b8[4] = iph->daddr & 0xff;
    133			key4.b8[5] = (iph->daddr >> 8) & 0xff;
    134			key4.b8[6] = (iph->daddr >> 16) & 0xff;
    135			key4.b8[7] = (iph->daddr >> 24) & 0xff;
    136
    137			prefix_value = bpf_map_lookup_elem(&lpm_map, &key4);
    138			if (!prefix_value)
    139				goto drop;
    140
    141			forward_to = prefix_value->ifindex;
    142			src_mac = &prefix_value->value;
    143			if (!src_mac)
    144				goto drop;
    145
    146			dest_mac = bpf_map_lookup_elem(&arp_table, &iph->daddr);
    147			if (!dest_mac) {
    148				if (!prefix_value->gw)
    149					goto drop;
    150
    151				dest_mac = bpf_map_lookup_elem(&arp_table,
    152							       &prefix_value->gw);
    153			}
    154		}
    155
    156		if (src_mac && dest_mac) {
    157			int ret;
    158
    159			__builtin_memcpy(eth->h_dest, dest_mac, ETH_ALEN);
    160			__builtin_memcpy(eth->h_source, src_mac, ETH_ALEN);
    161
    162			ret = bpf_redirect_map(&tx_port, forward_to, 0);
    163			if (ret == XDP_REDIRECT) {
    164				if (rec)
    165					NO_TEAR_INC(rec->xdp_redirect);
    166				return ret;
    167			}
    168		}
    169	}
    170	default:
    171		break;
    172	}
    173drop:
    174	if (rec)
    175		NO_TEAR_INC(rec->xdp_drop);
    176
    177	return XDP_DROP;
    178}
    179
    180char _license[] SEC("license") = "GPL";