Skip to content

Commit c6435b9

Browse files
committed
Merge branch 'packet03'
2 parents b8b327a + abd7fcf commit c6435b9

File tree

13 files changed

+1455
-126
lines changed

13 files changed

+1455
-126
lines changed

common/common_defines.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@ struct config {
1010
int ifindex;
1111
char *ifname;
1212
char ifname_buf[IF_NAMESIZE];
13+
int redirect_ifindex;
14+
char *redirect_ifname;
15+
char redirect_ifname_buf[IF_NAMESIZE];
1316
bool do_unload;
1417
char filename[512];
1518
char progsec[32];
19+
char src_mac[18];
20+
char dest_mac[18];
1621
};
1722

1823
/* Defined in common_params.o */

common/common_params.c

Lines changed: 24 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:ASNFUq",
94+
while ((opt = getopt_long(argc, argv, "hd:r:L:R:ASNFUq",
9595
long_options, &longindex)) != -1) {
9696
switch (opt) {
9797
case 'd':
@@ -109,6 +109,21 @@ void parse_cmdline_args(int argc, char **argv,
109109
goto error;
110110
}
111111
break;
112+
case 'r':
113+
if (strlen(optarg) >= IF_NAMESIZE) {
114+
fprintf(stderr, "ERR: --redirect-dev name too long\n");
115+
goto error;
116+
}
117+
cfg->redirect_ifname = (char *)&cfg->redirect_ifname_buf;
118+
strncpy(cfg->redirect_ifname, optarg, IF_NAMESIZE);
119+
cfg->redirect_ifindex = if_nametoindex(cfg->redirect_ifname);
120+
if (cfg->redirect_ifindex == 0) {
121+
fprintf(stderr,
122+
"ERR: --redirect-dev name unknown err(%d):%s\n",
123+
errno, strerror(errno));
124+
goto error;
125+
}
126+
break;
112127
case 'A':
113128
cfg->xdp_flags &= ~XDP_FLAGS_MODES; /* Clear flags */
114129
break;
@@ -144,6 +159,14 @@ void parse_cmdline_args(int argc, char **argv,
144159
case 'h':
145160
full_help = true;
146161
/* 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;
147170
error:
148171
default:
149172
usage(argv[0], doc, options_wrapper, full_help);

common/parsing_helpers.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ struct vlan_hdr {
4242
__be16 h_vlan_encapsulated_proto;
4343
};
4444

45+
/*
46+
* Struct icmphdr_common represents the common part of the icmphdr and icmp6hdr
47+
* structures.
48+
*/
49+
struct icmphdr_common {
50+
__u8 type;
51+
__u8 code;
52+
__sum16 cksum;
53+
};
54+
4555
#define VLAN_MAX_DEPTH 5
4656

4757
static __always_inline int proto_is_vlan(__u16 h_proto)
@@ -160,6 +170,21 @@ static __always_inline int parse_icmphdr(struct hdr_cursor *nh,
160170
return icmph->type;
161171
}
162172

173+
static __always_inline int parse_icmphdr_common(struct hdr_cursor *nh,
174+
void *data_end,
175+
struct icmphdr_common **icmphdr)
176+
{
177+
struct icmphdr_common *h = nh->pos;
178+
179+
if (h + 1 > data_end)
180+
return -1;
181+
182+
nh->pos = h + 1;
183+
*icmphdr = h;
184+
185+
return h->type;
186+
}
187+
163188
static __always_inline struct ethhdr *get_ethhdr(struct hdr_cursor *nh,
164189
void *data_end)
165190
{

common/rewrite_helpers.h

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* This file contains functions that are used in the packetXX XDP programs to
4+
* manipulate on packets data. The functions are marked as __always_inline, and
5+
* fully defined in this header file to be included in the BPF program.
6+
*/
7+
8+
#ifndef __REWRITE_HELPERS_H
9+
#define __REWRITE_HELPERS_H
10+
11+
#include <linux/bpf.h>
12+
#include <linux/ip.h>
13+
#include <linux/ipv6.h>
14+
#include <linux/if_ether.h>
15+
16+
#include "bpf_helpers.h"
17+
#include "bpf_endian.h"
18+
19+
/* Pops the outermost VLAN tag off the packet. Returns the popped VLAN ID on
20+
* success or negative errno on failure.
21+
*/
22+
static __always_inline int vlan_tag_pop(struct xdp_md *ctx, struct ethhdr *eth)
23+
{
24+
void *data_end = (void *)(long)ctx->data_end;
25+
struct ethhdr eth_cpy;
26+
struct vlan_hdr *vlh;
27+
__be16 h_proto;
28+
int vlid;
29+
30+
if (!proto_is_vlan(eth->h_proto))
31+
return -1;
32+
33+
/* Careful with the parenthesis here */
34+
vlh = (void *)(eth + 1);
35+
36+
/* Still need to do bounds checking */
37+
if (vlh + 1 > data_end)
38+
return -1;
39+
40+
/* Save vlan ID for returning, h_proto for updating Ethernet header */
41+
vlid = bpf_ntohs(vlh->h_vlan_TCI);
42+
h_proto = vlh->h_vlan_encapsulated_proto;
43+
44+
/* Make a copy of the outer Ethernet header before we cut it off */
45+
__builtin_memcpy(&eth_cpy, eth, sizeof(eth_cpy));
46+
47+
/* Actually adjust the head pointer */
48+
if (bpf_xdp_adjust_head(ctx, (int)sizeof(*vlh)))
49+
return -1;
50+
51+
/* Need to re-evaluate data *and* data_end and do new bounds checking
52+
* after adjusting head
53+
*/
54+
eth = (void *)(long)ctx->data;
55+
data_end = (void *)(long)ctx->data_end;
56+
if (eth + 1 > data_end)
57+
return -1;
58+
59+
/* Copy back the old Ethernet header and update the proto type */
60+
__builtin_memcpy(eth, &eth_cpy, sizeof(*eth));
61+
eth->h_proto = h_proto;
62+
63+
return vlid;
64+
}
65+
66+
/* Pushes a new VLAN tag after the Ethernet header. Returns 0 on success,
67+
* -1 on failure.
68+
*/
69+
static __always_inline int vlan_tag_push(struct xdp_md *ctx,
70+
struct ethhdr *eth, int vlid)
71+
{
72+
void *data_end = (void *)(long)ctx->data_end;
73+
struct ethhdr eth_cpy;
74+
struct vlan_hdr *vlh;
75+
76+
/* First copy the original Ethernet header */
77+
__builtin_memcpy(&eth_cpy, eth, sizeof(eth_cpy));
78+
79+
/* Then add space in front of the packet */
80+
if (bpf_xdp_adjust_head(ctx, 0 - (int)sizeof(*vlh)))
81+
return -1;
82+
83+
/* Need to re-evaluate data_end and data after head adjustment, and
84+
* bounds check, even though we know there is enough space (as we
85+
* increased it).
86+
*/
87+
data_end = (void *)(long)ctx->data_end;
88+
eth = (void *)(long)ctx->data;
89+
90+
if (eth + 1 > data_end)
91+
return -1;
92+
93+
/* Copy back the Ethernet header in the right place, populate the VLAN
94+
* tag with the ID and proto, and set the outer Ethernet header to VLAN
95+
* type. */
96+
__builtin_memcpy(eth, &eth_cpy, sizeof(*eth));
97+
98+
vlh = (void *)(eth +1);
99+
100+
if (vlh + 1 > data_end)
101+
return -1;
102+
103+
vlh->h_vlan_TCI = bpf_htons(vlid);
104+
vlh->h_vlan_encapsulated_proto = eth->h_proto;
105+
106+
eth->h_proto = bpf_htons(ETH_P_8021Q);
107+
return 0;
108+
}
109+
110+
/*
111+
* Swaps destination and source MAC addresses inside an Ethernet header
112+
*/
113+
static __always_inline void swap_src_dst_mac(struct ethhdr *eth)
114+
{
115+
__u8 h_tmp[ETH_ALEN];
116+
__builtin_memcpy(h_tmp, eth->h_source, ETH_ALEN);
117+
__builtin_memcpy(eth->h_source, eth->h_dest, ETH_ALEN);
118+
__builtin_memcpy(eth->h_dest, h_tmp, ETH_ALEN);
119+
}
120+
121+
/*
122+
* Swaps destination and source IPv6 addresses inside an IPv6 header
123+
*/
124+
static __always_inline void swap_src_dst_ipv6(struct ipv6hdr *ipv6)
125+
{
126+
struct in6_addr tmp = ipv6->saddr;
127+
ipv6->saddr = ipv6->daddr;
128+
ipv6->daddr = tmp;
129+
}
130+
131+
/*
132+
* Swaps destination and source IPv4 addresses inside an IPv4 header
133+
*/
134+
static __always_inline void swap_src_dst_ipv4(struct iphdr *iphdr)
135+
{
136+
__be32 tmp = iphdr->saddr;
137+
iphdr->saddr = iphdr->daddr;
138+
iphdr->daddr = tmp;
139+
}
140+
141+
#endif /* __REWRITE_HELPERS_H */

packet-solutions/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

packet-solutions/README.org

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# -*- fill-column: 76; -*-
2+
#+TITLE: Tutorial: Packet - solutions
3+
#+OPTIONS: ^:nil
4+
5+
This directory contains solutions to all the assignments in the
6+
[[file:../packet01-parsing/][packet01]],
7+
[[file:../packet02-rewriting/][packet02]], and
8+
[[file:../packet03-redirecting/][packet03]] lessons.

0 commit comments

Comments
 (0)