3 # dpdk-init: startup script to initialize a dpdk runtime environment
5 # Copyright 2015-2016 Canonical Ltd.
6 # Autor: Stefan Bader <stefan.bader@canonical.com>
7 # Autor: Christian Ehrhardt <christian.ehrhardt@canonical.com>
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.
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.
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/>.
23 DPDK_BIND="/usr/bin/dpdk-devbind.py"
24 DPDK_INTERF="/etc/dpdk/interfaces"
27 # pagesize supports [G|g]/[M|m]/[K|k]
31 unit=$(echo "${1}" | sed 's/[0-9]*//g')
32 num=$(echo "${1}" | sed 's/[^0-9]*//g')
35 echo $((num*1024*1024))
50 default_hpgsz=$(grep "Hugepagesize:" /proc/meminfo \
51 | sed 's/^Hugepagesize:\s*//g' | sed 's/\s*kB$//g')
52 echo "${default_hpgsz}"
55 get_hugetlbfs_mountpoint() {
58 requested_hpgsz=$(get_kbytes "${1}")
60 grep hugetlbfs /proc/mounts | while read \
61 mntfrom mntpoint mntfstype mntopt mntdump mntfsck; do
63 # check if the current muntpoint is of the requested huge page size
66 mp_hpgsz=$(echo "${mntopt}" | sed 's/.*pagesize=//g' | sed 's/,.*//g')
67 mp_hpgsz=$(get_kbytes "${mp_hpgsz}")
70 mp_hpgsz=$(get_default_hpgsz)
73 if [ "${requested_hpgsz}" -eq "${mp_hpgsz}" ]; then
81 local MNT="/dev/hugepages"
85 requested_hpgsz=$(get_kbytes "${1}")
86 default_hpgsz=$(get_default_hpgsz)
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"
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"
101 if [ ! -e "${MNT}" ]; then
103 if [ $? -ne 0 ]; then
104 echo "Could not create directory ${MNT}!" >&2
108 mount -thugetlbfs hugetlbfs "${MNT}" -o "${MNTOPTS}"
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.
118 if [ ! -r /etc/dpdk/dpdk.conf ]; then
121 . /etc/dpdk/dpdk.conf
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
127 if [ -n "${NR_16M_PAGES}" -a -z "$(get_hugetlbfs_mountpoint '16M')" ]; then
130 if [ -n "${NR_1G_PAGES}" -a -z "$(get_hugetlbfs_mountpoint '1G')" ]; then
136 MMDIR="/sys/kernel/mm/hugepages/${1}"
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
148 echo "$PAGES" > "$MMDIR/nr_hugepages"
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)."
156 echo "WARNING: $MMDIR/nr_hugepages not found/writable"
163 # Reserve a certain amount of hugepages (defined in /etc/dpdk.conf)
166 if [ ! -r /etc/dpdk/dpdk.conf ]; then
169 . /etc/dpdk/dpdk.conf
171 _setup_hugepages "hugepages-2048kB" "$NR_2M_PAGES"
172 _setup_hugepages "hugepages-16384kB" "$NR_16M_PAGES"
173 _setup_hugepages "hugepages-1048576kB" "$NR_1G_PAGES"
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}"
186 # Allow NICs to be automatically bound to DPDK compatible drivers on boot.
189 if [ ! -r "$DPDK_INTERF" ]; then
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'"
198 if [ "$BUS" != "pci" ]; then
199 echo "WARNING: incompatible bus '$BUS' in $DPDK_INTERF"
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"
209 if [ -L "$SYSFSPATH/driver" ]; then
210 CUR=$(readlink "$SYSFSPATH/driver")
211 CUR=$(basename "$CUR")
213 # device existing, but currently unregistered
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"
224 echo "Warning: failed assigning pci:$ID," \
225 " module $MOD not available"
228 echo "pci:$ID already assigned to $MOD"
251 echo "Usage: $0 {start|stop|reload|force-reload|status}"