Fuel plugin for Mellanox support
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sriov.sh 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. #!/bin/bash -x
  2. # Copyright 2016 Mellanox Technologies, Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  13. # implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. readonly SCRIPT_DIR=$(dirname "$0")
  17. source $SCRIPT_DIR/common
  18. readonly SCRIPT_MODE=$1
  19. readonly FALLBACK_NUM_VFS=8
  20. readonly SRIOV_ENABLED_FLAG=1
  21. readonly VF_MAC_CACHING_TIMEOUT=1
  22. readonly VF_MAC_CACHING_TIMEOUT_DEF=300
  23. readonly NEW_KERNEL_PARAM="intel_iommu=on"
  24. readonly GRUB_FILE_CENTOS="/boot/grub/grub.conf"
  25. readonly GRUB_FILE_UBUNTU="/boot/grub/grub.cfg"
  26. function get_port_type() {
  27. if [ $NETWORK_TYPE == 'ethernet' ]; then
  28. port_type=2
  29. else
  30. port_type=1
  31. fi
  32. echo $port_type
  33. }
  34. function get_num_probe_vfs () {
  35. if [ `get_port_type` -eq "2" ]; then
  36. probe_vfs=`calculate_total_vfs`
  37. else
  38. probe_vfs=0
  39. fi
  40. echo $probe_vfs
  41. }
  42. function calculate_total_vfs () {
  43. # validate num of vfs is an integer, 0 <= num <= 64
  44. if [ "${USER_NUM_OF_VFS}" -ne "${USER_NUM_OF_VFS}" ] 2>/dev/null ||
  45. [ "${USER_NUM_OF_VFS}" -gt ${MAX_VFS} ] ||
  46. [ "${USER_NUM_OF_VFS}" -lt ${MIN_VFS} ]; then
  47. logger_print error "Illegal number of VFs ${USER_NUM_OF_VFS}, value
  48. should be an integer between ${MIN_VFS},${MAX_VFS}"
  49. return 1
  50. fi
  51. num_of_vfs=0
  52. # Set Compute VFs storage network
  53. if [ $SRIOV == true ]; then
  54. # If ROLES not set and not controller or compute
  55. if ([ -z $ROLES ] && [[ ! $ROLE == *controller* ]]) || \
  56. ([ $ROLE == compute ] || [[ $ROLES == *compute* ]]); then
  57. num_of_vfs=${USER_NUM_OF_VFS}
  58. fi
  59. fi
  60. # Set Ethernet RDMA storage network
  61. if [ $ISER == true ] && [ `get_port_type` -eq "2" ] \
  62. && [ $num_of_vfs -eq 0 ]; then
  63. num_of_vfs=1
  64. fi
  65. # Enforce even num of vfs
  66. if [ $((${num_of_vfs} % 2)) -eq 1 ]; then
  67. let num_of_vfs="${num_of_vfs} + 1"
  68. fi
  69. echo ${num_of_vfs}
  70. }
  71. # Reduce mac caching time since VF is used for iSER with non permanent MAC
  72. function reduce_mac_caching_timeout () {
  73. probes=`get_num_probe_vfs`
  74. if [ $probes -ge 1 ]; then
  75. timeout=$VF_MAC_CACHING_TIMEOUT
  76. else
  77. timeout=$VF_MAC_CACHING_TIMEOUT_DEF
  78. fi
  79. sysctl_conf set 'net.ipv4.route.gc_timeout' "$timeout"
  80. }
  81. function is_vxlan_offloading_required () {
  82. [ $VXLAN_OFFLOADING == true ]
  83. return $?
  84. }
  85. function set_modprobe_file () {
  86. PROBE_VFS=`get_num_probe_vfs`
  87. MLX4_CORE_FILE="/etc/modprobe.d/mlx4_core.conf"
  88. PORT_TYPE=`get_port_type`
  89. MLX4_CORE_STR="options mlx4_core
  90. enable_64b_cqe_eqe=0"
  91. if [[ $DEBUG == "true" ]];then
  92. MLX4_CORE_STR="${MLX4_CORE_STR} debug_level=1"
  93. fi
  94. TOTAL_VFS=$1
  95. MLX4_CORE_STR="${MLX4_CORE_STR} port_type_array=${PORT_TYPE},${PORT_TYPE}"
  96. if [[ $TOTAL_VFS -gt 0 ]]; then
  97. if [ $PORT_TYPE -eq 1 ]; then
  98. num_vfs="${TOTAL_VFS}"
  99. probe_vf="${TOTAL_VFS}"
  100. else
  101. num_vfs="${TOTAL_VFS},0,0"
  102. probe_vf="${TOTAL_VFS},0,0"
  103. fi
  104. MLX4_CORE_STR="${MLX4_CORE_STR} num_vfs=$num_vfs"
  105. if [[ $PROBE_VFS -gt 0 ]]; then
  106. MLX4_CORE_STR="${MLX4_CORE_STR} probe_vf=$probe_vf"
  107. fi
  108. fi
  109. MLX4_CORE_STR="${MLX4_CORE_STR} log_num_mgm_entry_size=-1"
  110. echo ${MLX4_CORE_STR} > ${MLX4_CORE_FILE}
  111. }
  112. function set_kernel_params () {
  113. if [ "$DISTRO" == "redhat" ]; then
  114. grub_file=${GRUB_FILE_CENTOS}
  115. kernel_line=`egrep 'kernel\s+/vmlinuz' ${grub_file} | grep -v '#'`
  116. elif [ "$DISTRO" == "ubuntu" ]; then
  117. grub_file=${GRUB_FILE_UBUNTU}
  118. kernel_line=$(echo "$(egrep 'linux\s+/vmlinuz' ${grub_file} | grep -v '#')" | head -1)
  119. fi
  120. if [[ $? -ne 0 ]]; then
  121. echo "Couldn't find kernel line in grub file" >&2 && return 1
  122. fi
  123. if ! grep -q ${NEW_KERNEL_PARAM} ${grub_file} ; then
  124. line_num=$(echo "$(grep -n "${kernel_line}" ${grub_file} |cut -f1 -d: )" | head -1)
  125. new_kernel_line="${kernel_line} ${NEW_KERNEL_PARAM}"
  126. # delete original line
  127. sed -i "${line_num}d" ${grub_file}
  128. # insert the corrected line on the same line number
  129. sed -i "${line_num}i\ ${new_kernel_line}" ${grub_file}
  130. fi
  131. reduce_mac_caching_timeout
  132. }
  133. function burn_vfs_in_fw () {
  134. total_vfs=$1
  135. if [ $CX == 'ConnectX-3' ]; then
  136. # required for mlxconfig to discover mlnx devices
  137. service openibd start &>/dev/null
  138. service mst start &>/dev/null
  139. devices=$(mst status -v | grep $(echo $CX | tr -d '-')| grep pciconf | awk '{print $2}')
  140. for dev in $devices; do
  141. logger_print debug "device=$dev"
  142. mlxconfig -d $dev q | grep SRIOV | awk '{print $2}' | grep $SRIOV_ENABLED_FLAG &>/dev/null
  143. sriov_enabled=$?
  144. current_num_of_vfs=`mlxconfig -d $dev q | grep NUM_OF_VFS | awk '{print $2}'`
  145. if [ $sriov_enabled -eq 0 ] 2>/dev/null; then
  146. logger_print debug "Detected SR-IOV is already enabled"
  147. else
  148. logger_print debug "Detected SR-IOV is disabled"
  149. fi
  150. if [[ ! "$total_vfs" == "$current_num_of_vfs" ]] 2>/dev/null; then
  151. logger_print debug "Current allowed number of VFs is ${current_num_of_vfs}, required number is ${total_vfs}"
  152. logger_print debug "Trying mlxconfig -y -d ${dev} s SRIOV_EN=1 NUM_OF_VFS=${total_vfs}"
  153. mlxconfig -y -d $dev s SRIOV_EN=1 NUM_OF_VFS=$total_vfs 2>&1 >/dev/null
  154. if [ $? -ne 0 ]; then
  155. logger_print error "Failed changing number of VFs in FW for HCA ${dev}"
  156. fi
  157. else
  158. logger_print debug "Current number of VFs is correctly set to ${current_num_of_vfs} in FW."
  159. fi
  160. done
  161. service mst stop &>/dev/null
  162. fi
  163. if [ $CX == 'ConnectX-4' ]; then
  164. # required for mlxconfig to discover mlnx devices
  165. service openibd start &>/dev/null
  166. service mst start &>/dev/null
  167. devices=$(mst status -v | grep $(echo $CX | tr -d '-') | grep pciconf | awk '{print $2}')
  168. for dev in $devices; do
  169. current_fw_vfs=`mlxconfig -d $dev q | grep NUM_OF_VFS | awk '{print $2}'`
  170. if [ "$total_vfs" -gt "$current_fw_vfs" ]; then
  171. logger_print debug "device=$dev"
  172. logger_print debug "Trying mlxconfig -d ${dev} -y set NUM_OF_VFS=${total_vfs}"
  173. mlxconfig -d $dev -y set NUM_OF_VFS=$total_vfs
  174. fi
  175. done
  176. fi
  177. }
  178. function is_sriov_required () {
  179. [ $SRIOV == true ] ||
  180. ( [ $ISER == true ] && [ `get_port_type` -eq "2" ] )
  181. return $?
  182. }
  183. function configure_sriov () {
  184. if is_sriov_required; then
  185. # Calculate the total amount of virtual functions, based on user seclection
  186. total_vfs=`calculate_total_vfs`
  187. if [ -z ${total_vfs} ]; then
  188. exit 1
  189. fi
  190. logger_print info "Configuring ${total_vfs} virtual functions
  191. (only even number is currently supported)"
  192. probe_vfs=`get_num_probe_vfs`
  193. port_type=`get_port_type`
  194. set_kernel_params &&
  195. burn_vfs_in_fw $total_vfs
  196. if [ $CX == 'ConnectX-3' ]; then
  197. set_modprobe_file $total_vfs &&
  198. logger_print info "Detected: ConnectX-3 card"
  199. fi
  200. if [ $CX == 'ConnectX-4' ]; then
  201. set_sriov $total_vfs &&
  202. logger_print info "Detected: ConnectX-4 card"
  203. fi
  204. return $?
  205. else
  206. logger_print info "Skipping SR-IOV configuration"
  207. return 0
  208. fi
  209. }
  210. function validate_sriov () {
  211. if ! is_sriov_required; then
  212. logger_print info "Skipping SR-IOV validation, no virtual functions required"
  213. return 0
  214. fi
  215. logger_print info "Validating SR-IOV is enabled, and the required
  216. amount of virtual functions exist"
  217. # get number of VFs
  218. current_num_vfs=`lspci | grep -i mellanox | grep -i virtual | wc -l`
  219. total_vfs=`calculate_total_vfs`
  220. if [ -z ${total_vfs} ]; then
  221. exit 1
  222. fi
  223. # check if kernel was loaded with the new parameter
  224. grep ${NEW_KERNEL_PARAM} /proc/cmdline
  225. has_kernel_param_status=$?
  226. if [ $has_kernel_param_status -eq 0 ]; then
  227. if [ $current_num_vfs -eq $total_vfs ]; then
  228. logger_print info "Successfully verified SR-IOV is enabled with ${current_num_vfs} VFs"
  229. return 0
  230. fi
  231. else
  232. logger_print error "Kernel did not come up with the kernel parameter: ${NEW_KERNEL_PARAM},
  233. SR-IOV configuration failed"
  234. return 1
  235. fi
  236. # fallback only if kernel param exists and amount of vfs is not as expcted
  237. logger_print error "Failed , trying to fallback to ${FALLBACK_NUM_VFS}"
  238. probe_vfs=`get_num_probe_vfs`
  239. port_type=`get_port_type`
  240. if [ $CX == 'ConnectX-3' ]; then
  241. set_modprobe_file $FALLBACK_NUM_VFS
  242. service openibd restart &> /dev/null
  243. fi
  244. if [ $CX == 'ConnectX-4' ]; then
  245. set_sriov $FALLBACK_NUM_VFS
  246. fi
  247. current_num_vfs=`lspci | grep -i mellanox | grep -i virtual | wc -l`
  248. if [ $current_num_vfs -eq $FALLBACK_NUM_VFS ]; then
  249. logger_print info "Fallback to ${FALLBACK_NUM_VFS} succeeded"
  250. return 0
  251. else
  252. logger_print error "Failed to configure SR-IOV"
  253. return 1
  254. fi
  255. }
  256. function set_sriov () {
  257. PORT_TYPE=`get_port_type`
  258. TOTAL_VFS=$1
  259. device_up=$PHYSICAL_PORT
  260. if [ ${#device_up} -eq 0 ]; then
  261. logger_print error "Failed to find mlx5 up ports in ibdev2netdev."
  262. exit 1
  263. else
  264. if [ "$(lspci | grep -i mellanox | grep -i virtual | wc -l)" -ne "$TOTAL_VFS" ]; then
  265. if [ ! $REBOOT_REQUIRED == true ] || [ $SCRIPT_MODE == "validate" ] ; then
  266. res=`echo 0 > /sys/class/net/${device_up}/device/mlx5_num_vfs`
  267. res=`echo ${TOTAL_VFS} > /sys/class/net/${device_up}/device/mlx5_num_vfs`
  268. if [ ! $? -eq 0 ]; then
  269. logger_print error "Failed to write $TOTAL_VFS > /sys/class/net/${device_up}/device/mlx5_num_vfs"
  270. exit 1
  271. else
  272. logger_print debug "Configured total vfs ${TOTAL_VFS} on ${device_up}"
  273. fi
  274. # Give MACs to created VFs
  275. python ./configure_mellanox_vfs.py ${TOTAL_VFS}
  276. fi
  277. # Make number of VFs persistent
  278. persistent_ifup_script=/etc/network/if-up.d/persistent_mlnx_params
  279. echo "#!/bin/bash" > $persistent_ifup_script
  280. chmod +x $persistent_ifup_script
  281. echo "# VFs Persistency" >> $persistent_ifup_script
  282. echo "if ! lspci | grep -i mellanox | grep -i virtual; then" >> $persistent_ifup_script
  283. echo "echo 0 > /sys/class/net/${device_up}/device/mlx5_num_vfs" >> $persistent_ifup_script
  284. echo "echo ${TOTAL_VFS} > /sys/class/net/${device_up}/device/mlx5_num_vfs" >> $persistent_ifup_script
  285. echo "fi" >> $persistent_ifup_script
  286. # Make the MAC for iser vf persistent
  287. echo "# MACs Persistency" >> $persistent_ifup_script
  288. echo 'if ip link show | grep "vf 0"| grep "MAC 00:00:00:00:00:00"; then' >> $persistent_ifup_script
  289. echo "python /etc/fuel/plugins/mellanox-plugin-*/configure_mellanox_vfs.py ${TOTAL_VFS}" >> $persistent_ifup_script
  290. echo "fi" >> $persistent_ifup_script
  291. echo "if [ -f /etc/init.d/tgt ]; then /etc/init.d/tgt force-reload; else exit 0; fi" >> $persistent_ifup_script
  292. if [ $REBOOT_REQUIRED == true ] && [ $SCRIPT_MODE == "configure" ] ; then
  293. logger_print debug "Configured total vfs ${TOTAL_VFS} on ${device_up} will apply \
  294. on next reboot as reboot is required"
  295. fi
  296. if [ $SCRIPT_MODE == "validate" ] ; then
  297. logger_print debug "Configured total vfs ${TOTAL_VFS} on ${device_up}"
  298. fi
  299. fi
  300. fi
  301. }
  302. #################
  303. case $SCRIPT_MODE in
  304. 'configure')
  305. configure_sriov
  306. ;;
  307. 'validate')
  308. validate_sriov
  309. ;;
  310. *)
  311. logger_print error "Unsupported execution mode ${SCRIPT_MODE}"
  312. exit 1
  313. ;;
  314. esac
  315. # Setting interfaces up
  316. for interface in `ifconfig -a | sed 's/[ \t].*//;/^\(lo\|\)$/d' | \
  317. sed 's/://'`;do ifconfig $interface up; done
  318. exit $?