cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

test_lwt_ip_encap.sh (14931B)


      1#!/bin/bash
      2# SPDX-License-Identifier: GPL-2.0
      3#
      4# Setup/topology:
      5#
      6#    NS1             NS2             NS3
      7#   veth1 <---> veth2   veth3 <---> veth4 (the top route)
      8#   veth5 <---> veth6   veth7 <---> veth8 (the bottom route)
      9#
     10#   each vethN gets IPv[4|6]_N address
     11#
     12#   IPv*_SRC = IPv*_1
     13#   IPv*_DST = IPv*_4
     14#
     15#   all tests test pings from IPv*_SRC to IPv*_DST
     16#
     17#   by default, routes are configured to allow packets to go
     18#   IP*_1 <=> IP*_2 <=> IP*_3 <=> IP*_4 (the top route)
     19#
     20#   a GRE device is installed in NS3 with IPv*_GRE, and
     21#   NS1/NS2 are configured to route packets to IPv*_GRE via IP*_8
     22#   (the bottom route)
     23#
     24# Tests:
     25#
     26#   1. routes NS2->IPv*_DST are brought down, so the only way a ping
     27#      from IP*_SRC to IP*_DST can work is via IPv*_GRE
     28#
     29#   2a. in an egress test, a bpf LWT_XMIT program is installed on veth1
     30#       that encaps the packets with an IP/GRE header to route to IPv*_GRE
     31#
     32#       ping: SRC->[encap at veth1:egress]->GRE:decap->DST
     33#       ping replies go DST->SRC directly
     34#
     35#   2b. in an ingress test, a bpf LWT_IN program is installed on veth2
     36#       that encaps the packets with an IP/GRE header to route to IPv*_GRE
     37#
     38#       ping: SRC->[encap at veth2:ingress]->GRE:decap->DST
     39#       ping replies go DST->SRC directly
     40
     41if [[ $EUID -ne 0 ]]; then
     42	echo "This script must be run as root"
     43	echo "FAIL"
     44	exit 1
     45fi
     46
     47readonly NS1="ns1-$(mktemp -u XXXXXX)"
     48readonly NS2="ns2-$(mktemp -u XXXXXX)"
     49readonly NS3="ns3-$(mktemp -u XXXXXX)"
     50
     51readonly IPv4_1="172.16.1.100"
     52readonly IPv4_2="172.16.2.100"
     53readonly IPv4_3="172.16.3.100"
     54readonly IPv4_4="172.16.4.100"
     55readonly IPv4_5="172.16.5.100"
     56readonly IPv4_6="172.16.6.100"
     57readonly IPv4_7="172.16.7.100"
     58readonly IPv4_8="172.16.8.100"
     59readonly IPv4_GRE="172.16.16.100"
     60
     61readonly IPv4_SRC=$IPv4_1
     62readonly IPv4_DST=$IPv4_4
     63
     64readonly IPv6_1="fb01::1"
     65readonly IPv6_2="fb02::1"
     66readonly IPv6_3="fb03::1"
     67readonly IPv6_4="fb04::1"
     68readonly IPv6_5="fb05::1"
     69readonly IPv6_6="fb06::1"
     70readonly IPv6_7="fb07::1"
     71readonly IPv6_8="fb08::1"
     72readonly IPv6_GRE="fb10::1"
     73
     74readonly IPv6_SRC=$IPv6_1
     75readonly IPv6_DST=$IPv6_4
     76
     77TEST_STATUS=0
     78TESTS_SUCCEEDED=0
     79TESTS_FAILED=0
     80
     81TMPFILE=""
     82
     83process_test_results()
     84{
     85	if [[ "${TEST_STATUS}" -eq 0 ]] ; then
     86		echo "PASS"
     87		TESTS_SUCCEEDED=$((TESTS_SUCCEEDED+1))
     88	else
     89		echo "FAIL"
     90		TESTS_FAILED=$((TESTS_FAILED+1))
     91	fi
     92}
     93
     94print_test_summary_and_exit()
     95{
     96	echo "passed tests: ${TESTS_SUCCEEDED}"
     97	echo "failed tests: ${TESTS_FAILED}"
     98	if [ "${TESTS_FAILED}" -eq "0" ] ; then
     99		exit 0
    100	else
    101		exit 1
    102	fi
    103}
    104
    105setup()
    106{
    107	set -e  # exit on error
    108	TEST_STATUS=0
    109
    110	# create devices and namespaces
    111	ip netns add "${NS1}"
    112	ip netns add "${NS2}"
    113	ip netns add "${NS3}"
    114
    115	# rp_filter gets confused by what these tests are doing, so disable it
    116	ip netns exec ${NS1} sysctl -wq net.ipv4.conf.all.rp_filter=0
    117	ip netns exec ${NS2} sysctl -wq net.ipv4.conf.all.rp_filter=0
    118	ip netns exec ${NS3} sysctl -wq net.ipv4.conf.all.rp_filter=0
    119	ip netns exec ${NS1} sysctl -wq net.ipv4.conf.default.rp_filter=0
    120	ip netns exec ${NS2} sysctl -wq net.ipv4.conf.default.rp_filter=0
    121	ip netns exec ${NS3} sysctl -wq net.ipv4.conf.default.rp_filter=0
    122
    123	# disable IPv6 DAD because it sometimes takes too long and fails tests
    124	ip netns exec ${NS1} sysctl -wq net.ipv6.conf.all.accept_dad=0
    125	ip netns exec ${NS2} sysctl -wq net.ipv6.conf.all.accept_dad=0
    126	ip netns exec ${NS3} sysctl -wq net.ipv6.conf.all.accept_dad=0
    127	ip netns exec ${NS1} sysctl -wq net.ipv6.conf.default.accept_dad=0
    128	ip netns exec ${NS2} sysctl -wq net.ipv6.conf.default.accept_dad=0
    129	ip netns exec ${NS3} sysctl -wq net.ipv6.conf.default.accept_dad=0
    130
    131	ip link add veth1 type veth peer name veth2
    132	ip link add veth3 type veth peer name veth4
    133	ip link add veth5 type veth peer name veth6
    134	ip link add veth7 type veth peer name veth8
    135
    136	ip netns exec ${NS2} sysctl -wq net.ipv4.ip_forward=1
    137	ip netns exec ${NS2} sysctl -wq net.ipv6.conf.all.forwarding=1
    138
    139	ip link set veth1 netns ${NS1}
    140	ip link set veth2 netns ${NS2}
    141	ip link set veth3 netns ${NS2}
    142	ip link set veth4 netns ${NS3}
    143	ip link set veth5 netns ${NS1}
    144	ip link set veth6 netns ${NS2}
    145	ip link set veth7 netns ${NS2}
    146	ip link set veth8 netns ${NS3}
    147
    148	if [ ! -z "${VRF}" ] ; then
    149		ip -netns ${NS1} link add red type vrf table 1001
    150		ip -netns ${NS1} link set red up
    151		ip -netns ${NS1} route add table 1001 unreachable default metric 8192
    152		ip -netns ${NS1} -6 route add table 1001 unreachable default metric 8192
    153		ip -netns ${NS1} link set veth1 vrf red
    154		ip -netns ${NS1} link set veth5 vrf red
    155
    156		ip -netns ${NS2} link add red type vrf table 1001
    157		ip -netns ${NS2} link set red up
    158		ip -netns ${NS2} route add table 1001 unreachable default metric 8192
    159		ip -netns ${NS2} -6 route add table 1001 unreachable default metric 8192
    160		ip -netns ${NS2} link set veth2 vrf red
    161		ip -netns ${NS2} link set veth3 vrf red
    162		ip -netns ${NS2} link set veth6 vrf red
    163		ip -netns ${NS2} link set veth7 vrf red
    164	fi
    165
    166	# configure addesses: the top route (1-2-3-4)
    167	ip -netns ${NS1}    addr add ${IPv4_1}/24  dev veth1
    168	ip -netns ${NS2}    addr add ${IPv4_2}/24  dev veth2
    169	ip -netns ${NS2}    addr add ${IPv4_3}/24  dev veth3
    170	ip -netns ${NS3}    addr add ${IPv4_4}/24  dev veth4
    171	ip -netns ${NS1} -6 addr add ${IPv6_1}/128 nodad dev veth1
    172	ip -netns ${NS2} -6 addr add ${IPv6_2}/128 nodad dev veth2
    173	ip -netns ${NS2} -6 addr add ${IPv6_3}/128 nodad dev veth3
    174	ip -netns ${NS3} -6 addr add ${IPv6_4}/128 nodad dev veth4
    175
    176	# configure addresses: the bottom route (5-6-7-8)
    177	ip -netns ${NS1}    addr add ${IPv4_5}/24  dev veth5
    178	ip -netns ${NS2}    addr add ${IPv4_6}/24  dev veth6
    179	ip -netns ${NS2}    addr add ${IPv4_7}/24  dev veth7
    180	ip -netns ${NS3}    addr add ${IPv4_8}/24  dev veth8
    181	ip -netns ${NS1} -6 addr add ${IPv6_5}/128 nodad dev veth5
    182	ip -netns ${NS2} -6 addr add ${IPv6_6}/128 nodad dev veth6
    183	ip -netns ${NS2} -6 addr add ${IPv6_7}/128 nodad dev veth7
    184	ip -netns ${NS3} -6 addr add ${IPv6_8}/128 nodad dev veth8
    185
    186	ip -netns ${NS1} link set dev veth1 up
    187	ip -netns ${NS2} link set dev veth2 up
    188	ip -netns ${NS2} link set dev veth3 up
    189	ip -netns ${NS3} link set dev veth4 up
    190	ip -netns ${NS1} link set dev veth5 up
    191	ip -netns ${NS2} link set dev veth6 up
    192	ip -netns ${NS2} link set dev veth7 up
    193	ip -netns ${NS3} link set dev veth8 up
    194
    195	# configure routes: IP*_SRC -> veth1/IP*_2 (= top route) default;
    196	# the bottom route to specific bottom addresses
    197
    198	# NS1
    199	# top route
    200	ip -netns ${NS1}    route add ${IPv4_2}/32  dev veth1 ${VRF}
    201	ip -netns ${NS1}    route add default dev veth1 via ${IPv4_2} ${VRF}  # go top by default
    202	ip -netns ${NS1} -6 route add ${IPv6_2}/128 dev veth1 ${VRF}
    203	ip -netns ${NS1} -6 route add default dev veth1 via ${IPv6_2} ${VRF}  # go top by default
    204	# bottom route
    205	ip -netns ${NS1}    route add ${IPv4_6}/32  dev veth5 ${VRF}
    206	ip -netns ${NS1}    route add ${IPv4_7}/32  dev veth5 via ${IPv4_6} ${VRF}
    207	ip -netns ${NS1}    route add ${IPv4_8}/32  dev veth5 via ${IPv4_6} ${VRF}
    208	ip -netns ${NS1} -6 route add ${IPv6_6}/128 dev veth5 ${VRF}
    209	ip -netns ${NS1} -6 route add ${IPv6_7}/128 dev veth5 via ${IPv6_6} ${VRF}
    210	ip -netns ${NS1} -6 route add ${IPv6_8}/128 dev veth5 via ${IPv6_6} ${VRF}
    211
    212	# NS2
    213	# top route
    214	ip -netns ${NS2}    route add ${IPv4_1}/32  dev veth2 ${VRF}
    215	ip -netns ${NS2}    route add ${IPv4_4}/32  dev veth3 ${VRF}
    216	ip -netns ${NS2} -6 route add ${IPv6_1}/128 dev veth2 ${VRF}
    217	ip -netns ${NS2} -6 route add ${IPv6_4}/128 dev veth3 ${VRF}
    218	# bottom route
    219	ip -netns ${NS2}    route add ${IPv4_5}/32  dev veth6 ${VRF}
    220	ip -netns ${NS2}    route add ${IPv4_8}/32  dev veth7 ${VRF}
    221	ip -netns ${NS2} -6 route add ${IPv6_5}/128 dev veth6 ${VRF}
    222	ip -netns ${NS2} -6 route add ${IPv6_8}/128 dev veth7 ${VRF}
    223
    224	# NS3
    225	# top route
    226	ip -netns ${NS3}    route add ${IPv4_3}/32  dev veth4
    227	ip -netns ${NS3}    route add ${IPv4_1}/32  dev veth4 via ${IPv4_3}
    228	ip -netns ${NS3}    route add ${IPv4_2}/32  dev veth4 via ${IPv4_3}
    229	ip -netns ${NS3} -6 route add ${IPv6_3}/128 dev veth4
    230	ip -netns ${NS3} -6 route add ${IPv6_1}/128 dev veth4 via ${IPv6_3}
    231	ip -netns ${NS3} -6 route add ${IPv6_2}/128 dev veth4 via ${IPv6_3}
    232	# bottom route
    233	ip -netns ${NS3}    route add ${IPv4_7}/32  dev veth8
    234	ip -netns ${NS3}    route add ${IPv4_5}/32  dev veth8 via ${IPv4_7}
    235	ip -netns ${NS3}    route add ${IPv4_6}/32  dev veth8 via ${IPv4_7}
    236	ip -netns ${NS3} -6 route add ${IPv6_7}/128 dev veth8
    237	ip -netns ${NS3} -6 route add ${IPv6_5}/128 dev veth8 via ${IPv6_7}
    238	ip -netns ${NS3} -6 route add ${IPv6_6}/128 dev veth8 via ${IPv6_7}
    239
    240	# configure IPv4 GRE device in NS3, and a route to it via the "bottom" route
    241	ip -netns ${NS3} tunnel add gre_dev mode gre remote ${IPv4_1} local ${IPv4_GRE} ttl 255
    242	ip -netns ${NS3} link set gre_dev up
    243	ip -netns ${NS3} addr add ${IPv4_GRE} dev gre_dev
    244	ip -netns ${NS1} route add ${IPv4_GRE}/32 dev veth5 via ${IPv4_6} ${VRF}
    245	ip -netns ${NS2} route add ${IPv4_GRE}/32 dev veth7 via ${IPv4_8} ${VRF}
    246
    247
    248	# configure IPv6 GRE device in NS3, and a route to it via the "bottom" route
    249	ip -netns ${NS3} -6 tunnel add name gre6_dev mode ip6gre remote ${IPv6_1} local ${IPv6_GRE} ttl 255
    250	ip -netns ${NS3} link set gre6_dev up
    251	ip -netns ${NS3} -6 addr add ${IPv6_GRE} nodad dev gre6_dev
    252	ip -netns ${NS1} -6 route add ${IPv6_GRE}/128 dev veth5 via ${IPv6_6} ${VRF}
    253	ip -netns ${NS2} -6 route add ${IPv6_GRE}/128 dev veth7 via ${IPv6_8} ${VRF}
    254
    255	TMPFILE=$(mktemp /tmp/test_lwt_ip_encap.XXXXXX)
    256
    257	sleep 1  # reduce flakiness
    258	set +e
    259}
    260
    261cleanup()
    262{
    263	if [ -f ${TMPFILE} ] ; then
    264		rm ${TMPFILE}
    265	fi
    266
    267	ip netns del ${NS1} 2> /dev/null
    268	ip netns del ${NS2} 2> /dev/null
    269	ip netns del ${NS3} 2> /dev/null
    270}
    271
    272trap cleanup EXIT
    273
    274remove_routes_to_gredev()
    275{
    276	ip -netns ${NS1} route del ${IPv4_GRE} dev veth5 ${VRF}
    277	ip -netns ${NS2} route del ${IPv4_GRE} dev veth7 ${VRF}
    278	ip -netns ${NS1} -6 route del ${IPv6_GRE}/128 dev veth5 ${VRF}
    279	ip -netns ${NS2} -6 route del ${IPv6_GRE}/128 dev veth7 ${VRF}
    280}
    281
    282add_unreachable_routes_to_gredev()
    283{
    284	ip -netns ${NS1} route add unreachable ${IPv4_GRE}/32 ${VRF}
    285	ip -netns ${NS2} route add unreachable ${IPv4_GRE}/32 ${VRF}
    286	ip -netns ${NS1} -6 route add unreachable ${IPv6_GRE}/128 ${VRF}
    287	ip -netns ${NS2} -6 route add unreachable ${IPv6_GRE}/128 ${VRF}
    288}
    289
    290test_ping()
    291{
    292	local readonly PROTO=$1
    293	local readonly EXPECTED=$2
    294	local RET=0
    295
    296	if [ "${PROTO}" == "IPv4" ] ; then
    297		ip netns exec ${NS1} ping  -c 1 -W 1 -I veth1 ${IPv4_DST} 2>&1 > /dev/null
    298		RET=$?
    299	elif [ "${PROTO}" == "IPv6" ] ; then
    300		ip netns exec ${NS1} ping6 -c 1 -W 1 -I veth1 ${IPv6_DST} 2>&1 > /dev/null
    301		RET=$?
    302	else
    303		echo "    test_ping: unknown PROTO: ${PROTO}"
    304		TEST_STATUS=1
    305	fi
    306
    307	if [ "0" != "${RET}" ]; then
    308		RET=1
    309	fi
    310
    311	if [ "${EXPECTED}" != "${RET}" ] ; then
    312		echo "    test_ping failed: expected: ${EXPECTED}; got ${RET}"
    313		TEST_STATUS=1
    314	fi
    315}
    316
    317test_gso()
    318{
    319	local readonly PROTO=$1
    320	local readonly PKT_SZ=5000
    321	local IP_DST=""
    322	: > ${TMPFILE}  # trim the capture file
    323
    324	# check that nc is present
    325	command -v nc >/dev/null 2>&1 || \
    326		{ echo >&2 "nc is not available: skipping TSO tests"; return; }
    327
    328	# listen on port 9000, capture TCP into $TMPFILE
    329	if [ "${PROTO}" == "IPv4" ] ; then
    330		IP_DST=${IPv4_DST}
    331		ip netns exec ${NS3} bash -c \
    332			"nc -4 -l -p 9000 > ${TMPFILE} &"
    333	elif [ "${PROTO}" == "IPv6" ] ; then
    334		IP_DST=${IPv6_DST}
    335		ip netns exec ${NS3} bash -c \
    336			"nc -6 -l -p 9000 > ${TMPFILE} &"
    337		RET=$?
    338	else
    339		echo "    test_gso: unknown PROTO: ${PROTO}"
    340		TEST_STATUS=1
    341	fi
    342	sleep 1  # let nc start listening
    343
    344	# send a packet larger than MTU
    345	ip netns exec ${NS1} bash -c \
    346		"dd if=/dev/zero bs=$PKT_SZ count=1 > /dev/tcp/${IP_DST}/9000 2>/dev/null"
    347	sleep 2 # let the packet get delivered
    348
    349	# verify we received all expected bytes
    350	SZ=$(stat -c %s ${TMPFILE})
    351	if [ "$SZ" != "$PKT_SZ" ] ; then
    352		echo "    test_gso failed: ${PROTO}"
    353		TEST_STATUS=1
    354	fi
    355}
    356
    357test_egress()
    358{
    359	local readonly ENCAP=$1
    360	echo "starting egress ${ENCAP} encap test ${VRF}"
    361	setup
    362
    363	# by default, pings work
    364	test_ping IPv4 0
    365	test_ping IPv6 0
    366
    367	# remove NS2->DST routes, ping fails
    368	ip -netns ${NS2}    route del ${IPv4_DST}/32  dev veth3 ${VRF}
    369	ip -netns ${NS2} -6 route del ${IPv6_DST}/128 dev veth3 ${VRF}
    370	test_ping IPv4 1
    371	test_ping IPv6 1
    372
    373	# install replacement routes (LWT/eBPF), pings succeed
    374	if [ "${ENCAP}" == "IPv4" ] ; then
    375		ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \
    376			test_lwt_ip_encap.o sec encap_gre dev veth1 ${VRF}
    377		ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \
    378			test_lwt_ip_encap.o sec encap_gre dev veth1 ${VRF}
    379	elif [ "${ENCAP}" == "IPv6" ] ; then
    380		ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \
    381			test_lwt_ip_encap.o sec encap_gre6 dev veth1 ${VRF}
    382		ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \
    383			test_lwt_ip_encap.o sec encap_gre6 dev veth1 ${VRF}
    384	else
    385		echo "    unknown encap ${ENCAP}"
    386		TEST_STATUS=1
    387	fi
    388	test_ping IPv4 0
    389	test_ping IPv6 0
    390
    391	# skip GSO tests with VRF: VRF routing needs properly assigned
    392	# source IP/device, which is easy to do with ping and hard with dd/nc.
    393	if [ -z "${VRF}" ] ; then
    394		test_gso IPv4
    395		test_gso IPv6
    396	fi
    397
    398	# a negative test: remove routes to GRE devices: ping fails
    399	remove_routes_to_gredev
    400	test_ping IPv4 1
    401	test_ping IPv6 1
    402
    403	# another negative test
    404	add_unreachable_routes_to_gredev
    405	test_ping IPv4 1
    406	test_ping IPv6 1
    407
    408	cleanup
    409	process_test_results
    410}
    411
    412test_ingress()
    413{
    414	local readonly ENCAP=$1
    415	echo "starting ingress ${ENCAP} encap test ${VRF}"
    416	setup
    417
    418	# need to wait a bit for IPv6 to autoconf, otherwise
    419	# ping6 sometimes fails with "unable to bind to address"
    420
    421	# by default, pings work
    422	test_ping IPv4 0
    423	test_ping IPv6 0
    424
    425	# remove NS2->DST routes, pings fail
    426	ip -netns ${NS2}    route del ${IPv4_DST}/32  dev veth3 ${VRF}
    427	ip -netns ${NS2} -6 route del ${IPv6_DST}/128 dev veth3 ${VRF}
    428	test_ping IPv4 1
    429	test_ping IPv6 1
    430
    431	# install replacement routes (LWT/eBPF), pings succeed
    432	if [ "${ENCAP}" == "IPv4" ] ; then
    433		ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj \
    434			test_lwt_ip_encap.o sec encap_gre dev veth2 ${VRF}
    435		ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj \
    436			test_lwt_ip_encap.o sec encap_gre dev veth2 ${VRF}
    437	elif [ "${ENCAP}" == "IPv6" ] ; then
    438		ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj \
    439			test_lwt_ip_encap.o sec encap_gre6 dev veth2 ${VRF}
    440		ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj \
    441			test_lwt_ip_encap.o sec encap_gre6 dev veth2 ${VRF}
    442	else
    443		echo "FAIL: unknown encap ${ENCAP}"
    444		TEST_STATUS=1
    445	fi
    446	test_ping IPv4 0
    447	test_ping IPv6 0
    448
    449	# a negative test: remove routes to GRE devices: ping fails
    450	remove_routes_to_gredev
    451	test_ping IPv4 1
    452	test_ping IPv6 1
    453
    454	# another negative test
    455	add_unreachable_routes_to_gredev
    456	test_ping IPv4 1
    457	test_ping IPv6 1
    458
    459	cleanup
    460	process_test_results
    461}
    462
    463VRF=""
    464test_egress IPv4
    465test_egress IPv6
    466test_ingress IPv4
    467test_ingress IPv6
    468
    469VRF="vrf red"
    470test_egress IPv4
    471test_egress IPv6
    472test_ingress IPv4
    473test_ingress IPv6
    474
    475print_test_summary_and_exit