xref: /aosp_15_r20/external/bcc/examples/networking/distributed_bridge/tunnel.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1 // Copyright (c) PLUMgrid, Inc.
2 // Licensed under the Apache License, Version 2.0 (the "License")
3 #include <bcc/proto.h>
4 
5 BPF_HASH(vni2if, u32, int, 1024);
6 
7 struct vni_key {
8   u64 mac;
9   int ifindex;
10   int pad;
11 };
12 struct host {
13   u32 tunnel_id;
14   u32 remote_ipv4;
15   u64 rx_pkts;
16   u64 tx_pkts;
17 };
18 BPF_HASH(mac2host, struct vni_key, struct host);
19 
20 struct config {
21   int tunnel_ifindex;
22 };
23 BPF_HASH(conf, int, struct config, 1);
24 
25 // Handle packets from the encap device, demux into the dest tenant
handle_ingress(struct __sk_buff * skb)26 int handle_ingress(struct __sk_buff *skb) {
27   u8 *cursor = 0;
28 
29   struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
30 
31   struct bpf_tunnel_key tkey = {};
32   bpf_skb_get_tunnel_key(skb, &tkey,
33       offsetof(struct bpf_tunnel_key, remote_ipv6[1]), 0);
34 
35   int *ifindex = vni2if.lookup(&tkey.tunnel_id);
36   if (ifindex) {
37     //bpf_trace_printk("ingress tunnel_id=%d ifindex=%d\n", tkey.tunnel_id, *ifindex);
38     struct vni_key vk = {ethernet->src, *ifindex, 0};
39     struct host *src_host = mac2host.lookup_or_try_init(&vk,
40         &(struct host){tkey.tunnel_id, tkey.remote_ipv4, 0, 0});
41     if (src_host) {
42       lock_xadd(&src_host->rx_pkts, 1);
43     }
44     bpf_clone_redirect(skb, *ifindex, 1/*ingress*/);
45   } else {
46     bpf_trace_printk("ingress invalid tunnel_id=%d\n", tkey.tunnel_id);
47   }
48 
49   return 1;
50 }
51 
52 // Handle packets from the tenant, mux into the encap device
handle_egress(struct __sk_buff * skb)53 int handle_egress(struct __sk_buff *skb) {
54   u8 *cursor = 0;
55 
56   int one = 1;
57   struct config *cfg = conf.lookup(&one);
58   if (!cfg) return 1;
59 
60   struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
61 
62   struct vni_key vk = {ethernet->dst, skb->ifindex, 0};
63   struct host *dst_host = mac2host.lookup(&vk);
64   struct bpf_tunnel_key tkey = {};
65   if (dst_host) {
66     u32 zero = 0;
67     tkey.tunnel_id = dst_host->tunnel_id;
68     tkey.remote_ipv4 = dst_host->remote_ipv4;
69     bpf_skb_set_tunnel_key(skb, &tkey,
70         offsetof(struct bpf_tunnel_key, remote_ipv6[1]), 0);
71     lock_xadd(&dst_host->tx_pkts, 1);
72   } else {
73     struct bpf_tunnel_key tkey = {};
74     vk.mac = 0xFFFFFFFFFFFFull;
75     dst_host = mac2host.lookup(&vk);
76     if (!dst_host)
77       return 1;
78     tkey.tunnel_id = dst_host->tunnel_id;
79     tkey.remote_ipv4 = dst_host->remote_ipv4;
80     bpf_skb_set_tunnel_key(skb, &tkey,
81         offsetof(struct bpf_tunnel_key, remote_ipv6[1]), 0);
82   }
83   bpf_clone_redirect(skb, cfg->tunnel_ifindex, 0/*egress*/);
84   return 1;
85 }
86