Damjan Marion | 98a5d81 | 2018-06-09 15:11:52 +0200 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | |
| 3 | function die() { |
| 4 | echo "ERROR: $*" >&2 |
| 5 | exit 1 |
| 6 | } |
Damjan Marion | f4901f3 | 2019-01-31 19:41:50 +0100 | [diff] [blame] | 7 | function pci-unbind() { |
| 8 | echo $1 | sudo tee /sys/bus/pci/devices/$1/driver/unbind > /dev/null |
| 9 | } |
| 10 | function pci-bind() { |
| 11 | pci-unbind $1 |
| 12 | echo $2 | sudo tee /sys/bus/pci/devices/$1/driver_override > /dev/null |
| 13 | echo $1 | sudo tee /sys/bus/pci/drivers/$2/bind > /dev/null |
| 14 | echo | sudo tee /sys/bus/pci/devices/$1/driver_override > /dev/null |
| 15 | } |
Damjan Marion | 98a5d81 | 2018-06-09 15:11:52 +0200 | [diff] [blame] | 16 | |
| 17 | function show_vfs() { |
| 18 | path=$1 |
| 19 | netdev=$2 |
| 20 | printf "\nVirtual Functions:\n%-2s %-12s %-9s %-12s %-17s %s\n" \ |
| 21 | "ID" "PCI Addr" "PCI ID" "Driver" "MAC Addr" "Config" |
| 22 | for vf_path in ${path}/virtfn*; do |
| 23 | vf=$(basename $(readlink ${vf_path})) |
| 24 | vfid=$(basename ${vf_path//virtfn/}) |
| 25 | line=$(ip link show dev ${netdev} | grep "vf ${vfid}") |
| 26 | driver=$(basename $(readlink ${vf_path}/driver)) |
| 27 | pciid="$(cat ${vf_path}/vendor | cut -dx -f2):$(cat ${vf_path}/device | cut -dx -f2)" |
| 28 | mac=$(echo $line | sed -n -E -e 's/.*MAC ([0-9a-f:]+),.*/\1/p') |
| 29 | cfg=$(echo $line | cut -d, -f2-) |
| 30 | |
| 31 | printf "%-2s %-12s %-9s %-12s %-17s%s\n" \ |
| 32 | $vfid $vf $pciid $driver $mac "$cfg" |
| 33 | done |
| 34 | } |
| 35 | function get_pci_addr() { |
| 36 | local addr |
| 37 | if [ -d /sys/class/net/$2/device ]; then |
| 38 | addr=$(basename $(readlink /sys/class/net/${2}/device)) |
| 39 | else |
| 40 | addr=$2 |
| 41 | fi |
| 42 | if [ ! -d /sys/bus/pci/devices/${pci_addr} ]; then |
| 43 | die "PCI device $2 doesn't exist" |
| 44 | fi |
| 45 | eval "$1=${addr}" |
| 46 | } |
| 47 | |
| 48 | function show () { |
| 49 | get_pci_addr pci_addr $1 |
| 50 | path="/sys/bus/pci/devices/${pci_addr}" |
| 51 | |
| 52 | if [ ! -f ${path}/sriov_numvfs ]; then |
| 53 | die "PCI device $1 is not SR-IOV device" |
| 54 | fi |
| 55 | |
| 56 | printf "%-20s: %s\n" "PCI Address" ${pci_addr} |
| 57 | printf "%-20s: %s\n" "PCI ID" \ |
| 58 | "$(cat ${path}/vendor | cut -dx -f2):$(cat ${path}/device | cut -dx -f2)" |
| 59 | printf "%-20s: %s\n" "Driver name" $(basename $(readlink ${path}/driver)) |
| 60 | printf "%-20s: %s\n" "Driver Version" $(cat ${path}/driver/module/version) |
| 61 | printf "%-20s: %s\n" "PCI Link Speed (max)" "$(cat ${path}/current_link_speed) ($(cat ${path}/max_link_speed))" |
| 62 | printf "%-20s: %s\n" "PCI Link Width (max)" "$(cat ${path}/current_link_width) ($(cat ${path}/max_link_width))" |
| 63 | printf "%-20s: %s\n" "NUMA Node" $(cat ${path}/numa_node) |
| 64 | printf "%-20s: %s\n" "Number of VFs" $(cat ${path}/sriov_numvfs) |
| 65 | printf "%-20s: %s\n" "Total VFs" $(cat ${path}/sriov_totalvfs) |
| 66 | if [ -d ${path}/net/* ] ; then |
| 67 | netdev=$(basename ${path}/net/*) |
| 68 | netdev_path=${path}/net/${netdev} |
| 69 | printf "%-20s: %s\n" "Interface" ${netdev} |
| 70 | printf "%-20s: %s\n" "MAC Address" $(cat ${netdev_path}/address) |
| 71 | printf "%-20s: %s\n" "Speed" $(cat ${netdev_path}/speed) |
| 72 | printf "%-20s: %s\n" "State" $(cat ${netdev_path}/operstate) |
| 73 | fi |
| 74 | |
| 75 | [ $(cat ${path}/sriov_numvfs) -gt 0 ] && show_vfs ${path} ${netdev} |
| 76 | } |
| 77 | |
| 78 | function remove_all () { |
| 79 | get_pci_addr pci_addr $1 |
| 80 | path="/sys/bus/pci/devices/${pci_addr}" |
| 81 | [ $(cat ${path}/sriov_numvfs) -gt 0 ] || die "No VFs configured on $1" |
| 82 | echo 0 | sudo tee ${path}/sriov_numvfs > /dev/null |
| 83 | echo "VFs removed..." |
| 84 | } |
| 85 | |
| 86 | function create () { |
| 87 | get_pci_addr pci_addr $1 |
| 88 | path="/sys/bus/pci/devices/${pci_addr}" |
| 89 | [ $(cat ${path}/sriov_numvfs) -gt 0 ] && die "VFs already configured on $1" |
| 90 | [ "0$2" -gt 0 ] || die "Please specify number of VFs to create" |
| 91 | echo $2 | sudo tee ${path}/sriov_numvfs > /dev/null |
| 92 | [ -d ${path}/net/* ] || die "No net device for $1" |
| 93 | netdev=$(basename ${path}/net/*) |
| 94 | netdev_path=${path}/net/${netdev} |
| 95 | |
| 96 | mac_prefix=$(cat ${netdev_path}/address | cut -d: -f1,3,4,5,6 ) |
| 97 | for vf_path in ${path}/virtfn*; do |
| 98 | vf=$(basename $(readlink ${vf_path})) |
| 99 | vfid=$(basename ${vf_path//virtfn/}) |
| 100 | mac="${mac_prefix}:$(printf "%02x" ${vfid})" |
| 101 | sudo ip link set dev ${netdev} vf ${vfid} mac ${mac} |
Damjan Marion | 539e637 | 2018-10-26 13:43:43 +0200 | [diff] [blame] | 102 | sudo ip link set dev ${netdev} vf ${vfid} trust on |
| 103 | sudo ip link set dev ${netdev} vf ${vfid} spoofchk off |
Damjan Marion | f4901f3 | 2019-01-31 19:41:50 +0100 | [diff] [blame] | 104 | pci-bind ${vf} vfio-pci |
Damjan Marion | 98a5d81 | 2018-06-09 15:11:52 +0200 | [diff] [blame] | 105 | done |
| 106 | |
| 107 | [ $(cat ${path}/sriov_numvfs) -gt 0 ] && show_vfs ${path} ${netdev} |
| 108 | } |
| 109 | |
| 110 | function help() { |
| 111 | |
| 112 | cat << __EOF__ |
| 113 | |
| 114 | $0 show <dev> |
| 115 | Displays information about <dev> where <dev> is PCI address |
| 116 | or linux interface name. |
| 117 | |
| 118 | $0 remove-all <dev> |
| 119 | Remove all virtual functions from device <dev>. |
| 120 | |
Damjan Marion | 539e637 | 2018-10-26 13:43:43 +0200 | [diff] [blame] | 121 | $0 create <dev> <num> |
Damjan Marion | 98a5d81 | 2018-06-09 15:11:52 +0200 | [diff] [blame] | 122 | Create <num> virtual functions on device<dev>. |
| 123 | __EOF__ |
| 124 | } |
| 125 | |
| 126 | case $1 in |
| 127 | show) |
| 128 | show $2 |
| 129 | ;; |
| 130 | create) |
| 131 | create $2 $3 |
| 132 | ;; |
| 133 | remove-all) |
| 134 | remove_all $2 |
| 135 | ;; |
| 136 | help) |
| 137 | help $2 |
| 138 | ;; |
| 139 | *) |
| 140 | echo "Please specify command (show, create, remove-all)" |
| 141 | help |
| 142 | ;; |
| 143 | esac |
| 144 | |