misc: change VFIO group ownership and permissions in vfctl script
[vpp.git] / extras / scripts / vfctl
1 #!/bin/bash
2
3 function die() {
4         echo "ERROR: $*" >&2
5         exit 1
6 }
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 }
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                 iommu_group=$(basename $(readlink ${vf_path}/iommu_group))
100                 vfid=$(basename ${vf_path//virtfn/})
101                 mac="${mac_prefix}:$(printf "%02x" ${vfid})"
102                 sudo ip link set dev ${netdev} vf ${vfid} mac ${mac}
103                 sudo ip link set dev ${netdev} vf ${vfid} trust on
104                 sudo ip link set dev ${netdev} vf ${vfid} spoofchk off
105                 pci-bind ${vf} vfio-pci
106                 sudo chmod g+rw /dev/vfio/${iommu_group}
107                 sudo chgrp sudo /dev/vfio/${iommu_group}
108                 echo "VFIO group ${iommu_group} group ownership changed to sudo, group permissions changed to rw"
109         done
110
111         [ $(cat ${path}/sriov_numvfs) -gt 0 ] && show_vfs ${path} ${netdev}
112 }
113
114 function help() {
115
116 cat << __EOF__
117
118 $0 show <dev>
119   Displays information about <dev> where <dev> is PCI address
120   or linux interface name.
121
122 $0 remove-all <dev>
123   Remove all virtual functions from device <dev>.
124
125 $0 create <dev> <num>
126   Create <num> virtual functions on device<dev>.
127 __EOF__
128 }
129
130 case $1 in
131         show)
132                 show $2
133                 ;;
134         create)
135                 create $2 $3
136                 ;;
137         remove-all)
138                 remove_all $2
139                 ;;
140         help)
141                 help $2
142                 ;;
143         *)
144                 echo "Please specify command (show, create, remove-all)"
145                 help
146                 ;;
147 esac
148