// Copyright (c) PLUMgrid, Inc. // Licensed under the Apache License, Version 2.0 (the "License") #include struct config { int tunnel_ifindex; }; BPF_HASH(conf, int, struct config, 1); struct tunnel_key { u32 tunnel_id; u32 remote_ipv4; }; BPF_HASH(tunkey2if, struct tunnel_key, int, 1024); BPF_HASH(if2tunkey, int, struct tunnel_key, 1024); // Handle packets from the encap device, demux into the dest tenant int handle_ingress(struct __sk_buff *skb) { struct bpf_tunnel_key tkey = {}; struct tunnel_key key; bpf_skb_get_tunnel_key(skb, &tkey, offsetof(struct bpf_tunnel_key, remote_ipv6[1]), 0); key.tunnel_id = tkey.tunnel_id; key.remote_ipv4 = tkey.remote_ipv4; int *ifindex = tunkey2if.lookup(&key); if (ifindex) { //bpf_trace_printk("ingress tunnel_id=%d remote_ip=%08x ifindex=%d\n", // key.tunnel_id, key.remote_ipv4, *ifindex); // mark from external skb->tc_index = 1; bpf_clone_redirect(skb, *ifindex, 1/*ingress*/); } else { bpf_trace_printk("ingress invalid tunnel_id=%d\n", key.tunnel_id); } return 1; } // Handle packets from the tenant, mux into the encap device int handle_egress(struct __sk_buff *skb) { int ifindex = skb->ifindex; struct bpf_tunnel_key tkey = {}; struct tunnel_key *key_p; int one = 1; struct config *cfg = conf.lookup(&one); if (!cfg) return 1; if (skb->tc_index) { //bpf_trace_printk("from external\n"); // don't send it back out to encap device return 1; } key_p = if2tunkey.lookup(&ifindex); if (key_p) { tkey.tunnel_id = key_p->tunnel_id; tkey.remote_ipv4 = key_p->remote_ipv4; bpf_skb_set_tunnel_key(skb, &tkey, offsetof(struct bpf_tunnel_key, remote_ipv6[1]), 0); bpf_clone_redirect(skb, cfg->tunnel_ifindex, 0/*egress*/); } return 1; }