• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) PLUMgrid, Inc.
2 // Licensed under the Apache License, Version 2.0 (the "License")
3 
4 #include <bcc/proto.h>
5 
6 struct ifindex_leaf_t {
7   int out_ifindex;
8   int vlan_tci; // populated by phys2virt and used by virt2phys
9   int vlan_proto; // populated by phys2virt and used by virt2phys
10   u64 tx_pkts;
11   u64 tx_bytes;
12 };
13 
14 // redirect based on mac -> out_ifindex (auto-learning)
15 BPF_HASH(egress, int, struct ifindex_leaf_t, 4096);
16 
17 // redirect based on mac -> out_ifindex (config-driven)
18 BPF_HASH(ingress, u64, struct ifindex_leaf_t, 4096);
19 
handle_phys2virt(struct __sk_buff * skb)20 int handle_phys2virt(struct __sk_buff *skb) {
21   // only handle vlan packets
22   if (!skb->vlan_present)
23     return 1;
24   u8 *cursor = 0;
25   ethernet: {
26     struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
27     u64 src_mac = ethernet->src;
28     struct ifindex_leaf_t *leaf = ingress.lookup(&src_mac);
29     if (leaf) {
30       lock_xadd(&leaf->tx_pkts, 1);
31       lock_xadd(&leaf->tx_bytes, skb->len);
32       // auto-program reverse direction table
33       int out_ifindex = leaf->out_ifindex;
34       struct ifindex_leaf_t zleaf = {0};
35       struct ifindex_leaf_t *out_leaf = egress.lookup_or_init(&out_ifindex, &zleaf);
36       // to capture potential configuration changes
37       out_leaf->out_ifindex = skb->ifindex;
38       out_leaf->vlan_tci = skb->vlan_tci;
39       out_leaf->vlan_proto = skb->vlan_proto;
40       // pop the vlan header and send to the destination
41       bpf_skb_vlan_pop(skb);
42       bpf_clone_redirect(skb, leaf->out_ifindex, 0);
43     }
44   }
45   return 1;
46 }
47 
handle_virt2phys(struct __sk_buff * skb)48 int handle_virt2phys(struct __sk_buff *skb) {
49   u8 *cursor = 0;
50   ethernet: {
51     struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
52     int src_ifindex = skb->ifindex;
53     struct ifindex_leaf_t *leaf = egress.lookup(&src_ifindex);
54     if (leaf) {
55       lock_xadd(&leaf->tx_pkts, 1);
56       lock_xadd(&leaf->tx_bytes, skb->len);
57       bpf_skb_vlan_push(skb, leaf->vlan_proto, leaf->vlan_tci);
58       bpf_clone_redirect(skb, leaf->out_ifindex, 0);
59     }
60   }
61   return 1;
62 }
63