Skip to content

Commit 0fedd26

Browse files
committed
Add packet04-tailgrow
Start with trimmed down version of packet-solution files. Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
1 parent 7cd4b4c commit 0fedd26

3 files changed

Lines changed: 296 additions & 0 deletions

File tree

packet04-tailgrow/Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+
3+
XDP_TARGETS := xdp_prog_kern
4+
USER_TARGETS := xdp_prog_user
5+
6+
LIBBPF_DIR = ../libbpf/src/
7+
COMMON_DIR = ../common
8+
9+
COPY_LOADER := xdp_loader
10+
COPY_STATS := xdp_stats
11+
EXTRA_DEPS := $(COMMON_DIR)/parsing_helpers.h
12+
13+
include $(COMMON_DIR)/common.mk

packet04-tailgrow/xdp_prog_kern.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#include <linux/bpf.h>
3+
#include <linux/in.h>
4+
#include <bpf/bpf_helpers.h>
5+
#include <bpf/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+
#ifndef memcpy
16+
#define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))
17+
#endif
18+
19+
struct bpf_map_def SEC("maps") tx_port = {
20+
.type = BPF_MAP_TYPE_DEVMAP,
21+
.key_size = sizeof(int),
22+
.value_size = sizeof(int),
23+
.max_entries = 256,
24+
};
25+
26+
struct bpf_map_def SEC("maps") redirect_params = {
27+
.type = BPF_MAP_TYPE_HASH,
28+
.key_size = ETH_ALEN,
29+
.value_size = ETH_ALEN,
30+
.max_entries = 1,
31+
};
32+
33+
/* Solution to packet03/assignment-2 */
34+
SEC("xdp_redirect")
35+
int xdp_redirect_func(struct xdp_md *ctx)
36+
{
37+
void *data_end = (void *)(long)ctx->data_end;
38+
void *data = (void *)(long)ctx->data;
39+
struct hdr_cursor nh;
40+
struct ethhdr *eth;
41+
int eth_type;
42+
int action = XDP_PASS;
43+
unsigned char dst[ETH_ALEN] = { /* TODO: put your values here */ };
44+
unsigned ifindex = 0/* TODO: put your values here */;
45+
46+
/* These keep track of the next header type and iterator pointer */
47+
nh.pos = data;
48+
49+
/* Parse Ethernet and IP/IPv6 headers */
50+
eth_type = parse_ethhdr(&nh, data_end, &eth);
51+
if (eth_type == -1)
52+
goto out;
53+
54+
/* Set a proper destination address */
55+
memcpy(eth->h_dest, dst, ETH_ALEN);
56+
action = bpf_redirect(ifindex, 0);
57+
58+
out:
59+
return xdp_stats_record_action(ctx, action);
60+
}
61+
62+
/* Solution to packet03/assignment-3 */
63+
SEC("xdp_redirect_map")
64+
int xdp_redirect_map_func(struct xdp_md *ctx)
65+
{
66+
void *data_end = (void *)(long)ctx->data_end;
67+
void *data = (void *)(long)ctx->data;
68+
struct hdr_cursor nh;
69+
struct ethhdr *eth;
70+
int eth_type;
71+
int action = XDP_PASS;
72+
unsigned char *dst;
73+
74+
/* These keep track of the next header type and iterator pointer */
75+
nh.pos = data;
76+
77+
/* Parse Ethernet and IP/IPv6 headers */
78+
eth_type = parse_ethhdr(&nh, data_end, &eth);
79+
if (eth_type == -1)
80+
goto out;
81+
82+
/* Do we know where to redirect this packet? */
83+
dst = bpf_map_lookup_elem(&redirect_params, eth->h_source);
84+
if (!dst)
85+
goto out;
86+
87+
/* Set a proper destination address */
88+
memcpy(eth->h_dest, dst, ETH_ALEN);
89+
action = bpf_redirect_map(&tx_port, 0, 0);
90+
91+
out:
92+
return xdp_stats_record_action(ctx, action);
93+
}
94+
95+
SEC("xdp_pass")
96+
int xdp_pass_func(struct xdp_md *ctx)
97+
{
98+
return xdp_stats_record_action(ctx, XDP_PASS);
99+
}
100+
101+
char _license[] SEC("license") = "GPL";

