mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-08-16 08:08:49 +00:00

Zerocopy skbs are converted to regular copy skbs when data is queued to a local socket. This happens in the existing test with a sender and receiver communicating over a veth device. Zerocopy skbs are sent without copying if egressing a device. Verify that this behavior is maintained even in the common container setup where data is forwarded over a veth to the physical device. Update msg_zerocopy.sh to 1. Have a dummy network device to simulate a physical device. 2. Have forwarding enabled between veth and dummy. 3. Add a tx-only test that sends out dummy via the forwarding path. 4. Verify the exitcode of the sender, which signals zerocopy success. As dummy drops all packets, this cannot be a TCP connection. Test the new case with unconnected UDP only. Update msg_zerocopy.c to - Accept an argument whether send with zerocopy is expected. - Return an exitcode whether behavior matched that expectation. Signed-off-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20250630194312.1571410-3-willemdebruijn.kernel@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
162 lines
4.2 KiB
Bash
Executable File
162 lines
4.2 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Send data between two processes across namespaces
|
|
# Run twice: once without and once with zerocopy
|
|
|
|
set -e
|
|
|
|
readonly DEV="veth0"
|
|
readonly DUMMY_DEV="dummy0"
|
|
readonly DEV_MTU=65535
|
|
readonly BIN="./msg_zerocopy"
|
|
|
|
readonly RAND="$(mktemp -u XXXXXX)"
|
|
readonly NSPREFIX="ns-${RAND}"
|
|
readonly NS1="${NSPREFIX}1"
|
|
readonly NS2="${NSPREFIX}2"
|
|
|
|
readonly LPREFIX4='192.168.1'
|
|
readonly RPREFIX4='192.168.2'
|
|
readonly LPREFIX6='fd'
|
|
readonly RPREFIX6='fc'
|
|
|
|
|
|
readonly path_sysctl_mem="net.core.optmem_max"
|
|
|
|
# No arguments: automated test
|
|
if [[ "$#" -eq "0" ]]; then
|
|
ret=0
|
|
|
|
$0 4 tcp -t 1 || ret=1
|
|
$0 6 tcp -t 1 || ret=1
|
|
$0 4 udp -t 1 || ret=1
|
|
$0 6 udp -t 1 || ret=1
|
|
|
|
[[ "$ret" == "0" ]] && echo "OK. All tests passed"
|
|
exit $ret
|
|
fi
|
|
|
|
# Argument parsing
|
|
if [[ "$#" -lt "2" ]]; then
|
|
echo "Usage: $0 [4|6] [tcp|udp|raw|raw_hdrincl|packet|packet_dgram] <args>"
|
|
exit 1
|
|
fi
|
|
|
|
readonly IP="$1"
|
|
shift
|
|
readonly TXMODE="$1"
|
|
shift
|
|
readonly EXTRA_ARGS="$@"
|
|
|
|
# Argument parsing: configure addresses
|
|
if [[ "${IP}" == "4" ]]; then
|
|
readonly SADDR="${LPREFIX4}.1"
|
|
readonly DADDR="${LPREFIX4}.2"
|
|
readonly DUMMY_ADDR="${RPREFIX4}.1"
|
|
readonly DADDR_TXONLY="${RPREFIX4}.2"
|
|
readonly MASK="24"
|
|
elif [[ "${IP}" == "6" ]]; then
|
|
readonly SADDR="${LPREFIX6}::1"
|
|
readonly DADDR="${LPREFIX6}::2"
|
|
readonly DUMMY_ADDR="${RPREFIX6}::1"
|
|
readonly DADDR_TXONLY="${RPREFIX6}::2"
|
|
readonly MASK="64"
|
|
readonly NODAD="nodad"
|
|
else
|
|
echo "Invalid IP version ${IP}"
|
|
exit 1
|
|
fi
|
|
|
|
# Argument parsing: select receive mode
|
|
#
|
|
# This differs from send mode for
|
|
# - packet: use raw recv, because packet receives skb clones
|
|
# - raw_hdrinc: use raw recv, because hdrincl is a tx-only option
|
|
case "${TXMODE}" in
|
|
'packet' | 'packet_dgram' | 'raw_hdrincl')
|
|
RXMODE='raw'
|
|
;;
|
|
*)
|
|
RXMODE="${TXMODE}"
|
|
;;
|
|
esac
|
|
|
|
# Start of state changes: install cleanup handler
|
|
|
|
cleanup() {
|
|
ip netns del "${NS2}"
|
|
ip netns del "${NS1}"
|
|
}
|
|
|
|
trap cleanup EXIT
|
|
|
|
# Create virtual ethernet pair between network namespaces
|
|
ip netns add "${NS1}"
|
|
ip netns add "${NS2}"
|
|
|
|
# Configure system settings
|
|
ip netns exec "${NS1}" sysctl -w -q "${path_sysctl_mem}=1000000"
|
|
ip netns exec "${NS2}" sysctl -w -q "${path_sysctl_mem}=1000000"
|
|
|
|
ip link add "${DEV}" mtu "${DEV_MTU}" netns "${NS1}" type veth \
|
|
peer name "${DEV}" mtu "${DEV_MTU}" netns "${NS2}"
|
|
|
|
ip link add "${DUMMY_DEV}" mtu "${DEV_MTU}" netns "${NS2}" type dummy
|
|
|
|
# Bring the devices up
|
|
ip -netns "${NS1}" link set "${DEV}" up
|
|
ip -netns "${NS2}" link set "${DEV}" up
|
|
ip -netns "${NS2}" link set "${DUMMY_DEV}" up
|
|
|
|
# Set fixed MAC addresses on the devices
|
|
ip -netns "${NS1}" link set dev "${DEV}" address 02:02:02:02:02:02
|
|
ip -netns "${NS2}" link set dev "${DEV}" address 06:06:06:06:06:06
|
|
|
|
# Add fixed IP addresses to the devices
|
|
ip -netns "${NS1}" addr add "${SADDR}/${MASK}" dev "${DEV}" ${NODAD}
|
|
ip -netns "${NS2}" addr add "${DADDR}/${MASK}" dev "${DEV}" ${NODAD}
|
|
ip -netns "${NS2}" addr add "${DUMMY_ADDR}/${MASK}" dev "${DUMMY_DEV}" ${NODAD}
|
|
|
|
ip -netns "${NS1}" route add default via "${DADDR}" dev "${DEV}"
|
|
ip -netns "${NS2}" route add default via "${DADDR_TXONLY}" dev "${DUMMY_DEV}"
|
|
|
|
ip netns exec "${NS2}" sysctl -wq net.ipv4.ip_forward=1
|
|
ip netns exec "${NS2}" sysctl -wq net.ipv6.conf.all.forwarding=1
|
|
|
|
# Optionally disable sg or csum offload to test edge cases
|
|
# ip netns exec "${NS1}" ethtool -K "${DEV}" sg off
|
|
|
|
ret=0
|
|
|
|
do_test() {
|
|
local readonly ARGS="$1"
|
|
|
|
# tx-rx test
|
|
# packets queued to a local socket are copied,
|
|
# sender notification has SO_EE_CODE_ZEROCOPY_COPIED.
|
|
|
|
echo -e "\nipv${IP} ${TXMODE} ${ARGS} tx-rx\n"
|
|
ip netns exec "${NS2}" "${BIN}" "-${IP}" -i "${DEV}" -t 2 -C 2 \
|
|
-S "${SADDR}" -D "${DADDR}" ${ARGS} -r "${RXMODE}" &
|
|
sleep 0.2
|
|
ip netns exec "${NS1}" "${BIN}" "-${IP}" -i "${DEV}" -t 1 -C 3 \
|
|
-S "${SADDR}" -D "${DADDR}" ${ARGS} "${TXMODE}" -Z 0 || ret=1
|
|
wait
|
|
|
|
# next test is unconnected tx to dummy0, cannot exercise with tcp
|
|
[[ "${TXMODE}" == "tcp" ]] && return
|
|
|
|
# tx-only test: send out dummy0
|
|
# packets leaving the host are not copied,
|
|
# sender notification does not have SO_EE_CODE_ZEROCOPY_COPIED.
|
|
|
|
echo -e "\nipv${IP} ${TXMODE} ${ARGS} tx-only\n"
|
|
ip netns exec "${NS1}" "${BIN}" "-${IP}" -i "${DEV}" -t 1 -C 3 \
|
|
-S "${SADDR}" -D "${DADDR_TXONLY}" ${ARGS} "${TXMODE}" -Z 1 || ret=1
|
|
}
|
|
|
|
do_test "${EXTRA_ARGS}"
|
|
do_test "-z ${EXTRA_ARGS}"
|
|
|
|
[[ "$ret" == "0" ]] && echo "OK"
|