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