^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #!/bin/bash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) # Run a series of udpgro functional tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) # set global exit status, but never reset nonzero one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) check_err()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) if [ $ret -eq 0 ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) ret=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) cleanup() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) local -r jobs="$(jobs -p)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) local -r ns="$(ip netns list|grep $PEER_NS)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) [ -n "${jobs}" ] && kill -1 ${jobs} 2>/dev/null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) [ -n "$ns" ] && ip netns del $ns 2>/dev/null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) trap cleanup EXIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) cfg_veth() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) ip netns add "${PEER_NS}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) ip -netns "${PEER_NS}" link set lo up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ip link add type veth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ip link set dev veth0 up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ip addr add dev veth0 192.168.1.2/24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ip addr add dev veth0 2001:db8::2/64 nodad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ip link set dev veth1 netns "${PEER_NS}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ip -netns "${PEER_NS}" addr add dev veth1 192.168.1.1/24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ip -netns "${PEER_NS}" addr add dev veth1 2001:db8::1/64 nodad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ip -netns "${PEER_NS}" link set dev veth1 up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ip -n "${PEER_NS}" link set veth1 xdp object ../bpf/xdp_dummy.o section xdp_dummy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) run_one() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) # use 'rx' as separator between sender args and receiver args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) local -r all="$@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) local -r tx_args=${all%rx*}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) local -r rx_args=${all#*rx}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) cfg_veth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) echo "ok" || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) echo "failed" &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) # Hack: let bg programs complete the startup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) sleep 0.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ./udpgso_bench_tx ${tx_args}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ret=$?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) wait $(jobs -p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return $ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) run_test() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) local -r args=$@
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) printf " %-40s" "$1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ./in_netns.sh $0 __subprocess $2 rx -G -r $3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) run_one_nat() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) # use 'rx' as separator between sender args and receiver args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) local addr1 addr2 pid family="" ipt_cmd=ip6tables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) local -r all="$@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) local -r tx_args=${all%rx*}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) local -r rx_args=${all#*rx}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if [[ ${tx_args} = *-4* ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ipt_cmd=iptables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) family=-4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) addr1=192.168.1.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) addr2=192.168.1.3/24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) addr1=2001:db8::1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) addr2="2001:db8::3/64 nodad"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) cfg_veth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ip -netns "${PEER_NS}" addr add dev veth1 ${addr2}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) # fool the GRO engine changing the destination address ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ip netns exec "${PEER_NS}" $ipt_cmd -t nat -I PREROUTING -d ${addr1} -j DNAT --to-destination ${addr2%/*}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) # ... so that GRO will match the UDP_GRO enabled socket, but packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) # will land on the 'plain' one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ip netns exec "${PEER_NS}" ./udpgso_bench_rx -G ${family} -b ${addr1} -n 0 &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) pid=$!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) echo "ok" || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) echo "failed"&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) sleep 0.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ./udpgso_bench_tx ${tx_args}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ret=$?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) kill -INT $pid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) wait $(jobs -p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return $ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) run_one_2sock() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) # use 'rx' as separator between sender args and receiver args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) local -r all="$@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) local -r tx_args=${all%rx*}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) local -r rx_args=${all#*rx}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) cfg_veth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} -p 12345 &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) echo "ok" || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) echo "failed" &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) # Hack: let bg programs complete the startup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) sleep 0.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ./udpgso_bench_tx ${tx_args} -p 12345
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) sleep 0.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) # first UDP GSO socket should be closed at this point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ./udpgso_bench_tx ${tx_args}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ret=$?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) wait $(jobs -p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return $ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) run_nat_test() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) local -r args=$@
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) printf " %-40s" "$1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ./in_netns.sh $0 __subprocess_nat $2 rx -r $3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) run_2sock_test() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) local -r args=$@
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) printf " %-40s" "$1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ./in_netns.sh $0 __subprocess_2sock $2 rx -G -r $3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) run_all() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) local -r core_args="-l 4"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) local -r ipv4_args="${core_args} -4 -D 192.168.1.1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) local -r ipv6_args="${core_args} -6 -D 2001:db8::1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ret=0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) echo "ipv4"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) run_test "no GRO" "${ipv4_args} -M 10 -s 1400" "-4 -n 10 -l 1400"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) # explicitly check we are not receiving UDP_SEGMENT cmsg (-S -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) # when GRO does not take place
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) run_test "no GRO chk cmsg" "${ipv4_args} -M 10 -s 1400" "-4 -n 10 -l 1400 -S -1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) # the GSO packets are aggregated because:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) # * veth schedule napi after each xmit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) # * segmentation happens in BH context, veth napi poll is delayed after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) # the transmission of the last segment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) run_test "GRO" "${ipv4_args} -M 1 -s 14720 -S 0 " "-4 -n 1 -l 14720"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) run_test "GRO chk cmsg" "${ipv4_args} -M 1 -s 14720 -S 0 " "-4 -n 1 -l 14720 -S 1472"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) run_test "GRO with custom segment size" "${ipv4_args} -M 1 -s 14720 -S 500 " "-4 -n 1 -l 14720"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) run_test "GRO with custom segment size cmsg" "${ipv4_args} -M 1 -s 14720 -S 500 " "-4 -n 1 -l 14720 -S 500"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) run_nat_test "bad GRO lookup" "${ipv4_args} -M 1 -s 14720 -S 0" "-n 10 -l 1472"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) run_2sock_test "multiple GRO socks" "${ipv4_args} -M 1 -s 14720 -S 0 " "-4 -n 1 -l 14720 -S 1472"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) echo "ipv6"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) run_test "no GRO" "${ipv6_args} -M 10 -s 1400" "-n 10 -l 1400"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) run_test "no GRO chk cmsg" "${ipv6_args} -M 10 -s 1400" "-n 10 -l 1400 -S -1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) run_test "GRO" "${ipv6_args} -M 1 -s 14520 -S 0" "-n 1 -l 14520"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) run_test "GRO chk cmsg" "${ipv6_args} -M 1 -s 14520 -S 0" "-n 1 -l 14520 -S 1452"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) run_test "GRO with custom segment size" "${ipv6_args} -M 1 -s 14520 -S 500" "-n 1 -l 14520"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) run_test "GRO with custom segment size cmsg" "${ipv6_args} -M 1 -s 14520 -S 500" "-n 1 -l 14520 -S 500"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) run_nat_test "bad GRO lookup" "${ipv6_args} -M 1 -s 14520 -S 0" "-n 10 -l 1452"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) run_2sock_test "multiple GRO socks" "${ipv6_args} -M 1 -s 14520 -S 0 " "-n 1 -l 14520 -S 1452"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) check_err $?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return $ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if [ ! -f ../bpf/xdp_dummy.o ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) echo "Missing xdp_dummy helper. Build bpf selftest first"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) exit -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if [[ $# -eq 0 ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) run_all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) elif [[ $1 == "__subprocess" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) run_one $@
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) elif [[ $1 == "__subprocess_nat" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) run_one_nat $@
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) elif [[ $1 == "__subprocess_2sock" ]]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) run_one_2sock $@
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) exit $?