xref: /aosp_15_r20/external/bcc/tests/python/test_brb.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
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 #include <bcc/proto.h>
4*387f9dfdSAndroid Build Coastguard Worker 
5*387f9dfdSAndroid Build Coastguard Worker #define _memcpy __builtin_memcpy
6*387f9dfdSAndroid Build Coastguard Worker 
7*387f9dfdSAndroid Build Coastguard Worker // meta data passed between bpf programs
8*387f9dfdSAndroid Build Coastguard Worker typedef struct bpf_metadata {
9*387f9dfdSAndroid Build Coastguard Worker     u32 prog_id;
10*387f9dfdSAndroid Build Coastguard Worker     u32 rx_port_id;
11*387f9dfdSAndroid Build Coastguard Worker } bpf_metadata_t;
12*387f9dfdSAndroid Build Coastguard Worker 
13*387f9dfdSAndroid Build Coastguard Worker typedef struct bpf_dest {
14*387f9dfdSAndroid Build Coastguard Worker     u32 prog_id;
15*387f9dfdSAndroid Build Coastguard Worker     u32 port_id;
16*387f9dfdSAndroid Build Coastguard Worker } bpf_dest_t;
17*387f9dfdSAndroid Build Coastguard Worker 
18*387f9dfdSAndroid Build Coastguard Worker // use u64 to represent eth_addr.
19*387f9dfdSAndroid Build Coastguard Worker // maintain the structure though to indicate the semantics
20*387f9dfdSAndroid Build Coastguard Worker typedef struct eth_addr {
21*387f9dfdSAndroid Build Coastguard Worker     u64 addr;
22*387f9dfdSAndroid Build Coastguard Worker } eth_addr_t;
23*387f9dfdSAndroid Build Coastguard Worker 
24*387f9dfdSAndroid Build Coastguard Worker // Program table definitions for tail calls
25*387f9dfdSAndroid Build Coastguard Worker BPF_PROG_ARRAY(jump, 16);
26*387f9dfdSAndroid Build Coastguard Worker 
27*387f9dfdSAndroid Build Coastguard Worker // physical endpoint manager (pem) tables which connects to boeht bridge 1 and bridge 2
28*387f9dfdSAndroid Build Coastguard Worker // <port_id, bpf_dest>
29*387f9dfdSAndroid Build Coastguard Worker BPF_ARRAY(pem_dest, bpf_dest_t, 256);
30*387f9dfdSAndroid Build Coastguard Worker // <port_id, ifindex>
31*387f9dfdSAndroid Build Coastguard Worker BPF_ARRAY(pem_port, u32, 256);
32*387f9dfdSAndroid Build Coastguard Worker // <ifindex, port_id>
33*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(pem_ifindex, u32, u32, 256);
34*387f9dfdSAndroid Build Coastguard Worker // <0, tx2vm_pkts>
35*387f9dfdSAndroid Build Coastguard Worker BPF_ARRAY(pem_stats, u32, 1);
36*387f9dfdSAndroid Build Coastguard Worker 
37*387f9dfdSAndroid Build Coastguard Worker // bridge 1 (br1) tables
38*387f9dfdSAndroid Build Coastguard Worker // <port_id, bpf_dest>
39*387f9dfdSAndroid Build Coastguard Worker BPF_ARRAY(br1_dest, bpf_dest_t, 256);
40*387f9dfdSAndroid Build Coastguard Worker // <eth_addr, port_id>
41*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(br1_mac, eth_addr_t, u32, 256);
42*387f9dfdSAndroid Build Coastguard Worker // <0, rtr_ifindex>
43*387f9dfdSAndroid Build Coastguard Worker BPF_ARRAY(br1_rtr, u32, 1);
44*387f9dfdSAndroid Build Coastguard Worker // <mac, ifindex>
45*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(br1_mac_ifindex, eth_addr_t, u32, 1);
46*387f9dfdSAndroid Build Coastguard Worker 
47*387f9dfdSAndroid Build Coastguard Worker // bridge 2 (br2) tables
48*387f9dfdSAndroid Build Coastguard Worker // <port_id, bpf_dest>
49*387f9dfdSAndroid Build Coastguard Worker BPF_ARRAY(br2_dest, bpf_dest_t, 256);
50*387f9dfdSAndroid Build Coastguard Worker // <eth_addr, port_id>
51*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(br2_mac, eth_addr_t, u32, 256);
52*387f9dfdSAndroid Build Coastguard Worker // <0, rtr_ifindex>
53*387f9dfdSAndroid Build Coastguard Worker BPF_ARRAY(br2_rtr, u32, 1);
54*387f9dfdSAndroid Build Coastguard Worker // <mac, ifindex>
55*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(br2_mac_ifindex, eth_addr_t, u32, 1);
56*387f9dfdSAndroid Build Coastguard Worker 
pem(struct __sk_buff * skb)57*387f9dfdSAndroid Build Coastguard Worker int pem(struct __sk_buff *skb) {
58*387f9dfdSAndroid Build Coastguard Worker     bpf_metadata_t meta = {};
59*387f9dfdSAndroid Build Coastguard Worker     u32 ifindex;
60*387f9dfdSAndroid Build Coastguard Worker     u32 *tx_port_id_p;
61*387f9dfdSAndroid Build Coastguard Worker     u32 tx_port_id;
62*387f9dfdSAndroid Build Coastguard Worker     u32 rx_port;
63*387f9dfdSAndroid Build Coastguard Worker     u32 *ifindex_p;
64*387f9dfdSAndroid Build Coastguard Worker     bpf_dest_t *dest_p;
65*387f9dfdSAndroid Build Coastguard Worker 
66*387f9dfdSAndroid Build Coastguard Worker     // pem does not look at packet data
67*387f9dfdSAndroid Build Coastguard Worker     if (skb->tc_index == 0) {
68*387f9dfdSAndroid Build Coastguard Worker         skb->tc_index = 1;
69*387f9dfdSAndroid Build Coastguard Worker         skb->cb[0] = skb->cb[1] = 0;
70*387f9dfdSAndroid Build Coastguard Worker         meta.prog_id = meta.rx_port_id = 0;
71*387f9dfdSAndroid Build Coastguard Worker     } else {
72*387f9dfdSAndroid Build Coastguard Worker         meta.prog_id = skb->cb[0];
73*387f9dfdSAndroid Build Coastguard Worker         asm volatile("" ::: "memory");
74*387f9dfdSAndroid Build Coastguard Worker         meta.rx_port_id = skb->cb[1];
75*387f9dfdSAndroid Build Coastguard Worker     }
76*387f9dfdSAndroid Build Coastguard Worker     if (!meta.prog_id) {
77*387f9dfdSAndroid Build Coastguard Worker         /* from external */
78*387f9dfdSAndroid Build Coastguard Worker         ifindex = skb->ingress_ifindex;
79*387f9dfdSAndroid Build Coastguard Worker         tx_port_id_p = pem_ifindex.lookup(&ifindex);
80*387f9dfdSAndroid Build Coastguard Worker         if (tx_port_id_p) {
81*387f9dfdSAndroid Build Coastguard Worker             tx_port_id = *tx_port_id_p;
82*387f9dfdSAndroid Build Coastguard Worker             dest_p = pem_dest.lookup(&tx_port_id);
83*387f9dfdSAndroid Build Coastguard Worker             if (dest_p) {
84*387f9dfdSAndroid Build Coastguard Worker                 skb->cb[0] = dest_p->prog_id;
85*387f9dfdSAndroid Build Coastguard Worker                 skb->cb[1] = dest_p->port_id;
86*387f9dfdSAndroid Build Coastguard Worker                 jump.call(skb, dest_p->prog_id);
87*387f9dfdSAndroid Build Coastguard Worker             }
88*387f9dfdSAndroid Build Coastguard Worker         }
89*387f9dfdSAndroid Build Coastguard Worker     } else {
90*387f9dfdSAndroid Build Coastguard Worker         /* from internal */
91*387f9dfdSAndroid Build Coastguard Worker         rx_port = meta.rx_port_id;
92*387f9dfdSAndroid Build Coastguard Worker         ifindex_p = pem_port.lookup(&rx_port);
93*387f9dfdSAndroid Build Coastguard Worker         if (ifindex_p) {
94*387f9dfdSAndroid Build Coastguard Worker #if 1
95*387f9dfdSAndroid Build Coastguard Worker             /* accumulate stats, may hurt performance slightly */
96*387f9dfdSAndroid Build Coastguard Worker             u32 index = 0;
97*387f9dfdSAndroid Build Coastguard Worker             u32 *value = pem_stats.lookup(&index);
98*387f9dfdSAndroid Build Coastguard Worker             if (value)
99*387f9dfdSAndroid Build Coastguard Worker                 lock_xadd(value, 1);
100*387f9dfdSAndroid Build Coastguard Worker #endif
101*387f9dfdSAndroid Build Coastguard Worker             bpf_clone_redirect(skb, *ifindex_p, 0);
102*387f9dfdSAndroid Build Coastguard Worker         }
103*387f9dfdSAndroid Build Coastguard Worker     }
104*387f9dfdSAndroid Build Coastguard Worker 
105*387f9dfdSAndroid Build Coastguard Worker     return 1;
106*387f9dfdSAndroid Build Coastguard Worker }
107*387f9dfdSAndroid Build Coastguard Worker 
br_common(struct __sk_buff * skb,int which_br)108*387f9dfdSAndroid Build Coastguard Worker static int br_common(struct __sk_buff *skb, int which_br) {
109*387f9dfdSAndroid Build Coastguard Worker     u8 *cursor = 0;
110*387f9dfdSAndroid Build Coastguard Worker     u16 proto;
111*387f9dfdSAndroid Build Coastguard Worker     u16 arpop;
112*387f9dfdSAndroid Build Coastguard Worker     eth_addr_t dmac;
113*387f9dfdSAndroid Build Coastguard Worker     u8 *mac_p;
114*387f9dfdSAndroid Build Coastguard Worker     u32 dip;
115*387f9dfdSAndroid Build Coastguard Worker     u32 *tx_port_id_p;
116*387f9dfdSAndroid Build Coastguard Worker     u32 tx_port_id;
117*387f9dfdSAndroid Build Coastguard Worker     bpf_dest_t *dest_p;
118*387f9dfdSAndroid Build Coastguard Worker     u32 index, *rtrif_p;
119*387f9dfdSAndroid Build Coastguard Worker 
120*387f9dfdSAndroid Build Coastguard Worker     struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
121*387f9dfdSAndroid Build Coastguard Worker     /* handle ethernet packet header */
122*387f9dfdSAndroid Build Coastguard Worker     {
123*387f9dfdSAndroid Build Coastguard Worker         dmac.addr = ethernet->dst;
124*387f9dfdSAndroid Build Coastguard Worker         /* skb->tc_index may be preserved across router namespace if router simply rewrite packet
125*387f9dfdSAndroid Build Coastguard Worker          * and send it back.
126*387f9dfdSAndroid Build Coastguard Worker          */
127*387f9dfdSAndroid Build Coastguard Worker         if (skb->tc_index == 1) {
128*387f9dfdSAndroid Build Coastguard Worker             /* packet from pem, send to the router, set tc_index to 2 */
129*387f9dfdSAndroid Build Coastguard Worker             skb->tc_index = 2;
130*387f9dfdSAndroid Build Coastguard Worker             if (dmac.addr == 0xffffffffffffULL) {
131*387f9dfdSAndroid Build Coastguard Worker                  index = 0;
132*387f9dfdSAndroid Build Coastguard Worker                  if (which_br == 1)
133*387f9dfdSAndroid Build Coastguard Worker                      rtrif_p = br1_rtr.lookup(&index);
134*387f9dfdSAndroid Build Coastguard Worker                  else
135*387f9dfdSAndroid Build Coastguard Worker                      rtrif_p = br2_rtr.lookup(&index);
136*387f9dfdSAndroid Build Coastguard Worker                  if (rtrif_p)
137*387f9dfdSAndroid Build Coastguard Worker                      bpf_clone_redirect(skb, *rtrif_p, 0);
138*387f9dfdSAndroid Build Coastguard Worker              } else {
139*387f9dfdSAndroid Build Coastguard Worker                  /* the dmac address should match the router's */
140*387f9dfdSAndroid Build Coastguard Worker                  if (which_br == 1)
141*387f9dfdSAndroid Build Coastguard Worker                      rtrif_p = br1_mac_ifindex.lookup(&dmac);
142*387f9dfdSAndroid Build Coastguard Worker                  else
143*387f9dfdSAndroid Build Coastguard Worker                      rtrif_p = br2_mac_ifindex.lookup(&dmac);
144*387f9dfdSAndroid Build Coastguard Worker                  if (rtrif_p)
145*387f9dfdSAndroid Build Coastguard Worker                      bpf_clone_redirect(skb, *rtrif_p, 0);
146*387f9dfdSAndroid Build Coastguard Worker              }
147*387f9dfdSAndroid Build Coastguard Worker              return 1;
148*387f9dfdSAndroid Build Coastguard Worker         }
149*387f9dfdSAndroid Build Coastguard Worker 
150*387f9dfdSAndroid Build Coastguard Worker         /* set the tc_index to 1 so pem knows it is from internal */
151*387f9dfdSAndroid Build Coastguard Worker         skb->tc_index = 1;
152*387f9dfdSAndroid Build Coastguard Worker         switch (ethernet->type) {
153*387f9dfdSAndroid Build Coastguard Worker             case ETH_P_IP: goto ip;
154*387f9dfdSAndroid Build Coastguard Worker             case ETH_P_ARP: goto arp;
155*387f9dfdSAndroid Build Coastguard Worker             case ETH_P_8021Q: goto dot1q;
156*387f9dfdSAndroid Build Coastguard Worker             default: goto EOP;
157*387f9dfdSAndroid Build Coastguard Worker         }
158*387f9dfdSAndroid Build Coastguard Worker     }
159*387f9dfdSAndroid Build Coastguard Worker 
160*387f9dfdSAndroid Build Coastguard Worker     dot1q: {
161*387f9dfdSAndroid Build Coastguard Worker         struct dot1q_t *dot1q = cursor_advance(cursor, sizeof(*dot1q));
162*387f9dfdSAndroid Build Coastguard Worker         switch(dot1q->type) {
163*387f9dfdSAndroid Build Coastguard Worker             case ETH_P_IP: goto ip;
164*387f9dfdSAndroid Build Coastguard Worker             case ETH_P_ARP: goto arp;
165*387f9dfdSAndroid Build Coastguard Worker             default: goto EOP;
166*387f9dfdSAndroid Build Coastguard Worker         }
167*387f9dfdSAndroid Build Coastguard Worker     }
168*387f9dfdSAndroid Build Coastguard Worker 
169*387f9dfdSAndroid Build Coastguard Worker     arp: {
170*387f9dfdSAndroid Build Coastguard Worker         struct arp_t *arp = cursor_advance(cursor, sizeof(*arp));
171*387f9dfdSAndroid Build Coastguard Worker         /* mac learning */
172*387f9dfdSAndroid Build Coastguard Worker         arpop = arp->oper;
173*387f9dfdSAndroid Build Coastguard Worker         if (arpop == 2) {
174*387f9dfdSAndroid Build Coastguard Worker             index = 0;
175*387f9dfdSAndroid Build Coastguard Worker             if (which_br == 1)
176*387f9dfdSAndroid Build Coastguard Worker                 rtrif_p = br1_rtr.lookup(&index);
177*387f9dfdSAndroid Build Coastguard Worker             else
178*387f9dfdSAndroid Build Coastguard Worker                 rtrif_p = br2_rtr.lookup(&index);
179*387f9dfdSAndroid Build Coastguard Worker             if (rtrif_p) {
180*387f9dfdSAndroid Build Coastguard Worker                 __u32 ifindex = *rtrif_p;
181*387f9dfdSAndroid Build Coastguard Worker                 eth_addr_t smac;
182*387f9dfdSAndroid Build Coastguard Worker 
183*387f9dfdSAndroid Build Coastguard Worker                 smac.addr = ethernet->src;
184*387f9dfdSAndroid Build Coastguard Worker                 if (which_br == 1)
185*387f9dfdSAndroid Build Coastguard Worker                     br1_mac_ifindex.update(&smac, &ifindex);
186*387f9dfdSAndroid Build Coastguard Worker                 else
187*387f9dfdSAndroid Build Coastguard Worker                     br2_mac_ifindex.update(&smac, &ifindex);
188*387f9dfdSAndroid Build Coastguard Worker             }
189*387f9dfdSAndroid Build Coastguard Worker         }
190*387f9dfdSAndroid Build Coastguard Worker         goto xmit;
191*387f9dfdSAndroid Build Coastguard Worker     }
192*387f9dfdSAndroid Build Coastguard Worker 
193*387f9dfdSAndroid Build Coastguard Worker     ip: {
194*387f9dfdSAndroid Build Coastguard Worker         struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
195*387f9dfdSAndroid Build Coastguard Worker         goto xmit;
196*387f9dfdSAndroid Build Coastguard Worker     }
197*387f9dfdSAndroid Build Coastguard Worker 
198*387f9dfdSAndroid Build Coastguard Worker xmit:
199*387f9dfdSAndroid Build Coastguard Worker     if (which_br == 1)
200*387f9dfdSAndroid Build Coastguard Worker         tx_port_id_p = br1_mac.lookup(&dmac);
201*387f9dfdSAndroid Build Coastguard Worker     else
202*387f9dfdSAndroid Build Coastguard Worker         tx_port_id_p = br2_mac.lookup(&dmac);
203*387f9dfdSAndroid Build Coastguard Worker     if (tx_port_id_p) {
204*387f9dfdSAndroid Build Coastguard Worker         tx_port_id = *tx_port_id_p;
205*387f9dfdSAndroid Build Coastguard Worker         if (which_br == 1)
206*387f9dfdSAndroid Build Coastguard Worker             dest_p = br1_dest.lookup(&tx_port_id);
207*387f9dfdSAndroid Build Coastguard Worker         else
208*387f9dfdSAndroid Build Coastguard Worker             dest_p = br2_dest.lookup(&tx_port_id);
209*387f9dfdSAndroid Build Coastguard Worker         if (dest_p) {
210*387f9dfdSAndroid Build Coastguard Worker             skb->cb[0] = dest_p->prog_id;
211*387f9dfdSAndroid Build Coastguard Worker             skb->cb[1] = dest_p->port_id;
212*387f9dfdSAndroid Build Coastguard Worker             jump.call(skb, dest_p->prog_id);
213*387f9dfdSAndroid Build Coastguard Worker         }
214*387f9dfdSAndroid Build Coastguard Worker     }
215*387f9dfdSAndroid Build Coastguard Worker 
216*387f9dfdSAndroid Build Coastguard Worker EOP:
217*387f9dfdSAndroid Build Coastguard Worker     return 1;
218*387f9dfdSAndroid Build Coastguard Worker }
219*387f9dfdSAndroid Build Coastguard Worker 
br1(struct __sk_buff * skb)220*387f9dfdSAndroid Build Coastguard Worker int br1(struct __sk_buff *skb) {
221*387f9dfdSAndroid Build Coastguard Worker     return br_common(skb, 1);
222*387f9dfdSAndroid Build Coastguard Worker }
223*387f9dfdSAndroid Build Coastguard Worker 
br2(struct __sk_buff * skb)224*387f9dfdSAndroid Build Coastguard Worker int br2(struct __sk_buff *skb) {
225*387f9dfdSAndroid Build Coastguard Worker     return br_common(skb, 2);
226*387f9dfdSAndroid Build Coastguard Worker }
227