1 // Copyright (c) PLUMgrid, Inc.
2 // Licensed under the Apache License, Version 2.0 (the "License")
3 #include <bcc/proto.h>
4 struct IPKey {
5   u32 dip;
6   u32 sip;
7 };
8 struct IPLeaf {
9   u32 xdip;
10   u32 xsip;
11   u64 ip_xlated_pkts;
12   u64 arp_xlated_pkts;
13 };
14 BPF_HASH(xlate, struct IPKey, struct IPLeaf, 1024);
15 
on_packet(struct __sk_buff * skb)16 int on_packet(struct __sk_buff *skb) {
17   u8 *cursor = 0;
18 
19   u32 orig_dip = 0;
20   u32 orig_sip = 0;
21   struct IPLeaf xleaf = {};
22 
23   ethernet: {
24     struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
25     switch (ethernet->type) {
26       case ETH_P_IP: goto ip;
27       case ETH_P_ARP: goto arp;
28       case ETH_P_8021Q: goto dot1q;
29       default: goto EOP;
30     }
31   }
32 
33   dot1q: {
34     struct dot1q_t *dot1q = cursor_advance(cursor, sizeof(*dot1q));
35     switch (dot1q->type) {
36       case ETH_P_IP: goto ip;
37       case ETH_P_ARP: goto arp;
38       default: goto EOP;
39     }
40   }
41 
42   arp: {
43     struct arp_t *arp = cursor_advance(cursor, sizeof(*arp));
44     orig_dip = arp->tpa;
45     orig_sip = arp->spa;
46     struct IPKey key = {.dip=orig_dip, .sip=orig_sip};
47     struct IPLeaf *xleafp = xlate.lookup(&key);
48     if (xleafp) {
49       xleaf = *xleafp;
50       arp->tpa = xleaf.xdip;
51       arp->spa = xleaf.xsip;
52       lock_xadd(&xleafp->arp_xlated_pkts, 1);
53     }
54     goto EOP;
55   }
56 
57   ip: {
58     struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
59     orig_dip = ip->dst;
60     orig_sip = ip->src;
61     struct IPKey key = {.dip=orig_dip, .sip=orig_sip};
62     struct IPLeaf *xleafp = xlate.lookup(&key);
63     if (xleafp) {
64       xleaf = *xleafp;
65       ip->dst = xleaf.xdip;
66       incr_cksum_l3(&ip->hchecksum, orig_dip, xleaf.xdip);
67       ip->src = xleaf.xsip;
68       incr_cksum_l3(&ip->hchecksum, orig_sip, xleaf.xsip);
69       lock_xadd(&xleafp->ip_xlated_pkts, 1);
70     }
71     switch (ip->nextp) {
72       case 6: goto tcp;
73       case 17: goto udp;
74       default: goto EOP;
75     }
76   }
77 
78   udp: {
79     struct udp_t *udp = cursor_advance(cursor, sizeof(*udp));
80     if (xleaf.xdip) {
81       incr_cksum_l4(&udp->crc, orig_dip, xleaf.xdip, 1);
82       incr_cksum_l4(&udp->crc, orig_sip, xleaf.xsip, 1);
83     }
84     goto EOP;
85   }
86 
87   tcp: {
88     struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp));
89     if (xleaf.xdip) {
90       incr_cksum_l4(&tcp->cksum, orig_dip, xleaf.xdip, 1);
91       incr_cksum_l4(&tcp->cksum, orig_sip, xleaf.xsip, 1);
92     }
93     goto EOP;
94   }
95 
96 EOP:
97   return 0;
98 }
99