1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4readonly FLUSH_PATH="/sys/class/net/${dev}/gro_flush_timeout"
5readonly IRQ_PATH="/sys/class/net/${dev}/napi_defer_hard_irqs"
6readonly FLUSH_TIMEOUT="$(< ${FLUSH_PATH})"
7readonly HARD_IRQS="$(< ${IRQ_PATH})"
8
9netdev_check_for_carrier() {
10	local -r dev="$1"
11
12	for i in {1..5}; do
13		carrier="$(cat /sys/class/net/${dev}/carrier)"
14		if [[ "${carrier}" -ne 1 ]] ; then
15			echo "carrier not ready yet..." >&2
16			sleep 1
17		else
18			echo "carrier ready" >&2
19			break
20		fi
21	done
22	echo "${carrier}"
23}
24
25# Assumes that there is no existing ipvlan device on the physical device
26setup_loopback_environment() {
27	local dev="$1"
28
29	# Fail hard if cannot turn on loopback mode for current NIC
30	ethtool -K "${dev}" loopback on || exit 1
31	sleep 1
32
33	# Check for the carrier
34	carrier=$(netdev_check_for_carrier ${dev})
35	if [[ "${carrier}" -ne 1 ]] ; then
36		echo "setup_loopback_environment failed"
37		exit 1
38	fi
39}
40
41setup_macvlan_ns(){
42	local -r link_dev="$1"
43	local -r ns_name="$2"
44	local -r ns_dev="$3"
45	local -r ns_mac="$4"
46	local -r addr="$5"
47
48	ip link add link "${link_dev}" dev "${ns_dev}" \
49		address "${ns_mac}" type macvlan
50	exit_code=$?
51	if [[ "${exit_code}" -ne 0 ]]; then
52		echo "setup_macvlan_ns failed"
53		exit $exit_code
54	fi
55
56	[[ -e /var/run/netns/"${ns_name}" ]] || ip netns add "${ns_name}"
57	ip link set dev "${ns_dev}" netns "${ns_name}"
58	ip -netns "${ns_name}" link set dev "${ns_dev}" up
59	if [[ -n "${addr}" ]]; then
60		ip -netns "${ns_name}" addr add dev "${ns_dev}" "${addr}"
61	fi
62
63	sleep 1
64}
65
66cleanup_macvlan_ns(){
67	while (( $# >= 2 )); do
68		ns_name="$1"
69		ns_dev="$2"
70		ip -netns "${ns_name}" link del dev "${ns_dev}"
71		ip netns del "${ns_name}"
72		shift 2
73	done
74}
75
76cleanup_loopback(){
77	local -r dev="$1"
78
79	ethtool -K "${dev}" loopback off
80	sleep 1
81
82	# Check for the carrier
83	carrier=$(netdev_check_for_carrier ${dev})
84	if [[ "${carrier}" -ne 1 ]] ; then
85		echo "setup_loopback_environment failed"
86		exit 1
87	fi
88}
89
90setup_interrupt() {
91	# Use timer on  host to trigger the network stack
92	# Also disable device interrupt to not depend on NIC interrupt
93	# Reduce test flakiness caused by unexpected interrupts
94	echo 100000 >"${FLUSH_PATH}"
95	echo 50 >"${IRQ_PATH}"
96}
97
98setup_ns() {
99	# Set up server_ns namespace and client_ns namespace
100	setup_macvlan_ns "${dev}" server_ns server "${SERVER_MAC}"
101	setup_macvlan_ns "${dev}" client_ns client "${CLIENT_MAC}"
102}
103
104cleanup_ns() {
105	cleanup_macvlan_ns server_ns server client_ns client
106}
107
108setup() {
109	setup_loopback_environment "${dev}"
110	setup_interrupt
111}
112
113cleanup() {
114	cleanup_loopback "${dev}"
115
116	echo "${FLUSH_TIMEOUT}" >"${FLUSH_PATH}"
117	echo "${HARD_IRQS}" >"${IRQ_PATH}"
118}
119