tools: exit setup script without prompt
[dpdk.git] / tools / setup.sh
1 #! /bin/bash
2
3 #   BSD LICENSE
4 #
5 #   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
6 #   All rights reserved.
7 #
8 #   Redistribution and use in source and binary forms, with or without
9 #   modification, are permitted provided that the following conditions
10 #   are met:
11 #
12 #     * Redistributions of source code must retain the above copyright
13 #       notice, this list of conditions and the following disclaimer.
14 #     * Redistributions in binary form must reproduce the above copyright
15 #       notice, this list of conditions and the following disclaimer in
16 #       the documentation and/or other materials provided with the
17 #       distribution.
18 #     * Neither the name of Intel Corporation nor the names of its
19 #       contributors may be used to endorse or promote products derived
20 #       from this software without specific prior written permission.
21 #
22 #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 #   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 #   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 #   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 #   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 #   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 #   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34 #
35 # Run with "source /path/to/setup.sh"
36 #
37
38 #
39 # Change to DPDK directory ( <this-script's-dir>/.. ), and export it as RTE_SDK
40 #
41 cd $(dirname ${BASH_SOURCE[0]})/..
42 export RTE_SDK=$PWD
43 echo "------------------------------------------------------------------------------"
44 echo " RTE_SDK exported as $RTE_SDK"
45 echo "------------------------------------------------------------------------------"
46
47 #
48 # Application EAL parameters for setting memory options (amount/channels/ranks).
49 #
50 EAL_PARAMS='-n 4'
51
52 #
53 # Sets QUIT variable so script will finish.
54 #
55 quit()
56 {
57         QUIT=$1
58 }
59
60 # Shortcut for quit.
61 q()
62 {
63         quit
64 }
65
66 #
67 # Sets up environmental variables for ICC.
68 #
69 setup_icc()
70 {
71         DEFAULT_PATH=/opt/intel/bin/iccvars.sh
72         param=$1
73         shpath=`which iccvars.sh 2> /dev/null`
74         if [ $? -eq 0 ] ; then
75                 echo "Loading iccvars.sh from $shpath for $param"
76                 source $shpath $param
77         elif [ -f $DEFAULT_PATH ] ; then
78                 echo "Loading iccvars.sh from $DEFAULT_PATH for $param"
79                 source $DEFAULT_PATH $param
80         else
81                 echo "## ERROR: cannot find 'iccvars.sh' script to set up ICC."
82                 echo "##     To fix, please add the directory that contains"
83                 echo "##     iccvars.sh  to your 'PATH' environment variable."
84                 quit
85         fi
86 }
87
88 #
89 # Sets RTE_TARGET and does a "make install".
90 #
91 setup_target()
92 {
93         option=$1
94         export RTE_TARGET=${TARGETS[option]}
95
96         compiler=${RTE_TARGET##*-}
97         if [ "$compiler" == "icc" ] ; then
98                 platform=${RTE_TARGET%%-*}
99                 if [ "$platform" == "x86_64" ] ; then
100                         setup_icc intel64
101                 else
102                         setup_icc ia32
103                 fi
104         fi
105         if [ "$QUIT" == "0" ] ; then
106                 make install T=${RTE_TARGET}
107         fi
108         echo "------------------------------------------------------------------------------"
109         echo " RTE_TARGET exported as $RTE_TARGET"
110         echo "------------------------------------------------------------------------------"
111 }
112
113 #
114 # Uninstall all targets.
115 #
116 uninstall_targets()
117 {
118         make uninstall
119 }
120
121 #
122 # Creates hugepage filesystem.
123 #
124 create_mnt_huge()
125 {
126         echo "Creating /mnt/huge and mounting as hugetlbfs"
127         sudo mkdir -p /mnt/huge
128
129         grep -s '/mnt/huge' /proc/mounts > /dev/null
130         if [ $? -ne 0 ] ; then
131                 sudo mount -t hugetlbfs nodev /mnt/huge
132         fi
133 }
134
135 #
136 # Removes hugepage filesystem.
137 #
138 remove_mnt_huge()
139 {
140         echo "Unmounting /mnt/huge and removing directory"
141         grep -s '/mnt/huge' /proc/mounts > /dev/null
142         if [ $? -eq 0 ] ; then
143                 sudo umount /mnt/huge
144         fi
145
146         if [ -d /mnt/huge ] ; then
147                 sudo rm -R /mnt/huge
148         fi
149 }
150
151 #
152 # Unloads igb_uio.ko.
153 #
154 remove_igb_uio_module()
155 {
156         echo "Unloading any existing DPDK UIO module"
157         /sbin/lsmod | grep -s igb_uio > /dev/null
158         if [ $? -eq 0 ] ; then
159                 sudo /sbin/rmmod igb_uio
160         fi
161 }
162
163 #
164 # Loads new igb_uio.ko (and uio module if needed).
165 #
166 load_igb_uio_module()
167 {
168         if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko ];then
169                 echo "## ERROR: Target does not have the DPDK UIO Kernel Module."
170                 echo "       To fix, please try to rebuild target."
171                 return
172         fi
173
174         remove_igb_uio_module
175
176         /sbin/lsmod | grep -s uio > /dev/null
177         if [ $? -ne 0 ] ; then
178                 modinfo uio > /dev/null
179                 if [ $? -eq 0 ]; then
180                         echo "Loading uio module"
181                         sudo /sbin/modprobe uio
182                 fi
183         fi
184
185         # UIO may be compiled into kernel, so it may not be an error if it can't
186         # be loaded.
187
188         echo "Loading DPDK UIO module"
189         sudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko
190         if [ $? -ne 0 ] ; then
191                 echo "## ERROR: Could not load kmod/igb_uio.ko."
192                 quit
193         fi
194 }
195
196 #
197 # Unloads VFIO modules.
198 #
199 remove_vfio_module()
200 {
201         echo "Unloading any existing VFIO module"
202         /sbin/lsmod | grep -s vfio > /dev/null
203         if [ $? -eq 0 ] ; then
204                 sudo /sbin/rmmod vfio-pci
205                 sudo /sbin/rmmod vfio_iommu_type1
206                 sudo /sbin/rmmod vfio
207         fi
208 }
209
210 #
211 # Loads new vfio-pci (and vfio module if needed).
212 #
213 load_vfio_module()
214 {
215         remove_vfio_module
216
217         VFIO_PATH="kernel/drivers/vfio/pci/vfio-pci.ko"
218
219         echo "Loading VFIO module"
220         /sbin/lsmod | grep -s vfio_pci > /dev/null
221         if [ $? -ne 0 ] ; then
222                 if [ -f /lib/modules/$(uname -r)/$VFIO_PATH ] ; then
223                         sudo /sbin/modprobe vfio-pci
224                 fi
225         fi
226
227         # make sure regular users can read /dev/vfio
228         echo "chmod /dev/vfio"
229         sudo chmod a+x /dev/vfio
230         if [ $? -ne 0 ] ; then
231                 echo "FAIL"
232                 quit
233         fi
234         echo "OK"
235
236         # check if /dev/vfio/vfio exists - that way we
237         # know we either loaded the module, or it was
238         # compiled into the kernel
239         if [ ! -e /dev/vfio/vfio ] ; then
240                 echo "## ERROR: VFIO not found!"
241         fi
242 }
243
244 #
245 # Unloads the rte_kni.ko module.
246 #
247 remove_kni_module()
248 {
249         echo "Unloading any existing DPDK KNI module"
250         /sbin/lsmod | grep -s rte_kni > /dev/null
251         if [ $? -eq 0 ] ; then
252                 sudo /sbin/rmmod rte_kni
253         fi
254 }
255
256 #
257 # Loads the rte_kni.ko module.
258 #
259 load_kni_module()
260 {
261     # Check that the KNI module is already built.
262         if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/rte_kni.ko ];then
263                 echo "## ERROR: Target does not have the DPDK KNI Module."
264                 echo "       To fix, please try to rebuild target."
265                 return
266         fi
267
268     # Unload existing version if present.
269         remove_kni_module
270
271     # Now try load the KNI module.
272         echo "Loading DPDK KNI module"
273         sudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/rte_kni.ko
274         if [ $? -ne 0 ] ; then
275                 echo "## ERROR: Could not load kmod/rte_kni.ko."
276                 quit
277         fi
278 }
279
280 #
281 # Sets appropriate permissions on /dev/vfio/* files
282 #
283 set_vfio_permissions()
284 {
285         # make sure regular users can read /dev/vfio
286         echo "chmod /dev/vfio"
287         sudo chmod a+x /dev/vfio
288         if [ $? -ne 0 ] ; then
289                 echo "FAIL"
290                 quit
291         fi
292         echo "OK"
293
294         # make sure regular user can access everything inside /dev/vfio
295         echo "chmod /dev/vfio/*"
296         sudo chmod 0666 /dev/vfio/*
297         if [ $? -ne 0 ] ; then
298                 echo "FAIL"
299                 quit
300         fi
301         echo "OK"
302
303         # since permissions are only to be set when running as
304         # regular user, we only check ulimit here
305         #
306         # warn if regular user is only allowed
307         # to memlock <64M of memory
308         MEMLOCK_AMNT=`ulimit -l`
309
310         if [ "$MEMLOCK_AMNT" != "unlimited" ] ; then
311                 MEMLOCK_MB=`expr $MEMLOCK_AMNT / 1024`
312                 echo ""
313                 echo "Current user memlock limit: ${MEMLOCK_MB} MB"
314                 echo ""
315                 echo "This is the maximum amount of memory you will be"
316                 echo "able to use with DPDK and VFIO if run as current user."
317                 echo -n "To change this, please adjust limits.conf memlock "
318                 echo "limit for current user."
319
320                 if [ $MEMLOCK_AMNT -lt 65536 ] ; then
321                         echo ""
322                         echo "## WARNING: memlock limit is less than 64MB"
323                         echo -n "## DPDK with VFIO may not be able to initialize "
324                         echo "if run as current user."
325                 fi
326         fi
327 }
328
329 #
330 # Removes all reserved hugepages.
331 #
332 clear_huge_pages()
333 {
334         echo > .echo_tmp
335         for d in /sys/devices/system/node/node? ; do
336                 echo "echo 0 > $d/hugepages/hugepages-2048kB/nr_hugepages" >> .echo_tmp
337         done
338         echo "Removing currently reserved hugepages"
339         sudo sh .echo_tmp
340         rm -f .echo_tmp
341
342         remove_mnt_huge
343 }
344
345 #
346 # Creates hugepages.
347 #
348 set_non_numa_pages()
349 {
350         clear_huge_pages
351
352         echo ""
353         echo "  Input the number of 2MB pages"
354         echo "  Example: to have 128MB of hugepages available, enter '64' to"
355         echo "  reserve 64 * 2MB pages"
356         echo -n "Number of pages: "
357         read Pages
358
359         echo "echo $Pages > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages" > .echo_tmp
360
361         echo "Reserving hugepages"
362         sudo sh .echo_tmp
363         rm -f .echo_tmp
364
365         create_mnt_huge
366 }
367
368 #
369 # Creates hugepages on specific NUMA nodes.
370 #
371 set_numa_pages()
372 {
373         clear_huge_pages
374
375         echo ""
376         echo "  Input the number of 2MB pages for each node"
377         echo "  Example: to have 128MB of hugepages available per node,"
378         echo "  enter '64' to reserve 64 * 2MB pages on each node"
379
380         echo > .echo_tmp
381         for d in /sys/devices/system/node/node? ; do
382                 node=$(basename $d)
383                 echo -n "Number of pages for $node: "
384                 read Pages
385                 echo "echo $Pages > $d/hugepages/hugepages-2048kB/nr_hugepages" >> .echo_tmp
386         done
387         echo "Reserving hugepages"
388         sudo sh .echo_tmp
389         rm -f .echo_tmp
390
391         create_mnt_huge
392 }
393
394 #
395 # Run unit test application.
396 #
397 run_test_app()
398 {
399         echo ""
400         echo "  Enter hex bitmask of cores to execute test app on"
401         echo "  Example: to execute app on cores 0 to 7, enter 0xff"
402         echo -n "bitmask: "
403         read Bitmask
404         echo "Launching app"
405         sudo ${RTE_TARGET}/app/test -c $Bitmask $EAL_PARAMS
406 }
407
408 #
409 # Run unit testpmd application.
410 #
411 run_testpmd_app()
412 {
413         echo ""
414         echo "  Enter hex bitmask of cores to execute testpmd app on"
415         echo "  Example: to execute app on cores 0 to 7, enter 0xff"
416         echo -n "bitmask: "
417         read Bitmask
418         echo "Launching app"
419         sudo ${RTE_TARGET}/app/testpmd -c $Bitmask $EAL_PARAMS -- -i
420 }
421
422 #
423 # Print hugepage information.
424 #
425 grep_meminfo()
426 {
427         grep -i huge /proc/meminfo
428 }
429
430 #
431 # Calls dpdk_nic_bind.py --status to show the NIC and what they
432 # are all bound to, in terms of drivers.
433 #
434 show_nics()
435 {
436         if  /sbin/lsmod | grep -q -e igb_uio -e vfio_pci; then
437                 ${RTE_SDK}/tools/dpdk_nic_bind.py --status
438         else
439                 echo "# Please load the 'igb_uio' or 'vfio-pci' kernel module before "
440                 echo "# querying or adjusting NIC device bindings"
441         fi
442 }
443
444 #
445 # Uses dpdk_nic_bind.py to move devices to work with vfio-pci
446 #
447 bind_nics_to_vfio()
448 {
449         if /sbin/lsmod  | grep -q vfio_pci ; then
450                 ${RTE_SDK}/tools/dpdk_nic_bind.py --status
451                 echo ""
452                 echo -n "Enter PCI address of device to bind to VFIO driver: "
453                 read PCI_PATH
454                 sudo ${RTE_SDK}/tools/dpdk_nic_bind.py -b vfio-pci $PCI_PATH &&
455                         echo "OK"
456         else
457                 echo "# Please load the 'vfio-pci' kernel module before querying or "
458                 echo "# adjusting NIC device bindings"
459         fi
460 }
461
462 #
463 # Uses dpdk_nic_bind.py to move devices to work with igb_uio
464 #
465 bind_nics_to_igb_uio()
466 {
467         if  /sbin/lsmod  | grep -q igb_uio ; then
468                 ${RTE_SDK}/tools/dpdk_nic_bind.py --status
469                 echo ""
470                 echo -n "Enter PCI address of device to bind to IGB UIO driver: "
471                 read PCI_PATH
472                 sudo ${RTE_SDK}/tools/dpdk_nic_bind.py -b igb_uio $PCI_PATH && echo "OK"
473         else
474                 echo "# Please load the 'igb_uio' kernel module before querying or "
475                 echo "# adjusting NIC device bindings"
476         fi
477 }
478
479 #
480 # Uses dpdk_nic_bind.py to move devices to work with kernel drivers again
481 #
482 unbind_nics()
483 {
484         ${RTE_SDK}/tools/dpdk_nic_bind.py --status
485         echo ""
486         echo -n "Enter PCI address of device to unbind: "
487         read PCI_PATH
488         echo ""
489         echo -n "Enter name of kernel driver to bind the device to: "
490         read DRV
491         sudo ${RTE_SDK}/tools/dpdk_nic_bind.py -b $DRV $PCI_PATH && echo "OK"
492 }
493
494 #
495 # Options for building a target. Note that this step MUST be first as it sets
496 # up TARGETS[] starting from 1, and this is accessed in setup_target using the
497 # user entered option.
498 #
499 step1_func()
500 {
501         TITLE="Select the DPDK environment to build"
502         CONFIG_NUM=1
503         for cfg in config/defconfig_* ; do
504                 cfg=${cfg/config\/defconfig_/}
505                 TEXT[$CONFIG_NUM]="$cfg"
506                 TARGETS[$CONFIG_NUM]=$cfg
507                 FUNC[$CONFIG_NUM]="setup_target"
508                 let "CONFIG_NUM+=1"
509         done
510 }
511
512 #
513 # Options for setting up environment.
514 #
515 step2_func()
516 {
517         TITLE="Setup linuxapp environment"
518
519         TEXT[1]="Insert IGB UIO module"
520         FUNC[1]="load_igb_uio_module"
521
522         TEXT[2]="Insert VFIO module"
523         FUNC[2]="load_vfio_module"
524
525         TEXT[3]="Insert KNI module"
526         FUNC[3]="load_kni_module"
527
528         TEXT[4]="Setup hugepage mappings for non-NUMA systems"
529         FUNC[4]="set_non_numa_pages"
530
531         TEXT[5]="Setup hugepage mappings for NUMA systems"
532         FUNC[5]="set_numa_pages"
533
534         TEXT[6]="Display current Ethernet device settings"
535         FUNC[6]="show_nics"
536
537         TEXT[7]="Bind Ethernet device to IGB UIO module"
538         FUNC[7]="bind_nics_to_igb_uio"
539
540         TEXT[8]="Bind Ethernet device to VFIO module"
541         FUNC[8]="bind_nics_to_vfio"
542
543         TEXT[9]="Setup VFIO permissions"
544         FUNC[9]="set_vfio_permissions"
545 }
546
547 #
548 # Options for running applications.
549 #
550 step3_func()
551 {
552         TITLE="Run test application for linuxapp environment"
553
554         TEXT[1]="Run test application (\$RTE_TARGET/app/test)"
555         FUNC[1]="run_test_app"
556
557         TEXT[2]="Run testpmd application in interactive mode (\$RTE_TARGET/app/testpmd)"
558         FUNC[2]="run_testpmd_app"
559 }
560
561 #
562 # Other options
563 #
564 step4_func()
565 {
566         TITLE="Other tools"
567
568         TEXT[1]="List hugepage info from /proc/meminfo"
569         FUNC[1]="grep_meminfo"
570
571 }
572
573 #
574 # Options for cleaning up the system
575 #
576 step5_func()
577 {
578         TITLE="Uninstall and system cleanup"
579
580         TEXT[1]="Uninstall all targets"
581         FUNC[1]="uninstall_targets"
582
583         TEXT[2]="Unbind NICs from IGB UIO or VFIO driver"
584         FUNC[2]="unbind_nics"
585
586         TEXT[3]="Remove IGB UIO module"
587         FUNC[3]="remove_igb_uio_module"
588
589         TEXT[4]="Remove VFIO module"
590         FUNC[4]="remove_vfio_module"
591
592         TEXT[5]="Remove KNI module"
593         FUNC[5]="remove_kni_module"
594
595         TEXT[6]="Remove hugepage mappings"
596         FUNC[6]="clear_huge_pages"
597 }
598
599 STEPS[1]="step1_func"
600 STEPS[2]="step2_func"
601 STEPS[3]="step3_func"
602 STEPS[4]="step4_func"
603 STEPS[5]="step5_func"
604
605 QUIT=0
606
607 while [ "$QUIT" == "0" ]; do
608         OPTION_NUM=1
609
610         for s in $(seq ${#STEPS[@]}) ; do
611                 ${STEPS[s]}
612
613                 echo "----------------------------------------------------------"
614                 echo " Step $s: ${TITLE}"
615                 echo "----------------------------------------------------------"
616
617                 for i in $(seq ${#TEXT[@]}) ; do
618                         echo "[$OPTION_NUM] ${TEXT[i]}"
619                         OPTIONS[$OPTION_NUM]=${FUNC[i]}
620                         let "OPTION_NUM+=1"
621                 done
622
623                 # Clear TEXT and FUNC arrays before next step
624                 unset TEXT
625                 unset FUNC
626
627                 echo ""
628         done
629
630         echo "[$OPTION_NUM] Exit Script"
631         OPTIONS[$OPTION_NUM]="quit"
632         echo ""
633         echo -n "Option: "
634         read our_entry
635         echo ""
636         ${OPTIONS[our_entry]} ${our_entry}
637
638         if [ "$QUIT" == "0" ] ; then
639                 echo
640                 echo -n "Press enter to continue ..."; read
641         fi
642
643 done