Update librte-pmd-bond1.symbols with new symbol.
[deb_dpdk.git] / debian / dpdk-init
1 #!/bin/sh
2 #
3 # dpdk-init: startup script to initialize a dpdk runtime environment
4 #
5 # Copyright 2015-2016 Canonical Ltd.
6 # Autor: Stefan Bader <stefan.bader@canonical.com>
7 # Autor: Christian Ehrhardt <christian.ehrhardt@canonical.com>
8 #
9 #    This program is free software: you can redistribute it and/or modify
10 #    it under the terms of the GNU General Public License version 3,
11 #    as published by the Free Software Foundation.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU General Public License for more details.
17 #
18 #    You should have received a copy of the GNU General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 set -e
22
23 DPDK_BIND="/sbin/dpdk-devbind"
24 DPDK_INTERF="/etc/dpdk/interfaces"
25
26
27 # pagesize supports [G|g]/[M|m]/[K|k]
28 get_kbytes() {
29     local unit
30     local num
31     unit=$(echo "${1}" | sed 's/[0-9]*//g')
32     num=$(echo "${1}" | sed 's/[^0-9]*//g')
33     case ${unit} in
34     *g | *G)
35         echo $((num*1024*1024))
36         ;;
37     *m | *M)
38         echo $((num*1024))
39         ;;
40     *k | *K)
41         echo $((num))
42         ;;
43     *)
44         echo $((num/1024))
45         ;;
46     esac
47 }
48
49 get_default_hpgsz() {
50     default_hpgsz=$(grep "Hugepagesize:" /proc/meminfo \
51         | sed 's/^Hugepagesize:\s*//g' | sed 's/\s*kB$//g')
52     echo "${default_hpgsz}"
53 }
54
55 get_hugetlbfs_mountpoint() {
56     local requested_hpgsz
57     local mp_hpgsz
58     requested_hpgsz=$(get_kbytes "${1}")
59
60     grep hugetlbfs /proc/mounts | while read \
61         mntfrom mntpoint mntfstype mntopt mntdump mntfsck; do
62
63         # check if the current muntpoint is of the requested huge page size
64         case ${mntopt} in
65         *pagesize=*)
66             mp_hpgsz=$(echo "${mntopt}" | sed 's/.*pagesize=//g' | sed 's/,.*//g')
67             mp_hpgsz=$(get_kbytes "${mp_hpgsz}")
68             ;;
69         *)
70             mp_hpgsz=$(get_default_hpgsz)
71             ;;
72         esac
73         if [ "${requested_hpgsz}" -eq "${mp_hpgsz}" ]; then
74             echo "${mntpoint}"
75             return
76         fi
77     done
78 }
79
80 _mount_hugetlbfs() {
81     local MNT="/dev/hugepages"
82     local MNTOPTS=""
83     local requested_hpgsz
84     local default_hpgsz
85     requested_hpgsz=$(get_kbytes "${1}")
86     default_hpgsz=$(get_default_hpgsz)
87
88     # kernel might not support the requested size
89     if [ ! -d "/sys/kernel/mm/hugepages/hugepages-${requested_hpgsz}kB" ]; then
90         echo "WARNING: requested page size of ${requested_hpgsz}kB " \
91              "not supported by the kernel"
92         return 0
93     fi
94
95     # special case if this is not the default huge page size
96     if [ "${requested_hpgsz}" -ne "${default_hpgsz}" ]; then
97         MNT="${MNT}-${requested_hpgsz}"
98         MNTOPTS="pagesize=${requested_hpgsz}K"
99     fi
100
101     if [ ! -e "${MNT}" ]; then
102         mkdir "${MNT}"
103         if [ $? -ne 0 ]; then
104             echo "Could not create directory ${MNT}!" >&2
105             return 1
106         fi
107     fi
108     mount -thugetlbfs hugetlbfs "${MNT}" -o "${MNTOPTS}"
109     return $?
110 }
111
112 #
113 # The DPDK library will use the first mounted instance it finds for a given
114 # page size. so if there is already one for a given size there is no need to
115 # create another for the same huge page size.
116 #
117 mount_hugetlbfs() {
118     if [ ! -r /etc/dpdk/dpdk.conf ]; then
119         return 1
120     fi
121     . /etc/dpdk/dpdk.conf
122
123     # if a page size is requested, there has to be a mountpoint for that size
124     if [ -n "${NR_2M_PAGES}" -a -z "$(get_hugetlbfs_mountpoint '2M')" ]; then
125         _mount_hugetlbfs 2M
126     fi
127     if [ -n "${NR_16M_PAGES}" -a -z "$(get_hugetlbfs_mountpoint '16M')" ]; then
128         _mount_hugetlbfs 16M
129     fi
130     if [ -n "${NR_1G_PAGES}" -a -z "$(get_hugetlbfs_mountpoint '1G')" ]; then
131         _mount_hugetlbfs 1G
132     fi
133 }
134
135 _setup_hugepages() {
136     MMDIR="/sys/kernel/mm/hugepages/${1}"
137     PAGES=${2}
138
139     if [ "$PAGES" != "" ]; then
140         if [ "$PAGES" -gt 0 ]; then
141             if [ -d "$MMDIR" -a -w "$MMDIR/nr_hugepages" ]; then
142                 # increases the chance to allocate enough huge pages
143                 # configurable, since it comes at a perf penality
144                 if [ "$DROPCACHE_BEFORE_HP_ALLOC" = "1" ]; then
145                     echo 3 > /proc/sys/vm/drop_caches
146                 fi
147
148                 echo "$PAGES" > "$MMDIR/nr_hugepages"
149
150                 GOTPAGES=$(cat "$MMDIR/nr_hugepages")
151                 if [ "$GOTPAGES" -lt "$PAGES" ]; then
152                     echo "WARNING: could not allocate $PAGES at " \
153                          "$MMDIR/nr_hugepages (only got $GOTPAGES)."
154                 fi
155             else
156                 echo "WARNING: $MMDIR/nr_hugepages not found/writable"
157             fi
158         fi
159     fi
160 }
161
162 #
163 # Reserve a certain amount of hugepages (defined in /etc/dpdk.conf)
164 #
165 setup_hugepages() {
166     if [ ! -r /etc/dpdk/dpdk.conf ]; then
167         return 1
168     fi
169     . /etc/dpdk/dpdk.conf
170
171     _setup_hugepages "hugepages-2048kB" "$NR_2M_PAGES"
172     _setup_hugepages "hugepages-16384kB" "$NR_16M_PAGES"
173     _setup_hugepages "hugepages-1048576kB" "$NR_1G_PAGES"
174
175     # dpdk uses 2*#hugepages mappings, increase for huge systems LP #1507921
176     if [ -d /sys/kernel/mm/hugepages ]; then
177         max_map_count=$(awk -v pad=65530 '{tot+=$1}END{print tot*2+pad}' \
178             /sys/kernel/mm/hugepages/hugepages-*/nr_hugepages)
179         sysctl -q vm.max_map_count="${max_map_count:-65530}"
180     fi
181
182     return 0
183 }
184
185 #
186 # Allow NICs to be automatically bound to DPDK compatible drivers on boot.
187 #
188 bind_interfaces() {
189     if [ ! -r "$DPDK_INTERF" ]; then
190         return 0
191     fi
192     grep -v '^[ \t]*#' "$DPDK_INTERF" | while read BUS ID MOD; do
193         if [ "$BUS" = "" -o "$ID" = "" -o "$MOD" = "" ]; then
194             echo "WARNING: incomplete spec in $DPDK_INTERF" \
195                 " - BUS '$BUS' ID '$ID' MOD '$MOD'"
196             continue
197         fi
198         if [ "$BUS" != "pci" ]; then
199             echo "WARNING: incompatible bus '$BUS' in $DPDK_INTERF"
200             continue
201         fi
202
203         SYSFSPATH="/sys/bus/$BUS/devices/$ID"
204         if [ ! -e "$SYSFSPATH" ]; then
205             echo "WARNING: invalid pci ID '$ID' in $DPDK_INTERF" \
206                 " - '$SYSFSPATH' does not exist"
207             continue
208         fi
209         if [ -L "$SYSFSPATH/driver" ]; then
210             CUR=$(readlink "$SYSFSPATH/driver")
211             CUR=$(basename "$CUR")
212         else
213             # device existing, but currently unregistered
214             CUR=""
215         fi
216         if [ "$MOD" != "$CUR" ]; then
217             modprobe -q "$MOD" || true
218             # cloud img have no linux-image-extra initially (uip_pci_generic)
219             # so check if the module is available (loadable/built in)
220             if [ -e "/sys/bus/pci/drivers/${MOD}" ]; then
221                 echo "Reassigning pci:$ID to $MOD"
222                 $DPDK_BIND -b "$MOD" "$ID"
223             else
224                 echo "Warning: failed assigning pci:$ID," \
225                      " module $MOD not available"
226             fi
227         else
228             echo "pci:$ID already assigned to $MOD"
229         fi
230     done
231 }
232
233
234
235 case "$1" in
236 start)
237     mount_hugetlbfs
238     setup_hugepages
239     bind_interfaces
240     ;;
241 stop)
242     ;;
243 reload|force-reload)
244     setup_hugepages
245     bind_interfaces
246     ;;
247 status)
248     $DPDK_BIND --status
249     ;;
250 *)
251     echo "Usage: $0 {start|stop|reload|force-reload|status}"
252     exit 1
253     ;;
254 esac
255