Merge "TempFix: vCGNAPT/vACL ipv4 perf issue"
[samplevnf.git] / tools / vnf_build.sh
1 #! /bin/bash
2 #
3 # Copyright (c) 2017 Intel Corporation
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #
17
18 cd $(dirname ${BASH_SOURCE[0]})/..
19 export VNF_CORE=$PWD
20 echo "------------------------------------------------------------------------------"
21 echo " VNF_CORE exported as $VNF_CORE"
22 echo "------------------------------------------------------------------------------"
23
24 HUGEPGSZ=`cat /proc/meminfo  | grep Hugepagesize | cut -d : -f 2 | tr -d ' '`
25 MODPROBE="/sbin/modprobe"
26 INSMOD="/sbin/insmod"
27 DPDK_DOWNLOAD="Not initialized"
28 CIVETWEB_DOWNLOAD="Not initialized"
29 DPDK_DIR=$VNF_CORE/dpdk
30 DPDK_RTE_VER="17.02"
31
32 #
33 # Sets QUIT variable so script will finish.
34 #
35 quit()
36 {
37         QUIT=$1
38 }
39
40 # Shortcut for quit.
41 q()
42 {
43         quit
44 }
45
46 setup_http_proxy()
47 {
48         while true; do
49                 echo
50                 read -p "Enter Proxy : " proxy
51                 export http_proxy=$proxy
52                 export https_proxy=$proxy
53                 echo "Acquire::http::proxy \"$http_proxy\";" | sudo tee -a /etc/apt/apt.conf > /dev/null
54                 echo "Acquire::https::proxy \"$http_proxy\";" | sudo tee -a /etc/apt/apt.conf > /dev/null
55
56                 wget -T 20 -t 3 --spider http://www.google.com > /dev/null 2>&1
57                 if [ "$?" != 0 ]; then
58                         echo -e "No Internet connection. Proxy incorrect? Try again"
59                         echo -e "eg: http://<proxy>:<port>"
60                         exit 1
61                 fi
62         return
63         done
64         echo "Network connectivity successful."
65 }
66
67 step_1()
68 {
69         TITLE="Environment setup."
70         CONFIG_NUM=1
71         TEXT[1]="Check OS and network connection"
72         FUNC[1]="setup_env"
73         TEXT[2]="Select DPDK RTE version"
74         FUNC[2]="select_dpdk_rte_ver"
75 }
76 setup_env()
77 {
78         # a. Check for OS dependencies
79         source /etc/os-release
80         if [[ $VERSION_ID != "16.04" ]] ; then
81                 echo "WARNING: It is recommended to use Ubuntu 16.04..Your version is "$VERSION_ID
82         else
83                 echo "Ubuntu 16.04 OS requirement met..."
84         fi
85         echo
86         echo "Checking network connectivity..."
87         # b. Check for internet connections
88         wget -T 20 -t 3 --spider http://www.google.com > /dev/null 2>&1
89         if [ "$?" != 0 ]; then
90                 while true; do
91                         read -p "No Internet connection. Are you behind a proxy (y/n)? " yn
92                         case $yn in
93                                 [Yy]* ) $SETUP_PROXY ; return;;
94                                 [Nn]* ) echo "Please check your internet connection..." ; exit;;
95                                 * ) "Please answer yes or no.";;
96                         esac
97                 done
98         fi
99         echo "Network connectivity successful."
100 }
101 select_dpdk_rte_ver()
102 {
103
104         TITLE="Select the DPDK RTE version"
105         CONFIG_NUM=1
106         echo "[1] DPDK 16.04"
107         echo "[2] DPDK 16.11"
108         echo "[3] DPDK 17.02"
109         echo "[4] DPDK 17.05"
110         echo
111
112         while true; do
113                 read -p "Select DPDK version to be used: " yn
114                         case $yn in
115                                 [1]* ) DPDK_RTE_VER=16.04 ; return;;
116                                 [2]* ) DPDK_RTE_VER=16.11 ; return;;
117                                 [3]* ) DPDK_RTE_VER=17.02 ; return;;
118                                 [4]* ) DPDK_RTE_VER=17.05 ; return;;
119                                 * ) echo " Invalid selection...";;
120                         esac
121         done
122 }
123
124 step_2()
125 {
126         TITLE="Download and Install"
127         CONFIG_NUM=1
128         TEXT[1]="Agree to download"
129         FUNC[1]="get_agreement_download"
130         TEXT[2]="Download packages"
131         FUNC[2]="install_libs"
132         TEXT[3]="Download DPDK zip"
133         FUNC[3]="download_dpdk_zip"
134         TEXT[4]="Build and Install DPDK"
135         FUNC[4]="install_dpdk"
136         TEXT[5]="Setup hugepages"
137         FUNC[5]="setup_hugepages"
138         TEXT[6]="Download and Build civetweb"
139         FUNC[6]="download_civetweb_zip"
140 }
141 get_agreement_download()
142 {
143         echo
144         echo "List of packages needed for VNFs build and installation:"
145         echo "-------------------------------------------------------"
146         echo "1. DPDK version $DPDK_RTE_VER"
147         echo "2. build-essential"
148         echo "3. linux-headers-generic"
149         echo "4. git"
150         echo "5. unzip"
151         echo "6. libpcap-dev"
152         echo "7. make"
153         echo "8. and other library dependencies"
154         while true; do
155                 read -p "We need download above mentioned package. Press (y/n) to continue? " yn
156                 case $yn in
157                         [Yy]* )
158                                 touch .agree
159                                 return;;
160                         [Nn]* ) exit;;
161                         * ) "Please answer yes or no.";;
162                 esac
163         done
164 }
165
166 install_libs()
167 {
168         echo "Install libs needed to build and run VNFs..."
169         file_name=".agree"
170         if [ ! -e "$file_name" ]; then
171                 echo "Please choose option '2.Agree to download' first"
172                 return
173         fi
174         file_name=".download"
175         if [ -e "$file_name" ]; then
176                 clear
177                 return
178         fi
179         sudo apt-get update
180         sudo apt-get -y install build-essential linux-headers-$(uname -r) git unzip libpcap0.8-dev gcc \
181                 make libc6 libc6-dev g++-multilib libzmq3-dev libcurl4-openssl-dev net-tools wget gcc unzip \
182                 libpcap-dev libncurses-dev libedit-dev pciutils liblua5.2-dev libncursesw5-dev libjson-c-dev libssl-dev
183         touch .download
184 }
185
186 download_dpdk_zip()
187 {
188         echo "Download DPDK zip"
189         file_name=".agree"
190         if [ ! -e "$file_name" ]; then
191                 echo "Please choose option '2.Agree to download' first"
192                 return
193         fi
194         DPDK_DOWNLOAD="http://dpdk.org/browse/dpdk/snapshot/dpdk-$DPDK_RTE_VER.zip"
195         rm -rf $DPDK_DIR
196         if [ ! -e ${DPDK_DOWNLOAD##*/} ] ; then
197                 wget ${DPDK_DOWNLOAD}
198         fi
199         unzip -o ${DPDK_DOWNLOAD##*/}
200         mv $VNF_CORE/dpdk-$DPDK_RTE_VER $VNF_CORE/dpdk
201 }
202
203 download_civetweb_zip()
204 {
205         echo "Download CIVETWEB zip"
206         CIVETWEB_DOWNLOAD="https://sourceforge.net/projects/civetweb/files/1.9/CivetWeb_V1.9.zip"
207         if [ ! -e ${CIVETWEB_DOWNLOAD##*/} ] ; then
208                 wget ${CIVETWEB_DOWNLOAD}
209         fi
210         unzip -o ${CIVETWEB_DOWNLOAD##*/}
211         mv $VNF_CORE/civetweb-master $VNF_CORE/civetweb
212         pushd $VNF_CORE/civetweb
213         make lib
214         popd
215 }
216
217 install_dpdk()
218 {
219         echo "Build DPDK"
220
221         if [ ! -d "$DPDK_DIR" ]; then
222      echo "Please choose option '4 Download DPDK zip'"
223      return
224         fi
225
226         export RTE_TARGET=x86_64-native-linuxapp-gcc
227
228         pushd $DPDK_DIR
229
230         if [ $DPDK_RTE_VER == "16.04" ] ; then
231                 echo "Apply dpdk custom patches..."
232                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-link-management.patch
233                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-Rx-hang-when-disable-LLDP.patch
234                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-link-status-change-interrupt.patch
235                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-VF-bonded-device-link-down.patch
236                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/disable-acl-debug-logs.patch
237                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/set-log-level-to-info.patch
238         fi
239
240         make -j16 install T=$RTE_TARGET
241         if [ $? -ne 0 ] ; then
242                 echo "Failed to build dpdk, please check the errors."
243                 return
244         fi
245         sudo modinfo igb_uio
246         if [ $? -ne 0 ] ; then
247                 sudo $MODPROBE -v uio
248                 sudo $INSMOD $RTE_TARGET/kmod/igb_uio.ko
249                 sudo cp -f $RTE_TARGET/kmod/igb_uio.ko /lib/modules/$(uname -r)
250                 echo "uio" | sudo tee -a /etc/modules
251                 echo "igb_uio" | sudo tee -a /etc/modules
252                 sudo depmod
253         fi
254   if [ -d "dpdk/usertools/" ]; then
255             cp usertools/dpdk-devbind.py /usr/sbin/dpdk-devbind
256         else
257             cp tools/dpdk_nic_bind.py /usr/sbin/dpdk-devbind
258   fi
259         popd
260 }
261
262 setup_hugepages()
263 {
264         #----
265         Pages=16
266         if [[ "$HUGEPGSZ" = "2048kB" ]] ; then
267                 Pages=8192
268         fi
269         if [ ! "`grep nr_hugepages /etc/sysctl.conf`" ] ; then
270                 echo "vm.nr_hugepages=$Pages" | sudo tee /etc/sysctl.conf
271         fi
272         sudo sysctl -p
273
274         sudo service procps start
275
276         grep -s '/dev/hugepages' /proc/mounts
277         if [ $? -ne 0 ] ; then
278                 echo "Creating /mnt/huge and mounting as hugetlbfs"
279                 sudo mkdir -p /mnt/huge
280                 sudo mount -t hugetlbfs nodev /mnt/huge
281                 echo "nodev /mnt/huge hugetlbfs defaults 0 0" | sudo tee -a /etc/fstab > /dev/null
282         fi
283 }
284
285 step_3()
286 {
287         TITLE="Build VNFs"
288         CONFIG_NUM=1
289                                 TEXT[1]="Build all VNFs (vACL, vCGNAPT, vFW, UDP_Replay)"
290         FUNC[1]="build_vnfs"
291 }
292
293 build_vnfs()
294 {
295
296         if [ ! -d "$DPDK_DIR" ]; then
297      echo "Please choose option '4 Download DPDK zip'"
298      return
299         fi
300
301         if [ ! -d "$DPDK_DIR/x86_64-native-linuxapp-gcc" ]; then
302      echo "Please choose option '5 Build and Install DPDK'"
303      return
304         fi
305
306         export RTE_SDK=$DPDK_DIR
307         export RTE_TARGET=x86_64-native-linuxapp-gcc
308         pushd $VNF_CORE
309         make clean
310         make || { echo -e "\nVNF: Make failed\n"; }
311         popd
312 }
313
314 non_interactive()
315 {
316   #--- Add non intractive option to build vnfs
317   if [[ "$1" = "true" ]];then
318                   DPDK_VER=("" "16.04" "16.11" "17.02" "17.05")
319                   member="$2"
320                   for item in "${DPDK_VER[@]}"; do
321                            if [[ "$member" == "$item" ]]; then
322                       DPDK_RTE_VER="$member"
323                     fi
324     done
325     pushd $VNF_CORE
326
327     echo "Install required libraries..."
328     touch .agree
329     install_libs
330
331     echo "Download dpdk for VNF build..."
332     download_dpdk_zip
333
334     echo "Download civetweb for VNF build..."
335     download_civetweb_zip
336
337     echo "Build dpdk..."
338     install_dpdk
339
340     echo "Setup hugepages..."
341     setup_hugepages
342
343     echo "build VNFS..."
344     build_vnfs
345
346     popd
347     exit
348   fi
349 }
350
351 interactive()
352 {
353   SETUP_PROXY="setup_http_proxy"
354   STEPS[1]="step_1"
355   STEPS[2]="step_2"
356   STEPS[3]="step_3"
357
358   QUIT=0
359
360   while [ "$QUIT" == "0" ]; do
361     OPTION_NUM=1
362     for s in $(seq ${#STEPS[@]}) ; do
363       ${STEPS[s]}
364
365       echo "----------------------------------------------------------"
366       echo " Step $s: ${TITLE}"
367       echo "----------------------------------------------------------"
368
369       for i in $(seq ${#TEXT[@]}) ; do
370               echo "[$OPTION_NUM] ${TEXT[i]}"
371               OPTIONS[$OPTION_NUM]=${FUNC[i]}
372               let "OPTION_NUM+=1"
373       done
374
375       # Clear TEXT and FUNC arrays before next step
376       unset TEXT
377       unset FUNC
378
379       echo ""
380     done
381
382     echo "[$OPTION_NUM] Exit Script"
383     OPTIONS[$OPTION_NUM]="quit"
384     echo ""
385     echo -n "Option: "
386     read our_entry
387     echo ""
388     ${OPTIONS[our_entry]} ${our_entry}
389
390     if [ "$QUIT" == "0" ] ; then
391       echo
392       echo -n "Press enter to continue ..."; read
393       clear
394       continue
395       exit
396     fi
397     echo "Installation successfully complete."
398   done
399 }
400
401 # -- main script
402 clear
403 sudo -n true
404 if [ $? -ne 0 ]; then
405   echo -n "Checking for user permission.. "
406   echo "Password-less sudo user must run this script" 1>&2
407   exit 1
408 fi
409
410 NON_INTERACTIVE=false
411 INTERACTIVE=true
412 DPDK_VERSION=$DPDK_RTE_VER
413
414 for i in "$@"
415 do
416 case $i in
417                 -s|--silient)
418                 NON_INTERACTIVE=true
419   INTERACTIVE=false
420                 ;;
421                 -i|--interactive)
422                 INTERACTIVE=true
423                 ;;
424                 -p=*|--proxy=*)
425                 export http_proxy="${i#*=}"
426                 export https_proxy="${i#*=}"
427                 ;;
428                 -d=*|--dpdk=*)
429                 DPDK_VERSION="${i#*=}"
430                 ;;
431                 -h|--help)
432                 echo "CommandLine options:"
433                 echo "===================="
434                 echo "1. Intractive mode:"
435                 echo "./tools/vnf_build.sh or ./tools/vnf_build.sh -i"
436                 echo
437                 echo "1. Non-Intractive mode:"
438                 echo "./tools/vnf_build.sh -s [Default dpdk 17.02]"
439                 echo "If system is behind proxy use -p=<proxy> and to use different dpdk version use -d=<dpdk>"
440                 echo "eg: ./tools/vnf_build.sh -s -p=http://proxy.com -d=17.05"
441                 echo 'Note:- supported dpdk version ("16.04" "16.11" "17.02" "17.05")'
442                 echo
443                 exit
444                 ;;
445                 --default)
446                 INTERACTIVE=true
447                 ;;
448                 *)
449   ;;
450 esac
451 done
452
453 if [[ "$INTERACTIVE" == "true" ]]; then
454                         interactive
455                         exit
456 fi
457
458 if [[ "$NON_INTERACTIVE" == "true" ]]; then
459                         non_interactive $NON_INTERACTIVE $DPDK_VERSION
460                         exit
461 fi