提交 3f13de6d 编写于 作者: D Daniel Borkmann

Merge branch 'bpf-tunnel-metadata-selftests'

William Tu says:

====================
The patch series provide end-to-end eBPF tunnel testsute.  A common topology
is created below for all types of tunnels:

Topology:
---------
     root namespace   |     at_ns0 namespace
                      |
      -----------     |     -----------
      | tnl dev |     |     | tnl dev |  (overlay network)
      -----------     |     -----------
      metadata-mode   |     native-mode
       with bpf       |
                      |
      ----------      |     ----------
      |  veth1  | --------- |  veth0  |  (underlay network)
      ----------    peer    ----------

Device Configuration
--------------------
 Root namespace with metadata-mode tunnel + BPF
 Device names and addresses:
       veth1 IP: 172.16.1.200, IPv6: 00::22 (underlay)
       tunnel dev <type>11, ex: gre11, IPv4: 10.1.1.200 (overlay)

 Namespace at_ns0 with native tunnel
 Device names and addresses:
       veth0 IPv4: 172.16.1.100, IPv6: 00::11 (underlay)
       tunnel dev <type>00, ex: gre00, IPv4: 10.1.1.100 (overlay)

End-to-end ping packet flow
---------------------------
 Most of the tests start by namespace creation, device configuration,
 then ping the underlay and overlay network.  When doing 'ping 10.1.1.100'
 from root namespace, the following operations happen:
 1) Route lookup shows 10.1.1.100/24 belongs to tnl dev, fwd to tnl dev.
 2) Tnl device's egress BPF program is triggered and set the tunnel metadata,
    with remote_ip=172.16.1.200 and others.
 3) Outer tunnel header is prepended and route the packet to veth1's egress
 4) veth0's ingress queue receive the tunneled packet at namespace at_ns0
 5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet
 6) Forward the packet to the overlay tnl dev

Test Cases
-----------------------------
 Tunnel Type |  BPF Programs
-----------------------------
 GRE:          gre_set_tunnel, gre_get_tunnel
 IP6GRE:       ip6gretap_set_tunnel, ip6gretap_get_tunnel
 ERSPAN:       erspan_set_tunnel, erspan_get_tunnel
 IP6ERSPAN:    ip4ip6erspan_set_tunnel, ip4ip6erspan_get_tunnel
 VXLAN:        vxlan_set_tunnel, vxlan_get_tunnel
 IP6VXLAN:     ip6vxlan_set_tunnel, ip6vxlan_get_tunnel
 GENEVE:       geneve_set_tunnel, geneve_get_tunnel
 IP6GENEVE:    ip6geneve_set_tunnel, ip6geneve_get_tunnel
 IPIP:         ipip_set_tunnel, ipip_get_tunnel
 IP6IP:        ipip6_set_tunnel, ipip6_get_tunnel,
               ip6ip6_set_tunnel, ip6ip6_get_tunnel
 XFRM:         xfrm_get_state
