| // Copyright (c) PLUMgrid, Inc. | |
| // Licensed under the Apache License, Version 2.0 (the "License") | |
| #include <bcc/proto.h> | |
| struct IPKey { | |
| u32 dip; | |
| u32 sip; | |
| }; | |
| struct IPLeaf { | |
| u32 xdip; | |
| u32 xsip; | |
| u64 ip_xlated_pkts; | |
| u64 arp_xlated_pkts; | |
| }; | |
| BPF_HASH(xlate, struct IPKey, struct IPLeaf, 1024); | |
| int on_packet(struct __sk_buff *skb) { | |
| u8 *cursor = 0; | |
| u32 orig_dip = 0; | |
| u32 orig_sip = 0; | |
| struct IPLeaf xleaf = {}; | |
| ethernet: { | |
| struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); | |
| switch (ethernet->type) { | |
| case ETH_P_IP: goto ip; | |
| case ETH_P_ARP: goto arp; | |
| case ETH_P_8021Q: goto dot1q; | |
| default: goto EOP; | |
| } | |
| } | |
| dot1q: { | |
| struct dot1q_t *dot1q = cursor_advance(cursor, sizeof(*dot1q)); | |
| switch (dot1q->type) { | |
| case ETH_P_IP: goto ip; | |
| case ETH_P_ARP: goto arp; | |
| default: goto EOP; | |
| } | |
| } | |
| arp: { | |
| struct arp_t *arp = cursor_advance(cursor, sizeof(*arp)); | |
| orig_dip = arp->tpa; | |
| orig_sip = arp->spa; | |
| struct IPKey key = {.dip=orig_dip, .sip=orig_sip}; | |
| struct IPLeaf *xleafp = xlate.lookup(&key); | |
| if (xleafp) { | |
| xleaf = *xleafp; | |
| arp->tpa = xleaf.xdip; | |
| arp->spa = xleaf.xsip; | |
| lock_xadd(&xleafp->arp_xlated_pkts, 1); | |
| } | |
| goto EOP; | |
| } | |
| ip: { | |
| struct ip_t *ip = cursor_advance(cursor, sizeof(*ip)); | |
| orig_dip = ip->dst; | |
| orig_sip = ip->src; | |
| struct IPKey key = {.dip=orig_dip, .sip=orig_sip}; | |
| struct IPLeaf *xleafp = xlate.lookup(&key); | |
| if (xleafp) { | |
| xleaf = *xleafp; | |
| ip->dst = xleaf.xdip; | |
| incr_cksum_l3(&ip->hchecksum, orig_dip, xleaf.xdip); | |
| ip->src = xleaf.xsip; | |
| incr_cksum_l3(&ip->hchecksum, orig_sip, xleaf.xsip); | |
| lock_xadd(&xleafp->ip_xlated_pkts, 1); | |
| } | |
| switch (ip->nextp) { | |
| case 6: goto tcp; | |
| case 17: goto udp; | |
| default: goto EOP; | |
| } | |
| } | |
| udp: { | |
| struct udp_t *udp = cursor_advance(cursor, sizeof(*udp)); | |
| if (xleaf.xdip) { | |
| incr_cksum_l4(&udp->crc, orig_dip, xleaf.xdip, 1); | |
| incr_cksum_l4(&udp->crc, orig_sip, xleaf.xsip, 1); | |
| } | |
| goto EOP; | |
| } | |
| tcp: { | |
| struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp)); | |
| if (xleaf.xdip) { | |
| incr_cksum_l4(&tcp->cksum, orig_dip, xleaf.xdip, 1); | |
| incr_cksum_l4(&tcp->cksum, orig_sip, xleaf.xsip, 1); | |
| } | |
| goto EOP; | |
| } | |
| EOP: | |
| return 0; | |
| } |