1*4882a593Smuzhiyun#!/bin/bash 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# Send data between two processes across namespaces 4*4882a593Smuzhiyun# Run twice: once without and once with zerocopy 5*4882a593Smuzhiyun 6*4882a593Smuzhiyunset -e 7*4882a593Smuzhiyun 8*4882a593Smuzhiyunreadonly DEV="veth0" 9*4882a593Smuzhiyunreadonly DEV_MTU=65535 10*4882a593Smuzhiyunreadonly BIN="./msg_zerocopy" 11*4882a593Smuzhiyun 12*4882a593Smuzhiyunreadonly RAND="$(mktemp -u XXXXXX)" 13*4882a593Smuzhiyunreadonly NSPREFIX="ns-${RAND}" 14*4882a593Smuzhiyunreadonly NS1="${NSPREFIX}1" 15*4882a593Smuzhiyunreadonly NS2="${NSPREFIX}2" 16*4882a593Smuzhiyun 17*4882a593Smuzhiyunreadonly SADDR4='192.168.1.1' 18*4882a593Smuzhiyunreadonly DADDR4='192.168.1.2' 19*4882a593Smuzhiyunreadonly SADDR6='fd::1' 20*4882a593Smuzhiyunreadonly DADDR6='fd::2' 21*4882a593Smuzhiyun 22*4882a593Smuzhiyunreadonly path_sysctl_mem="net.core.optmem_max" 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun# No arguments: automated test 25*4882a593Smuzhiyunif [[ "$#" -eq "0" ]]; then 26*4882a593Smuzhiyun $0 4 tcp -t 1 27*4882a593Smuzhiyun $0 6 tcp -t 1 28*4882a593Smuzhiyun $0 4 udp -t 1 29*4882a593Smuzhiyun $0 6 udp -t 1 30*4882a593Smuzhiyun echo "OK. All tests passed" 31*4882a593Smuzhiyun exit 0 32*4882a593Smuzhiyunfi 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun# Argument parsing 35*4882a593Smuzhiyunif [[ "$#" -lt "2" ]]; then 36*4882a593Smuzhiyun echo "Usage: $0 [4|6] [tcp|udp|raw|raw_hdrincl|packet|packet_dgram] <args>" 37*4882a593Smuzhiyun exit 1 38*4882a593Smuzhiyunfi 39*4882a593Smuzhiyun 40*4882a593Smuzhiyunreadonly IP="$1" 41*4882a593Smuzhiyunshift 42*4882a593Smuzhiyunreadonly TXMODE="$1" 43*4882a593Smuzhiyunshift 44*4882a593Smuzhiyunreadonly EXTRA_ARGS="$@" 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun# Argument parsing: configure addresses 47*4882a593Smuzhiyunif [[ "${IP}" == "4" ]]; then 48*4882a593Smuzhiyun readonly SADDR="${SADDR4}" 49*4882a593Smuzhiyun readonly DADDR="${DADDR4}" 50*4882a593Smuzhiyunelif [[ "${IP}" == "6" ]]; then 51*4882a593Smuzhiyun readonly SADDR="${SADDR6}" 52*4882a593Smuzhiyun readonly DADDR="${DADDR6}" 53*4882a593Smuzhiyunelse 54*4882a593Smuzhiyun echo "Invalid IP version ${IP}" 55*4882a593Smuzhiyun exit 1 56*4882a593Smuzhiyunfi 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun# Argument parsing: select receive mode 59*4882a593Smuzhiyun# 60*4882a593Smuzhiyun# This differs from send mode for 61*4882a593Smuzhiyun# - packet: use raw recv, because packet receives skb clones 62*4882a593Smuzhiyun# - raw_hdrinc: use raw recv, because hdrincl is a tx-only option 63*4882a593Smuzhiyuncase "${TXMODE}" in 64*4882a593Smuzhiyun'packet' | 'packet_dgram' | 'raw_hdrincl') 65*4882a593Smuzhiyun RXMODE='raw' 66*4882a593Smuzhiyun ;; 67*4882a593Smuzhiyun*) 68*4882a593Smuzhiyun RXMODE="${TXMODE}" 69*4882a593Smuzhiyun ;; 70*4882a593Smuzhiyunesac 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun# Start of state changes: install cleanup handler 73*4882a593Smuzhiyunsave_sysctl_mem="$(sysctl -n ${path_sysctl_mem})" 74*4882a593Smuzhiyun 75*4882a593Smuzhiyuncleanup() { 76*4882a593Smuzhiyun ip netns del "${NS2}" 77*4882a593Smuzhiyun ip netns del "${NS1}" 78*4882a593Smuzhiyun sysctl -w -q "${path_sysctl_mem}=${save_sysctl_mem}" 79*4882a593Smuzhiyun} 80*4882a593Smuzhiyun 81*4882a593Smuzhiyuntrap cleanup EXIT 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun# Configure system settings 84*4882a593Smuzhiyunsysctl -w -q "${path_sysctl_mem}=1000000" 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun# Create virtual ethernet pair between network namespaces 87*4882a593Smuzhiyunip netns add "${NS1}" 88*4882a593Smuzhiyunip netns add "${NS2}" 89*4882a593Smuzhiyun 90*4882a593Smuzhiyunip link add "${DEV}" mtu "${DEV_MTU}" netns "${NS1}" type veth \ 91*4882a593Smuzhiyun peer name "${DEV}" mtu "${DEV_MTU}" netns "${NS2}" 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun# Bring the devices up 94*4882a593Smuzhiyunip -netns "${NS1}" link set "${DEV}" up 95*4882a593Smuzhiyunip -netns "${NS2}" link set "${DEV}" up 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun# Set fixed MAC addresses on the devices 98*4882a593Smuzhiyunip -netns "${NS1}" link set dev "${DEV}" address 02:02:02:02:02:02 99*4882a593Smuzhiyunip -netns "${NS2}" link set dev "${DEV}" address 06:06:06:06:06:06 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun# Add fixed IP addresses to the devices 102*4882a593Smuzhiyunip -netns "${NS1}" addr add 192.168.1.1/24 dev "${DEV}" 103*4882a593Smuzhiyunip -netns "${NS2}" addr add 192.168.1.2/24 dev "${DEV}" 104*4882a593Smuzhiyunip -netns "${NS1}" addr add fd::1/64 dev "${DEV}" nodad 105*4882a593Smuzhiyunip -netns "${NS2}" addr add fd::2/64 dev "${DEV}" nodad 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun# Optionally disable sg or csum offload to test edge cases 108*4882a593Smuzhiyun# ip netns exec "${NS1}" ethtool -K "${DEV}" sg off 109*4882a593Smuzhiyun 110*4882a593Smuzhiyundo_test() { 111*4882a593Smuzhiyun local readonly ARGS="$1" 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun echo "ipv${IP} ${TXMODE} ${ARGS}" 114*4882a593Smuzhiyun ip netns exec "${NS2}" "${BIN}" "-${IP}" -i "${DEV}" -t 2 -C 2 -S "${SADDR}" -D "${DADDR}" ${ARGS} -r "${RXMODE}" & 115*4882a593Smuzhiyun sleep 0.2 116*4882a593Smuzhiyun ip netns exec "${NS1}" "${BIN}" "-${IP}" -i "${DEV}" -t 1 -C 3 -S "${SADDR}" -D "${DADDR}" ${ARGS} "${TXMODE}" 117*4882a593Smuzhiyun wait 118*4882a593Smuzhiyun} 119*4882a593Smuzhiyun 120*4882a593Smuzhiyundo_test "${EXTRA_ARGS}" 121*4882a593Smuzhiyundo_test "-z ${EXTRA_ARGS}" 122*4882a593Smuzhiyunecho ok 123