packet04-tailgrow/xdp_prog_user.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
static const char *__doc__ = "XDP redirect helper\n"
4+
" - Allows to populate/query tx_port and redirect_params maps\n";
5+
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <string.h>
9+
#include <errno.h>
10+
#include <getopt.h>
11+
#include <stdbool.h>
12+
13+
#include <locale.h>
14+
#include <unistd.h>
15+
#include <time.h>
16+
17+
#include <bpf/bpf.h>
18+
#include <bpf/libbpf.h>
19+
20+
#include <net/if.h>
21+
#include <linux/if_ether.h>
22+
#include <linux/if_link.h> /* depend on kernel-headers installed */
23+
24+
#include "../common/common_params.h"
25+
#include "../common/common_user_bpf_xdp.h"
26+
#include "../common/common_libbpf.h"
27+
28+
#include "../common/xdp_stats_kern_user.h"
29+
30+
static const struct option_wrapper long_options[] = {
31+
32+
{{"help", no_argument, NULL, 'h' },
33+
"Show help", false},
34+
35+
{{"dev", required_argument, NULL, 'd' },
36+
"Operate on device <ifname>", "<ifname>", true},
37+
38+
{{"redirect-dev", required_argument, NULL, 'r' },
39+
"Redirect to device <ifname>", "<ifname>", true},
40+
41+
{{"src-mac", required_argument, NULL, 'L' },
42+
"Source MAC address of <dev>", "<mac>", true },
43+
44+
{{"dest-mac", required_argument, NULL, 'R' },
45+
"Destination MAC address of <redirect-dev>", "<mac>", true },
46+
47+
{{"quiet", no_argument, NULL, 'q' },
48+
"Quiet mode (no output)"},
49+
50+
{{0, 0, NULL, 0 }, NULL, false}
51+
};
52+
53+
static int parse_u8(char *str, unsigned char *x)
54+
{
55+
unsigned long z;
56+
57+
z = strtoul(str, 0, 16);
58+
if (z > 0xff)
59+
return -1;
60+
61+
if (x)
62+
*x = z;
63+
64+
return 0;
65+
}
66+
67+
static int parse_mac(char *str, unsigned char mac[ETH_ALEN])
68+
{
69+
if (parse_u8(str, &mac[0]) < 0)
70+
return -1;
71+
if (parse_u8(str + 3, &mac[1]) < 0)
72+
return -1;
73+
if (parse_u8(str + 6, &mac[2]) < 0)
74+
return -1;
75+
if (parse_u8(str + 9, &mac[3]) < 0)
76+
return -1;
77+
if (parse_u8(str + 12, &mac[4]) < 0)
78+
return -1;
79+
if (parse_u8(str + 15, &mac[5]) < 0)
80+
return -1;
81+
82+
return 0;
83+
}
84+
85+
static int write_iface_params(int map_fd, unsigned char *src, unsigned char *dest)
86+
{
87+
if (bpf_map_update_elem(map_fd, src, dest, 0) < 0) {
88+
fprintf(stderr,
89+
"WARN: Failed to update bpf map file: err(%d):%s\n",
90+
errno, strerror(errno));
91+
return -1;
92+
}
93+
94+
printf("forward: %02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x\n",
95+
src[0], src[1], src[2], src[3], src[4], src[5],
96+
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]
97+
);
98+
99+
return 0;
100+
}
101+
102+
#ifndef PATH_MAX
103+
#define PATH_MAX 4096
104+
#endif
105+
106+
const char *pin_basedir = "/sys/fs/bpf";
107+
108+
int main(int argc, char **argv)
109+
{
110+
int i;
111+
int len;
112+
int map_fd;
113+
bool redirect_map;
114+
char pin_dir[PATH_MAX];
115+
unsigned char src[ETH_ALEN];
116+
unsigned char dest[ETH_ALEN];
117+
118+
struct config cfg = {
119+
.ifindex = -1,
120+
.redirect_ifindex = -1,
121+
};
122+
123+
/* Cmdline options can change progsec */
124+
parse_cmdline_args(argc, argv, long_options, &cfg, __doc__);
125+
126+
redirect_map = (cfg.ifindex > 0) && (cfg.redirect_ifindex > 0);
127+
128+
if (cfg.redirect_ifindex > 0 && cfg.ifindex == -1) {
129+
fprintf(stderr, "ERR: required option --dev missing\n\n");
130+
usage(argv[0], __doc__, long_options, (argc == 1));
131+
return EXIT_FAIL_OPTION;
132+
}
133+
134+
len = snprintf(pin_dir, PATH_MAX, "%s/%s", pin_basedir, cfg.ifname);
135+
if (len < 0) {
136+
fprintf(stderr, "ERR: creating pin dirname\n");
137+
return EXIT_FAIL_OPTION;
138+
}
139+
140+
if (parse_mac(cfg.src_mac, src) < 0) {
141+
fprintf(stderr, "ERR: can't parse mac address %s\n", cfg.src_mac);
142+
return EXIT_FAIL_OPTION;
143+
}
144+
145+
if (parse_mac(cfg.dest_mac, dest) < 0) {
146+
fprintf(stderr, "ERR: can't parse mac address %s\n", cfg.dest_mac);
147+
return EXIT_FAIL_OPTION;
148+
}
149+
150+
/* Open the tx_port map corresponding to the cfg.ifname interface */
151+
map_fd = open_bpf_map_file(pin_dir, "tx_port", NULL);
152+
if (map_fd < 0) {
153+
return EXIT_FAIL_BPF;
154+
}
155+
156+
printf("map dir: %s\n", pin_dir);
157+
158+
if (redirect_map) {
159+
/* setup a virtual port for the static redirect */
160+
i = 0;
161+
bpf_map_update_elem(map_fd, &i, &cfg.redirect_ifindex, 0);
162+
printf("redirect from ifnum=%d to ifnum=%d\n", cfg.ifindex, cfg.redirect_ifindex);
163+
164+
/* Open the redirect_params map */
165+
map_fd = open_bpf_map_file(pin_dir, "redirect_params", NULL);
166+
if (map_fd < 0) {
167+
return EXIT_FAIL_BPF;
168+
}
169+
170+
/* Setup the mapping containing MAC addresses */
171+
if (write_iface_params(map_fd, src, dest) < 0) {
172+
fprintf(stderr, "can't write iface params\n");
173+
return 1;
174+
}
175+
} else {
176+
/* setup 1-1 mapping for the dynamic router */
177+
for (i = 1; i < 256; ++i)
178+
bpf_map_update_elem(map_fd, &i, &i, 0);
179+
}
180+
181+
return EXIT_OK;
182+
}

0 commit comments

Comments
 (0)