msg_zerocopy.sh 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #!/bin/bash
  2. #
  3. # Send data between two processes across namespaces
  4. # Run twice: once without and once with zerocopy
  5. set -e
  6. readonly DEV="veth0"
  7. readonly DUMMY_DEV="dummy0"
  8. readonly DEV_MTU=65535
  9. readonly BIN="./msg_zerocopy"
  10. readonly RAND="$(mktemp -u XXXXXX)"
  11. readonly NSPREFIX="ns-${RAND}"
  12. readonly NS1="${NSPREFIX}1"
  13. readonly NS2="${NSPREFIX}2"
  14. readonly LPREFIX4='192.168.1'
  15. readonly RPREFIX4='192.168.2'
  16. readonly LPREFIX6='fd'
  17. readonly RPREFIX6='fc'
  18. readonly path_sysctl_mem="net.core.optmem_max"
  19. # No arguments: automated test
  20. if [[ "$#" -eq "0" ]]; then
  21. ret=0
  22. $0 4 tcp -t 1 || ret=1
  23. $0 6 tcp -t 1 || ret=1
  24. $0 4 udp -t 1 || ret=1
  25. $0 6 udp -t 1 || ret=1
  26. [[ "$ret" == "0" ]] && echo "OK. All tests passed"
  27. exit $ret
  28. fi
  29. # Argument parsing
  30. if [[ "$#" -lt "2" ]]; then
  31. echo "Usage: $0 [4|6] [tcp|udp|raw|raw_hdrincl|packet|packet_dgram] <args>"
  32. exit 1
  33. fi
  34. readonly IP="$1"
  35. shift
  36. readonly TXMODE="$1"
  37. shift
  38. readonly EXTRA_ARGS="$@"
  39. # Argument parsing: configure addresses
  40. if [[ "${IP}" == "4" ]]; then
  41. readonly SADDR="${LPREFIX4}.1"
  42. readonly DADDR="${LPREFIX4}.2"
  43. readonly DUMMY_ADDR="${RPREFIX4}.1"
  44. readonly DADDR_TXONLY="${RPREFIX4}.2"
  45. readonly MASK="24"
  46. elif [[ "${IP}" == "6" ]]; then
  47. readonly SADDR="${LPREFIX6}::1"
  48. readonly DADDR="${LPREFIX6}::2"
  49. readonly DUMMY_ADDR="${RPREFIX6}::1"
  50. readonly DADDR_TXONLY="${RPREFIX6}::2"
  51. readonly MASK="64"
  52. readonly NODAD="nodad"
  53. else
  54. echo "Invalid IP version ${IP}"
  55. exit 1
  56. fi
  57. # Argument parsing: select receive mode
  58. #
  59. # This differs from send mode for
  60. # - packet: use raw recv, because packet receives skb clones
  61. # - raw_hdrinc: use raw recv, because hdrincl is a tx-only option
  62. case "${TXMODE}" in
  63. 'packet' | 'packet_dgram' | 'raw_hdrincl')
  64. RXMODE='raw'
  65. ;;
  66. *)
  67. RXMODE="${TXMODE}"
  68. ;;
  69. esac
  70. # Start of state changes: install cleanup handler
  71. cleanup() {
  72. ip netns del "${NS2}"
  73. ip netns del "${NS1}"
  74. }
  75. trap cleanup EXIT
  76. # Create virtual ethernet pair between network namespaces
  77. ip netns add "${NS1}"
  78. ip netns add "${NS2}"
  79. # Configure system settings
  80. ip netns exec "${NS1}" sysctl -w -q "${path_sysctl_mem}=1000000"
  81. ip netns exec "${NS2}" sysctl -w -q "${path_sysctl_mem}=1000000"
  82. ip link add "${DEV}" mtu "${DEV_MTU}" netns "${NS1}" type veth \
  83. peer name "${DEV}" mtu "${DEV_MTU}" netns "${NS2}"
  84. ip link add "${DUMMY_DEV}" mtu "${DEV_MTU}" netns "${NS2}" type dummy
  85. # Bring the devices up
  86. ip -netns "${NS1}" link set "${DEV}" up
  87. ip -netns "${NS2}" link set "${DEV}" up
  88. ip -netns "${NS2}" link set "${DUMMY_DEV}" up
  89. # Set fixed MAC addresses on the devices
  90. ip -netns "${NS1}" link set dev "${DEV}" address 02:02:02:02:02:02
  91. ip -netns "${NS2}" link set dev "${DEV}" address 06:06:06:06:06:06
  92. # Add fixed IP addresses to the devices
  93. ip -netns "${NS1}" addr add "${SADDR}/${MASK}" dev "${DEV}" ${NODAD}
  94. ip -netns "${NS2}" addr add "${DADDR}/${MASK}" dev "${DEV}" ${NODAD}
  95. ip -netns "${NS2}" addr add "${DUMMY_ADDR}/${MASK}" dev "${DUMMY_DEV}" ${NODAD}
  96. ip -netns "${NS1}" route add default via "${DADDR}" dev "${DEV}"
  97. ip -netns "${NS2}" route add default via "${DADDR_TXONLY}" dev "${DUMMY_DEV}"
  98. ip netns exec "${NS2}" sysctl -wq net.ipv4.ip_forward=1
  99. ip netns exec "${NS2}" sysctl -wq net.ipv6.conf.all.forwarding=1
  100. # Optionally disable sg or csum offload to test edge cases
  101. # ip netns exec "${NS1}" ethtool -K "${DEV}" sg off
  102. ret=0
  103. do_test() {
  104. local readonly ARGS="$1"
  105. # tx-rx test
  106. # packets queued to a local socket are copied,
  107. # sender notification has SO_EE_CODE_ZEROCOPY_COPIED.
  108. echo -e "\nipv${IP} ${TXMODE} ${ARGS} tx-rx\n"
  109. ip netns exec "${NS2}" "${BIN}" "-${IP}" -i "${DEV}" -t 2 -C 2 \
  110. -S "${SADDR}" -D "${DADDR}" ${ARGS} -r "${RXMODE}" &
  111. sleep 0.2
  112. ip netns exec "${NS1}" "${BIN}" "-${IP}" -i "${DEV}" -t 1 -C 3 \
  113. -S "${SADDR}" -D "${DADDR}" ${ARGS} "${TXMODE}" -Z 0 || ret=1
  114. wait
  115. # next test is unconnected tx to dummy0, cannot exercise with tcp
  116. [[ "${TXMODE}" == "tcp" ]] && return
  117. # tx-only test: send out dummy0
  118. # packets leaving the host are not copied,
  119. # sender notification does not have SO_EE_CODE_ZEROCOPY_COPIED.
  120. echo -e "\nipv${IP} ${TXMODE} ${ARGS} tx-only\n"
  121. ip netns exec "${NS1}" "${BIN}" "-${IP}" -i "${DEV}" -t 1 -C 3 \
  122. -S "${SADDR}" -D "${DADDR_TXONLY}" ${ARGS} "${TXMODE}" -Z 1 || ret=1
  123. }
  124. do_test "${EXTRA_ARGS}"
  125. do_test "-z ${EXTRA_ARGS}"
  126. [[ "$ret" == "0" ]] && echo "OK"