Commit 3f13de6d authored by Daniel Borkmann's avatar 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: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents f7613120 b05cd740
...@@ -114,7 +114,6 @@ always += sock_flags_kern.o ...@@ -114,7 +114,6 @@ always += sock_flags_kern.o
always += test_probe_write_user_kern.o always += test_probe_write_user_kern.o
always += trace_output_kern.o always += trace_output_kern.o
always += tcbpf1_kern.o always += tcbpf1_kern.o
always += tcbpf2_kern.o
always += tc_l2_redirect_kern.o always += tc_l2_redirect_kern.o
always += lathist_kern.o always += lathist_kern.o
always += offwaketime_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 ...@@ -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 \ 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 \ 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 \ 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 # Order correspond to 'make run_tests' order
TEST_PROGS := test_kmod.sh \ TEST_PROGS := test_kmod.sh \
...@@ -40,7 +40,8 @@ TEST_PROGS := test_kmod.sh \ ...@@ -40,7 +40,8 @@ TEST_PROGS := test_kmod.sh \
test_xdp_redirect.sh \ test_xdp_redirect.sh \
test_xdp_meta.sh \ test_xdp_meta.sh \
test_offload.py \ test_offload.py \
test_sock_addr.sh test_sock_addr.sh \
test_tunnel.sh
# Compile but not part of 'make run_tests' # Compile but not part of 'make run_tests'
TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr
......
#!/bin/bash #!/bin/bash
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# In Namespace 0 (at_ns0) using native tunnel
# Overlay IP: 10.1.1.100
# local 192.16.1.100 remote 192.16.1.200
# veth0 IP: 172.16.1.100, tunnel dev <type>00
# Out of Namespace using BPF set/get on lwtunnel # End-to-end eBPF tunnel test suite
# Overlay IP: 10.1.1.200 # The script tests BPF network tunnel implementation.
# local 172.16.1.200 remote 172.16.1.100 #
# veth1 IP: 172.16.1.200, tunnel dev <type>11 # Topology:
# ---------
function config_device { # 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
PING_ARG="-c 3 -w 10 -q"
ret=0
GREEN='\033[0;92m'
RED='\033[0;31m'
NC='\033[0m' # No Color
config_device()
{
ip netns add at_ns0 ip netns add at_ns0
ip link add veth0 type veth peer name veth1 ip link add veth0 type veth peer name veth1
ip link set veth0 netns at_ns0 ip link set veth0 netns at_ns0
...@@ -20,21 +62,23 @@ function config_device { ...@@ -20,21 +62,23 @@ function config_device {
ip addr add dev veth1 172.16.1.200/24 ip addr add dev veth1 172.16.1.200/24
} }
function add_gre_tunnel { add_gre_tunnel()
# in namespace {
# at_ns0 namespace
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE seq key 2 \ ip link add dev $DEV_NS type $TYPE seq key 2 \
local 172.16.1.100 remote 172.16.1.200 local 172.16.1.100 remote 172.16.1.200
ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip link set dev $DEV_NS up
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
# out of namespace # root namespace
ip link add dev $DEV type $TYPE key 2 external ip link add dev $DEV type $TYPE key 2 external
ip link set dev $DEV up ip link set dev $DEV up
ip addr add dev $DEV 10.1.1.200/24 ip addr add dev $DEV 10.1.1.200/24
} }
function add_ip6gretap_tunnel { add_ip6gretap_tunnel()
{
# assign ipv6 address # assign ipv6 address
ip netns exec at_ns0 ip addr add ::11/96 dev veth0 ip netns exec at_ns0 ip addr add ::11/96 dev veth0
...@@ -42,7 +86,7 @@ function add_ip6gretap_tunnel { ...@@ -42,7 +86,7 @@ function add_ip6gretap_tunnel {
ip addr add dev veth1 ::22/96 ip addr add dev veth1 ::22/96
ip link set dev veth1 up ip link set dev veth1 up
# in namespace # at_ns0 namespace
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE seq flowlabel 0xbcdef key 2 \ ip link add dev $DEV_NS type $TYPE seq flowlabel 0xbcdef key 2 \
local ::11 remote ::22 local ::11 remote ::22
...@@ -51,15 +95,16 @@ function add_ip6gretap_tunnel { ...@@ -51,15 +95,16 @@ function add_ip6gretap_tunnel {
ip netns exec at_ns0 ip addr add dev $DEV_NS fc80::100/96 ip netns exec at_ns0 ip addr add dev $DEV_NS fc80::100/96
ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip link set dev $DEV_NS up
# out of namespace # root namespace
ip link add dev $DEV type $TYPE external ip link add dev $DEV type $TYPE external
ip addr add dev $DEV 10.1.1.200/24 ip addr add dev $DEV 10.1.1.200/24
ip addr add dev $DEV fc80::200/24 ip addr add dev $DEV fc80::200/24
ip link set dev $DEV up ip link set dev $DEV up
} }
function add_erspan_tunnel { add_erspan_tunnel()
# in namespace {
# at_ns0 namespace
if [ "$1" == "v1" ]; then if [ "$1" == "v1" ]; then
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE seq key 2 \ ip link add dev $DEV_NS type $TYPE seq key 2 \
...@@ -74,13 +119,14 @@ function add_erspan_tunnel { ...@@ -74,13 +119,14 @@ function add_erspan_tunnel {
ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip link set dev $DEV_NS up
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
# out of namespace # root namespace
ip link add dev $DEV type $TYPE external ip link add dev $DEV type $TYPE external
ip link set dev $DEV up ip link set dev $DEV up
ip addr add dev $DEV 10.1.1.200/24 ip addr add dev $DEV 10.1.1.200/24
} }
function add_ip6erspan_tunnel { add_ip6erspan_tunnel()
{
# assign ipv6 address # assign ipv6 address
ip netns exec at_ns0 ip addr add ::11/96 dev veth0 ip netns exec at_ns0 ip addr add ::11/96 dev veth0
...@@ -88,7 +134,7 @@ function add_ip6erspan_tunnel { ...@@ -88,7 +134,7 @@ function add_ip6erspan_tunnel {
ip addr add dev veth1 ::22/96 ip addr add dev veth1 ::22/96
ip link set dev veth1 up ip link set dev veth1 up
# in namespace # at_ns0 namespace
if [ "$1" == "v1" ]; then if [ "$1" == "v1" ]; then
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE seq key 2 \ ip link add dev $DEV_NS type $TYPE seq key 2 \
...@@ -103,288 +149,581 @@ function add_ip6erspan_tunnel { ...@@ -103,288 +149,581 @@ function add_ip6erspan_tunnel {
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip link set dev $DEV_NS up
# out of namespace # root namespace
ip link add dev $DEV type $TYPE external ip link add dev $DEV type $TYPE external
ip addr add dev $DEV 10.1.1.200/24 ip addr add dev $DEV 10.1.1.200/24
ip link set dev $DEV up ip link set dev $DEV up
} }
function add_vxlan_tunnel { add_vxlan_tunnel()
{
# Set static ARP entry here because iptables set-mark works # Set static ARP entry here because iptables set-mark works
# on L3 packet, as a result not applying to ARP packets, # on L3 packet, as a result not applying to ARP packets,
# causing errors at get_tunnel_{key/opt}. # causing errors at get_tunnel_{key/opt}.
# in namespace # at_ns0 namespace
ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE \
id 2 dstport 4789 gbp remote 172.16.1.200
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE id 2 dstport 4789 gbp remote 172.16.1.200 ip link set dev $DEV_NS address 52:54:00:d9:01:00 up
ip netns exec at_ns0 ip link set dev $DEV_NS address 52:54:00:d9:01:00 up
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
ip netns exec at_ns0 arp -s 10.1.1.200 52:54:00:d9:02:00 ip netns exec at_ns0 arp -s 10.1.1.200 52:54:00:d9:02:00
ip netns exec at_ns0 iptables -A OUTPUT -j MARK --set-mark 0x800FF ip netns exec at_ns0 iptables -A OUTPUT -j MARK --set-mark 0x800FF
# out of namespace # root namespace
ip link add dev $DEV type $TYPE external gbp dstport 4789 ip link add dev $DEV type $TYPE external gbp dstport 4789
ip link set dev $DEV address 52:54:00:d9:02:00 up ip link set dev $DEV address 52:54:00:d9:02:00 up
ip addr add dev $DEV 10.1.1.200/24 ip addr add dev $DEV 10.1.1.200/24
arp -s 10.1.1.100 52:54:00:d9:01:00 arp -s 10.1.1.100 52:54:00:d9:01:00
} }
function add_geneve_tunnel { add_ip6vxlan_tunnel()
# in namespace {
#ip netns exec at_ns0 ip -4 addr del 172.16.1.100 dev veth0
ip netns exec at_ns0 ip -6 addr add ::11/96 dev veth0
ip netns exec at_ns0 ip link set dev veth0 up
#ip -4 addr del 172.16.1.200 dev veth1
ip -6 addr add dev veth1 ::22/96
ip link set dev veth1 up
# at_ns0 namespace
ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE id 22 dstport 4789 \
local ::11 remote ::22
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
ip netns exec at_ns0 ip link set dev $DEV_NS up
# root namespace
ip link add dev $DEV type $TYPE external dstport 4789
ip addr add dev $DEV 10.1.1.200/24
ip link set dev $DEV up
}
add_geneve_tunnel()
{
# at_ns0 namespace
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE id 2 dstport 6081 remote 172.16.1.200 ip link add dev $DEV_NS type $TYPE \
id 2 dstport 6081 remote 172.16.1.200
ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip link set dev $DEV_NS up
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
# out of namespace # root namespace
ip link add dev $DEV type $TYPE dstport 6081 external ip link add dev $DEV type $TYPE dstport 6081 external
ip link set dev $DEV up ip link set dev $DEV up
ip addr add dev $DEV 10.1.1.200/24 ip addr add dev $DEV 10.1.1.200/24
} }
function add_ipip_tunnel { add_ip6geneve_tunnel()
# in namespace {
ip netns exec at_ns0 ip addr add ::11/96 dev veth0
ip netns exec at_ns0 ip link set dev veth0 up
ip addr add dev veth1 ::22/96
ip link set dev veth1 up
# at_ns0 namespace
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE local 172.16.1.100 remote 172.16.1.200 ip link add dev $DEV_NS type $TYPE id 22 \
ip netns exec at_ns0 ip link set dev $DEV_NS up remote ::22 # geneve has no local option
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
ip netns exec at_ns0 ip link set dev $DEV_NS up
# out of namespace # root namespace
ip link add dev $DEV type $TYPE external ip link add dev $DEV type $TYPE external
ip link set dev $DEV up
ip addr add dev $DEV 10.1.1.200/24 ip addr add dev $DEV 10.1.1.200/24
ip link set dev $DEV up
} }
function setup_xfrm_tunnel { add_ipip_tunnel()
auth=0x$(printf '1%.0s' {1..40}) {
enc=0x$(printf '2%.0s' {1..32}) # at_ns0 namespace
spi_in_to_out=0x1
spi_out_to_in=0x2
# in namespace
# in -> out
ip netns exec at_ns0 \
ip xfrm state add src 172.16.1.100 dst 172.16.1.200 proto esp \
spi $spi_in_to_out reqid 1 mode tunnel \
auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
ip netns exec at_ns0 \
ip xfrm policy add src 10.1.1.100/32 dst 10.1.1.200/32 dir out \
tmpl src 172.16.1.100 dst 172.16.1.200 proto esp reqid 1 \
mode tunnel
# out -> in
ip netns exec at_ns0 \
ip xfrm state add src 172.16.1.200 dst 172.16.1.100 proto esp \
spi $spi_out_to_in reqid 2 mode tunnel \
auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip xfrm policy add src 10.1.1.200/32 dst 10.1.1.100/32 dir in \ ip link add dev $DEV_NS type $TYPE \
tmpl src 172.16.1.200 dst 172.16.1.100 proto esp reqid 2 \ local 172.16.1.100 remote 172.16.1.200
mode tunnel ip netns exec at_ns0 ip link set dev $DEV_NS up
# address & route ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
ip netns exec at_ns0 \
ip addr add dev veth0 10.1.1.100/32
ip netns exec at_ns0 \
ip route add 10.1.1.200 dev veth0 via 172.16.1.200 \
src 10.1.1.100
# out of namespace # root namespace
# in -> out ip link add dev $DEV type $TYPE external
ip xfrm state add src 172.16.1.100 dst 172.16.1.200 proto esp \ ip link set dev $DEV up
spi $spi_in_to_out reqid 1 mode tunnel \ ip addr add dev $DEV 10.1.1.200/24
auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
ip xfrm policy add src 10.1.1.100/32 dst 10.1.1.200/32 dir in \
tmpl src 172.16.1.100 dst 172.16.1.200 proto esp reqid 1 \
mode tunnel
# out -> in
ip xfrm state add src 172.16.1.200 dst 172.16.1.100 proto esp \
spi $spi_out_to_in reqid 2 mode tunnel \
auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
ip xfrm policy add src 10.1.1.200/32 dst 10.1.1.100/32 dir out \
tmpl src 172.16.1.200 dst 172.16.1.100 proto esp reqid 2 \
mode tunnel
# address & route
ip addr add dev veth1 10.1.1.200/32
ip route add 10.1.1.100 dev veth1 via 172.16.1.100 src 10.1.1.200
} }
function attach_bpf { add_ipip6tnl_tunnel()
DEV=$1 {
SET_TUNNEL=$2 ip netns exec at_ns0 ip addr add ::11/96 dev veth0
GET_TUNNEL=$3 ip netns exec at_ns0 ip link set dev veth0 up
tc qdisc add dev $DEV clsact ip addr add dev veth1 ::22/96
tc filter add dev $DEV egress bpf da obj tcbpf2_kern.o sec $SET_TUNNEL ip link set dev veth1 up
tc filter add dev $DEV ingress bpf da obj tcbpf2_kern.o sec $GET_TUNNEL
# at_ns0 namespace
ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE \
local ::11 remote ::22
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
ip netns exec at_ns0 ip link set dev $DEV_NS up
# root namespace
ip link add dev $DEV type $TYPE external
ip addr add dev $DEV 10.1.1.200/24
ip link set dev $DEV up
} }
function test_gre { test_gre()
{
TYPE=gretap TYPE=gretap
DEV_NS=gretap00 DEV_NS=gretap00
DEV=gretap11 DEV=gretap11
ret=0
check $TYPE
config_device config_device
add_gre_tunnel add_gre_tunnel
attach_bpf $DEV gre_set_tunnel gre_get_tunnel attach_bpf $DEV gre_set_tunnel gre_get_tunnel
ping -c 1 10.1.1.100 ping $PING_ARG 10.1.1.100
ip netns exec at_ns0 ping -c 1 10.1.1.200 check_err $?
ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
check_err $?
cleanup cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: $TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: $TYPE"${NC}
} }
function test_ip6gre { test_ip6gre()
{
TYPE=ip6gre TYPE=ip6gre
DEV_NS=ip6gre00 DEV_NS=ip6gre00
DEV=ip6gre11 DEV=ip6gre11
ret=0
check $TYPE
config_device config_device
# reuse the ip6gretap function # reuse the ip6gretap function
add_ip6gretap_tunnel add_ip6gretap_tunnel
attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel
# underlay # underlay
ping6 -c 4 ::11 ping6 $PING_ARG ::11
# overlay: ipv4 over ipv6 # overlay: ipv4 over ipv6
ip netns exec at_ns0 ping -c 1 10.1.1.200 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
ping -c 1 10.1.1.100 ping $PING_ARG 10.1.1.100
check_err $?
# overlay: ipv6 over ipv6 # overlay: ipv6 over ipv6
ip netns exec at_ns0 ping6 -c 1 fc80::200 ip netns exec at_ns0 ping6 $PING_ARG fc80::200
check_err $?
cleanup cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: $TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: $TYPE"${NC}
} }
function test_ip6gretap { test_ip6gretap()
{
TYPE=ip6gretap TYPE=ip6gretap
DEV_NS=ip6gretap00 DEV_NS=ip6gretap00
DEV=ip6gretap11 DEV=ip6gretap11
ret=0
check $TYPE
config_device config_device
add_ip6gretap_tunnel add_ip6gretap_tunnel
attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel attach_bpf $DEV ip6gretap_set_tunnel ip6gretap_get_tunnel
# underlay # underlay
ping6 -c 4 ::11 ping6 $PING_ARG ::11
# overlay: ipv4 over ipv6 # overlay: ipv4 over ipv6
ip netns exec at_ns0 ping -i .2 -c 1 10.1.1.200 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
ping -c 1 10.1.1.100 ping $PING_ARG 10.1.1.100
check_err $?
# overlay: ipv6 over ipv6 # overlay: ipv6 over ipv6
ip netns exec at_ns0 ping6 -c 1 fc80::200 ip netns exec at_ns0 ping6 $PING_ARG fc80::200
check_err $?
cleanup cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: $TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: $TYPE"${NC}
} }
function test_erspan { test_erspan()
{
TYPE=erspan TYPE=erspan
DEV_NS=erspan00 DEV_NS=erspan00
DEV=erspan11 DEV=erspan11
ret=0
check $TYPE
config_device config_device
add_erspan_tunnel $1 add_erspan_tunnel $1
attach_bpf $DEV erspan_set_tunnel erspan_get_tunnel attach_bpf $DEV erspan_set_tunnel erspan_get_tunnel
ping -c 1 10.1.1.100 ping $PING_ARG 10.1.1.100
ip netns exec at_ns0 ping -c 1 10.1.1.200 check_err $?
ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
check_err $?
cleanup cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: $TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: $TYPE"${NC}
} }
function test_ip6erspan { test_ip6erspan()
{
TYPE=ip6erspan TYPE=ip6erspan
DEV_NS=ip6erspan00 DEV_NS=ip6erspan00
DEV=ip6erspan11 DEV=ip6erspan11
ret=0
check $TYPE
config_device config_device
add_ip6erspan_tunnel $1 add_ip6erspan_tunnel $1
attach_bpf $DEV ip4ip6erspan_set_tunnel ip4ip6erspan_get_tunnel attach_bpf $DEV ip4ip6erspan_set_tunnel ip4ip6erspan_get_tunnel
ping6 -c 3 ::11 ping6 $PING_ARG ::11
ip netns exec at_ns0 ping -c 1 10.1.1.200 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
check_err $?
cleanup cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: $TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: $TYPE"${NC}
} }
function test_vxlan { test_vxlan()
{
TYPE=vxlan TYPE=vxlan
DEV_NS=vxlan00 DEV_NS=vxlan00
DEV=vxlan11 DEV=vxlan11
ret=0
check $TYPE
config_device config_device
add_vxlan_tunnel add_vxlan_tunnel
attach_bpf $DEV vxlan_set_tunnel vxlan_get_tunnel attach_bpf $DEV vxlan_set_tunnel vxlan_get_tunnel
ping -c 1 10.1.1.100 ping $PING_ARG 10.1.1.100
ip netns exec at_ns0 ping -c 1 10.1.1.200 check_err $?
ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
check_err $?
cleanup cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: $TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: $TYPE"${NC}
} }
function test_geneve { test_ip6vxlan()
{
TYPE=vxlan
DEV_NS=ip6vxlan00
DEV=ip6vxlan11
ret=0
check $TYPE
config_device
add_ip6vxlan_tunnel
ip link set dev veth1 mtu 1500
attach_bpf $DEV ip6vxlan_set_tunnel ip6vxlan_get_tunnel
# underlay
ping6 $PING_ARG ::11
# ip4 over ip6
ping $PING_ARG 10.1.1.100
check_err $?
ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
check_err $?
cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: ip6$TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: ip6$TYPE"${NC}
}
test_geneve()
{
TYPE=geneve TYPE=geneve
DEV_NS=geneve00 DEV_NS=geneve00
DEV=geneve11 DEV=geneve11
ret=0
check $TYPE
config_device config_device
add_geneve_tunnel add_geneve_tunnel
attach_bpf $DEV geneve_set_tunnel geneve_get_tunnel attach_bpf $DEV geneve_set_tunnel geneve_get_tunnel
ping -c 1 10.1.1.100 ping $PING_ARG 10.1.1.100
ip netns exec at_ns0 ping -c 1 10.1.1.200 check_err $?
ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
check_err $?
cleanup cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: $TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: $TYPE"${NC}
}
test_ip6geneve()
{
TYPE=geneve
DEV_NS=ip6geneve00
DEV=ip6geneve11
ret=0
check $TYPE
config_device
add_ip6geneve_tunnel
attach_bpf $DEV ip6geneve_set_tunnel ip6geneve_get_tunnel
ping $PING_ARG 10.1.1.100
check_err $?
ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
check_err $?
cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: ip6$TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: ip6$TYPE"${NC}
} }
function test_ipip { test_ipip()
{
TYPE=ipip TYPE=ipip
DEV_NS=ipip00 DEV_NS=ipip00
DEV=ipip11 DEV=ipip11
ret=0
check $TYPE
config_device config_device
tcpdump -nei veth1 &
cat /sys/kernel/debug/tracing/trace_pipe &
add_ipip_tunnel add_ipip_tunnel
ethtool -K veth1 gso off gro off rx off tx off
ip link set dev veth1 mtu 1500 ip link set dev veth1 mtu 1500
attach_bpf $DEV ipip_set_tunnel ipip_get_tunnel attach_bpf $DEV ipip_set_tunnel ipip_get_tunnel
ping -c 1 10.1.1.100 ping $PING_ARG 10.1.1.100
ip netns exec at_ns0 ping -c 1 10.1.1.200 check_err $?
ip netns exec at_ns0 iperf -sD -p 5200 > /dev/null ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
sleep 0.2 check_err $?
iperf -c 10.1.1.100 -n 5k -p 5200 cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: $TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: $TYPE"${NC}
}
test_ipip6()
{
TYPE=ip6tnl
DEV_NS=ipip6tnl00
DEV=ipip6tnl11
ret=0
check $TYPE
config_device
add_ipip6tnl_tunnel
ip link set dev veth1 mtu 1500
attach_bpf $DEV ipip6_set_tunnel ipip6_get_tunnel
# underlay
ping6 $PING_ARG ::11
# ip4 over ip6
ping $PING_ARG 10.1.1.100
check_err $?
ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
check_err $?
cleanup cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: $TYPE"${NC}
return 1
fi
echo -e ${GREEN}"PASS: $TYPE"${NC}
}
setup_xfrm_tunnel()
{
auth=0x$(printf '1%.0s' {1..40})
enc=0x$(printf '2%.0s' {1..32})
spi_in_to_out=0x1
spi_out_to_in=0x2
# at_ns0 namespace
# at_ns0 -> root
ip netns exec at_ns0 \
ip xfrm state add src 172.16.1.100 dst 172.16.1.200 proto esp \
spi $spi_in_to_out reqid 1 mode tunnel \
auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
ip netns exec at_ns0 \
ip xfrm policy add src 10.1.1.100/32 dst 10.1.1.200/32 dir out \
tmpl src 172.16.1.100 dst 172.16.1.200 proto esp reqid 1 \
mode tunnel
# root -> at_ns0
ip netns exec at_ns0 \
ip xfrm state add src 172.16.1.200 dst 172.16.1.100 proto esp \
spi $spi_out_to_in reqid 2 mode tunnel \
auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
ip netns exec at_ns0 \
ip xfrm policy add src 10.1.1.200/32 dst 10.1.1.100/32 dir in \
tmpl src 172.16.1.200 dst 172.16.1.100 proto esp reqid 2 \
mode tunnel
# address & route
ip netns exec at_ns0 \
ip addr add dev veth0 10.1.1.100/32
ip netns exec at_ns0 \
ip route add 10.1.1.200 dev veth0 via 172.16.1.200 \
src 10.1.1.100
# root namespace
# at_ns0 -> root
ip xfrm state add src 172.16.1.100 dst 172.16.1.200 proto esp \
spi $spi_in_to_out reqid 1 mode tunnel \
auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
ip xfrm policy add src 10.1.1.100/32 dst 10.1.1.200/32 dir in \
tmpl src 172.16.1.100 dst 172.16.1.200 proto esp reqid 1 \
mode tunnel
# root -> at_ns0
ip xfrm state add src 172.16.1.200 dst 172.16.1.100 proto esp \
spi $spi_out_to_in reqid 2 mode tunnel \
auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
ip xfrm policy add src 10.1.1.200/32 dst 10.1.1.100/32 dir out \
tmpl src 172.16.1.200 dst 172.16.1.100 proto esp reqid 2 \
mode tunnel
# address & route
ip addr add dev veth1 10.1.1.200/32
ip route add 10.1.1.100 dev veth1 via 172.16.1.100 src 10.1.1.200
} }
function test_xfrm_tunnel { test_xfrm_tunnel()
{
config_device config_device
tcpdump -nei veth1 ip & #tcpdump -nei veth1 ip &
output=$(mktemp) output=$(mktemp)
cat /sys/kernel/debug/tracing/trace_pipe | tee $output & cat /sys/kernel/debug/tracing/trace_pipe | tee $output &
setup_xfrm_tunnel setup_xfrm_tunnel
tc qdisc add dev veth1 clsact tc qdisc add dev veth1 clsact
tc filter add dev veth1 proto ip ingress bpf da obj tcbpf2_kern.o \ tc filter add dev veth1 proto ip ingress bpf da obj test_tunnel_kern.o \
sec xfrm_get_state sec xfrm_get_state
ip netns exec at_ns0 ping -c 1 10.1.1.200 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
sleep 1
grep "reqid 1" $output grep "reqid 1" $output
check_err $?
grep "spi 0x1" $output grep "spi 0x1" $output
check_err $?
grep "remote ip 0xac100164" $output grep "remote ip 0xac100164" $output
check_err $?
cleanup cleanup
if [ $ret -ne 0 ]; then
echo -e ${RED}"FAIL: xfrm tunnel"${NC}
return 1
fi
echo -e ${GREEN}"PASS: xfrm tunnel"${NC}
} }
function cleanup { attach_bpf()
set +ex {
pkill iperf DEV=$1
ip netns delete at_ns0 SET=$2
ip link del veth1 GET=$3
ip link del ipip11 tc qdisc add dev $DEV clsact
ip link del gretap11 tc filter add dev $DEV egress bpf da obj test_tunnel_kern.o sec $SET
ip link del ip6gre11 tc filter add dev $DEV ingress bpf da obj test_tunnel_kern.o sec $GET
ip link del ip6gretap11
ip link del vxlan11
ip link del geneve11
ip link del erspan11
ip link del ip6erspan11
ip x s flush
ip x p flush
pkill tcpdump
pkill cat
set -ex
} }
trap cleanup 0 2 3 6 9 cleanup()
{
ip netns delete at_ns0 2> /dev/null
ip link del veth1 2> /dev/null
ip link del ipip11 2> /dev/null
ip link del ipip6tnl11 2> /dev/null
ip link del gretap11 2> /dev/null
ip link del ip6gre11 2> /dev/null
ip link del ip6gretap11 2> /dev/null
ip link del vxlan11 2> /dev/null
ip link del ip6vxlan11 2> /dev/null
ip link del geneve11 2> /dev/null
ip link del ip6geneve11 2> /dev/null
ip link del erspan11 2> /dev/null
ip link del ip6erspan11 2> /dev/null
}
cleanup_exit()
{
echo "CATCH SIGKILL or SIGINT, cleanup and exit"
cleanup
exit 0
}
check()
{
ip link help $1 2>&1 | grep -q "^Usage:"
if [ $? -ne 0 ];then
echo "SKIP $1: iproute2 not support"
cleanup
return 1
fi
}
enable_debug()
{
echo 'file ip_gre.c +p' > /sys/kernel/debug/dynamic_debug/control
echo 'file ip6_gre.c +p' > /sys/kernel/debug/dynamic_debug/control
echo 'file vxlan.c +p' > /sys/kernel/debug/dynamic_debug/control
echo 'file geneve.c +p' > /sys/kernel/debug/dynamic_debug/control
echo 'file ipip.c +p' > /sys/kernel/debug/dynamic_debug/control
}
check_err()
{
if [ $ret -eq 0 ]; then
ret=$1
fi
}
bpf_tunnel_test()
{
echo "Testing GRE tunnel..."
test_gre
echo "Testing IP6GRE tunnel..."
test_ip6gre
echo "Testing IP6GRETAP tunnel..."
test_ip6gretap
echo "Testing ERSPAN tunnel..."
test_erspan v2
echo "Testing IP6ERSPAN tunnel..."
test_ip6erspan v2
echo "Testing VXLAN tunnel..."
test_vxlan
echo "Testing IP6VXLAN tunnel..."
test_ip6vxlan
echo "Testing GENEVE tunnel..."
test_geneve
echo "Testing IP6GENEVE tunnel..."
test_ip6geneve
echo "Testing IPIP tunnel..."
test_ipip
echo "Testing IPIP6 tunnel..."
test_ipip6
echo "Testing IPSec tunnel..."
test_xfrm_tunnel
}
trap cleanup 0 3 6
trap cleanup_exit 2 9
cleanup cleanup
echo "Testing GRE tunnel..." bpf_tunnel_test
test_gre
echo "Testing IP6GRE tunnel..." exit 0
test_ip6gre
echo "Testing IP6GRETAP tunnel..."
test_ip6gretap
echo "Testing ERSPAN tunnel..."
test_erspan v1
test_erspan v2
echo "Testing IP6ERSPAN tunnel..."
test_ip6erspan v1
test_ip6erspan v2
echo "Testing VXLAN tunnel..."
test_vxlan
echo "Testing GENEVE tunnel..."
test_geneve
echo "Testing IPIP tunnel..."
test_ipip
echo "Testing IPSec tunnel..."
test_xfrm_tunnel
echo "*** PASS ***"
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2016 VMware /* Copyright (c) 2016 VMware
* Copyright (c) 2016 Facebook * Copyright (c) 2016 Facebook
* *
...@@ -5,39 +6,41 @@ ...@@ -5,39 +6,41 @@
* modify it under the terms of version 2 of the GNU General Public * modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation. * License as published by the Free Software Foundation.
*/ */
#define KBUILD_MODNAME "foo" #include <stddef.h>
#include <uapi/linux/bpf.h> #include <string.h>
#include <uapi/linux/if_ether.h> #include <arpa/inet.h>
#include <uapi/linux/if_packet.h> #include <linux/bpf.h>
#include <uapi/linux/ip.h> #include <linux/if_ether.h>
#include <uapi/linux/ipv6.h> #include <linux/if_packet.h>
#include <uapi/linux/in.h> #include <linux/ip.h>
#include <uapi/linux/tcp.h> #include <linux/ipv6.h>
#include <uapi/linux/filter.h> #include <linux/types.h>
#include <uapi/linux/pkt_cls.h> #include <linux/tcp.h>
#include <uapi/linux/erspan.h> #include <linux/socket.h>
#include <net/ipv6.h> #include <linux/pkt_cls.h>
#include <linux/erspan.h>
#include "bpf_helpers.h" #include "bpf_helpers.h"
#include "bpf_endian.h" #include "bpf_endian.h"
#define _htonl __builtin_bswap32
#define ERROR(ret) do {\ #define ERROR(ret) do {\
char fmt[] = "ERROR line:%d ret:%d\n";\ char fmt[] = "ERROR line:%d ret:%d\n";\
bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \ bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
} while(0) } while (0)
int _version SEC("version") = 1;
struct geneve_opt { struct geneve_opt {
__be16 opt_class; __be16 opt_class;
u8 type; __u8 type;
u8 length:5; __u8 length:5;
u8 r3:1; __u8 r3:1;
u8 r2:1; __u8 r2:1;
u8 r1:1; __u8 r1:1;
u8 opt_data[8]; /* hard-coded to 8 byte */ __u8 opt_data[8]; /* hard-coded to 8 byte */
}; };
struct vxlan_metadata { struct vxlan_metadata {
u32 gbp; __u32 gbp;
}; };
SEC("gre_set_tunnel") SEC("gre_set_tunnel")
...@@ -86,7 +89,7 @@ int _ip6gretap_set_tunnel(struct __sk_buff *skb) ...@@ -86,7 +89,7 @@ int _ip6gretap_set_tunnel(struct __sk_buff *skb)
int ret; int ret;
__builtin_memset(&key, 0x0, sizeof(key)); __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_id = 2;
key.tunnel_tos = 0; key.tunnel_tos = 0;
key.tunnel_ttl = 64; key.tunnel_ttl = 64;
...@@ -136,7 +139,8 @@ int _erspan_set_tunnel(struct __sk_buff *skb) ...@@ -136,7 +139,8 @@ int _erspan_set_tunnel(struct __sk_buff *skb)
key.tunnel_tos = 0; key.tunnel_tos = 0;
key.tunnel_ttl = 64; 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) { if (ret < 0) {
ERROR(ret); ERROR(ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
...@@ -147,8 +151,8 @@ int _erspan_set_tunnel(struct __sk_buff *skb) ...@@ -147,8 +151,8 @@ int _erspan_set_tunnel(struct __sk_buff *skb)
md.version = 1; md.version = 1;
md.u.index = bpf_htonl(123); md.u.index = bpf_htonl(123);
#else #else
u8 direction = 1; __u8 direction = 1;
u8 hwid = 7; __u8 hwid = 7;
md.version = 2; md.version = 2;
md.u.md2.dir = direction; md.u.md2.dir = direction;
...@@ -171,7 +175,7 @@ int _erspan_get_tunnel(struct __sk_buff *skb) ...@@ -171,7 +175,7 @@ int _erspan_get_tunnel(struct __sk_buff *skb)
char fmt[] = "key %d remote ip 0x%x erspan version %d\n"; char fmt[] = "key %d remote ip 0x%x erspan version %d\n";
struct bpf_tunnel_key key; struct bpf_tunnel_key key;
struct erspan_metadata md; struct erspan_metadata md;
u32 index; __u32 index;
int ret; int ret;
ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
...@@ -214,7 +218,7 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb) ...@@ -214,7 +218,7 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
int ret; int ret;
__builtin_memset(&key, 0x0, sizeof(key)); __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_id = 2;
key.tunnel_tos = 0; key.tunnel_tos = 0;
key.tunnel_ttl = 64; key.tunnel_ttl = 64;
...@@ -229,11 +233,11 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb) ...@@ -229,11 +233,11 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
__builtin_memset(&md, 0, sizeof(md)); __builtin_memset(&md, 0, sizeof(md));
#ifdef ERSPAN_V1 #ifdef ERSPAN_V1
md.u.index = htonl(123); md.u.index = bpf_htonl(123);
md.version = 1; md.version = 1;
#else #else
u8 direction = 0; __u8 direction = 0;
u8 hwid = 17; __u8 hwid = 17;
md.version = 2; md.version = 2;
md.u.md2.dir = direction; md.u.md2.dir = direction;
...@@ -256,10 +260,11 @@ int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb) ...@@ -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"; char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n";
struct bpf_tunnel_key key; struct bpf_tunnel_key key;
struct erspan_metadata md; struct erspan_metadata md;
u32 index; __u32 index;
int ret; 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) { if (ret < 0) {
ERROR(ret); ERROR(ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
...@@ -304,7 +309,8 @@ int _vxlan_set_tunnel(struct __sk_buff *skb) ...@@ -304,7 +309,8 @@ int _vxlan_set_tunnel(struct __sk_buff *skb)
key.tunnel_tos = 0; key.tunnel_tos = 0;
key.tunnel_ttl = 64; 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) { if (ret < 0) {
ERROR(ret); ERROR(ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
...@@ -346,6 +352,48 @@ int _vxlan_get_tunnel(struct __sk_buff *skb) ...@@ -346,6 +352,48 @@ int _vxlan_get_tunnel(struct __sk_buff *skb)
return TC_ACT_OK; 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") SEC("geneve_set_tunnel")
int _geneve_set_tunnel(struct __sk_buff *skb) int _geneve_set_tunnel(struct __sk_buff *skb)
{ {
...@@ -360,15 +408,16 @@ int _geneve_set_tunnel(struct __sk_buff *skb) ...@@ -360,15 +408,16 @@ int _geneve_set_tunnel(struct __sk_buff *skb)
key.tunnel_ttl = 64; key.tunnel_ttl = 64;
__builtin_memset(&gopt, 0x0, sizeof(gopt)); __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.type = 0x08;
gopt.r1 = 0; gopt.r1 = 0;
gopt.r2 = 0; gopt.r2 = 0;
gopt.r3 = 0; gopt.r3 = 0;
gopt.length = 2; /* 4-byte multiple */ 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) { if (ret < 0) {
ERROR(ret); ERROR(ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
...@@ -408,6 +457,71 @@ int _geneve_get_tunnel(struct __sk_buff *skb) ...@@ -408,6 +457,71 @@ int _geneve_get_tunnel(struct __sk_buff *skb)
return TC_ACT_OK; 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") SEC("ipip_set_tunnel")
int _ipip_set_tunnel(struct __sk_buff *skb) int _ipip_set_tunnel(struct __sk_buff *skb)
{ {
...@@ -431,9 +545,9 @@ 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) if (iph->protocol != IPPROTO_TCP || iph->ihl != 5)
return TC_ACT_SHOT; return TC_ACT_SHOT;
if (tcp->dest == htons(5200)) if (tcp->dest == bpf_htons(5200))
key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 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 */ key.remote_ipv4 = 0xac100165; /* 172.16.1.101 */
else else
return TC_ACT_SHOT; return TC_ACT_SHOT;
...@@ -481,28 +595,12 @@ int _ipip6_set_tunnel(struct __sk_buff *skb) ...@@ -481,28 +595,12 @@ int _ipip6_set_tunnel(struct __sk_buff *skb)
return TC_ACT_SHOT; 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; key.tunnel_ttl = 64;
if (iph->protocol == IPPROTO_ICMP) { ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
key.remote_ipv6[3] = _htonl(1); BPF_F_TUNINFO_IPV6);
} 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);
if (ret < 0) { if (ret < 0) {
ERROR(ret); ERROR(ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
...@@ -518,14 +616,15 @@ int _ipip6_get_tunnel(struct __sk_buff *skb) ...@@ -518,14 +616,15 @@ int _ipip6_get_tunnel(struct __sk_buff *skb)
struct bpf_tunnel_key key; struct bpf_tunnel_key key;
char fmt[] = "remote ip6 %x::%x\n"; 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) { if (ret < 0) {
ERROR(ret); ERROR(ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
} }
bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]), bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
_htonl(key.remote_ipv6[3])); bpf_htonl(key.remote_ipv6[3]));
return TC_ACT_OK; return TC_ACT_OK;
} }
...@@ -545,28 +644,29 @@ int _ip6ip6_set_tunnel(struct __sk_buff *skb) ...@@ -545,28 +644,29 @@ int _ip6ip6_set_tunnel(struct __sk_buff *skb)
return TC_ACT_SHOT; return TC_ACT_SHOT;
} }
key.remote_ipv6[0] = _htonl(0x2401db00); key.remote_ipv6[0] = bpf_htonl(0x2401db00);
key.tunnel_ttl = 64; key.tunnel_ttl = 64;
if (iph->nexthdr == NEXTHDR_ICMP) { if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {
key.remote_ipv6[3] = _htonl(1); key.remote_ipv6[3] = bpf_htonl(1);
} else { } else {
if (iph->nexthdr != NEXTHDR_TCP) { if (iph->nexthdr != 6 /* NEXTHDR_TCP */) {
ERROR(iph->nexthdr); ERROR(iph->nexthdr);
return TC_ACT_SHOT; return TC_ACT_SHOT;
} }
if (tcp->dest == htons(5200)) { if (tcp->dest == bpf_htons(5200)) {
key.remote_ipv6[3] = _htonl(1); key.remote_ipv6[3] = bpf_htonl(1);
} else if (tcp->dest == htons(5201)) { } else if (tcp->dest == bpf_htons(5201)) {
key.remote_ipv6[3] = _htonl(2); key.remote_ipv6[3] = bpf_htonl(2);
} else { } else {
ERROR(tcp->dest); ERROR(tcp->dest);
return TC_ACT_SHOT; 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) { if (ret < 0) {
ERROR(ret); ERROR(ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
...@@ -582,14 +682,15 @@ int _ip6ip6_get_tunnel(struct __sk_buff *skb) ...@@ -582,14 +682,15 @@ int _ip6ip6_get_tunnel(struct __sk_buff *skb)
struct bpf_tunnel_key key; struct bpf_tunnel_key key;
char fmt[] = "remote ip6 %x::%x\n"; 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) { if (ret < 0) {
ERROR(ret); ERROR(ret);
return TC_ACT_SHOT; return TC_ACT_SHOT;
} }
bpf_trace_printk(fmt, sizeof(fmt), _htonl(key.remote_ipv6[0]), bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
_htonl(key.remote_ipv6[3])); bpf_htonl(key.remote_ipv6[3]));
return TC_ACT_OK; return TC_ACT_OK;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment