link_faults.sh 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. # shellcheck disable=SC2329
  4. source ../lib.sh
  5. ALL_TESTS="
  6. test_clean_hsrv0
  7. test_cut_link_hsrv0
  8. test_packet_loss_hsrv0
  9. test_high_packet_loss_hsrv0
  10. test_reordering_hsrv0
  11. test_clean_hsrv1
  12. test_cut_link_hsrv1
  13. test_packet_loss_hsrv1
  14. test_high_packet_loss_hsrv1
  15. test_reordering_hsrv1
  16. test_clean_prp
  17. test_cut_link_prp
  18. test_packet_loss_prp
  19. test_high_packet_loss_prp
  20. test_reordering_prp
  21. "
  22. # The tests are running ping for 5sec with a relatively short interval in
  23. # different scenarios with faulty links (cut links, packet loss, delay,
  24. # reordering) that should be recoverable by HSR/PRP. The ping interval (10ms)
  25. # is short enough that the base delay (50ms) leads to a queue in the netem
  26. # qdiscs which is needed for reordering.
  27. setup_hsr_topo()
  28. {
  29. # Three HSR nodes in a ring, every node has a LAN A interface connected
  30. # to the LAN B interface of the next node.
  31. #
  32. # node1 node2
  33. #
  34. # vethA -------- vethB
  35. # hsr1 hsr2
  36. # vethB vethA
  37. # \ /
  38. # vethA vethB
  39. # hsr3
  40. #
  41. # node3
  42. local ver="$1"
  43. setup_ns node1 node2 node3
  44. # veth links
  45. # shellcheck disable=SC2154 # variables assigned by setup_ns
  46. ip link add vethA netns "$node1" type veth peer name vethB netns "$node2"
  47. # shellcheck disable=SC2154 # variables assigned by setup_ns
  48. ip link add vethA netns "$node2" type veth peer name vethB netns "$node3"
  49. ip link add vethA netns "$node3" type veth peer name vethB netns "$node1"
  50. # MAC addresses (not needed for HSR operation, but helps with debugging)
  51. ip -net "$node1" link set address 00:11:22:00:01:01 dev vethA
  52. ip -net "$node1" link set address 00:11:22:00:01:02 dev vethB
  53. ip -net "$node2" link set address 00:11:22:00:02:01 dev vethA
  54. ip -net "$node2" link set address 00:11:22:00:02:02 dev vethB
  55. ip -net "$node3" link set address 00:11:22:00:03:01 dev vethA
  56. ip -net "$node3" link set address 00:11:22:00:03:02 dev vethB
  57. # HSR interfaces
  58. ip -net "$node1" link add name hsr1 type hsr proto 0 version "$ver" \
  59. slave1 vethA slave2 vethB supervision 45
  60. ip -net "$node2" link add name hsr2 type hsr proto 0 version "$ver" \
  61. slave1 vethA slave2 vethB supervision 45
  62. ip -net "$node3" link add name hsr3 type hsr proto 0 version "$ver" \
  63. slave1 vethA slave2 vethB supervision 45
  64. # IP addresses
  65. ip -net "$node1" addr add 100.64.0.1/24 dev hsr1
  66. ip -net "$node2" addr add 100.64.0.2/24 dev hsr2
  67. ip -net "$node3" addr add 100.64.0.3/24 dev hsr3
  68. # Set all links up
  69. ip -net "$node1" link set vethA up
  70. ip -net "$node1" link set vethB up
  71. ip -net "$node1" link set hsr1 up
  72. ip -net "$node2" link set vethA up
  73. ip -net "$node2" link set vethB up
  74. ip -net "$node2" link set hsr2 up
  75. ip -net "$node3" link set vethA up
  76. ip -net "$node3" link set vethB up
  77. ip -net "$node3" link set hsr3 up
  78. }
  79. setup_prp_topo()
  80. {
  81. # Two PRP nodes, connected by two links (treated as LAN A and LAN B).
  82. #
  83. # vethA ----- vethA
  84. # prp1 prp2
  85. # vethB ----- vethB
  86. #
  87. # node1 node2
  88. setup_ns node1 node2
  89. # veth links
  90. ip link add vethA netns "$node1" type veth peer name vethA netns "$node2"
  91. ip link add vethB netns "$node1" type veth peer name vethB netns "$node2"
  92. # MAC addresses will be copied from LAN A interface
  93. ip -net "$node1" link set address 00:11:22:00:00:01 dev vethA
  94. ip -net "$node2" link set address 00:11:22:00:00:02 dev vethA
  95. # PRP interfaces
  96. ip -net "$node1" link add name prp1 type hsr \
  97. slave1 vethA slave2 vethB supervision 45 proto 1
  98. ip -net "$node2" link add name prp2 type hsr \
  99. slave1 vethA slave2 vethB supervision 45 proto 1
  100. # IP addresses
  101. ip -net "$node1" addr add 100.64.0.1/24 dev prp1
  102. ip -net "$node2" addr add 100.64.0.2/24 dev prp2
  103. # All links up
  104. ip -net "$node1" link set vethA up
  105. ip -net "$node1" link set vethB up
  106. ip -net "$node1" link set prp1 up
  107. ip -net "$node2" link set vethA up
  108. ip -net "$node2" link set vethB up
  109. ip -net "$node2" link set prp2 up
  110. }
  111. wait_for_hsr_node_table()
  112. {
  113. log_info "Wait for node table entries to be merged."
  114. WAIT=5
  115. while [ "${WAIT}" -gt 0 ]; do
  116. nts=$(cat /sys/kernel/debug/hsr/hsr*/node_table)
  117. # We need entries in the node tables, and they need to be merged
  118. if (echo "$nts" | grep -qE "^([0-9a-f]{2}:){5}") && \
  119. ! (echo "$nts" | grep -q "00:00:00:00:00:00"); then
  120. return
  121. fi
  122. sleep 1
  123. ((WAIT--))
  124. done
  125. check_err 1 "Failed to wait for merged node table entries"
  126. }
  127. setup_topo()
  128. {
  129. local proto="$1"
  130. if [ "$proto" = "HSRv0" ]; then
  131. setup_hsr_topo 0
  132. wait_for_hsr_node_table
  133. elif [ "$proto" = "HSRv1" ]; then
  134. setup_hsr_topo 1
  135. wait_for_hsr_node_table
  136. elif [ "$proto" = "PRP" ]; then
  137. setup_prp_topo
  138. else
  139. check_err 1 "Unknown protocol (${proto})"
  140. fi
  141. }
  142. check_ping()
  143. {
  144. local node="$1"
  145. local dst="$2"
  146. local accepted_dups="$3"
  147. local ping_args="-q -i 0.01 -c 400"
  148. log_info "Running ping $node -> $dst"
  149. # shellcheck disable=SC2086
  150. output=$(ip netns exec "$node" ping $ping_args "$dst" | \
  151. grep "packets transmitted")
  152. log_info "$output"
  153. dups=0
  154. loss=0
  155. if [[ "$output" =~ \+([0-9]+)" duplicates" ]]; then
  156. dups="${BASH_REMATCH[1]}"
  157. fi
  158. if [[ "$output" =~ ([0-9\.]+\%)" packet loss" ]]; then
  159. loss="${BASH_REMATCH[1]}"
  160. fi
  161. if [ "$dups" -gt "$accepted_dups" ]; then
  162. check_err 1 "Unexpected duplicate packets (${dups})"
  163. fi
  164. if [ "$loss" != "0%" ]; then
  165. check_err 1 "Unexpected packet loss (${loss})"
  166. fi
  167. }
  168. test_clean()
  169. {
  170. local proto="$1"
  171. RET=0
  172. tname="${FUNCNAME[0]} - ${proto}"
  173. setup_topo "$proto"
  174. if ((RET != ksft_pass)); then
  175. log_test "${tname} setup"
  176. return
  177. fi
  178. check_ping "$node1" "100.64.0.2" 0
  179. log_test "${tname}"
  180. }
  181. test_clean_hsrv0()
  182. {
  183. test_clean "HSRv0"
  184. }
  185. test_clean_hsrv1()
  186. {
  187. test_clean "HSRv1"
  188. }
  189. test_clean_prp()
  190. {
  191. test_clean "PRP"
  192. }
  193. test_cut_link()
  194. {
  195. local proto="$1"
  196. RET=0
  197. tname="${FUNCNAME[0]} - ${proto}"
  198. setup_topo "$proto"
  199. if ((RET != ksft_pass)); then
  200. log_test "${tname} setup"
  201. return
  202. fi
  203. # Cutting link from subshell, so check_ping can run in the normal shell
  204. # with access to global variables from the test harness.
  205. (
  206. sleep 2
  207. log_info "Cutting link"
  208. ip -net "$node1" link set vethB down
  209. ) &
  210. check_ping "$node1" "100.64.0.2" 0
  211. wait
  212. log_test "${tname}"
  213. }
  214. test_cut_link_hsrv0()
  215. {
  216. test_cut_link "HSRv0"
  217. }
  218. test_cut_link_hsrv1()
  219. {
  220. test_cut_link "HSRv1"
  221. }
  222. test_cut_link_prp()
  223. {
  224. test_cut_link "PRP"
  225. }
  226. test_packet_loss()
  227. {
  228. local proto="$1"
  229. local loss="$2"
  230. RET=0
  231. tname="${FUNCNAME[0]} - ${proto}, ${loss}"
  232. setup_topo "$proto"
  233. if ((RET != ksft_pass)); then
  234. log_test "${tname} setup"
  235. return
  236. fi
  237. # Packet loss with lower delay makes sure the packets on the lossy link
  238. # arrive first.
  239. tc -net "$node1" qdisc add dev vethA root netem delay 50ms
  240. tc -net "$node1" qdisc add dev vethB root netem delay 20ms loss "$loss"
  241. check_ping "$node1" "100.64.0.2" 40
  242. log_test "${tname}"
  243. }
  244. test_packet_loss_hsrv0()
  245. {
  246. test_packet_loss "HSRv0" "20%"
  247. }
  248. test_packet_loss_hsrv1()
  249. {
  250. test_packet_loss "HSRv1" "20%"
  251. }
  252. test_packet_loss_prp()
  253. {
  254. test_packet_loss "PRP" "20%"
  255. }
  256. test_high_packet_loss_hsrv0()
  257. {
  258. test_packet_loss "HSRv0" "80%"
  259. }
  260. test_high_packet_loss_hsrv1()
  261. {
  262. test_packet_loss "HSRv1" "80%"
  263. }
  264. test_high_packet_loss_prp()
  265. {
  266. test_packet_loss "PRP" "80%"
  267. }
  268. test_reordering()
  269. {
  270. local proto="$1"
  271. RET=0
  272. tname="${FUNCNAME[0]} - ${proto}"
  273. setup_topo "$proto"
  274. if ((RET != ksft_pass)); then
  275. log_test "${tname} setup"
  276. return
  277. fi
  278. tc -net "$node1" qdisc add dev vethA root netem delay 50ms
  279. tc -net "$node1" qdisc add dev vethB root netem delay 50ms reorder 20%
  280. check_ping "$node1" "100.64.0.2" 40
  281. log_test "${tname}"
  282. }
  283. test_reordering_hsrv0()
  284. {
  285. test_reordering "HSRv0"
  286. }
  287. test_reordering_hsrv1()
  288. {
  289. test_reordering "HSRv1"
  290. }
  291. test_reordering_prp()
  292. {
  293. test_reordering "PRP"
  294. }
  295. cleanup()
  296. {
  297. cleanup_all_ns
  298. }
  299. trap cleanup EXIT
  300. tests_run
  301. exit $EXIT_STATUS