Skip to content

Commit a4f52bb

Browse files
committed
packet03: pass MAC addresses to xdp_prog_user as arguments
Instead of running a sudo command from the xdp_prog_user program, do pass MAC addresses as parameters. Add a new set_redirect_map command to the testenv.sh script which simplifies the process of calling the xdp_prog_user for this purpose. Update the readme correspondingly. Signed-off-by: Anton Protopopov <a.s.protopopov@gmail.com>
1 parent e270df1 commit a4f52bb

6 files changed

Lines changed: 104 additions & 50 deletions

File tree

common/common_defines.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ struct config {
1212
bool do_unload;
1313
char filename[512];
1414
char progsec[32];
15+
char src_mac[18];
16+
char dest_mac[18];
1517
};
1618

1719
/* Defined in common_params.o */

common/common_params.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ void parse_cmdline_args(int argc, char **argv,
9191
}
9292

9393
/* Parse commands line args */
94-
while ((opt = getopt_long(argc, argv, "hd:r:ASNFUq",
94+
while ((opt = getopt_long(argc, argv, "hd:r:L:R:ASNFUq",
9595
long_options, &longindex)) != -1) {
9696
switch (opt) {
9797
case 'd':
@@ -159,6 +159,14 @@ void parse_cmdline_args(int argc, char **argv,
159159
case 'h':
160160
full_help = true;
161161
/* fall-through */
162+
case 'L': /* --src-mac */
163+
dest = (char *)&cfg->src_mac;
164+
strncpy(dest, optarg, sizeof(cfg->src_mac));
165+
break;
166+
case 'R': /* --dest-mac */
167+
dest = (char *)&cfg->dest_mac;
168+
strncpy(dest, optarg, sizeof(cfg->dest_mac));
169+
break;
162170
error:
163171
default:
164172
usage(argv[0], doc, options_wrapper, full_help);

packet-solutions/xdp_prog_user.c

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,57 +38,52 @@ static const struct option_wrapper long_options[] = {
3838
{{"redirect-dev", required_argument, NULL, 'r' },
3939
"Redirect to device <ifname>", "<ifname>", true},
4040

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+
4147
{{"quiet", no_argument, NULL, 'q' },
4248
"Quiet mode (no output)"},
4349

4450
{{0, 0, NULL, 0 }, NULL, false}
4551
};
4652

47-
static void read_output(const char *cmd, char *str, size_t str_size)
53+
static int parse_u8(char *str, unsigned char *x)
4854
{
49-
FILE *f = popen(cmd, "r");
50-
if (!f) {
51-
fprintf(stderr, "can't execute %s", cmd);
52-
exit(EXIT_FAILURE);
53-
}
55+
unsigned long z;
5456

55-
if (fgets(str, str_size, f) == NULL) {
56-
fprintf(stderr, "can't read from popen(%s)", cmd);
57-
exit(EXIT_FAILURE);
58-
}
57+
z = strtoul(str, 0, 16);
58+
if (z > 0xff)
59+
return -1;
5960

60-
pclose(f);
61-
}
61+
if (x)
62+
*x = z;
6263

63-
static void parse_mac(char *str, unsigned char mac[ETH_ALEN])
64-
{
65-
mac[0] = strtoul(str, 0, 16);
66-
mac[1] = strtoul(str+3, 0, 16);
67-
mac[2] = strtoul(str+6, 0, 16);
68-
mac[3] = strtoul(str+9, 0, 16);
69-
mac[4] = strtoul(str+12, 0, 16);
70-
mac[5] = strtoul(str+15, 0, 16);
64+
return 0;
7165
}
7266

73-
static void veth_inner_mac(const char *ifname, unsigned char mac[ETH_ALEN])
67+
static int parse_mac(char *str, unsigned char mac[ETH_ALEN])
7468
{
75-
char str[64];
76-
char cmd[128];
77-
const char *fmt = "sudo ip netns exec %s cat /sys/class/net/veth0/address";
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;
7881

79-
snprintf(cmd, sizeof(cmd), fmt, ifname);
80-
read_output(cmd, str, sizeof(str));
81-
parse_mac(str, mac);
82+
return 0;
8283
}
8384

84-
static int write_iface_params(int map_fd, struct config *cfg)
85+
static int write_iface_params(int map_fd, unsigned char *src, unsigned char *dest)
8586
{
86-
unsigned char src[ETH_ALEN];
87-
unsigned char dest[ETH_ALEN];
88-
89-
veth_inner_mac(cfg->ifname, src);
90-
veth_inner_mac(cfg->redirect_ifname, dest);
91-
9287
if (bpf_map_update_elem(map_fd, src, dest, 0) < 0) {
9388
fprintf(stderr,
9489
"WARN: Failed to update bpf map file: err(%d):%s\n",
@@ -138,6 +133,8 @@ int main(int argc, char **argv)
138133
int map_fd;
139134
bool redirect_map;
140135
char pin_dir[PATH_MAX];
136+
unsigned char src[ETH_ALEN];
137+
unsigned char dest[ETH_ALEN];
141138

142139
struct config cfg = {
143140
.ifindex = -1,
@@ -161,6 +158,16 @@ int main(int argc, char **argv)
161158
return EXIT_FAIL_OPTION;
162159
}
163160

161+
if (parse_mac(cfg.src_mac, src) < 0) {
162+
fprintf(stderr, "ERR: can't parse mac address %s\n", cfg.src_mac);
163+
return EXIT_FAIL_OPTION;
164+
}
165+
166+
if (parse_mac(cfg.dest_mac, dest) < 0) {
167+
fprintf(stderr, "ERR: can't parse mac address %s\n", cfg.dest_mac);
168+
return EXIT_FAIL_OPTION;
169+
}
170+
164171
/* Open the tx_port map corresponding to the cfg.ifname interface */
165172
map_fd = open_bpf_map_file(pin_dir, "tx_port");
166173
if (map_fd < 0) {
@@ -182,7 +189,7 @@ int main(int argc, char **argv)
182189
}
183190

184191
/* Setup the mapping containing MAC addresses */
185-
if (write_iface_params(map_fd, &cfg) < 0) {
192+
if (write_iface_params(map_fd, src, dest) < 0) {
186193
fprintf(stderr, "can't write iface params\n");
187194
return 1;
188195
}

packet03-redirecting/README.org

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,12 @@ To test the code, configure environment as in the Assignment 2 and install the
176176
$ sudo ./xdp_loader -d left -F --progsec xdp_redirect_map --skb
177177
$ sudo ./xdp_loader -d right -F --progsec xdp_redirect_map --skb
178178
#+end_src
179-
Configure parameters for both interfaces using the new =xdp_prog_user= helper:
179+
Configure parameters for both interfaces using the new =xdp_prog_user= helper.
180+
For simplicity there is a new special helper, =t set_redirect_map=, which will
181+
do the work for you. See its implementation to see how it obtains inner MAC
182+
addresses by interface names.
180183
#+begin_src sh
181-
$ sudo ./xdp_prog_user -d left -r right
182-
$ sudo ./xdp_prog_user -d right -r left
184+
$ t set_redirect_map right left
183185
#+end_src
184186
Pings between the two inner interfaces should pass now. Check that they are
185187
actually forwarded by our programs by running =xdp_stats= on both interfaces:

packet03-redirecting/xdp_prog_user.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,26 @@ static const struct option_wrapper long_options[] = {
3838
{{"redirect-dev", required_argument, NULL, 'r' },
3939
"Redirect to device <ifname>", "<ifname>", true},
4040

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+
4147
{{"quiet", no_argument, NULL, 'q' },
4248
"Quiet mode (no output)"},
4349

4450
{{0, 0, NULL, 0 }, NULL, false}
4551
};
4652

47-
static void veth_inner_mac(const char *ifname, unsigned char mac[ETH_ALEN])
53+
static int parse_mac(char *str, unsigned char mac[ETH_ALEN])
4854
{
49-
/* Assignment 3: put the MAC address of the ifname's veth peer device
50-
* to the mac array */
55+
/* Assignment 3: parse a MAC address in this function and place the
56+
* result in the mac array */
5157
}
5258

53-
static int write_iface_params(int map_fd, struct config *cfg)
59+
static int write_iface_params(int map_fd, unsigned char *src, unsigned char *dest)
5460
{
55-
unsigned char src[ETH_ALEN];
56-
unsigned char dest[ETH_ALEN];
57-
58-
veth_inner_mac(cfg->ifname, src);
59-
veth_inner_mac(cfg->redirect_ifname, dest);
60-
6161
if (bpf_map_update_elem(map_fd, src, dest, 0) < 0) {
6262
fprintf(stderr,
6363
"WARN: Failed to update bpf map file: err(%d):%s\n",
@@ -86,6 +86,8 @@ int main(int argc, char **argv)
8686
int map_fd;
8787
bool redirect_map;
8888
char pin_dir[PATH_MAX];
89+
unsigned char src[ETH_ALEN];
90+
unsigned char dest[ETH_ALEN];
8991

9092
struct config cfg = {
9193
.ifindex = -1,
@@ -109,6 +111,17 @@ int main(int argc, char **argv)
109111
return EXIT_FAIL_OPTION;
110112
}
111113

114+
if (parse_mac(cfg.src_mac, src) < 0) {
115+
fprintf(stderr, "ERR: can't parse mac address %s\n", cfg.src_mac);
116+
return EXIT_FAIL_OPTION;
117+
}
118+
119+
if (parse_mac(cfg.dest_mac, dest) < 0) {
120+
fprintf(stderr, "ERR: can't parse mac address %s\n", cfg.dest_mac);
121+
return EXIT_FAIL_OPTION;
122+
}
123+
124+
112125
/* Assignment 3: open the tx_port map corresponding to the cfg.ifname interface */
113126
map_fd = -1;
114127

@@ -124,7 +137,7 @@ int main(int argc, char **argv)
124137
map_fd = -1;
125138

126139
/* Setup the mapping containing MAC addresses */
127-
if (write_iface_params(map_fd, &cfg) < 0) {
140+
if (write_iface_params(map_fd, src, dest) < 0) {
128141
fprintf(stderr, "can't write iface params\n");
129142
return 1;
130143
}

testenv/testenv.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,23 @@ print_alias()
400400
echo "alias t='$sudo$scriptname'"
401401
}
402402

403+
#
404+
# This command can be used to set maps for the assignment 3 of the
405+
# packet03-redirecting lesson. It takes two arguments: the source and the
406+
# destination interface names.
407+
#
408+
set_redirect_map()
409+
{
410+
local src="$1"
411+
local dest="$2"
412+
local src_mac=$(ip netns exec $src cat /sys/class/net/veth0/address)
413+
local dest_mac=$(ip netns exec $dest cat /sys/class/net/veth0/address)
414+
415+
# set bidirectional forwarding
416+
./xdp_prog_user -d $src -r $dest --src-mac $src_mac --dest-mac $dest_mac
417+
./xdp_prog_user -d $dest -r $src --src-mac $dest_mac --dest-mac $src_mac
418+
}
419+
403420
xdp_load()
404421
{
405422
get_nsname && ensure_nsname
@@ -443,6 +460,7 @@ usage()
443460
echo "unload Unload XDP program on outer interface"
444461
echo "tcpdump Run on outer interface (or inner with --inner)"
445462
echo "stats Run the XDP statistics program"
463+
echo "set_redirect_map Setup redirect maps for packet03 lessons"
446464
echo ""
447465

448466
if [ -z "$FULL" ] ; then
@@ -552,6 +570,10 @@ case "$1" in
552570
ping|tcpdump)
553571
CMD="run_$1"
554572
;;
573+
set_redirect_map)
574+
CMD="set_redirect_map $2 $3"
575+
shift 2
576+
;;
555577
"alias")
556578
print_alias
557579
exit 0

0 commit comments

Comments
 (0)