• 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_try_init(&out_ifindex, &zleaf);
36       if (out_leaf) {
37 	// to capture potential configuration changes
38 	out_leaf->out_ifindex = skb->ifindex;
39 	out_leaf->vlan_tci = skb->vlan_tci;
40 	out_leaf->vlan_proto = skb->vlan_proto;
41       }
42       // pop the vlan header and send to the destination
43       bpf_skb_vlan_pop(skb);
44       bpf_clone_redirect(skb, leaf->out_ifindex, 0);
45     }
46   }
47   return 1;
48 }
49 
handle_virt2phys(struct __sk_buff * skb)50 int handle_virt2phys(struct __sk_buff *skb) {
51   u8 *cursor = 0;
52   ethernet: {
53     struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
54     int src_ifindex = skb->ifindex;
55     struct ifindex_leaf_t *leaf = egress.lookup(&src_ifindex);
56     if (leaf) {
57       lock_xadd(&leaf->tx_pkts, 1);
58       lock_xadd(&leaf->tx_bytes, skb->len);
59       bpf_skb_vlan_push(skb, leaf->vlan_proto, leaf->vlan_tci);
60       bpf_clone_redirect(skb, leaf->out_ifindex, 0);
61     }
62   }
63   return 1;
64 }
65