Skip to content

Commit 9ee02ae

Browse files
authored
Merge pull request #168 from xdp-project/tutorial32-improve-parsing-rebase01.public
Tutorial improve parsing of VLANs (rebased #73)
2 parents 6d8c0da + 2bb3dbc commit 9ee02ae

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

common/parsing_helpers.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,15 @@ struct icmphdr_common {
5656

5757
/* Allow users of header file to redefine VLAN max depth */
5858
#ifndef VLAN_MAX_DEPTH
59-
#define VLAN_MAX_DEPTH 4
59+
#define VLAN_MAX_DEPTH 2
6060
#endif
6161

62+
#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
63+
/* Struct for collecting VLANs after parsing via parse_ethhdr_vlan */
64+
struct collect_vlans {
65+
__u16 id[VLAN_MAX_DEPTH];
66+
};
67+
6268
static __always_inline int proto_is_vlan(__u16 h_proto)
6369
{
6470
return !!(h_proto == bpf_htons(ETH_P_8021Q) ||
@@ -70,8 +76,10 @@ static __always_inline int proto_is_vlan(__u16 h_proto)
7076
* Ethernet header. Thus, caller can look at eth->h_proto to see if this was a
7177
* VLAN tagged packet.
7278
*/
73-
static __always_inline int parse_ethhdr(struct hdr_cursor *nh, void *data_end,
74-
struct ethhdr **ethhdr)
79+
static __always_inline int parse_ethhdr_vlan(struct hdr_cursor *nh,
80+
void *data_end,
81+
struct ethhdr **ethhdr,
82+
struct collect_vlans *vlans)
7583
{
7684
struct ethhdr *eth = nh->pos;
7785
int hdrsize = sizeof(*eth);
@@ -102,13 +110,25 @@ static __always_inline int parse_ethhdr(struct hdr_cursor *nh, void *data_end,
102110
break;
103111

104112
h_proto = vlh->h_vlan_encapsulated_proto;
113+
if (vlans) /* collect VLAN ids */
114+
vlans->id[i] =
115+
(bpf_ntohs(vlh->h_vlan_TCI) & VLAN_VID_MASK);
116+
105117
vlh++;
106118
}
107119

108120
nh->pos = vlh;
109121
return h_proto; /* network-byte-order */
110122
}
111123

124+
static __always_inline int parse_ethhdr(struct hdr_cursor *nh,
125+
void *data_end,
126+
struct ethhdr **ethhdr)
127+
{
128+
/* Expect compiler removes the code that collects VLAN ids */
129+
return parse_ethhdr_vlan(nh, data_end, ethhdr, NULL);
130+
}
131+
112132
static __always_inline int parse_ip6hdr(struct hdr_cursor *nh,
113133
void *data_end,
114134
struct ipv6hdr **ip6hdr)

packet-solutions/xdp_vlan02_kern.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@
1010
#define VLAN_MAX_DEPTH 10
1111
#include "../common/parsing_helpers.h"
1212

13+
#if 0
1314
#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
14-
struct vlans {
15+
struct collect_vlans {
1516
__u16 id[VLAN_MAX_DEPTH];
1617
};
18+
#endif
1719

20+
#if 0 /* moved to parsing_helpers.h */
1821
/* Based on parse_ethhdr() */
1922
static __always_inline int __parse_ethhdr_vlan(struct hdr_cursor *nh,
2023
void *data_end,
2124
struct ethhdr **ethhdr,
22-
struct vlans *vlans)
25+
struct collect_vlans *vlans)
2326
{
2427
struct ethhdr *eth = nh->pos;
2528
int hdrsize = sizeof(*eth);
@@ -51,14 +54,16 @@ static __always_inline int __parse_ethhdr_vlan(struct hdr_cursor *nh,
5154

5255
h_proto = vlh->h_vlan_encapsulated_proto;
5356
if (vlans) {
54-
vlans->id[i] = vlh->h_vlan_TCI & VLAN_VID_MASK;
57+
vlans->id[i] =
58+
bpf_ntohs(vlh->h_vlan_TCI) & VLAN_VID_MASK;
5559
}
5660
vlh++;
5761
}
5862

5963
nh->pos = vlh;
6064
return h_proto; /* network-byte-order */
6165
}
66+
#endif
6267

6368
SEC("xdp_vlan02")
6469
int xdp_vlan_02(struct xdp_md *ctx)
@@ -71,13 +76,17 @@ int xdp_vlan_02(struct xdp_md *ctx)
7176
int eth_type;
7277
nh.pos = data;
7378

74-
struct vlans vlans;
79+
struct collect_vlans vlans;
7580

7681
struct ethhdr *eth;
77-
eth_type = __parse_ethhdr_vlan(&nh, data_end, &eth, &vlans);
7882

83+
eth_type = parse_ethhdr_vlan(&nh, data_end, &eth, &vlans);
7984
if (eth_type < 0)
8085
return XDP_ABORTED;
86+
/* The eth_type have skipped VLAN-types, but collected VLAN ids. The
87+
* eth ptr still points to Ethernet header, thus to check if this is a
88+
* VLAN packet do proto_is_vlan(eth->h_proto).
89+
*/
8190

8291
/* The LLVM compiler is very clever, it sees that program only access
8392
* 2nd "inner" vlan (array index 1), and only does loop unroll of 2, and
@@ -112,7 +121,7 @@ int xdp_vlan_02(struct xdp_md *ctx)
112121
}
113122
#endif
114123
/* Hint: to inspect BPF byte-code run:
115-
* llvm-objdump -S xdp_vlan02_kern.o
124+
* llvm-objdump --no-show-raw-insn -S xdp_vlan02_kern.o
116125
*/
117126
return XDP_PASS;
118127
}

0 commit comments

Comments
 (0)