Skip to content

Commit 8d91b14

Browse files
author
Yoel Caspersen
committed
Upstream direction works with QinQ packets only
When allowing packets with 1 VLAN tag only, verifier complains about BPF program being too large. Compiled with LLVM 13. Signed-off-by: Yoel Caspersen <[email protected]>
1 parent 83b9795 commit 8d91b14

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

dhcp-relay/dhcp-relay.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#define DHCP_REQUEST 1
1919
#define DHCP_REPLY 2
2020

21+
#define MAX_LOOPS 40
22+
2123
/* Structure for sub-options in option 82 */
2224
struct sub_option {
2325
__u8 option_id;

dhcp-relay/dhcp_kern_xdp.c

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ void memcpy_var(void *to, void *from, __u64 len) {
6060
__u8 *t8 = to, *f8 = from;
6161
int i;
6262

63-
for (i = 0; i < len; i++) {
63+
for (i = 0; i < len && i < MAX_LOOPS; i++) {
6464
*t8++ = *f8++;
6565
}
6666

@@ -70,7 +70,7 @@ void memset_var(void *d, __u8 c, __u64 len) {
7070
__u8 *d8 = d;
7171
int i;
7272

73-
for (i = 0; i < len; i++) {
73+
for (i = 0; i < len && i < MAX_LOOPS; i++) {
7474
*d8++ = c;
7575
}
7676

@@ -84,6 +84,8 @@ static __always_inline int write_dhcp_option_82(void *ctx, int offset,
8484

8585
struct dhcp_option_82 option;
8686

87+
static __u8 buf[RAI_OPTION_LEN];
88+
8789
option.t = DHO_DHCP_AGENT_OPTIONS;
8890
option.len = sizeof (struct sub_option) + sizeof (struct sub_option);
8991
option.circuit_id.option_id = RAI_CIRCUIT_ID;
@@ -104,15 +106,16 @@ static __always_inline int write_dhcp_option_82(void *ctx, int offset,
104106
* contains null bytes.
105107
*/
106108

107-
char buf[RAI_OPTION_LEN];
108109
memset(buf, 0, sizeof (buf));
109110

110111
int c = VLAN_ASCII_MAX; /* We will need 4 bytes at most */
111112
int i = RAI_OPTION_LEN - 1;
113+
112114
__u16 inner_vlan = vlans->id[1];
113115
__u16 outer_vlan = vlans->id[0];
114116

115117
/* Convert inner VLAN to ASCII */
118+
#pragma unroll VLAN_ASCII_MAX
116119
for (c = VLAN_ASCII_MAX; c > 0; c--) {
117120
buf[i--] = (inner_vlan % 10) + '0';
118121
inner_vlan /= 10;
@@ -124,6 +127,7 @@ static __always_inline int write_dhcp_option_82(void *ctx, int offset,
124127
buf[i--] = '.';
125128

126129
/* Convert outer VLAN to ASCII */
130+
#pragma unroll VLAN_ASCII_MAX
127131
for (c = VLAN_ASCII_MAX; c > 0; c--) {
128132
buf[i--] = (outer_vlan % 10) + '0';
129133
outer_vlan /= 10;
@@ -132,10 +136,10 @@ static __always_inline int write_dhcp_option_82(void *ctx, int offset,
132136
}
133137
}
134138

135-
136139
buf[i--] = '.';
137140

138141
/* Append interface name */
142+
#pragma unroll RAI_OPTION_LEN
139143
for (c = RAI_OPTION_LEN - 1; c >= 0; c--) {
140144
if (dev[c] != 0)
141145
buf[i--] = dev[c];
@@ -148,8 +152,9 @@ static __always_inline int write_dhcp_option_82(void *ctx, int offset,
148152
/* Copy resulting interface name to circuit_id */
149153
if (sizeof (option.circuit_id.val) == sizeof (buf)) {
150154
memcpy_var(option.circuit_id.val, buf + i, sizeof (buf) - i);
155+
//memcpy_var(option.circuit_id.val, buf, sizeof (buf));
151156
}
152-
157+
153158
return xdp_store_bytes(ctx, offset, &option, sizeof (option), 0);
154159
}
155160

@@ -206,10 +211,10 @@ int xdp_dhcp_relay(struct xdp_md *ctx) {
206211
int res = bpf_xdp_adjust_tail(ctx, delta);
207212
if (res != 0) {
208213
bpf_printk("Cannot tail extend packet, delta %i - error code %i", delta, res);
209-
return XDP_ABORTED;
214+
return XDP_PASS;
210215
}
211216

212-
bpf_printk("Tail extended packet by %i bytes", delta);
217+
//bpf_printk("Tail extended packet by %i bytes", delta);
213218

214219
void *data_end = (void *) (long) ctx->data_end;
215220
void *data = (void *) (long) ctx->data;
@@ -240,27 +245,34 @@ int xdp_dhcp_relay(struct xdp_md *ctx) {
240245
int key = 0;
241246
int len = 0;
242247

243-
if (data + 1 > data_end)
244-
return XDP_ABORTED;
248+
if (data + 1 > data_end) {
249+
bpf_printk("Empty packet\n");
250+
goto out;
251+
}
245252

246253
nh.pos = data;
247254
ether_type = parse_ethhdr_vlan(&nh, data_end, &eth, &vlans);
248255
/* check for valid ether type */
249256
if (ether_type < 0) {
250-
bpf_printk("Cannot determine ethertype");
251-
rc = XDP_ABORTED;
257+
bpf_printk("Cannot determine ethertype\n");
252258
goto out;
253259
}
260+
254261
if (ether_type != bpf_htons(ETH_P_IP)) {
255-
bpf_printk("Ethertype %#x is not ETH_P_IP", bpf_ntohs(ether_type));
262+
//bpf_printk("Ethertype %x is not ETH_P_IP\n", bpf_ntohs(ether_type));
256263
goto out;
257264
}
258265

259-
bpf_printk("Ethertype %x", bpf_ntohs(ether_type));
260-
266+
bpf_printk("Ethertype %x\n", bpf_ntohs(ether_type));
267+
261268
/* Check at least two vlan tags are present */
269+
if (vlans.id[0] == 0) {
270+
bpf_printk("No outer VLAN tag set\n");
271+
goto out;
272+
}
273+
262274
if (vlans.id[1] == 0) {
263-
bpf_printk("No VLAN tags set");
275+
bpf_printk("No inner VLAN tag set\n");
264276
goto out;
265277
}
266278

@@ -287,6 +299,8 @@ int xdp_dhcp_relay(struct xdp_md *ctx) {
287299

288300
/* Increase UDP length header */
289301
udp->len += bpf_htons(delta);
302+
303+
udp->check = 0;
290304

291305
/* Read DHCP server IP from config map */
292306
key = 0;
@@ -317,6 +331,7 @@ int xdp_dhcp_relay(struct xdp_md *ctx) {
317331
// goto out;
318332

319333
/* Increment offset by 4 bytes for each VLAN (to accomodate VLAN headers */
334+
#pragma unroll VLAN_MAX_DEPTH
320335
for (i = 0; i < VLAN_MAX_DEPTH; i++) {
321336
if (vlans.id[i]) {
322337

@@ -449,7 +464,7 @@ int xdp_dhcp_relay(struct xdp_md *ctx) {
449464
bpf_printk("Could not write DHCP option 82 at offset %i", option_offset);
450465
return XDP_ABORTED;
451466
}
452-
467+
453468
/* Set END option */
454469

455470
/* Verifier check */

0 commit comments

Comments
 (0)