Skip to content

Commit f4afc73

Browse files
TropicaoKernel Patches Daemon
authored andcommitted
selftests/bpf: make test_tc_tunnel.bpf.c compatible with big endian platforms
When trying to run bpf-based encapsulation in a s390x environment, some parts of test_tc_tunnel.bpf.o do not encapsulate correctly the traffic, leading to tests failures. Adding some logs shows for example that packets about to be sent on an interface with the ip6vxlan_eth program attached do not have the expected value 5 in the ip header ihl field, and so are ignored by the program. This phenomenon appears when trying to cross-compile the selftests, rather than compiling it from a virtualized host: the selftests build system may then wrongly pick some host headers. If <asm/byteorder.h> ends up being picked on the host (and if the host has a endianness different from the target one), it will then expose wrong endianness defines (e.g __LITTLE_ENDIAN_BITFIELD instead of __BIT_ENDIAN_BITFIELD), and it will for example mess up the iphdr structure layout used in the ebpf program. To prevent this, directly use the vmlinux.h header generated by the selftests build system rather than including directly specific kernel headers. As a consequence, add some missing definitions that are not exposed by vmlinux.h, and adapt the bitfield manipulations to allow building and using the program on both types of platforms. Signed-off-by: Alexis Lothoré (eBPF Foundation) <[email protected]>
1 parent 252ec5f commit f4afc73

File tree

1 file changed

+22
-35
lines changed

1 file changed

+22
-35
lines changed

tools/testing/selftests/bpf/progs/test_tc_tunnel.c

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,11 @@
22

33
/* In-place tunneling */
44

5-
#include <stdbool.h>
6-
#include <string.h>
7-
8-
#include <linux/stddef.h>
9-
#include <linux/bpf.h>
10-
#include <linux/if_ether.h>
11-
#include <linux/in.h>
12-
#include <linux/ip.h>
13-
#include <linux/ipv6.h>
14-
#include <linux/mpls.h>
15-
#include <linux/tcp.h>
16-
#include <linux/udp.h>
17-
#include <linux/pkt_cls.h>
18-
#include <linux/types.h>
5+
#include <vmlinux.h>
196

20-
#include <bpf/bpf_endian.h>
217
#include <bpf/bpf_helpers.h>
8+
#include <bpf/bpf_endian.h>
9+
#include "bpf_tracing_net.h"
2210
#include "bpf_compiler.h"
2311

2412
#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
@@ -27,6 +15,14 @@ static const int cfg_port = 8000;
2715

2816
static const int cfg_udp_src = 20000;
2917

18+
#define ETH_P_MPLS_UC 0x8847
19+
#define ETH_P_TEB 0x6558
20+
21+
#define MPLS_LS_S_MASK 0x00000100
22+
#define BPF_F_ADJ_ROOM_ENCAP_L2(len) \
23+
(((__u64)len & BPF_ADJ_ROOM_ENCAP_L2_MASK) \
24+
<< BPF_ADJ_ROOM_ENCAP_L2_SHIFT)
25+
3026
#define L2_PAD_SZ (sizeof(struct vxlanhdr) + ETH_HLEN)
3127

3228
#define UDP_PORT 5555
@@ -36,10 +32,9 @@ static const int cfg_udp_src = 20000;
3632

3733
#define EXTPROTO_VXLAN 0x1
3834

39-
#define VXLAN_N_VID (1u << 24)
40-
#define VXLAN_VNI_MASK bpf_htonl((VXLAN_N_VID - 1) << 8)
41-
#define VXLAN_FLAGS 0x8
42-
#define VXLAN_VNI 1
35+
#define VXLAN_FLAGS bpf_htonl(1<<27)
36+
#define VNI_ID 1
37+
#define VXLAN_VNI bpf_htonl(VNI_ID << 8)
4338

