f60a364429c03ac3a3c1a6ab23763c2f567683be
[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 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 libjson0 \
183                 libjson0-dev libssl-dev
184         touch .download
185 }
186
187 download_dpdk_zip()
188 {
189         echo "Download DPDK zip"
190         file_name=".agree"
191         if [ ! -e "$file_name" ]; then
192                 echo "Please choose option '2.Agree to download' first"
193                 return
194         fi
195         DPDK_DOWNLOAD="http://dpdk.org/browse/dpdk/snapshot/dpdk-$DPDK_RTE_VER.zip"
196         rm -rf $DPDK_DIR
197         if [ ! -e ${DPDK_DOWNLOAD##*/} ] ; then
198                 wget ${DPDK_DOWNLOAD}
199         fi
200         unzip -o ${DPDK_DOWNLOAD##*/}
201         mv $VNF_CORE/dpdk-$DPDK_RTE_VER $VNF_CORE/dpdk
202 }
203
204 download_civetweb_zip()
205 {
206         echo "Download CIVETWEB zip"
207         CIVETWEB_DOWNLOAD="https://sourceforge.net/projects/civetweb/files/1.9/CivetWeb_V1.9.zip"
208         if [ ! -e ${CIVETWEB_DOWNLOAD##*/} ] ; then
209                 wget ${CIVETWEB_DOWNLOAD}
210         fi
211         unzip -o ${CIVETWEB_DOWNLOAD##*/}
212         mv $VNF_CORE/civetweb-master $VNF_CORE/civetweb
213         pushd $VNF_CORE/civetweb
214         make lib
215         popd
216 }
217
218 install_dpdk()
219 {
220         echo "Build DPDK"
221
222         if [ ! -d "$DPDK_DIR" ]; then
223      echo "Please choose option '4 Download DPDK zip'"
224      return
225         fi
226
227         export RTE_TARGET=x86_64-native-linuxapp-gcc
228
229         pushd $DPDK_DIR
230
231         if [ $DPDK_RTE_VER == "16.04" ] ; then
232                 echo "Apply dpdk custom patches..."
233                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-link-management.patch
234                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-Rx-hang-when-disable-LLDP.patch
235                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-link-status-change-interrupt.patch
236                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-VF-bonded-device-link-down.patch
237                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/disable-acl-debug-logs.patch
238                         patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/set-log-level-to-info.patch
239         fi
240
241         make -j16 install T=$RTE_TARGET
242         if [ $? -ne 0 ] ; then
243                 echo "Failed to build dpdk, please check the errors."
244                 return
245         fi
246         sudo modinfo igb_uio
247         if [ $? -ne 0 ] ; then
248                 sudo $MODPROBE -v uio
249                 sudo $INSMOD $RTE_TARGET/kmod/igb_uio.ko
250                 sudo cp -f $RTE_TARGET/kmod/igb_uio.ko /lib/modules/$(uname -r)
251                 echo "uio" | sudo tee -a /etc/modules
252                 echo "igb_uio" | sudo tee -a /etc/modules
253                 sudo depmod
254         fi
255   if [ -d "dpdk/usertools/" ]; then
256             cp usertools/dpdk-devbind.py /usr/sbin/dpdk-devbind
257         else
258             cp tools/dpdk_nic_bind.py /usr/sbin/dpdk-devbind
259   fi
260         popd
261 }
262
263 setup_hugepages()
264 {
265         #----
266         Pages=16
267         if [[ "$HUGEPGSZ" = "2048kB" ]] ; then
268                 Pages=8192
269         fi
270         if [ ! "`grep nr_hugepages /etc/sysctl.conf`" ] ; then
271                 echo "vm.nr_hugepages=$Pages" | sudo tee /etc/sysctl.conf
272         fi
273         sudo sysctl -p
274
275         sudo service procps start
276
277         grep -s '/dev/hugepages' /proc/mounts
278         if [ $? -ne 0 ] ; then
279                 echo "Creating /mnt/huge and mounting as hugetlbfs"
280                 sudo mkdir -p /mnt/huge
281                 sudo mount -t hugetlbfs nodev /mnt/huge
282                 echo "nodev /mnt/huge hugetlbfs defaults 0 0" | sudo tee -a /etc/fstab > /dev/null
283         fi
284 }
285
286 step_3()
287 {
288         TITLE="Build VNFs"
289         CONFIG_NUM=1
290                                 TEXT[1]="Build all VNFs (vACL, vCGNAPT, vFW, UDP_Replay)"
291         FUNC[1]="build_vnfs"
292 }
293
294 build_vnfs()
295 {
296
297         if [ ! -d "$DPDK_DIR" ]; then
298      echo "Please choose option '4 Download DPDK zip'"
299      return
300         fi
301
302         if [ ! -d "$DPDK_DIR/x86_64-native-linuxapp-gcc" ]; then
303      echo "Please choose option '5 Build and Install DPDK'"
304      return
305         fi
306
307         export RTE_SDK=$DPDK_DIR
308         export RTE_TARGET=x86_64-native-linuxapp-gcc
309         pushd $VNF_CORE
310         make clean
311         make || { echo -e "\nVNF: Make failed\n"; }
312         popd
313 }
314
315 non_interactive()
316 {
317   #--- Add non intractive option to build vnfs
318   if [[ "$1" = "true" ]];then
319                   DPDK_VER=("" "16.04" "16.11" "17.02" "17.05")
320                   member="$2"
321                   for item in "${DPDK_VER[@]}"; do
322                            if [[ "$member" == "$item" ]]; then
323                       DPDK_RTE_VER="$member"
324                     fi
325     done
326     pushd $VNF_CORE
327
328     echo "Install required libraries..."
329     touch .agree
330     install_libs
331
332     echo "Download dpdk for VNF build..."
333     download_dpdk_zip
334
335     echo "Download civetweb for VNF build..."
336     download_civetweb_zip
337
338     echo "Build dpdk..."
339     install_dpdk
340
341     echo "Setup hugepages..."
342     setup_hugepages
343
344     echo "build VNFS..."
345     build_vnfs
346
347     popd
348     exit
349   fi
350 }
351
352 interactive()
353 {
354   SETUP_PROXY="setup_http_proxy"
355   STEPS[1]="step_1"
356   STEPS[2]="step_2"
357   STEPS[3]="step_3"
358
359   QUIT=0
360
361   while [ "$QUIT" == "0" ]; do
362     OPTION_NUM=1
363     for s in $(seq ${#STEPS[@]}) ; do
364       ${STEPS[s]}
365
366       echo "----------------------------------------------------------"
367       echo " Step $s: ${TITLE}"
368       echo "----------------------------------------------------------"
369
370       for i in $(seq ${#TEXT[@]}) ; do
371               echo "[$OPTION_NUM] ${TEXT[i]}"
372               OPTIONS[$OPTION_NUM]=${FUNC[i]}
373               let "OPTION_NUM+=1"
374       done
375
376       # Clear TEXT and FUNC arrays before next step
377       unset TEXT
378       unset FUNC
379
380       echo ""
381     done
382
383     echo "[$OPTION_NUM] Exit Script"
384     OPTIONS[$OPTION_NUM]="quit"
385     echo ""
386     echo -n "Option: "
387     read our_entry
388     echo ""
389     ${OPTIONS[our_entry]} ${our_entry}
390
391     if [ "$QUIT" == "0" ] ; then
392       echo
393       echo -n "Press enter to continue ..."; read
394       clear
395       continue
396       exit
397     fi
398     echo "Installation successfully complete."
399   done
400 }
401
402 # -- main script
403 clear
404 sudo -n true
405 if [ $? -ne 0 ]; then
406   echo -n "Checking for user permission.. "
407   echo "Password-less sudo user must run this script" 1>&2
408   exit 1
409 fi
410
411 NON_INTERACTIVE=false
412 INTERACTIVE=true
413 DPDK_VERSION=$DPDK_RTE_VER
414
415 for i in "$@"
416 do
417 case $i in
418                 -s|--silient)
419                 NON_INTERACTIVE=true
420   INTERACTIVE=false
421                 ;;
422                 -i|--interactive)
423                 INTERACTIVE=true
424                 ;;
425                 -p=*|--proxy=*)
426                 export http_proxy="${i#*=}"
427                 export https_proxy="${i#*=}"
428                 ;;
429                 -d=*|--dpdk=*)
430                 DPDK_VERSION="${i#*=}"
431                 ;;
432                 -h|--help)
433                 echo "CommandLine options:"
434                 echo "===================="
435                 echo "1. Intractive mode:"
436                 echo "./tools/vnf_build.sh or ./tools/vnf_build.sh -i"
437                 echo
438                 echo "1. Non-Intractive mode:"
439                 echo "./tools/vnf_build.sh -s [Default dpdk 17.02]"
440                 echo "If system is behind proxy use -p=<proxy> and to use different dpdk version use -d=<dpdk>"
441                 echo "eg: ./tools/vnf_build.sh -s -p=http://proxy.com -d=17.05"
442                 echo 'Note:- supported dpdk version ("16.04" "16.11" "17.02" "17.05")'
443                 echo
444                 exit
445                 ;;
446                 --default)
447                 INTERACTIVE=true
448                 ;;
449                 *)
450   ;;
451 esac
452 done
453
454 if [[ "$INTERACTIVE" == "true" ]]; then
455                         interactive
456                         exit
457 fi
458
459 if [[ "$NON_INTERACTIVE" == "true" ]]; then
460                         non_interactive $NON_INTERACTIVE $DPDK_VERSION
461                         exit
462 fi