Skip to content

Commit 2874eb7

Browse files
committed
packet-solutions: extract solutions to separate files
In order to split solutions for different lessons we move XDP code to individual files. This commit creates files containing solutions for the packet03-redirecting and packet02-rewriting lessons. In particular, add a solution for the first assignment of the packet-02 lesson: rewrite UDP and TCP ports for incoming packets. The packet01-parsing is pretty simple and examples of using parsing functions can be found in all consequent examples. Signed-off-by: Anton Protopopov <a.s.protopopov@gmail.com>
1 parent f8ab60f commit 2874eb7

File tree

4 files changed

+149
-30
lines changed

4 files changed

+149
-30
lines changed

common/parsing_helpers.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include <linux/ipv6.h>
2727
#include <linux/icmp.h>
2828
#include <linux/icmpv6.h>
29+
#include <linux/udp.h>
30+
#include <linux/tcp.h>
2931

3032
/* Header cursor to keep track of current parsing position */
3133
struct hdr_cursor {
@@ -185,4 +187,50 @@ static __always_inline int parse_icmphdr_common(struct hdr_cursor *nh,
185187
return h->type;
186188
}
187189

190+
/*
191+
* parse_tcphdr: parse the udp header and return the length of the udp payload
192+
*/
193+
static __always_inline int parse_udphdr(struct hdr_cursor *nh,
194+
void *data_end,
195+
struct udphdr **udphdr)
196+
{
197+
int len;
198+
struct udphdr *h = nh->pos;
199+
200+
if (h + 1 > data_end)
201+
return -1;
202+
203+
nh->pos = h + 1;
204+
*udphdr = h;
205+
206+
len = bpf_ntohs(h->len) - sizeof(struct udphdr);
207+
if (len < 0)
208+
return -1;
209+
210+
return len;
211+
}
212+
213+
/*
214+
* parse_tcphdr: parse and return the length of the tcp header
215+
*/
216+
static __always_inline int parse_tcphdr(struct hdr_cursor *nh,
217+
void *data_end,
218+
struct tcphdr **tcphdr)
219+
{
220+
int len;
221+
struct tcphdr *h = nh->pos;
222+
223+
if (h + 1 > data_end)
224+
return -1;
225+
226+
len = h->doff * 4;
227+
if ((void *) h + len > data_end)
228+
return -1;
229+
230+
nh->pos = h + 1;
231+
*tcphdr = h;
232+
233+
return len;
234+
}
235+
188236
#endif /* __PARSING_HELPERS_H */

packet-solutions/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
22

3-
XDP_TARGETS := xdp_prog_kern
3+
XDP_TARGETS := xdp_prog_kern_02 xdp_prog_kern_03
44
USER_TARGETS := xdp_prog_user
55

66
LIBBPF_DIR = ../libbpf/src/
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#include <linux/bpf.h>
3+
#include <linux/in.h>
4+
#include "bpf_helpers.h"
5+
#include "bpf_endian.h"
6+
7+
// The parsing helper functions from the packet01 lesson have moved here
8+
#include "../common/parsing_helpers.h"
9+
#include "../common/rewrite_helpers.h"
10+
11+
/* Defines xdp_stats_map */
12+
#include "../common/xdp_stats_kern_user.h"
13+
#include "../common/xdp_stats_kern.h"
14+
15+
/*
16+
* Solution to the assignment 1 in lesson packet02
17+
*/
18+
SEC("xdp_patch_ports")
19+
int xdp_patch_ports_func(struct xdp_md *ctx)
20+
{
21+
int action = XDP_PASS;
22+
int eth_type, ip_type;
23+
struct ethhdr *eth;
24+
struct iphdr *iphdr;
25+
struct ipv6hdr *ipv6hdr;
26+
struct udphdr *udphdr;
27+
struct tcphdr *tcphdr;
28+
void *data_end = (void *)(long)ctx->data_end;
29+
void *data = (void *)(long)ctx->data;
30+
struct hdr_cursor nh = { .pos = data };
31+
32+
eth_type = parse_ethhdr(&nh, data_end, &eth);
33+
if (eth_type < 0) {
34+
action = XDP_ABORTED;
35+
goto out;
36+
}
37+
38+
if (eth_type == ETH_P_IP) {
39+
ip_type = parse_iphdr(&nh, data_end, &iphdr);
40+
} else if (eth_type == ETH_P_IPV6) {
41+
ip_type = parse_ip6hdr(&nh, data_end, &ipv6hdr);
42+
} else {
43+
goto out;
44+
}
45+
46+
if (ip_type == IPPROTO_UDP) {
47+
if (parse_udphdr(&nh, data_end, &udphdr) < 0) {
48+
action = XDP_ABORTED;
49+
goto out;
50+
}
51+
udphdr->dest = bpf_htons(bpf_ntohs(udphdr->dest) - 1);
52+
} else if (ip_type == IPPROTO_TCP) {
53+
if (parse_tcphdr(&nh, data_end, &tcphdr) < 0) {
54+
action = XDP_ABORTED;
55+
goto out;
56+
}
57+
tcphdr->dest = bpf_htons(bpf_ntohs(tcphdr->dest) - 1);
58+
}
59+
60+
out:
61+
return xdp_stats_record_action(ctx, action);
62+
}
63+
64+
/*
65+
* Solution to the assignments 2 and 3 in lesson packet02: Will pop outermost
66+
* VLAN tag if it exists, otherwise push a new one with ID 1
67+
*/
68+
SEC("xdp_vlan_swap")
69+
int xdp_vlan_swap_func(struct xdp_md *ctx)
70+
{
71+
void *data_end = (void *)(long)ctx->data_end;
72+
void *data = (void *)(long)ctx->data;
73+
74+
/* These keep track of the next header type and iterator pointer */
75+
struct hdr_cursor nh;
76+
int nh_type;
77+
nh.pos = data;
78+
79+
struct ethhdr *eth;
80+
nh_type = parse_ethhdr(&nh, data_end, &eth);
81+
if (nh_type < 0)
82+
return XDP_PASS;
83+
84+
if (proto_is_vlan(eth->h_proto))
85+
vlan_tag_pop(ctx, eth);
86+
else
87+
vlan_tag_push(ctx, eth, 1);
88+
89+
return XDP_PASS;
90+
}
91+
92+
SEC("xdp_pass")
93+
int xdp_pass_func(struct xdp_md *ctx)
94+
{
95+
return XDP_PASS;
96+
}
97+
98+
char _license[] SEC("license") = "GPL";

packet-solutions/xdp_prog_kern.c renamed to packet-solutions/xdp_prog_kern_03.c

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,33 +30,6 @@ struct bpf_map_def SEC("maps") redirect_params = {
3030
.max_entries = 1,
3131
};
3232

33-
/* Solution to the assignments in lesson packet02: Will pop outermost VLAN tag
34-
* if it exists, otherwise push a new one with ID 1
35-
*/
36-
SEC("xdp_vlan_swap")
37-
int xdp_vlan_swap_func(struct xdp_md *ctx)
38-
{
39-
void *data_end = (void *)(long)ctx->data_end;
40-
void *data = (void *)(long)ctx->data;
41-
42-
/* These keep track of the next header type and iterator pointer */
43-
struct hdr_cursor nh;
44-
int nh_type;
45-
nh.pos = data;
46-
47-
struct ethhdr *eth;
48-
nh_type = parse_ethhdr(&nh, data_end, &eth);
49-
if (nh_type < 0)
50-
return XDP_PASS;
51-
52-
if (proto_is_vlan(eth->h_proto))
53-
vlan_tag_pop(ctx, eth);
54-
else
55-
vlan_tag_push(ctx, eth, 1);
56-
57-
return XDP_PASS;
58-
}
59-
6033
static __always_inline __u16 csum_fold_helper(__u32 csum)
6134
{
6235
return ~((csum & 0xffff) + (csum >> 16));
@@ -172,7 +145,7 @@ int xdp_icmp_echo_func(struct xdp_md *ctx)
172145
return xdp_stats_record_action(ctx, action);
173146
}
174147

175-
/* Assignment 2 */
148+
/* Solution to packet03/assignment-2 */
176149
SEC("xdp_redirect")
177150
int xdp_redirect_func(struct xdp_md *ctx)
178151
{
@@ -201,7 +174,7 @@ int xdp_redirect_func(struct xdp_md *ctx)
201174
return xdp_stats_record_action(ctx, action);
202175
}
203176

204-
/* Assignment 3 */
177+
/* Solution to packet03/assignment-3 */
205178
SEC("xdp_redirect_map")
206179
int xdp_redirect_map_func(struct xdp_md *ctx)
207180
{

0 commit comments

Comments
 (0)