4439
#ifndef NEXTHDR_DEST
4540
#define NEXTHDR_DEST 60
@@ -48,12 +43,6 @@ static const int cfg_udp_src = 20000;
4843
/* MPLS label 1000 with S bit (last label) set and ttl of 255. */
4944
static const __u32 mpls_label = __bpf_constant_htonl(1000 << 12 |
5045
MPLS_LS_S_MASK | 0xff);
51-
52-
struct vxlanhdr {
53-
__be32 vx_flags;
54-
__be32 vx_vni;
55-
} __attribute__((packed));
56-
5746
struct gre_hdr {
5847
__be16 flags;
5948
__be16 protocol;
@@ -94,8 +83,8 @@ static __always_inline void set_ipv4_csum(struct iphdr *iph)
9483
static __always_inline int __encap_ipv4(struct __sk_buff *skb, __u8 encap_proto,
9584
__u16 l2_proto, __u16 ext_proto)
9685
{
86+
struct iphdr iph_inner = {0};
9787
__u16 udp_dst = UDP_PORT;
98-
struct iphdr iph_inner;
9988
struct v4hdr h_outer;
10089
struct tcphdr tcph;
10190
int olen, l2_len;
@@ -122,7 +111,6 @@ static __always_inline int __encap_ipv4(struct __sk_buff *skb, __u8 encap_proto,
122111
return TC_ACT_OK;
123112

124113
/* Derive the IPv4 header fields from the IPv6 header */
125-
memset(&iph_inner, 0, sizeof(iph_inner));
126114
iph_inner.version = 4;
127115
iph_inner.ihl = 5;
128116
iph_inner.tot_len = bpf_htons(sizeof(iph6_inner) +
@@ -210,7 +198,7 @@ static __always_inline int __encap_ipv4(struct __sk_buff *skb, __u8 encap_proto,
210198
struct vxlanhdr *vxlan_hdr = (struct vxlanhdr *)l2_hdr;
211199

212200
vxlan_hdr->vx_flags = VXLAN_FLAGS;
213-
vxlan_hdr->vx_vni = bpf_htonl((VXLAN_VNI & VXLAN_VNI_MASK) << 8);
201+
vxlan_hdr->vx_vni = VXLAN_VNI;
214202

215203
l2_hdr += sizeof(struct vxlanhdr);
216204
}
@@ -340,7 +328,7 @@ static __always_inline int __encap_ipv6(struct __sk_buff *skb, __u8 encap_proto,
340328
struct vxlanhdr *vxlan_hdr = (struct vxlanhdr *)l2_hdr;
341329

342330
vxlan_hdr->vx_flags = VXLAN_FLAGS;
343-
vxlan_hdr->vx_vni = bpf_htonl((VXLAN_VNI & VXLAN_VNI_MASK) << 8);
331+
vxlan_hdr->vx_vni = VXLAN_VNI;
344332

345333
l2_hdr += sizeof(struct vxlanhdr);
346334
}
@@ -372,8 +360,8 @@ static __always_inline int __encap_ipv6(struct __sk_buff *skb, __u8 encap_proto,
372360

373361
static int encap_ipv6_ipip6(struct __sk_buff *skb)
374362
{
363+
struct v6hdr h_outer = {0};
375364
struct iphdr iph_inner;
376-
struct v6hdr h_outer;
377365
struct tcphdr tcph;
378366
struct ethhdr eth;
379367
__u64 flags;
@@ -400,13 +388,12 @@ static int encap_ipv6_ipip6(struct __sk_buff *skb)
400388
return TC_ACT_SHOT;
401389

402390
/* prepare new outer network header */
403-
memset(&h_outer.ip, 0, sizeof(h_outer.ip));
404391
h_outer.ip.version = 6;
405392
h_outer.ip.hop_limit = iph_inner.ttl;
406-
h_outer.ip.saddr.s6_addr[1] = 0xfd;
407-
h_outer.ip.saddr.s6_addr[15] = 1;
408-
h_outer.ip.daddr.s6_addr[1] = 0xfd;
409-
h_outer.ip.daddr.s6_addr[15] = 2;
393+
h_outer.ip.saddr.in6_u.u6_addr8[1] = 0xfd;
394+
h_outer.ip.saddr.in6_u.u6_addr8[15] = 1;
395+
h_outer.ip.daddr.in6_u.u6_addr8[1] = 0xfd;
396+
h_outer.ip.daddr.in6_u.u6_addr8[15] = 2;
410397
h_outer.ip.payload_len = iph_inner.tot_len;
411398
h_outer.ip.nexthdr = IPPROTO_IPIP;
412399

0 commit comments

Comments
 (0)