1*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) PLUMgrid, Inc.
2*387f9dfdSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License")
3*387f9dfdSAndroid Build Coastguard Worker
4*387f9dfdSAndroid Build Coastguard Worker #include <bcc/proto.h>
5*387f9dfdSAndroid Build Coastguard Worker
6*387f9dfdSAndroid Build Coastguard Worker // hash
7*387f9dfdSAndroid Build Coastguard Worker struct FwdKey {
8*387f9dfdSAndroid Build Coastguard Worker u32 dip:32;
9*387f9dfdSAndroid Build Coastguard Worker };
10*387f9dfdSAndroid Build Coastguard Worker struct FwdLeaf {
11*387f9dfdSAndroid Build Coastguard Worker u32 fwd_idx:32;
12*387f9dfdSAndroid Build Coastguard Worker };
13*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(fwd_map, struct FwdKey, struct FwdLeaf, 1);
14*387f9dfdSAndroid Build Coastguard Worker
15*387f9dfdSAndroid Build Coastguard Worker // array
16*387f9dfdSAndroid Build Coastguard Worker struct ConfigLeaf {
17*387f9dfdSAndroid Build Coastguard Worker u32 bpfdev_ip;
18*387f9dfdSAndroid Build Coastguard Worker u32 slave_ip;
19*387f9dfdSAndroid Build Coastguard Worker };
20*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE("array", u32, struct ConfigLeaf, config_map, 1);
21*387f9dfdSAndroid Build Coastguard Worker
22*387f9dfdSAndroid Build Coastguard Worker // hash
23*387f9dfdSAndroid Build Coastguard Worker struct MacaddrKey {
24*387f9dfdSAndroid Build Coastguard Worker u32 ip;
25*387f9dfdSAndroid Build Coastguard Worker };
26*387f9dfdSAndroid Build Coastguard Worker struct MacaddrLeaf {
27*387f9dfdSAndroid Build Coastguard Worker u64 mac;
28*387f9dfdSAndroid Build Coastguard Worker };
29*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(macaddr_map, struct MacaddrKey, struct MacaddrLeaf, 11);
30*387f9dfdSAndroid Build Coastguard Worker
31*387f9dfdSAndroid Build Coastguard Worker // hash
32*387f9dfdSAndroid Build Coastguard Worker struct SlaveKey {
33*387f9dfdSAndroid Build Coastguard Worker u32 slave_ip;
34*387f9dfdSAndroid Build Coastguard Worker };
35*387f9dfdSAndroid Build Coastguard Worker struct SlaveLeaf {
36*387f9dfdSAndroid Build Coastguard Worker u32 slave_ifindex;
37*387f9dfdSAndroid Build Coastguard Worker };
38*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(slave_map, struct SlaveKey, struct SlaveLeaf, 10);
39*387f9dfdSAndroid Build Coastguard Worker
handle_packet(struct __sk_buff * skb)40*387f9dfdSAndroid Build Coastguard Worker int handle_packet(struct __sk_buff *skb) {
41*387f9dfdSAndroid Build Coastguard Worker int ret = 0;
42*387f9dfdSAndroid Build Coastguard Worker u8 *cursor = 0;
43*387f9dfdSAndroid Build Coastguard Worker
44*387f9dfdSAndroid Build Coastguard Worker if (skb->pkt_type == 0) {
45*387f9dfdSAndroid Build Coastguard Worker // tx
46*387f9dfdSAndroid Build Coastguard Worker // make sure configured
47*387f9dfdSAndroid Build Coastguard Worker u32 slave_ip;
48*387f9dfdSAndroid Build Coastguard Worker
49*387f9dfdSAndroid Build Coastguard Worker u32 cfg_key = 0;
50*387f9dfdSAndroid Build Coastguard Worker struct ConfigLeaf *cfg_leaf = config_map.lookup(&cfg_key);
51*387f9dfdSAndroid Build Coastguard Worker if (cfg_leaf) {
52*387f9dfdSAndroid Build Coastguard Worker slave_ip = cfg_leaf->slave_ip;
53*387f9dfdSAndroid Build Coastguard Worker } else {
54*387f9dfdSAndroid Build Coastguard Worker return 0xffffffff;
55*387f9dfdSAndroid Build Coastguard Worker }
56*387f9dfdSAndroid Build Coastguard Worker
57*387f9dfdSAndroid Build Coastguard Worker // make sure slave configured
58*387f9dfdSAndroid Build Coastguard Worker // tx, default to the single slave
59*387f9dfdSAndroid Build Coastguard Worker struct SlaveKey slave_key = {.slave_ip = slave_ip};
60*387f9dfdSAndroid Build Coastguard Worker struct SlaveLeaf *slave_leaf = slave_map.lookup(&slave_key);
61*387f9dfdSAndroid Build Coastguard Worker if (slave_leaf) {
62*387f9dfdSAndroid Build Coastguard Worker ret = slave_leaf->slave_ifindex;
63*387f9dfdSAndroid Build Coastguard Worker } else {
64*387f9dfdSAndroid Build Coastguard Worker return 0xffffffff;
65*387f9dfdSAndroid Build Coastguard Worker }
66*387f9dfdSAndroid Build Coastguard Worker } else {
67*387f9dfdSAndroid Build Coastguard Worker // rx, default to stack
68*387f9dfdSAndroid Build Coastguard Worker ret = 0;
69*387f9dfdSAndroid Build Coastguard Worker }
70*387f9dfdSAndroid Build Coastguard Worker
71*387f9dfdSAndroid Build Coastguard Worker struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
72*387f9dfdSAndroid Build Coastguard Worker switch (ethernet->type) {
73*387f9dfdSAndroid Build Coastguard Worker case ETH_P_IP: goto ip;
74*387f9dfdSAndroid Build Coastguard Worker case ETH_P_ARP: goto arp;
75*387f9dfdSAndroid Build Coastguard Worker case ETH_P_8021Q: goto dot1q;
76*387f9dfdSAndroid Build Coastguard Worker default: goto EOP;
77*387f9dfdSAndroid Build Coastguard Worker }
78*387f9dfdSAndroid Build Coastguard Worker
79*387f9dfdSAndroid Build Coastguard Worker dot1q: {
80*387f9dfdSAndroid Build Coastguard Worker struct dot1q_t *dot1q = cursor_advance(cursor, sizeof(*dot1q));
81*387f9dfdSAndroid Build Coastguard Worker switch (dot1q->type) {
82*387f9dfdSAndroid Build Coastguard Worker case ETH_P_IP: goto ip;
83*387f9dfdSAndroid Build Coastguard Worker case ETH_P_ARP: goto arp;
84*387f9dfdSAndroid Build Coastguard Worker default: goto EOP;
85*387f9dfdSAndroid Build Coastguard Worker }
86*387f9dfdSAndroid Build Coastguard Worker }
87*387f9dfdSAndroid Build Coastguard Worker
88*387f9dfdSAndroid Build Coastguard Worker arp: {
89*387f9dfdSAndroid Build Coastguard Worker struct arp_t *arp = cursor_advance(cursor, sizeof(*arp));
90*387f9dfdSAndroid Build Coastguard Worker if (skb->pkt_type) {
91*387f9dfdSAndroid Build Coastguard Worker if (arp->oper == 1) {
92*387f9dfdSAndroid Build Coastguard Worker struct MacaddrKey mac_key = {.ip=arp->spa};
93*387f9dfdSAndroid Build Coastguard Worker struct MacaddrLeaf mac_leaf = {.mac=arp->sha};
94*387f9dfdSAndroid Build Coastguard Worker macaddr_map.update(&mac_key, &mac_leaf);
95*387f9dfdSAndroid Build Coastguard Worker }
96*387f9dfdSAndroid Build Coastguard Worker }
97*387f9dfdSAndroid Build Coastguard Worker goto EOP;
98*387f9dfdSAndroid Build Coastguard Worker }
99*387f9dfdSAndroid Build Coastguard Worker
100*387f9dfdSAndroid Build Coastguard Worker struct ip_t *ip;
101*387f9dfdSAndroid Build Coastguard Worker ip: {
102*387f9dfdSAndroid Build Coastguard Worker ip = cursor_advance(cursor, sizeof(*ip));
103*387f9dfdSAndroid Build Coastguard Worker switch (ip->nextp) {
104*387f9dfdSAndroid Build Coastguard Worker case 6: goto tcp;
105*387f9dfdSAndroid Build Coastguard Worker case 17: goto udp;
106*387f9dfdSAndroid Build Coastguard Worker default: goto EOP;
107*387f9dfdSAndroid Build Coastguard Worker }
108*387f9dfdSAndroid Build Coastguard Worker }
109*387f9dfdSAndroid Build Coastguard Worker tcp: {
110*387f9dfdSAndroid Build Coastguard Worker struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp));
111*387f9dfdSAndroid Build Coastguard Worker goto EOP;
112*387f9dfdSAndroid Build Coastguard Worker }
113*387f9dfdSAndroid Build Coastguard Worker udp: {
114*387f9dfdSAndroid Build Coastguard Worker struct udp_t *udp = cursor_advance(cursor, sizeof(*udp));
115*387f9dfdSAndroid Build Coastguard Worker if (udp->dport != 5000) {
116*387f9dfdSAndroid Build Coastguard Worker goto EOP;
117*387f9dfdSAndroid Build Coastguard Worker }
118*387f9dfdSAndroid Build Coastguard Worker if (skb->pkt_type) {
119*387f9dfdSAndroid Build Coastguard Worker // lookup and then forward
120*387f9dfdSAndroid Build Coastguard Worker struct FwdKey fwd_key = {.dip=ip->dst};
121*387f9dfdSAndroid Build Coastguard Worker struct FwdLeaf *fwd_val = fwd_map.lookup(&fwd_key);
122*387f9dfdSAndroid Build Coastguard Worker if (fwd_val) {
123*387f9dfdSAndroid Build Coastguard Worker return fwd_val->fwd_idx;
124*387f9dfdSAndroid Build Coastguard Worker }
125*387f9dfdSAndroid Build Coastguard Worker } else {
126*387f9dfdSAndroid Build Coastguard Worker // rewrite the packet and send to a pre-configured index if needed
127*387f9dfdSAndroid Build Coastguard Worker u32 new_ip;
128*387f9dfdSAndroid Build Coastguard Worker u32 old_ip;
129*387f9dfdSAndroid Build Coastguard Worker u64 src_mac;
130*387f9dfdSAndroid Build Coastguard Worker u64 dst_mac;
131*387f9dfdSAndroid Build Coastguard Worker
132*387f9dfdSAndroid Build Coastguard Worker u32 cfg_key = 0;
133*387f9dfdSAndroid Build Coastguard Worker struct ConfigLeaf *cfg_leaf = config_map.lookup(&cfg_key);
134*387f9dfdSAndroid Build Coastguard Worker if (cfg_leaf) {
135*387f9dfdSAndroid Build Coastguard Worker struct MacaddrKey mac_key = {.ip = cfg_leaf->bpfdev_ip};
136*387f9dfdSAndroid Build Coastguard Worker struct MacaddrLeaf *mac_leaf;
137*387f9dfdSAndroid Build Coastguard Worker
138*387f9dfdSAndroid Build Coastguard Worker mac_key.ip = cfg_leaf->bpfdev_ip;
139*387f9dfdSAndroid Build Coastguard Worker mac_leaf = macaddr_map.lookup(&mac_key);
140*387f9dfdSAndroid Build Coastguard Worker if (mac_leaf) {
141*387f9dfdSAndroid Build Coastguard Worker src_mac = mac_leaf->mac;
142*387f9dfdSAndroid Build Coastguard Worker } else {
143*387f9dfdSAndroid Build Coastguard Worker goto EOP;
144*387f9dfdSAndroid Build Coastguard Worker }
145*387f9dfdSAndroid Build Coastguard Worker
146*387f9dfdSAndroid Build Coastguard Worker mac_key.ip = cfg_leaf->slave_ip;
147*387f9dfdSAndroid Build Coastguard Worker mac_leaf = macaddr_map.lookup(&mac_key);
148*387f9dfdSAndroid Build Coastguard Worker if (mac_leaf) {
149*387f9dfdSAndroid Build Coastguard Worker dst_mac = mac_leaf->mac;
150*387f9dfdSAndroid Build Coastguard Worker } else {
151*387f9dfdSAndroid Build Coastguard Worker goto EOP;
152*387f9dfdSAndroid Build Coastguard Worker }
153*387f9dfdSAndroid Build Coastguard Worker
154*387f9dfdSAndroid Build Coastguard Worker // rewrite ethernet header
155*387f9dfdSAndroid Build Coastguard Worker ethernet->dst = dst_mac;
156*387f9dfdSAndroid Build Coastguard Worker ethernet->src = src_mac;
157*387f9dfdSAndroid Build Coastguard Worker
158*387f9dfdSAndroid Build Coastguard Worker // ip & udp checksum
159*387f9dfdSAndroid Build Coastguard Worker incr_cksum_l4(&udp->crc, ip->src, cfg_leaf->bpfdev_ip, 1);
160*387f9dfdSAndroid Build Coastguard Worker incr_cksum_l4(&udp->crc, ip->dst, cfg_leaf->slave_ip, 1);
161*387f9dfdSAndroid Build Coastguard Worker
162*387f9dfdSAndroid Build Coastguard Worker // rewrite ip src/dst fields
163*387f9dfdSAndroid Build Coastguard Worker ip->src = cfg_leaf->bpfdev_ip;
164*387f9dfdSAndroid Build Coastguard Worker ip->dst = cfg_leaf->slave_ip;
165*387f9dfdSAndroid Build Coastguard Worker }
166*387f9dfdSAndroid Build Coastguard Worker }
167*387f9dfdSAndroid Build Coastguard Worker goto EOP;
168*387f9dfdSAndroid Build Coastguard Worker }
169*387f9dfdSAndroid Build Coastguard Worker
170*387f9dfdSAndroid Build Coastguard Worker EOP:
171*387f9dfdSAndroid Build Coastguard Worker return ret;
172*387f9dfdSAndroid Build Coastguard Worker }
173