Skip to content

Commit

Permalink
Merge pull request #168 from xdp-project/tutorial32-improve-parsing-r…
Browse files Browse the repository at this point in the history
…ebase01.public

Tutorial improve parsing of VLANs (rebased #73)
  • Loading branch information
netoptimizer authored Nov 15, 2020
2 parents 6d8c0da + 2bb3dbc commit 9ee02ae
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 9 deletions.
26 changes: 23 additions & 3 deletions common/parsing_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,15 @@ struct icmphdr_common {

/* Allow users of header file to redefine VLAN max depth */
#ifndef VLAN_MAX_DEPTH
#define VLAN_MAX_DEPTH 4
#define VLAN_MAX_DEPTH 2
#endif

#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
/* Struct for collecting VLANs after parsing via parse_ethhdr_vlan */
struct collect_vlans {
__u16 id[VLAN_MAX_DEPTH];
};

static __always_inline int proto_is_vlan(__u16 h_proto)
{
return !!(h_proto == bpf_htons(ETH_P_8021Q) ||
Expand All @@ -70,8 +76,10 @@ static __always_inline int proto_is_vlan(__u16 h_proto)
* Ethernet header. Thus, caller can look at eth->h_proto to see if this was a
* VLAN tagged packet.
*/
static __always_inline int parse_ethhdr(struct hdr_cursor *nh, void *data_end,
struct ethhdr **ethhdr)
static __always_inline int parse_ethhdr_vlan(struct hdr_cursor *nh,
void *data_end,
struct ethhdr **ethhdr,
struct collect_vlans *vlans)
{
struct ethhdr *eth = nh->pos;
int hdrsize = sizeof(*eth);
Expand Down Expand Up @@ -102,13 +110,25 @@ static __always_inline int parse_ethhdr(struct hdr_cursor *nh, void *data_end,
break;

h_proto = vlh->h_vlan_encapsulated_proto;
if (vlans) /* collect VLAN ids */
vlans->id[i] =
(bpf_ntohs(vlh->h_vlan_TCI) & VLAN_VID_MASK);

vlh++;
}

nh->pos = vlh;
return h_proto; /* network-byte-order */
}

static __always_inline int parse_ethhdr(struct hdr_cursor *nh,
void *data_end,
struct ethhdr **ethhdr)
{
/* Expect compiler removes the code that collects VLAN ids */
return parse_ethhdr_vlan(nh, data_end, ethhdr, NULL);
}

static __always_inline int parse_ip6hdr(struct hdr_cursor *nh,
void *data_end,
struct ipv6hdr **ip6hdr)
Expand Down
21 changes: 15 additions & 6 deletions packet-solutions/xdp_vlan02_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@
#define VLAN_MAX_DEPTH 10
#include "../common/parsing_helpers.h"

#if 0
#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
struct vlans {
struct collect_vlans {
__u16 id[VLAN_MAX_DEPTH];
};
#endif

#if 0 /* moved to parsing_helpers.h */
/* Based on parse_ethhdr() */
static __always_inline int __parse_ethhdr_vlan(struct hdr_cursor *nh,
void *data_end,
struct ethhdr **ethhdr,
struct vlans *vlans)
struct collect_vlans *vlans)
{
struct ethhdr *eth = nh->pos;
int hdrsize = sizeof(*eth);
Expand Down Expand Up @@ -51,14 +54,16 @@ static __always_inline int __parse_ethhdr_vlan(struct hdr_cursor *nh,

h_proto = vlh->h_vlan_encapsulated_proto;
if (vlans) {
vlans->id[i] = vlh->h_vlan_TCI & VLAN_VID_MASK;
vlans->id[i] =
bpf_ntohs(vlh->h_vlan_TCI) & VLAN_VID_MASK;
}
vlh++;
}

nh->pos = vlh;
return h_proto; /* network-byte-order */
}
#endif

SEC("xdp_vlan02")
int xdp_vlan_02(struct xdp_md *ctx)
Expand All @@ -71,13 +76,17 @@ int xdp_vlan_02(struct xdp_md *ctx)
int eth_type;
nh.pos = data;

struct vlans vlans;
struct collect_vlans vlans;

struct ethhdr *eth;
eth_type = __parse_ethhdr_vlan(&nh, data_end, &eth, &vlans);

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

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

0 comments on commit 9ee02ae

Please sign in to comment.