1cba9514dSMichal Berger#!/usr/bin/env bash 2eb53c232Spaul luse# SPDX-License-Identifier: BSD-3-Clause 3eb53c232Spaul luse# Copyright (C) 2020 Intel Corporation 4eb53c232Spaul luse# All rights reserved. 5eb53c232Spaul luse# 6cba9514dSMichal Berger[[ $(uname -s) == Linux ]] || exit 0 7cba9514dSMichal Berger 8cba9514dSMichal Bergershopt -s extglob nullglob 9cba9514dSMichal Berger 10cba9514dSMichal Bergerdeclare -r rdma_rxe=/sys/module/rdma_rxe 11cba9514dSMichal Bergerdeclare -r rdma_rxe_add=$rdma_rxe/parameters/add 12cba9514dSMichal Bergerdeclare -r rdma_rxe_rm=$rdma_rxe/parameters/remove 13cba9514dSMichal Berger 14cba9514dSMichal Bergerdeclare -r infiniband=/sys/class/infiniband 15fc7d5d4eSMichal Bergerdeclare -r infiniband_verbs=/sys/class/infiniband_verbs 16cba9514dSMichal Bergerdeclare -r net=/sys/class/net 17cba9514dSMichal Berger 1860f3b6b2SMichal Bergerdeclare -A net_devices 1960f3b6b2SMichal Bergerdeclare -A net_to_rxe 2060f3b6b2SMichal Bergerdeclare -A rxe_to_net 2160f3b6b2SMichal Berger 22cba9514dSMichal Bergeruevent() ( 23cba9514dSMichal Berger [[ -e $1/uevent ]] || return 0 24cba9514dSMichal Berger 25cba9514dSMichal Berger source "$1/uevent" 26cba9514dSMichal Berger 27cba9514dSMichal Berger if [[ -v $2 ]]; then 28cba9514dSMichal Berger echo "${!2}" 29cba9514dSMichal Berger elif [[ -n $3 ]]; then 30cba9514dSMichal Berger echo "$3" 31cba9514dSMichal Berger fi 32cba9514dSMichal Berger) 33cba9514dSMichal Berger 34cba9514dSMichal Bergermodprobeq() { 35cba9514dSMichal Berger modprobe -q "$@" 36cba9514dSMichal Berger} 37cba9514dSMichal Berger 38cba9514dSMichal Bergerget_ipv4() { 39cba9514dSMichal Berger local ip 40cba9514dSMichal Berger 41cba9514dSMichal Berger # Get only the first ip 42cba9514dSMichal Berger read -r _ _ _ ip _ < <(ip -o -4 addr show dev "$1") 43cba9514dSMichal Berger if [[ -n $ip ]]; then 44cba9514dSMichal Berger echo "${ip%/*}" 45cba9514dSMichal Berger else 46cba9514dSMichal Berger echo " " 47cba9514dSMichal Berger fi 48cba9514dSMichal Berger} 49cba9514dSMichal Berger 50cba9514dSMichal Bergerget_rxe_mtu() { 51cba9514dSMichal Berger local rxe=$1 52cba9514dSMichal Berger local mtu 53fc7d5d4eSMichal Berger local uverb 54cba9514dSMichal Berger 55fc7d5d4eSMichal Berger for uverb in "$infiniband_verbs/uverbs"*; do 56fc7d5d4eSMichal Berger if [[ $(< "$uverb/ibdev") == "$rxe" ]] \ 57fc7d5d4eSMichal Berger && [[ -c /dev/infiniband/${uverb##*/} ]]; then 58cba9514dSMichal Berger [[ $(ibv_devinfo -d "$rxe") =~ active_mtu:(.*\ \(.*\)) ]] 59cba9514dSMichal Berger echo "${BASH_REMATCH[1]:-(?)}" 60fc7d5d4eSMichal Berger return 0 61fc7d5d4eSMichal Berger fi 62fc7d5d4eSMichal Berger done 63cba9514dSMichal Berger} 64cba9514dSMichal Berger 65cba9514dSMichal Bergerstart() { 66cba9514dSMichal Berger local modules module 67cba9514dSMichal Berger 68cba9514dSMichal Berger modules=( 69cba9514dSMichal Berger "ib_core" 70cba9514dSMichal Berger "ib_uverbs" 71cba9514dSMichal Berger "rdma_ucm" 72cba9514dSMichal Berger "rdma_rxe" 73cba9514dSMichal Berger ) 74cba9514dSMichal Berger 75cba9514dSMichal Berger for module in "${modules[@]}"; do 76cba9514dSMichal Berger [[ -e /sys/module/$module ]] && continue 77cba9514dSMichal Berger if [[ ! -e $(modinfo -F filename "$module") ]]; then 78cba9514dSMichal Berger return 0 79cba9514dSMichal Berger fi 80cba9514dSMichal Berger done 2> /dev/null 81cba9514dSMichal Berger 82cba9514dSMichal Berger modprobeq -a "${modules[@]}" || return 1 83cba9514dSMichal Berger add_rxe all 84cba9514dSMichal Berger} 85cba9514dSMichal Berger 86cba9514dSMichal Bergerstop() { 8760f3b6b2SMichal Berger remove_rxe 88cba9514dSMichal Berger 89cba9514dSMichal Berger if ! modprobeq -r rdma_rxe \ 90cba9514dSMichal Berger || [[ -e $rdma_rxe ]]; then 91cba9514dSMichal Berger printf 'unable to unload drivers, reboot required\n' 92cba9514dSMichal Berger fi 93cba9514dSMichal Berger} 94cba9514dSMichal Berger 95cba9514dSMichal Bergerstatus_header() { 96cba9514dSMichal Berger local header=("Name" "Link" "Driver" "Speed" "NMTU" "IPv4_addr" "RDEV" "RMTU") 97cba9514dSMichal Berger 98cba9514dSMichal Berger size_print_fields "${header[@]}" 99cba9514dSMichal Berger} 100cba9514dSMichal Berger 101cba9514dSMichal Bergerstatus() { 102cba9514dSMichal Berger if [[ ! -e $rdma_rxe ]]; then 103cba9514dSMichal Berger printf 'rdma_rxe module not loaded\n' >&2 104cba9514dSMichal Berger fi 105cba9514dSMichal Berger 10660f3b6b2SMichal Berger local dev 107cba9514dSMichal Berger local link_map 108cba9514dSMichal Berger 109cba9514dSMichal Berger link_map[0]=no 110cba9514dSMichal Berger link_map[1]=yes 111cba9514dSMichal Berger 112cba9514dSMichal Berger status_header 113cba9514dSMichal Berger 114cba9514dSMichal Berger local name link driver speed mtu ip rxe rxe_dev active_mtu 11560f3b6b2SMichal Berger for dev in "${net_devices[@]}"; do 116cba9514dSMichal Berger name="" link="" driver="" 117cba9514dSMichal Berger speed="" mtu="" ip="" 118cba9514dSMichal Berger rxe_dev="" active_mtu="" 119cba9514dSMichal Berger 120cba9514dSMichal Berger name=${dev##*/} 12160f3b6b2SMichal Berger rxe_dev=${net_to_rxe["$name"]} 122cba9514dSMichal Berger active_mtu=$(get_rxe_mtu "$rxe_dev") 123cba9514dSMichal Berger 124cba9514dSMichal Berger link=${link_map[$(< "$dev/carrier")]} 125cba9514dSMichal Berger 126cba9514dSMichal Berger if [[ -e $dev/device/driver ]]; then 127cba9514dSMichal Berger driver=$(readlink -f "$dev/device/driver") 128cba9514dSMichal Berger driver=${driver##*/} 129cba9514dSMichal Berger elif [[ -e /sys/devices/virtual/net/${dev##*/} ]]; then 130cba9514dSMichal Berger # Try to be smart and get the type of the device instead 131cba9514dSMichal Berger driver=$(uevent "$dev" "DEVTYPE" "virtual") 132cba9514dSMichal Berger fi 133cba9514dSMichal Berger 134cba9514dSMichal Berger if [[ $link == yes ]]; then 135cba9514dSMichal Berger speed=$(< "$dev/speed") 136623c3bc6SMichal Berger if ((speed >= 1000)); then 137623c3bc6SMichal Berger speed=$((speed / 1000))GigE 138cba9514dSMichal Berger elif ((speed > 0)); then 139cba9514dSMichal Berger speed=${speed}Mb/s 140cba9514dSMichal Berger else 141cba9514dSMichal Berger speed="" 142cba9514dSMichal Berger fi 143cba9514dSMichal Berger fi 144cba9514dSMichal Berger 145cba9514dSMichal Berger mtu=$(< "$dev/mtu") 146cba9514dSMichal Berger ip=$(get_ipv4 "$name") 147cba9514dSMichal Berger 148cba9514dSMichal Berger size_print_fields \ 149cba9514dSMichal Berger "$name" \ 150cba9514dSMichal Berger "$link" \ 151cba9514dSMichal Berger "$driver" \ 152cba9514dSMichal Berger "$speed" \ 153cba9514dSMichal Berger "$mtu" \ 154cba9514dSMichal Berger "$ip" \ 155cba9514dSMichal Berger "$rxe_dev" \ 156cba9514dSMichal Berger "$active_mtu" 157cba9514dSMichal Berger done 2> /dev/null 158cba9514dSMichal Berger print_status 159cba9514dSMichal Berger} 160cba9514dSMichal Berger 161cba9514dSMichal Bergersize_print_fields() { 162cba9514dSMichal Berger local fields=("$@") field 163cba9514dSMichal Berger local -g lengths lines lineno 164cba9514dSMichal Berger 165cba9514dSMichal Berger for field in "${!fields[@]}"; do 166cba9514dSMichal Berger if [[ -z ${fields[field]} ]]; then 167cba9514dSMichal Berger fields[field]="###" 168cba9514dSMichal Berger fi 169cba9514dSMichal Berger if [[ -z ${lengths[field]} ]]; then 170cba9514dSMichal Berger lengths[field]=${#fields[field]} 171cba9514dSMichal Berger else 172cba9514dSMichal Berger lengths[field]=$((lengths[field] > ${#fields[field]} ? lengths[field] : ${#fields[field]})) 173cba9514dSMichal Berger fi 174cba9514dSMichal Berger done 175cba9514dSMichal Berger 176cba9514dSMichal Berger eval "local -g _line_$lineno=(\"\${fields[@]}\")" 177cba9514dSMichal Berger lines+=("_line_${lineno}[@]") 178cba9514dSMichal Berger ((++lineno)) 179cba9514dSMichal Berger} 180cba9514dSMichal Berger 181cba9514dSMichal Bergerprint_status() { 182cba9514dSMichal Berger local field field_ref fieldidx 183cba9514dSMichal Berger local pad 184cba9514dSMichal Berger 1854d52dae3SMichal Berger if [[ -n $NO_HEADER ]]; then 1864d52dae3SMichal Berger unset -v "lines[0]" 1874d52dae3SMichal Berger fi 1884d52dae3SMichal Berger 189cba9514dSMichal Berger for field_ref in "${lines[@]}"; do 190cba9514dSMichal Berger printf ' ' 191cba9514dSMichal Berger fieldidx=0 192cba9514dSMichal Berger for field in "${!field_ref}"; do 193cba9514dSMichal Berger if [[ -n $field ]]; then 194cba9514dSMichal Berger pad=$((lengths[fieldidx] - ${#field} + 2)) 195cba9514dSMichal Berger else 196cba9514dSMichal Berger pad=$((lengths[fieldidx] + 2)) 197cba9514dSMichal Berger fi 198cba9514dSMichal Berger if [[ -n $field && $field != "###" ]]; then 199cba9514dSMichal Berger printf '%s' "$field" 200cba9514dSMichal Berger else 201cba9514dSMichal Berger printf ' ' 202cba9514dSMichal Berger fi 203cba9514dSMichal Berger printf '%*s' "$pad" "" 204cba9514dSMichal Berger ((++fieldidx)) 205cba9514dSMichal Berger done 206cba9514dSMichal Berger printf '\n' 207cba9514dSMichal Berger done 208cba9514dSMichal Berger} 209cba9514dSMichal Berger 210cba9514dSMichal Bergeradd_rxe() { 211cba9514dSMichal Berger local dev net_devs 212cba9514dSMichal Berger 213fc7d5d4eSMichal Berger [[ -e $rdma_rxe_add ]] || return 0 214cba9514dSMichal Berger 215cba9514dSMichal Berger if [[ -z $1 || $1 == all ]]; then 21660f3b6b2SMichal Berger net_devs=("${!net_devices[@]}") 21760f3b6b2SMichal Berger elif [[ -n ${net_to_rxe["$1"]} ]]; then 21860f3b6b2SMichal Berger printf '%s interface already in use (%s)\n' \ 21960f3b6b2SMichal Berger "$1" "${net_to_rxe["$1"]}" 22060f3b6b2SMichal Berger return 0 22160f3b6b2SMichal Berger elif [[ -n ${net_devices["$1"]} ]]; then 22260f3b6b2SMichal Berger net_devs=("$1") 223cba9514dSMichal Berger else 224cba9514dSMichal Berger printf '%s interface does not exist\n' "$1" 225cba9514dSMichal Berger return 1 226cba9514dSMichal Berger fi 227cba9514dSMichal Berger 228cba9514dSMichal Berger for dev in "${net_devs[@]}"; do 22960f3b6b2SMichal Berger if [[ -z ${net_to_rxe["$dev"]} ]]; then 230cba9514dSMichal Berger echo "${dev##*/}" > "$rdma_rxe_add" 23160f3b6b2SMichal Berger fi 2328e43a261SMichal Berger link_up "${dev##*/}" 233cba9514dSMichal Berger done 2> /dev/null 234cba9514dSMichal Berger} 235cba9514dSMichal Berger 236cba9514dSMichal Bergerremove_rxe() { 23760f3b6b2SMichal Berger local rxes rxe 23860f3b6b2SMichal Berger 239fc7d5d4eSMichal Berger [[ -e $rdma_rxe_rm ]] || return 0 240fc7d5d4eSMichal Berger 24160f3b6b2SMichal Berger rxes=("${!rxe_to_net[@]}") 24260f3b6b2SMichal Berger if [[ -z $1 || $1 == all ]]; then 24360f3b6b2SMichal Berger rxes=("${!rxe_to_net[@]}") 24460f3b6b2SMichal Berger elif [[ -z ${rxe_to_net["$1"]} ]]; then 24560f3b6b2SMichal Berger printf '%s rxe interface does not exist\n' "$1" 24660f3b6b2SMichal Berger return 0 24760f3b6b2SMichal Berger elif [[ -n ${rxe_to_net["$1"]} ]]; then 24860f3b6b2SMichal Berger rxes=("$1") 24960f3b6b2SMichal Berger fi 25060f3b6b2SMichal Berger 25160f3b6b2SMichal Berger for rxe in "${rxes[@]}"; do 25260f3b6b2SMichal Berger echo "$rxe" > "$rdma_rxe_rm" 253fc7d5d4eSMichal Berger done 2> /dev/null 254cba9514dSMichal Berger} 255cba9514dSMichal Berger 256cba9514dSMichal Bergerlink_up() { 257cba9514dSMichal Berger [[ -e $net/$1 ]] || return 0 258cba9514dSMichal Berger 259cba9514dSMichal Berger echo $(($(< "$net/$1/flags") | 0x1)) > "$net/$1/flags" 260cba9514dSMichal Berger} 261cba9514dSMichal Berger 262e99cfdb6SMichal Bergercollect_net_devices() { 263e99cfdb6SMichal Berger local net_dev 26460f3b6b2SMichal Berger 26560f3b6b2SMichal Berger for net_dev in "$net/"!(bonding_masters); do 26660f3b6b2SMichal Berger (($(< "$net_dev/type") != 1)) && continue 26760f3b6b2SMichal Berger net_devices["${net_dev##*/}"]=$net_dev 26860f3b6b2SMichal Berger done 26960f3b6b2SMichal Berger} 27060f3b6b2SMichal Berger 271e99cfdb6SMichal Bergercollect_rxe_devices() { 272e99cfdb6SMichal Berger local rxe_dev net_dev 273e99cfdb6SMichal Berger 274e99cfdb6SMichal Berger for rxe_dev in "$infiniband/"*; do 275e99cfdb6SMichal Berger if [[ -e $rxe_dev/parent ]]; then 276e99cfdb6SMichal Berger # Soft 277e99cfdb6SMichal Berger net_dev=$(< "$rxe_dev/parent") 278e99cfdb6SMichal Berger elif [[ -e $rxe_dev/device/net ]]; then 279e99cfdb6SMichal Berger # HW 280e99cfdb6SMichal Berger net_dev=$(readlink -f "$rxe_dev/device/net/"*) 281e99cfdb6SMichal Berger net_dev=${net_dev##*/} 282e99cfdb6SMichal Berger else 283e99cfdb6SMichal Berger continue 284e99cfdb6SMichal Berger fi 2> /dev/null 285e99cfdb6SMichal Berger 286e99cfdb6SMichal Berger [[ -n ${net_devices["$net_dev"]} ]] || continue 287e99cfdb6SMichal Berger net_to_rxe["$net_dev"]=${rxe_dev##*/} 288e99cfdb6SMichal Berger rxe_to_net["${rxe_dev##*/}"]=$net_dev 289e99cfdb6SMichal Berger done 290e99cfdb6SMichal Berger} 291e99cfdb6SMichal Berger 292e99cfdb6SMichal Bergercollect_net_devices 293e99cfdb6SMichal Bergercollect_rxe_devices 29460f3b6b2SMichal Berger 295cba9514dSMichal Bergercase "${1:-status}" in 296cba9514dSMichal Berger start) 297cba9514dSMichal Berger start 298cba9514dSMichal Berger ;; 299cba9514dSMichal Berger stop) 300cba9514dSMichal Berger stop 301cba9514dSMichal Berger ;; 302cba9514dSMichal Berger add) 303cba9514dSMichal Berger add_rxe "${2:-all}" 304cba9514dSMichal Berger ;; 305cba9514dSMichal Berger remove) 30660f3b6b2SMichal Berger remove_rxe "${2:-all}" 307cba9514dSMichal Berger ;; 308cba9514dSMichal Berger status) 309cba9514dSMichal Berger IFS= read -r match < <( 310cba9514dSMichal Berger IFS="|" 311cba9514dSMichal Berger printf '%s\n' "${*:2}" 312cba9514dSMichal Berger ) 313cba9514dSMichal Berger status | grep -E "${match:-.}" 314cba9514dSMichal Berger ;; 315c09b139eSMichal Berger rxe-net) 316*e7b45cb3SMichal Berger ((${#rxe_to_net[@]} > 0)) && printf '%s\n' "${rxe_to_net[@]}" 317c09b139eSMichal Berger ;; 318cba9514dSMichal Berger *) 319cba9514dSMichal Berger printf 'Invalid argument (%s)\n' "$1" 320cba9514dSMichal Berger ;; 321cba9514dSMichal Bergeresac 322