====================
Signed-off-by: NDaniel Borkmann <daniel@iogearbox.net>
......@@ -114,7 +114,6 @@ always += sock_flags_kern.o
always += test_probe_write_user_kern.o
always += trace_output_kern.o
always += tcbpf1_kern.o
always += tcbpf2_kern.o
always += tc_l2_redirect_kern.o
always += lathist_kern.o
always += offwaketime_kern.o
......
......@@ -32,7 +32,7 @@ TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test
test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \
sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o \
sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o test_adjust_tail.o \
test_btf_haskv.o test_btf_nokv.o test_sockmap_kern.o
test_btf_haskv.o test_btf_nokv.o test_sockmap_kern.o test_tunnel_kern.o
# Order correspond to 'make run_tests' order
TEST_PROGS := test_kmod.sh \
......@@ -40,7 +40,8 @@ TEST_PROGS := test_kmod.sh \
test_xdp_redirect.sh \
test_xdp_meta.sh \
test_offload.py \
test_sock_addr.sh
test_sock_addr.sh \
test_tunnel.sh
# Compile but not part of 'make run_tests'
TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr
......
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2016 VMware
* Copyright (c) 2016 Facebook
*
......@@ -5,39 +6,41 @@
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
#define KBUILD_MODNAME "foo"
#include <uapi/linux/bpf.h>
#include <uapi/linux/if_ether.h>
#include <uapi/linux/if_packet.h>
#include <uapi/linux/ip.h>
#include <uapi/linux/ipv6.h>
#include <uapi/linux/in.h>
#include <uapi/linux/tcp.h>
#include <uapi/linux/filter.h>
#include <uapi/linux/pkt_cls.h>
#include <uapi/linux/erspan.h>
#include <net/ipv6.h>
#include <stddef.h>
#include <string.h>
#include <arpa/inet.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/types.h>
#include <linux/tcp.h>
#include <linux/socket.h>
#include <linux/pkt_cls.h>
#include <linux/erspan.h>
#include "bpf_helpers.h"
#include "bpf_endian.h"
#define _htonl __builtin_bswap32
#define ERROR(ret) do {\
char fmt[] = "ERROR line:%d ret:%d\n";\
bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
} while(0)
} while (0)
int _version SEC("version") = 1;
struct geneve_opt {
__be16 opt_class;
u8 type;
u8 length:5;
u8 r3:1;
u8 r2:1;
u8 r1:1;
u8 opt_data[8]; /* hard-coded to 8 byte */
__u8 type;
__u8 length:5;
__u8 r3:1;
__u8 r2:1;
__u8 r1:1;
__u8 opt_data[8]; /* hard-coded to 8 byte */
};
struct vxlan_metadata {
u32 gbp;
__u32 gbp;
};
SEC("gre_set_tunnel")
......@@ -86,7 +89,7 @@ int _ip6gretap_set_tunnel(struct __sk_buff *skb)
int ret;
__builtin_memset(&key, 0x0, sizeof(key));
key.remote_ipv6[3] = _htonl(0x11); /* ::11 */
key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
key.tunnel_id = 2;
key.tunnel_tos = 0;
key.tunnel_ttl = 64;
......@@ -136,7 +139,8 @@ int _erspan_set_tunnel(struct __sk_buff *skb)
key.tunnel_tos = 0;
key.tunnel_ttl = 64;
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
BPF_F_ZERO_CSUM_TX);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
......@@ -147,8 +151,8 @@ int _erspan_set_tunnel(struct __sk_buff *skb)
md.version = 1;
md.u.index = bpf_htonl(123);
#else
u8 direction = 1;
u8 hwid = 7;
__u8 direction = 1;
__u8 hwid = 7;
md.version = 2;
md.u.md2.dir = direction;
......@@ -171,7 +175,7 @@ int _erspan_get_tunnel(struct __sk_buff *skb)
char fmt[] = "key %d remote ip 0x%x erspan version %d\n";
struct bpf_tunnel_key key;
struct erspan_metadata md;
u32 index;
__u32 index;
int ret;
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
......@@ -214,7 +218,7 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
int ret;
__builtin_memset(&key, 0x0, sizeof(key));
key.remote_ipv6[3] = _htonl(0x11);
key.remote_ipv6[3] = bpf_htonl(0x11);
key.tunnel_id = 2;
key.tunnel_tos = 0;
key.tunnel_ttl = 64;
......@@ -229,11 +233,11 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
__builtin_memset(&md, 0, sizeof(md));
#ifdef ERSPAN_V1
md.u.index = htonl(123);
md.u.index = bpf_htonl(123);
md.version = 1;
#else
u8 direction = 0;
u8 hwid = 17;
__u8 direction = 0;
__u8 hwid = 17;
md.version = 2;
md.u.md2.dir = direction;
......@@ -256,10 +260,11 @@ int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n";
struct bpf_tunnel_key key;
struct erspan_metadata md;
u32 index;
__u32 index;
int ret;
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
BPF_F_TUNINFO_IPV6);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
......@@ -304,7 +309,8 @@ int _vxlan_set_tunnel(struct __sk_buff *skb)
key.tunnel_tos = 0;
key.tunnel_ttl = 64;
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
BPF_F_ZERO_CSUM_TX);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
......@@ -346,6 +352,48 @@ int _vxlan_get_tunnel(struct __sk_buff *skb)
return TC_ACT_OK;
}
SEC("ip6vxlan_set_tunnel")
int _ip6vxlan_set_tunnel(struct __sk_buff *skb)
{
struct bpf_tunnel_key key;
int ret;
__builtin_memset(&key, 0x0, sizeof(key));
key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
key.tunnel_id = 22;
key.tunnel_tos = 0;
key.tunnel_ttl = 64;
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
BPF_F_TUNINFO_IPV6);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
}
return TC_ACT_OK;
}
SEC("ip6vxlan_get_tunnel")
int _ip6vxlan_get_tunnel(struct __sk_buff *skb)
{
char fmt[] = "key %d remote ip6 ::%x label %x\n";
struct bpf_tunnel_key key;
int ret;
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
BPF_F_TUNINFO_IPV6);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
}
bpf_trace_printk(fmt, sizeof(fmt),
key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
return TC_ACT_OK;
}
SEC("geneve_set_tunnel")
int _geneve_set_tunnel(struct __sk_buff *skb)
{
......@@ -360,15 +408,16 @@ int _geneve_set_tunnel(struct __sk_buff *skb)
key.tunnel_ttl = 64;
__builtin_memset(&gopt, 0x0, sizeof(gopt));
gopt.opt_class = 0x102; /* Open Virtual Networking (OVN) */
gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
gopt.type = 0x08;
gopt.r1 = 0;
gopt.r2 = 0;
gopt.r3 = 0;
gopt.length = 2; /* 4-byte multiple */
*(int *) &gopt.opt_data = 0xdeadbeef;
*(int *) &gopt.opt_data = bpf_htonl(0xdeadbeef);
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_ZERO_CSUM_TX);
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
BPF_F_ZERO_CSUM_TX);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
......@@ -408,6 +457,71 @@ int _geneve_get_tunnel(struct __sk_buff *skb)
return TC_ACT_OK;
}
SEC("ip6geneve_set_tunnel")
int _ip6geneve_set_tunnel(struct __sk_buff *skb)
{
struct bpf_tunnel_key key;
struct geneve_opt gopt;
int ret;
__builtin_memset(&key, 0x0, sizeof(key));
key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
key.tunnel_id = 22;
key.tunnel_tos = 0;
key.tunnel_ttl = 64;
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
BPF_F_TUNINFO_IPV6);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
}
__builtin_memset(&gopt, 0x0, sizeof(gopt));
gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
gopt.type = 0x08;
gopt.r1 = 0;
gopt.r2 = 0;
gopt.r3 = 0;
gopt.length = 2; /* 4-byte multiple */
*(int *) &gopt.opt_data = bpf_htonl(0xfeedbeef);
ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
}
return TC_ACT_OK;
}
SEC("ip6geneve_get_tunnel")
int _ip6geneve_get_tunnel(struct __sk_buff *skb)
{
char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
struct bpf_tunnel_key key;
struct geneve_opt gopt;
int ret;
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
BPF_F_TUNINFO_IPV6);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
}
ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
}
bpf_trace_printk(fmt, sizeof(fmt),
key.tunnel_id, key.remote_ipv4, gopt.opt_class);
return TC_ACT_OK;
}
SEC("ipip_set_tunnel")
int _ipip_set_tunnel(struct __sk_buff *skb)
{
......@@ -431,9 +545,9 @@ int _ipip_set_tunnel(struct __sk_buff *skb)
if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
return TC_ACT_SHOT;
if (tcp->dest == htons(5200))
if (tcp->dest == bpf_htons(5200))
key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
else if (tcp->dest == htons(5201))
else if (tcp->dest == bpf_htons(5201))
key.remote_ipv4 = 0xac100165; /* 172.16.1.101 */
else
return TC_ACT_SHOT;
......@@ -481,28 +595,12 @@ int _ipip6_set_tunnel(struct __sk_buff *skb)
return TC_ACT_SHOT;
}
key.remote_ipv6[0] = _htonl(0x2401db00);
__builtin_memset(&key, 0x0, sizeof(key));
key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
key.tunnel_ttl = 64;
if (iph->protocol == IPPROTO_ICMP) {
key.remote_ipv6[3] = _htonl(1);
} else {
if (iph->protocol != IPPROTO_TCP || iph->ihl != 5) {
ERROR(iph->protocol);
return TC_ACT_SHOT;
}
if (tcp->dest == htons(5200)) {
key.remote_ipv6[3] = _htonl(1);
} else if (tcp->dest == htons(5201)) {
key.remote_ipv6[3] = _htonl(2);
} else {
ERROR(tcp->dest);
return TC_ACT_SHOT;
}
}
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
BPF_F_TUNINFO_IPV6);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
......@@ -518,14 +616,15 @@ int _ipip6_get_tunnel(struct __sk_buff *skb)
struct bpf_tunnel_key key;
char fmt[] = "remote ip6 %x::%x\n";
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
BPF_F_TUNINFO_IPV6);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
}
bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
_htonl(key.remote_ipv6[3]));
bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
bpf_htonl(key.remote_ipv6[3]));
return TC_ACT_OK;
}
......@@ -545,28 +644,29 @@ int _ip6ip6_set_tunnel(struct __sk_buff *skb)
return TC_ACT_SHOT;
}
key.remote_ipv6[0] = _htonl(0x2401db00);
key.remote_ipv6[0] = bpf_htonl(0x2401db00);
key.tunnel_ttl = 64;
if (iph->nexthdr == NEXTHDR_ICMP) {
key.remote_ipv6[3] = _htonl(1);
if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {
key.remote_ipv6[3] = bpf_htonl(1);
} else {
if (iph->nexthdr != NEXTHDR_TCP) {
if (iph->nexthdr != 6 /* NEXTHDR_TCP */) {
ERROR(iph->nexthdr);
return TC_ACT_SHOT;
}
if (tcp->dest == htons(5200)) {
key.remote_ipv6[3] = _htonl(1);
} else if (tcp->dest == htons(5201)) {
key.remote_ipv6[3] = _htonl(2);
if (tcp->dest == bpf_htons(5200)) {
key.remote_ipv6[3] = bpf_htonl(1);
} else if (tcp->dest == bpf_htons(5201)) {
key.remote_ipv6[3] = bpf_htonl(2);
} else {
ERROR(tcp->dest);
return TC_ACT_SHOT;
}
}
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
BPF_F_TUNINFO_IPV6);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
......@@ -582,14 +682,15 @@ int _ip6ip6_get_tunnel(struct __sk_buff *skb)
struct bpf_tunnel_key key;
char fmt[] = "remote ip6 %x::%x\n";
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), BPF_F_TUNINFO_IPV6);
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
BPF_F_TUNINFO_IPV6);
if (ret < 0) {
ERROR(ret);
return TC_ACT_SHOT;
}
bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]),
_htonl(key.remote_ipv6[3]));
bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
bpf_htonl(key.remote_ipv6[3]));
return TC_ACT_OK;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册