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 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