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