| // 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 { |
| u64 rx_pkts; |
| u64 tx_pkts; |
| }; |
| |
| BPF_HASH(stats, struct IPKey, struct IPLeaf, 256); |
| |
| int on_packet(struct __sk_buff *skb) { |
| u8 *cursor = 0; |
| ethernet: { |
| struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); |
| switch (ethernet->type) { |
| case ETH_P_IP: goto ip; |
| 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_8021Q: goto ip; |
| default: goto EOP; |
| } |
| } |
| |
| ip: { |
| struct ip_t *ip = cursor_advance(cursor, sizeof(*ip)); |
| int rx = 0, tx = 0; |
| struct IPKey key; |
| if (ip->dst > ip->src) { |
| key.dip = ip->dst; |
| key.sip = ip->src; |
| rx = 1; |
| } else { |
| key.dip = ip->src; |
| key.sip = ip->dst; |
| tx = 1; |
| } |
| struct IPLeaf zleaf = {0}; |
| struct IPLeaf *leaf = stats.lookup_or_try_init(&key, &zleaf); |
| if (leaf) { |
| lock_xadd(&leaf->rx_pkts, rx); |
| lock_xadd(&leaf->tx_pkts, tx); |
| } |
| } |
| |
| EOP: |
| return 0; |
| } |