qos_pfc.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. #
  4. # This test injects a 10-MB burst of traffic with VLAN tag and 802.1p priority
  5. # of 1. This stream is consistently prioritized as priority 1, is put to PG
  6. # buffer 1, and scheduled at TC 1.
  7. #
  8. # - the stream first ingresses through $swp1, where it is forwarded to $swp3
  9. #
  10. # - then it ingresses through $swp4. Here it is put to a lossless buffer and put
  11. # to a small pool ("PFC pool"). The traffic is forwarded to $swp2, which is
  12. # shaped, and thus the PFC pool eventually fills, therefore the headroom
  13. # fills, and $swp3 is paused.
  14. #
  15. # - since $swp3 now can't send traffic, the traffic ingressing $swp1 is kept at
  16. # a pool ("overflow pool"). The overflow pool needs to be large enough to
  17. # contain the whole burst.
  18. #
  19. # - eventually the PFC pool gets some traffic out, headroom therefore gets some
  20. # traffic to the pool, and $swp3 is unpaused again. This way the traffic is
  21. # gradually forwarded from the overflow pool, through the PFC pool, out of
  22. # $swp2, and eventually to $h2.
  23. #
  24. # - if PFC works, all lossless flow packets that ingress through $swp1 should
  25. # also be seen ingressing $h2. If it doesn't, there will be drops due to
  26. # discrepancy between the speeds of $swp1 and $h2.
  27. #
  28. # - it should all play out relatively quickly, so that SLL and HLL will not
  29. # cause drops.
  30. #
  31. # +-----------------------+
  32. # | H1 |
  33. # | + $h1.111 |
  34. # | | 192.0.2.33/28 |
  35. # | | |
  36. # | + $h1 |
  37. # +---|-------------------+ +--------------------+
  38. # | | |
  39. # +---|----------------------|--------------------|---------------------------+
  40. # | + $swp1 $swp3 + + $swp4 |
  41. # | | iPOOL1 iPOOL0 | | iPOOL2 |
  42. # | | ePOOL4 ePOOL5 | | ePOOL4 |
  43. # | | PFC:enabled=1 | | PFC:enabled=1 |
  44. # | +-|----------------------|-+ +-|------------------------+ |
  45. # | | + $swp1.111 $swp3.111 + | | + $swp4.111 | |
  46. # | | | | | |
  47. # | | BR1 | | BR2 | |
  48. # | | | | | |
  49. # | | | | + $swp2.111 | |
  50. # | +--------------------------+ +---------|----------------+ |
  51. # | | |
  52. # | iPOOL0: 500KB dynamic | |
  53. # | iPOOL1: 10MB static | |
  54. # | iPOOL2: 1MB static + $swp2 |
  55. # | ePOOL4: 500KB dynamic | iPOOL0 |
  56. # | ePOOL5: 10MB static | ePOOL6 |
  57. # | ePOOL6: "infinite" static | 200Mbps shaper |
  58. # +-------------------------------------------------------|-------------------+
  59. # |
  60. # +---|-------------------+
  61. # | + $h2 H2 |
  62. # | | |
  63. # | + $h2.111 |
  64. # | 192.0.2.34/28 |
  65. # +-----------------------+
  66. #
  67. # iPOOL0+ePOOL4 is a helper pool for control traffic etc.
  68. # iPOOL1+ePOOL5 are overflow pools.
  69. # iPOOL2+ePOOL6 are PFC pools.
  70. ALL_TESTS="
  71. ping_ipv4
  72. test_qos_pfc
  73. "
  74. lib_dir=$(dirname $0)/../../../net/forwarding
  75. NUM_NETIFS=6
  76. source $lib_dir/lib.sh
  77. source $lib_dir/devlink_lib.sh
  78. _1KB=1000
  79. _100KB=$((100 * _1KB))
  80. _500KB=$((500 * _1KB))
  81. _1MB=$((1000 * _1KB))
  82. _10MB=$((10 * _1MB))
  83. h1_create()
  84. {
  85. simple_if_init $h1
  86. mtu_set $h1 10000
  87. vlan_create $h1 111 v$h1 192.0.2.33/28
  88. }
  89. h1_destroy()
  90. {
  91. vlan_destroy $h1 111
  92. mtu_restore $h1
  93. simple_if_fini $h1
  94. }
  95. h2_create()
  96. {
  97. simple_if_init $h2
  98. mtu_set $h2 10000
  99. vlan_create $h2 111 v$h2 192.0.2.34/28
  100. }
  101. h2_destroy()
  102. {
  103. vlan_destroy $h2 111
  104. mtu_restore $h2
  105. simple_if_fini $h2
  106. }
  107. switch_create()
  108. {
  109. local lanes_swp4
  110. local pg1_size
  111. # pools
  112. # -----
  113. devlink_pool_size_thtype_save 0
  114. devlink_pool_size_thtype_save 4
  115. devlink_pool_size_thtype_save 1
  116. devlink_pool_size_thtype_save 5
  117. devlink_pool_size_thtype_save 2
  118. devlink_pool_size_thtype_save 6
  119. devlink_port_pool_th_save $swp1 1
  120. devlink_port_pool_th_save $swp2 6
  121. devlink_port_pool_th_save $swp3 5
  122. devlink_port_pool_th_save $swp4 2
  123. devlink_tc_bind_pool_th_save $swp1 1 ingress
  124. devlink_tc_bind_pool_th_save $swp2 1 egress
  125. devlink_tc_bind_pool_th_save $swp3 1 egress
  126. devlink_tc_bind_pool_th_save $swp4 1 ingress
  127. # Control traffic pools. Just reduce the size. Keep them dynamic so that
  128. # we don't need to change all the uninteresting quotas.
  129. devlink_pool_size_thtype_set 0 dynamic $_500KB
  130. devlink_pool_size_thtype_set 4 dynamic $_500KB
  131. # Overflow pools.
  132. devlink_pool_size_thtype_set 1 static $_10MB
  133. devlink_pool_size_thtype_set 5 static $_10MB
  134. # PFC pools. As per the writ, the size of egress PFC pool should be
  135. # infinice, but actually it just needs to be large enough to not matter
  136. # in practice, so reuse the 10MB limit.
  137. devlink_pool_size_thtype_set 2 static $_1MB
  138. devlink_pool_size_thtype_set 6 static $_10MB
  139. # $swp1
  140. # -----
  141. ip link set dev $swp1 up
  142. mtu_set $swp1 10000
  143. vlan_create $swp1 111
  144. ip link set dev $swp1.111 type vlan ingress-qos-map 0:0 1:1
  145. devlink_port_pool_th_set $swp1 1 $_10MB
  146. devlink_tc_bind_pool_th_set $swp1 1 ingress 1 $_10MB
  147. # Configure qdisc so that we can configure PG and therefore pool
  148. # assignment.
  149. tc qdisc replace dev $swp1 root handle 1: \
  150. ets bands 8 strict 8 priomap 7 6
  151. dcb buffer set dev $swp1 prio-buffer all:0 1:1
  152. # $swp2
  153. # -----
  154. ip link set dev $swp2 up
  155. mtu_set $swp2 10000
  156. vlan_create $swp2 111
  157. ip link set dev $swp2.111 type vlan egress-qos-map 0:0 1:1
  158. devlink_port_pool_th_set $swp2 6 $_10MB
  159. devlink_tc_bind_pool_th_set $swp2 1 egress 6 $_10MB
  160. # prio 0->TC0 (band 7), 1->TC1 (band 6). TC1 is shaped.
  161. tc qdisc replace dev $swp2 root handle 1: \
  162. ets bands 8 strict 8 priomap 7 6
  163. tc qdisc replace dev $swp2 parent 1:7 handle 17: \
  164. tbf rate 200Mbit burst 131072 limit 1M
  165. # $swp3
  166. # -----
  167. ip link set dev $swp3 up
  168. mtu_set $swp3 10000
  169. vlan_create $swp3 111
  170. ip link set dev $swp3.111 type vlan egress-qos-map 0:0 1:1
  171. devlink_port_pool_th_set $swp3 5 $_10MB
  172. devlink_tc_bind_pool_th_set $swp3 1 egress 5 $_10MB
  173. # prio 0->TC0 (band 7), 1->TC1 (band 6)
  174. tc qdisc replace dev $swp3 root handle 1: \
  175. ets bands 8 strict 8 priomap 7 6
  176. # Need to enable PFC so that PAUSE takes effect. Therefore need to put
  177. # the lossless prio into a buffer of its own. Don't bother with buffer
  178. # sizes though, there is not going to be any pressure in the "backward"
  179. # direction.
  180. dcb buffer set dev $swp3 prio-buffer all:0 1:1
  181. dcb pfc set dev $swp3 prio-pfc all:off 1:on
  182. # $swp4
  183. # -----
  184. ip link set dev $swp4 up
  185. mtu_set $swp4 10000
  186. vlan_create $swp4 111
  187. ip link set dev $swp4.111 type vlan ingress-qos-map 0:0 1:1
  188. devlink_port_pool_th_set $swp4 2 $_1MB
  189. devlink_tc_bind_pool_th_set $swp4 1 ingress 2 $_1MB
  190. # Configure qdisc so that we can hand-tune headroom.
  191. tc qdisc replace dev $swp4 root handle 1: \
  192. ets bands 8 strict 8 priomap 7 6
  193. dcb buffer set dev $swp4 prio-buffer all:0 1:1
  194. dcb pfc set dev $swp4 prio-pfc all:off 1:on
  195. # PG0 will get autoconfigured to Xoff, give PG1 arbitrarily 100K, which
  196. # is (-2*MTU) about 80K of delay provision.
  197. pg1_size=$_100KB
  198. setup_wait_dev_with_timeout $swp4
  199. lanes_swp4=$(ethtool $swp4 | grep 'Lanes:')
  200. lanes_swp4=${lanes_swp4#*"Lanes: "}
  201. # 8-lane ports use two buffers among which the configured buffer
  202. # is split, so double the size to get twice (20K + 80K).
  203. if [[ $lanes_swp4 -eq 8 ]]; then
  204. pg1_size=$((pg1_size * 2))
  205. fi
  206. dcb buffer set dev $swp4 buffer-size all:0 1:$pg1_size
  207. # bridges
  208. # -------
  209. ip link add name br1 type bridge vlan_filtering 0
  210. ip link set dev $swp1.111 master br1
  211. ip link set dev $swp3.111 master br1
  212. ip link set dev br1 up
  213. ip link add name br2 type bridge vlan_filtering 0
  214. ip link set dev $swp2.111 master br2
  215. ip link set dev $swp4.111 master br2
  216. ip link set dev br2 up
  217. }
  218. switch_destroy()
  219. {
  220. # Do this first so that we can reset the limits to values that are only
  221. # valid for the original static / dynamic setting.
  222. devlink_pool_size_thtype_restore 6
  223. devlink_pool_size_thtype_restore 5
  224. devlink_pool_size_thtype_restore 4
  225. devlink_pool_size_thtype_restore 2
  226. devlink_pool_size_thtype_restore 1
  227. devlink_pool_size_thtype_restore 0
  228. # bridges
  229. # -------
  230. ip link set dev br2 down
  231. ip link set dev $swp4.111 nomaster
  232. ip link set dev $swp2.111 nomaster
  233. ip link del dev br2
  234. ip link set dev br1 down
  235. ip link set dev $swp3.111 nomaster
  236. ip link set dev $swp1.111 nomaster
  237. ip link del dev br1
  238. # $swp4
  239. # -----
  240. dcb buffer set dev $swp4 buffer-size all:0
  241. dcb pfc set dev $swp4 prio-pfc all:off
  242. dcb buffer set dev $swp4 prio-buffer all:0
  243. tc qdisc del dev $swp4 root
  244. devlink_tc_bind_pool_th_restore $swp4 1 ingress
  245. devlink_port_pool_th_restore $swp4 2
  246. vlan_destroy $swp4 111
  247. mtu_restore $swp4
  248. ip link set dev $swp4 down
  249. # $swp3
  250. # -----
  251. dcb pfc set dev $swp3 prio-pfc all:off
  252. dcb buffer set dev $swp3 prio-buffer all:0
  253. tc qdisc del dev $swp3 root
  254. devlink_tc_bind_pool_th_restore $swp3 1 egress
  255. devlink_port_pool_th_restore $swp3 5
  256. vlan_destroy $swp3 111
  257. mtu_restore $swp3
  258. ip link set dev $swp3 down
  259. # $swp2
  260. # -----
  261. tc qdisc del dev $swp2 parent 1:7
  262. tc qdisc del dev $swp2 root
  263. devlink_tc_bind_pool_th_restore $swp2 1 egress
  264. devlink_port_pool_th_restore $swp2 6
  265. vlan_destroy $swp2 111
  266. mtu_restore $swp2
  267. ip link set dev $swp2 down
  268. # $swp1
  269. # -----
  270. dcb buffer set dev $swp1 prio-buffer all:0
  271. tc qdisc del dev $swp1 root
  272. devlink_tc_bind_pool_th_restore $swp1 1 ingress
  273. devlink_port_pool_th_restore $swp1 1
  274. vlan_destroy $swp1 111
  275. mtu_restore $swp1
  276. ip link set dev $swp1 down
  277. }
  278. setup_prepare()
  279. {
  280. h1=${NETIFS[p1]}
  281. swp1=${NETIFS[p2]}
  282. swp2=${NETIFS[p3]}
  283. h2=${NETIFS[p4]}
  284. swp3=${NETIFS[p5]}
  285. swp4=${NETIFS[p6]}
  286. h2mac=$(mac_get $h2)
  287. vrf_prepare
  288. h1_create
  289. h2_create
  290. switch_create
  291. }
  292. cleanup()
  293. {
  294. pre_cleanup
  295. switch_destroy
  296. h2_destroy
  297. h1_destroy
  298. vrf_cleanup
  299. }
  300. ping_ipv4()
  301. {
  302. ping_test $h1 192.0.2.34
  303. }
  304. test_qos_pfc()
  305. {
  306. RET=0
  307. # 10M pool, each packet is 8K of payload + headers
  308. local pkts=$((_10MB / 8050))
  309. local size=$((pkts * 8050))
  310. local in0=$(ethtool_stats_get $swp1 rx_octets_prio_1)
  311. local out0=$(ethtool_stats_get $swp2 tx_octets_prio_1)
  312. $MZ $h1 -p 8000 -Q 1:111 -A 192.0.2.33 -B 192.0.2.34 \
  313. -a own -b $h2mac -c $pkts -t udp -q
  314. sleep 2
  315. local in1=$(ethtool_stats_get $swp1 rx_octets_prio_1)
  316. local out1=$(ethtool_stats_get $swp2 tx_octets_prio_1)
  317. local din=$((in1 - in0))
  318. local dout=$((out1 - out0))
  319. local pct_in=$((din * 100 / size))
  320. ((pct_in > 95 && pct_in < 105))
  321. check_err $? "Relative ingress out of expected bounds, $pct_in% should be 100%"
  322. ((dout == din))
  323. check_err $? "$((din - dout)) bytes out of $din ingressed got lost"
  324. log_test "PFC"
  325. }
  326. bail_on_lldpad "configure DCB" "configure Qdiscs"
  327. trap cleanup EXIT
  328. setup_prepare
  329. setup_wait
  330. tests_run
  331. exit $EXIT_STATUS