File: test_clang_complex.c

package info (click to toggle)
bpfcc 0.18.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 12,368 kB
  • sloc: ansic: 132,727; python: 36,226; cpp: 26,973; sh: 710; yacc: 525; makefile: 141; lex: 94
file content (175 lines) | stat: -rw-r--r-- 4,036 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright (c) PLUMgrid, Inc.
// Licensed under the Apache License, Version 2.0 (the "License")

#include <bcc/proto.h>

// hash
struct FwdKey {
  u32 dip:32;
};
struct FwdLeaf {
  u32 fwd_idx:32;
};
BPF_HASH(fwd_map, struct FwdKey, struct FwdLeaf, 1);

// array
struct ConfigKey {
  u32 index;
};
struct ConfigLeaf {
  u32 bpfdev_ip;
  u32 slave_ip;
};
BPF_TABLE("array", struct ConfigKey, struct ConfigLeaf, config_map, 1);

// hash
struct MacaddrKey {
  u32 ip;
};
struct MacaddrLeaf {
  u64 mac;
};
BPF_HASH(macaddr_map, struct MacaddrKey, struct MacaddrLeaf, 11);

// hash
struct SlaveKey {
  u32 slave_ip;
};
struct SlaveLeaf {
  u32 slave_ifindex;
};
BPF_HASH(slave_map, struct SlaveKey, struct SlaveLeaf, 10);

int handle_packet(struct __sk_buff *skb) {
  int ret = 0;
  u8 *cursor = 0;

  if (skb->pkt_type == 0) {
    // tx
    // make sure configured
    u32 slave_ip;

    struct ConfigKey cfg_key = {.index = 0};
    struct ConfigLeaf *cfg_leaf = config_map.lookup(&cfg_key);
    if (cfg_leaf) {
      slave_ip = cfg_leaf->slave_ip;
    } else {
      return 0xffffffff;
    }

    // make sure slave configured
    // tx, default to the single slave
    struct SlaveKey slave_key = {.slave_ip = slave_ip};
    struct SlaveLeaf *slave_leaf = slave_map.lookup(&slave_key);
    if (slave_leaf) {
      ret = slave_leaf->slave_ifindex;
    } else {
      return 0xffffffff;
    }
  } else {
    // rx, default to stack
    ret = 0;
  }

  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));
    if (skb->pkt_type) {
      if (arp->oper == 1) {
        struct MacaddrKey mac_key = {.ip=arp->spa};
        struct MacaddrLeaf mac_leaf = {.mac=arp->sha};
        macaddr_map.update(&mac_key, &mac_leaf);
      }
    }
    goto EOP;
  }

  struct ip_t *ip;
  ip: {
    ip = cursor_advance(cursor, sizeof(*ip));
    switch (ip->nextp) {
      case 6: goto tcp;
      case 17: goto udp;
      default: goto EOP;
    }
  }
  tcp: {
    struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp));
    goto EOP;
  }
  udp: {
    struct udp_t *udp = cursor_advance(cursor, sizeof(*udp));
    if (udp->dport != 5000) {
       goto EOP;
    }
    if (skb->pkt_type) {
      // lookup and then forward
      struct FwdKey fwd_key = {.dip=ip->dst};
      struct FwdLeaf *fwd_val = fwd_map.lookup(&fwd_key);
      if (fwd_val) {
         return fwd_val->fwd_idx;
      }
    } else {
      // rewrite the packet and send to a pre-configured index if needed
      u32 new_ip;
      u32 old_ip;
      u64 src_mac;
      u64 dst_mac;

      struct ConfigKey cfg_key = {.index = 0};
      struct ConfigLeaf *cfg_leaf = config_map.lookup(&cfg_key);
      if (cfg_leaf) {
        struct MacaddrKey mac_key = {.ip = cfg_leaf->bpfdev_ip};
        struct MacaddrLeaf *mac_leaf;

        mac_key.ip = cfg_leaf->bpfdev_ip;
        mac_leaf = macaddr_map.lookup(&mac_key);
        if (mac_leaf) {
          src_mac = mac_leaf->mac;
        } else {
          goto EOP;
        }

        mac_key.ip = cfg_leaf->slave_ip;
        mac_leaf = macaddr_map.lookup(&mac_key);
        if (mac_leaf) {
          dst_mac = mac_leaf->mac;
        } else {
          goto EOP;
        }

        // rewrite ethernet header
        ethernet->dst = dst_mac;
        ethernet->src = src_mac;

        // ip & udp checksum
        incr_cksum_l4(&udp->crc, ip->src, cfg_leaf->bpfdev_ip, 1);
        incr_cksum_l4(&udp->crc, ip->dst, cfg_leaf->slave_ip, 1);

        // rewrite ip src/dst fields
        ip->src = cfg_leaf->bpfdev_ip;
        ip->dst = cfg_leaf->slave_ip;
      }
    }
    goto EOP;
  }

EOP:
  return ret;
}