| #!/bin/bash | |
| # SPDX-License-Identifier: GPL-2.0 | |
| # Setup script for running ksft tests over a real interface in loopback mode. | |
| # This scripts replaces the historical setup_loopback.sh. It puts | |
| # a (presumably) real hardware interface into loopback mode, creates macvlan | |
| # interfaces on top and places them in a network namespace for isolation. | |
| # | |
| # NETIF env variable must be exported to indicate the real target device. | |
| # Note that the test will override NETIF with one of the macvlans, the | |
| # actual ksft test will only see the macvlans. | |
| # | |
| # Example use: | |
| # export NETIF=eth0 | |
| # ./net/lib/ksft_setup_loopback.sh ./drivers/net/gro.py | |
| if [ -z "$NETIF" ]; then | |
| echo "Error: NETIF variable not set" | |
| exit 1 | |
| fi | |
| if ! [ -d "/sys/class/net/$NETIF" ]; then | |
| echo "Error: Can't find $NETIF, invalid netdevice" | |
| exit 1 | |
| fi | |
| # Save original settings for cleanup | |
| readonly FLUSH_PATH="/sys/class/net/${NETIF}/gro_flush_timeout" | |
| readonly IRQ_PATH="/sys/class/net/${NETIF}/napi_defer_hard_irqs" | |
| FLUSH_TIMEOUT="$(< "${FLUSH_PATH}")" | |
| readonly FLUSH_TIMEOUT | |
| HARD_IRQS="$(< "${IRQ_PATH}")" | |
| readonly HARD_IRQS | |
| SERVER_NS=$(mktemp -u server-XXXXXXXX) | |
| readonly SERVER_NS | |
| CLIENT_NS=$(mktemp -u client-XXXXXXXX) | |
| readonly CLIENT_NS | |
| readonly SERVER_MAC="aa:00:00:00:00:02" | |
| readonly CLIENT_MAC="aa:00:00:00:00:01" | |
| # ksft expects addresses to communicate with remote | |
| export LOCAL_V6=2001:db8:1::1 | |
| export REMOTE_V6=2001:db8:1::2 | |
| cleanup() { | |
| local exit_code=$? | |
| echo "Cleaning up..." | |
| # Remove macvlan interfaces and namespaces | |
| ip -netns "${SERVER_NS}" link del dev server 2>/dev/null || true | |
| ip netns del "${SERVER_NS}" 2>/dev/null || true | |
| ip -netns "${CLIENT_NS}" link del dev client 2>/dev/null || true | |
| ip netns del "${CLIENT_NS}" 2>/dev/null || true | |
| # Disable loopback | |
| ethtool -K "${NETIF}" loopback off 2>/dev/null || true | |
| sleep 1 | |
| echo "${FLUSH_TIMEOUT}" >"${FLUSH_PATH}" | |
| echo "${HARD_IRQS}" >"${IRQ_PATH}" | |
| exit $exit_code | |
| } | |
| trap cleanup EXIT INT TERM | |
| # Enable loopback mode | |
| echo "Enabling loopback on ${NETIF}..." | |
| ethtool -K "${NETIF}" loopback on || { | |
| echo "Failed to enable loopback mode" | |
| exit 1 | |
| } | |
| # The interface may need time to get carrier back, but selftests | |
| # will wait for carrier, so no need to wait / sleep here. | |
| # Use timer on host to trigger the network stack | |
| # Also disable device interrupt to not depend on NIC interrupt | |
| # Reduce test flakiness caused by unexpected interrupts | |
| echo 100000 >"${FLUSH_PATH}" | |
| echo 50 >"${IRQ_PATH}" | |
| # Create server namespace with macvlan | |
| ip netns add "${SERVER_NS}" | |
| ip link add link "${NETIF}" dev server address "${SERVER_MAC}" type macvlan | |
| ip link set dev server netns "${SERVER_NS}" | |
| ip -netns "${SERVER_NS}" link set dev server up | |
| ip -netns "${SERVER_NS}" addr add $LOCAL_V6/64 dev server | |
| ip -netns "${SERVER_NS}" link set dev lo up | |
| # Create client namespace with macvlan | |
| ip netns add "${CLIENT_NS}" | |
| ip link add link "${NETIF}" dev client address "${CLIENT_MAC}" type macvlan | |
| ip link set dev client netns "${CLIENT_NS}" | |
| ip -netns "${CLIENT_NS}" link set dev client up | |
| ip -netns "${CLIENT_NS}" addr add $REMOTE_V6/64 dev client | |
| ip -netns "${CLIENT_NS}" link set dev lo up | |
| echo "Setup complete!" | |
| echo " Device: ${NETIF}" | |
| echo " Server NS: ${SERVER_NS}" | |
| echo " Client NS: ${CLIENT_NS}" | |
| echo "" | |
| # Setup environment variables for tests | |
| export NETIF=server | |
| export REMOTE_TYPE=netns | |
| export REMOTE_ARGS="${CLIENT_NS}" | |
| # Run the command | |
| ip netns exec "${SERVER_NS}" "$@" |