/
vhost-vfio
393 lines (335 loc) · 11.8 KB
/
vhost-vfio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
#!/bin/bash
# if we are installing ovs for vfio_vhost networking we don't install standard ovs packages
if [ $VHOST_VFIO_INSTALL == 'True' ]; then
function _neutron_ovs_base_install_agent_packages {
: # no op
}
fi
function vhost_vfio_config_update {
sudo -EH crudini --set "${NEUTRON_CORE_PLUGIN_CONF}" "agent" "agent_type" "${VHOST_VFIO_AGENT_TYPE}"
}
function start_ovs_net_vhost_vfio {
# Start management_port and flow_driver service
start_management_port
start_flow_driver
#Start ovsdb
start_ovsdb
# Start vswitchd
start_vswitchd
sudo ovs-vsctl set Open_vSwitch . other_config:hw-offload=true
sudo ovs-vsctl set Open_vSwitch . other_config:flow-limit=$NUM_FLOWS
sudo ovs-vsctl set Open_vSwitch . other_config:n-handler-threads=1
sudo ovs-vsctl set Open_vSwitch . other_config:n-revalidator-threads=1
}
function stop_ovs_net_vhost_vfio {
# Stop services
stop_vswitchd
stop_ovsdb
stop_flow_driver
stop_management_port
# Disable services
disable_services
}
function disable_services {
sudo -EH systemctl disable vswitchd-net-vhost-vfio
sudo -EH systemctl disable ovsdb-net-vhost-vfio
sudo -EH systemctl disable flow_driver
sudo -EH systemctl disable management_port
# Remove service files
sudo rm -f /etc/systemd/system/ovsdb-net-vhost-vfio.service
sudo rm -f /etc/systemd/system/flow_driver.service
sudo rm -f /etc/systemd/system/management_port.service
sudo rm -f /etc/systemd/system/vswitchd-net-vhost-vfio.service
}
function allocate_VFs {
allocate_VFs_service
sudo -EH systemctl start ovs-alloc-vfs
}
function deallocate_VFs {
if [ -e "/etc/systemd/system/ovs-alloc-vfs.service" ]; then
sudo -EH systemctl stop ovs-alloc-vfs
sudo -EH systemctl disable ovs-alloc-vfs
sudo rm -f /etc/systemd/system/ovs-alloc-vfs.service
fi
}
function start_management_port {
setup_management_port_service
sudo -EH systemctl start management_port
}
function stop_management_port {
if [ -e "/etc/systemd/system/management_port.service" ]; then
sudo -EH systemctl stop management_port
fi
}
function start_ovsdb {
setup_ovsdb_service
sudo -EH systemctl start ovsdb-net-vhost-vfio
sudo ovs-vsctl --no-wait init
}
function stop_ovsdb {
if [ -e "/etc/systemd/system/ovsdb-net-vhost-vfio.service" ]; then
sudo -EH systemctl stop ovsdb-net-vhost-vfio
fi
}
function start_flow_driver {
setup_flow_driver_service
sudo -EH systemctl start flow_driver
}
function stop_flow_driver {
if [ -e "/etc/systemd/system/flow_driver.service" ]; then
sudo -EH systemctl stop flow_driver
fi
}
function start_vswitchd {
setup_vswitchd_service
sudo -EH systemctl start vswitchd-net-vhost-vfio
}
function stop_vswitchd {
if [ -e "/etc/systemd/system/vswitchd-net-vhost-vfio.service" ]; then
sudo -EH systemctl stop vswitchd-net-vhost-vfio
fi
}
function install_networking_vhost_vfio_ovs {
# Uninstall existing version
# Install dependencies
set +o errexit
if is_ubuntu; then
if $(dpkg -s openvswitch-switch 2>&1 | grep installed | grep -v -i "not installed" &> /dev/null ); then
stop_service openvswitch-switch
uninstall_package openvswitch-switch openvswitch-datapath-dkms openvswitch-common
fi
install_package autoconf libtool libfuse-dev screen bison flex
else
if $(rpm -qa 2>&1 | grep openvswitch &> /dev/null ); then
stop_service openvswitch
uninstall_package openvswitch
fi
install_package pciutils autoconf libtool fuse-devel screen bison flex
fi
# This function exits on an error so that errors don't compound and you see
# only the first error that occurred.
# Removes previously built version of openvswitch
lsmod | grep openvswitch > /dev/null && sudo -EH rmmod openvswitch
set -o errexit
# Build/Setup pre-requisites including: ifc driver, services, flow_driver, ovs
build_ifc_driver
build_flow_driver
build_ovs
install_kernel_modules
# Create service foe allocating the VFs
allocate_VFs_service
# Setup ovs as a service
setup_flow_driver_service
setup_ovsdb_service
setup_vswitchd_service
}
function build_ifc_driver {
if [ -e "$IFC_BIN_INSTALL" ]; then
sudo -EH yum install $IFC_BIN_INSTALL
sudo -EH modprobe ifc
elif [ -e "$IFC_REPO" ]; then
echo "Installing IFC driver from source."
# Install pre-requisites: coccinelle
install_package pkgconfig chrpath ocaml ocaml-findlib ocaml-findlib-devel ocaml-ocamldoc
git_clone 'https://github.com/coccinelle/coccinelle' ${DEST}/coccinelle master
cd ${DEST}/coccinelle
sudo -EH ./autogen
sudo -EH ./configure
sudo -EH make clean
sudo -EH make
sudo -EH make install
sudo -EH make install-bash
# Configure and install IFC driver
cd ${IFC_REPO}
sudo -EH make -j $(nproc)
cd ifc-*/src
sudo -EH make -j $(nproc)
sudo -EH make install
sudo -EH modprobe ifc
else
echo "Nothing to do for ifc driver installation."
fi
}
function build_flow_driver {
if [ -e "$FLOW_DRIVER_BIN_INSTALL" ]; then
sudo -EH cp $FLOW_DRIVER_BIN_INSTALL /usr/bin/
elif [ -e "$FLOW_DRIVER_REPO" ]; then
cd $FLOW_DRIVER_REPO
sudo -EH make -j $(nproc)
sudo -EH cp build/flow_driver /usr/bin
else
echo "Nothing to do for flow_driver installation"
fi
}
function build_ovs {
if [ -e "$OVS_BIN_INSTALL" ]; then
sudo -EH yum install $OVS_BIN_INSTALL
elif [ -e "$OVS_REPO" ]; then
get_repo $OVS_REPO $OVS_BRANCH ${DEST}/ovs
cd $OVS_REPO
sudo -EH ./boot.sh
sudo -EH ./configure --with-linux=/lib/modules/`uname -r`/build
sudo -EH make clean
sudo -EH make -j $(nproc)
sudo -EH make install
sudo -EH make modules_install
sudo -EH modprobe openvswitch
else
echo "Nothing to be done for OVS installation."
fi
}
function git_update_repo {
local git_dest=$1
local git_ref=$2
pushd $git_dest
git fetch
git checkout -f $git_ref # Clean modified tracked files
git clean -d -f # Clean untracked files
popd
}
function clone_repo {
local git_remote=$1
local git_dest=$2
local git_ref=$3
git_timed clone $git_remote $git_dest
pushd $git_dest
git checkout -f $git_ref # Clean modified tracked files
git clean -d -f # Clean untracked files
popd
}
function get_repo {
local git_remote=$1
local git_ref=$2
local git_dest=$3
if [ ! -d $git_dest ] || [ "$RECLONE" == True ]; then
# If directory exists and should be just refreshed
# it's not possible to use devstack git_clone with commit's id
if [ -d $git_dest} ]; then
git_update_repo $git_dest $git_ref
else
git_clone $git_remote $git_dest $git_ref
fi
fi
}
function install_kernel_modules {
MODULE=$OVS_INTERFACE_DRIVER
# rename to module name
if [[ "$OVS_INTERFACE_DRIVER" == "vfio-pci" ]]; then
MODULE="vfio_pci"
fi
# remove first if already exists
lsmod | grep $MODULE > /dev/null && sudo -EH rmmod $MODULE
if [ -e "/etc/modules" ]; then
echo -e "# ADDED by OVS, this line +1 will be removed on unstack\n$MODULE" | sudo tee -a /etc/modules
else
echo "WARNING: Unable to detect type of module autoloading"
fi
}
function setup_ovsdb_service {
if [ ! -e "/etc/systemd/system/ovsdb-net-vhost-vfio.service" ]; then
cat << EOF | sudo tee "/etc/systemd/system/ovsdb-net-vhost-vfio.service"
[Unit]
Description=Ovsdb service for networking_vhost_vfio
Before=network-pre.target
After=syslog.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'ovsdb-tool create /usr/local/etc/openvswitch/conf.db /usr/local/share/openvswitch/vswitch.ovsschema'
ExecStart=/bin/bash -c 'taskset -ac $CPU_NUM ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock --remote=db:Open_vSwitch,Open_vSwitch,manager_options --pidfile --detach'
ExecStop=/bin/bash -c 'pkill -9 ovsdb-server'
ExecStop=/bin/bash -c 'sudo rm -rf /usr/local/etc/openvswitch/conf.db'
ExecStop=/bin/bash -c 'sudo rm -rf /usr/local/etc/openvswitch/.conf.db*'
ExecStop=/bin/bash -c 'sudo rm -rf /usr/local/var/run/openvswitch/*.pid'
ExecStop=/bin/bash -c 'sudo rm -rf /usr/local/var/run/openvswitch/*.ctl'
[Install]
WantedBy=multi-user.target
EOF
# Initialize the alloc_VFs service
type systemctl 2>&1 >/dev/null && sudo -EH systemctl daemon-reload
fi
}
function setup_vswitchd_service {
if [ ! -e "/etc/systemd/system/vswitchd-net-vhost-vfio.service" ]; then
cat << EOF | sudo tee "/etc/systemd/system/vswitchd-net-vhost-vfio.service"
[Unit]
Description=Vswitchd service for networking_vhost_vfio
Before=network-pre.target
After=syslog.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'taskset -ac $CPU_NUM ovs-vswitchd --pidfile --detach --mlockall --log-file=/tmp/ovs-vswitchd.log'
ExecStart=/bin/bash -c 'ovs-appctl vlog/set ANY:ANY:ERR'
ExecStop=/bin/bash -c 'pkill -9 ovs-vswitchd'
[Install]
WantedBy=multi-user.target
EOF
# Initialize the alloc_VFs service
type systemctl 2>&1 >/dev/null && sudo -EH systemctl daemon-reload
fi
}
function setup_flow_driver_service {
if [ ! -e "/etc/systemd/system/flow_driver.service" ]; then
cat << EOF | sudo tee "/etc/systemd/system/flow_driver.service"
[Unit]
Description=Flow_driver service for networking_vhost_vfio
Before=network-pre.target
After=syslog.target
[Service]
Type=oneshot
RemainAfterExit=yes
LimitCORE=infinity
LimitNOFILE=65536
ExecStartPre=/bin/bash -c 'ifconfig | grep $OVS_OFFLOAD_INTERFACE.$MANAGEMENT_PORT > /dev/null'
ExecStart=/bin/bash -c 'taskset -ac $CPU_NUM /usr/bin/flow_driver --flows=$NUM_FLOWS --intf $OVS_OFFLOAD_INTERFACE.$MANAGEMENT_PORT &'
ExecStop=/bin/bash -c 'pkill -9 flow_driver'
[Install]
WantedBy=multi-user.target
EOF
# Initialize the alloc_VFs service
type systemctl 2>&1 >/dev/null && sudo -EH systemctl daemon-reload
fi
}
function setup_management_port_service {
if [ ! -e "/etc/systemd/system/management_port.service" ]; then
cat << EOF | sudo tee "/etc/systemd/system/management_port.service"
[Unit]
Description=Creating interface for flow_driver service for networking_vhost_vfio
Before=network-pre.target
After=syslog.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'ip link add link $OVS_OFFLOAD_INTERFACE name ${OVS_OFFLOAD_INTERFACE}.$MANAGEMENT_PORT type vlan id $MANAGEMENT_PORT'
ExecStart=/bin/bash -c 'ip link set dev $OVS_OFFLOAD_INTERFACE.$MANAGEMENT_PORT up'
ExecStop=/bin/bash -c 'ip link delete $OVS_OFFLOAD_INTERFACE.$MANAGEMENT_PORT'
[Install]
WantedBy=multi-user.target
EOF
# Initialize the alloc_VFs service
type systemctl 2>&1 >/dev/null && sudo -EH systemctl daemon-reload
fi
}
function allocate_VFs_service {
# Create the service that will allocate the VFs
if [ ! -e "/etc/systemd/system/ovs-alloc-vfs.service" ]; then
PCI_ADDR=`ls --ignore={bind,module,unbind,new_id,remove_id,uevent} /sys/bus/pci/drivers/ifc/`
cat << EOF | sudo tee "/etc/systemd/system/ovs-alloc-vfs.service"
[Unit]
Description=Allocate VFs for networking_vhost_vfio
Before=network-pre.target
After=syslog.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/bin/bash -c 'cat /sys/bus/pci/drivers/ifc/$PCI_ADDR/sriov_numvfs | grep 0 > /dev/null'
ExecStart=/bin/bash -c '/usr/bin/echo 64 > /sys/bus/pci/drivers/ifc/$PCI_ADDR/sriov_numvfs'
ExecStop=/bin/bash -c '/usr/bin/echo 0 > /sys/bus/pci/drivers/ifc/$PCI_ADDR/sriov_numvfs'
[Install]
WantedBy=multi-user.target
EOF
# Initialize the alloc_VFs service
type systemctl 2>&1 >/dev/null && sudo -EH systemctl daemon-reload
fi
}