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 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 netns exec at_ns0 \
ip route add 10.1.1.200 dev veth0 via 172.16.1.200 \ ip link add dev $DEV_NS type $TYPE \
src 10.1.1.100 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 addr add dev $DEV_NS 10.1.1.100/24
# 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}
}
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}
} }
function test_geneve { 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
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 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 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
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}
}
attach_bpf()
{
DEV=$1
SET=$2
GET=$3
tc qdisc add dev $DEV clsact
tc filter add dev $DEV egress bpf da obj test_tunnel_kern.o sec $SET
tc filter add dev $DEV ingress bpf da obj test_tunnel_kern.o sec $GET
}
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
} }
function cleanup { cleanup_exit()
set +ex {
pkill iperf echo "CATCH SIGKILL or SIGINT, cleanup and exit"
ip netns delete at_ns0 cleanup
ip link del veth1 exit 0
ip link del ipip11
ip link del gretap11
ip link del ip6gre11
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 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