Itsuro Oda b0a66719b9 upgrade DPDK version to v20.02
networking-spp has not been able to upgrade DPDK/SPP version from
v18.08 because DPDK v18.11 and later have a problem that secondary
processes can not use vhost PMD.
Now the problem is fixed in DPDK v20.02, this patch makes Neutron
SPP driver use DPDK/SPP v20.02.

Change-Id: Ic51071c10bf8f7b954586c82bbf85421918be55e
Blueprint: upgrade-dpdk-2002
2020-07-20 07:35:55 +09:00

360 lines
11 KiB
Bash

function spp_pre_install(){
OFFLINE=$(trueorfalse False OFFLINE)
if [ "$OFFLINE" != True ]; then
if is_ubuntu; then
echo "TODO: install packages necessary for DPDK build"
sudo apt-get install -y libnuma-dev
sudo apt-get install -y liblz4-dev
sudo apt-get install -y python3
sudo apt-get install -y python3-pip
sudo apt-get install -y linux-modules-extra-$(uname -r) # for uio_pci_generic
#NOTE(oda): it is environment dependent.
fi
#TODO: other OS support (ex. CentOS)
fi
}
function clone_spp_dpdk(){
OFFLINE=$(trueorfalse False OFFLINE)
RECLONE=$(trueorfalse False RECLONE)
if [[ "$OFFLINE" != True ]]; then
if [ ! -d "${DPDK_DIR}" ] || [ "$RECLONE" == True ]; then
git_clone ${DPDK_GIT_REPO} ${DPDK_DIR} ${DPDK_GIT_TAG}
fi
if [ ! -d "${SPP_DIR}" ] || [ "$RECLONE" == True ]; then
git_clone ${SPP_GIT_REPO} ${SPP_DIR} ${SPP_GIT_TAG}
fi
fi
}
function build_spp_dpdk(){
if [[ "$SPP_DPDK_BUILD_SKIP" != True ]]; then
pushd ${DPDK_DIR}
sudo make config T=${RTE_TARGET}
if [ -e "${RTE_TARGET}" ]; then
rm -rf $RTE_TARGET
fi
ln -s -f build ${RTE_TARGET}
sudo make
cd ${SPP_DIR}
sudo SPP_HOME=${SPP_DIR} RTE_TARGET=${RTE_TARGET} RTE_SDK=${RTE_SDK} make
# for spp-ctl
sudo -H pip3 install -r requirements.txt
sudo chmod +x ${SPP_DIR}/src/spp-ctl/spp-ctl
popd
fi
}
function free_hugepages(){
HUGEPAGE_SIZE=$(grep Hugepagesize /proc/meminfo | awk '{ print $2 }')
sudo rm -rf ${SPP_HUGEPAGE_MOUNT}/rtemap*
sudo umount ${SPP_HUGEPAGE_MOUNT}
if [ $SPP_ALLOCATE_HUGEPAGES == 'True' ]; then
for d in /sys/devices/system/node/node? ; do
echo 0 | sudo tee $d/hugepages/hugepages-${HUGEPAGE_SIZE}kB/nr_hugepages
done
fi
}
function alloc_hugepages(){
HUGEPAGE_SIZE=$(grep Hugepagesize /proc/meminfo | awk '{ print $2 }')
if [ $SPP_NUM_HUGEPAGES -eq 0 ]; then
die 6 $LINENO "SPP_NUM_HUGEPAGES not set"
fi
if grep -ws $SPP_HUGEPAGE_MOUNT /proc/mounts > /dev/null; then
free_hugepages
fi
if [ $SPP_ALLOCATE_HUGEPAGES == 'True' ]; then
for d in /sys/devices/system/node/node? ; do
echo $SPP_NUM_HUGEPAGES | sudo tee $d/hugepages/hugepages-${HUGEPAGE_SIZE}kB/nr_hugepages
done
fi
sudo mkdir -p $SPP_HUGEPAGE_MOUNT
sudo mount -t hugetlbfs nodev $SPP_HUGEPAGE_MOUNT
#TODO: restart libvirtd ?
}
function bind_nics() {
if [ -n "$DPDK_PORT_MAPPINGS" ]; then
sudo modprobe uio_pci_generic
MAPPINGS=${DPDK_PORT_MAPPINGS//,/ }
ARRAY=( $MAPPINGS )
NICS=""
for pair in "${ARRAY[@]}"; do
addr=`echo $pair | cut -f 1 -d "#"`
NICS="$NICS $addr"
done
sudo $DPDK_DIR/usertools/dpdk-devbind.py -b uio_pci_generic $NICS
fi
}
function unbind_nic() {
pci=$1
out=$(lspci -s $pci -k | grep 'Kernel modules:')
driver=${out##*:}
if [ -n "$driver" ]; then
sudo $DPDK_DIR/usertools/dpdk-devbind.py -b $driver $pci
else
sudo $DPDK_DIR/usertools/dpdk-devbind.py --force -u $pci
fi
}
function unbind_nics() {
if [ -n "$DPDK_PORT_MAPPINGS" ]; then
MAPPINGS=${DPDK_PORT_MAPPINGS//,/ }
ARRAY=( $MAPPINGS )
for pair in "${ARRAY[@]}"; do
addr=`echo $pair | cut -f 1 -d "#"`
unbind_nic $addr
done
fi
}
function prepare_spp_dpdk(){
alloc_hugepages
bind_nics
}
function cleanup_spp_dpdk(){
unbind_nics
if grep -ws $SPP_HUGEPAGE_MOUNT /proc/mounts > /dev/null; then
free_hugepages
fi
}
function configure_etcd() {
iniset /$Q_PLUGIN_CONF_FILE spp etcd_host $ETCD_HOST
iniset /$Q_PLUGIN_CONF_FILE spp etcd_port $ETCD_PORT
}
function configure_spp_agent() {
iniset /$Q_PLUGIN_CONF_FILE spp api_ip_addr $SPP_CTL_IP_ADDR
iniset /$Q_PLUGIN_CONF_FILE spp api_port $SPP_API_PORT
if [ -z "$SPP_HOST" ]; then
SPP_HOST=$(hostname -s)
fi
export DPDK_PORT_MAPPINGS SPP_HOST ETCD_HOST ETCD_PORT SPP_COMPONENT_CONF SPP_MIRROR
$PYTHON $NETWORKING_SPP_DIR/devstack/spp-config-build.py
}
function unconfigure_spp_agent() {
if [ -z "$SPP_HOST" ]; then
SPP_HOST=$(hostname -s)
fi
$PYTHON $NETWORKING_SPP_DIR/devstack/spp-config-destroy.py \
$SPP_HOST $ETCD_HOST $ETCD_PORT
}
function build_spp_ctl_service() {
local service="spp_ctl.service"
local unitfile="$SYSTEMD_DIR/$service"
CTL_CMD="$SPP_DIR/src/spp-ctl/spp-ctl -p $SPP_PRIMARY_SOCK_PORT -s $SPP_SECONDARY_SOCK_PORT -a $SPP_API_PORT -b $SPP_CTL_IP_ADDR"
iniset -sudo $unitfile "Unit" "Description" "Devstack $service"
iniset -sudo $unitfile "Service" "User" "$STACK_USER"
iniset -sudo $unitfile "Service" "ExecStart" "$CTL_CMD"
}
function build_spp_primary_service() {
local service="spp_primary.service"
local unitfile="$SYSTEMD_DIR/$service"
MAPPINGS=${DPDK_PORT_MAPPINGS//,/ }
ARRAY=( $MAPPINGS )
NUM_VHOST=0
for map in "${ARRAY[@]}"; do
num=`echo $map | cut -f 3 -d "#"`
NUM_VHOST=$(( $NUM_VHOST + $num ))
done
PORT_MASK=0
for ((i=0; i<${#ARRAY[@]}; i++)); do
PORT_MASK=$(( $PORT_MASK + (1 << $i) ))
done
NUM_MIRROR=0
if [[ -n "$SPP_MIRROR" ]]; then
NUM_MIRROR=`echo $SPP_MIRROR | cut -f 1 -d "#"`
fi
NUM_RING=$(( $NUM_VHOST * 2 + $NUM_MIRROR * 2 ))
# this is a workaround for https://bugs.launchpad.net/networking-spp/+bug/1814834.
# it is necessary for DPDK v18.08.
VIRTADDR_OPT=
if [[ -n "$BASE_VIRTADDR" ]]; then
VIRTADDR_OPT="--base-virtaddr $BASE_VIRTADDR"
fi
PRIMARY_BIN=$SPP_DIR/src/primary/${RTE_TARGET}/spp_primary
PRIMARY_CMD="$PRIMARY_BIN -c $SPP_PRIMARY_CORE_MASK -n 4 --socket-mem $SPP_PRIMARY_SOCKET_MEM --huge-dir $SPP_HUGEPAGE_MOUNT --proc-type primary $VIRTADDR_OPT -- -p $PORT_MASK -n $NUM_RING -s $SPP_CTL_IP_ADDR:$SPP_PRIMARY_SOCK_PORT"
iniset -sudo $unitfile "Unit" "Description" "Devstack $service"
iniset -sudo $unitfile "Service" "User" "root"
iniset -sudo $unitfile "Service" "ExecStart" "$PRIMARY_CMD"
}
function build_spp_vf_service() {
local sec_id=$1
local core_mask=$2
local service="spp_vf-$sec_id.service"
local unitfile="$SYSTEMD_DIR/$service"
SEC_BIN=$SPP_DIR/src/vf/${RTE_TARGET}/spp_vf
SEC_CMD="$SEC_BIN -c $core_mask -n 4 --proc-type secondary -- --client-id $sec_id -s $SPP_CTL_IP_ADDR:$SPP_SECONDARY_SOCK_PORT --vhost-client"
iniset -sudo $unitfile "Unit" "Description" "Devstack $service"
iniset -sudo $unitfile "Service" "User" "root"
iniset -sudo $unitfile "Service" "ExecStart" "$SEC_CMD"
}
function build_spp_mirror_service() {
local sec_id=$1
local core_mask=$2
local service="spp_mirror.service"
local unitfile="$SYSTEMD_DIR/$service"
SEC_BIN=$SPP_DIR/src/mirror/${RTE_TARGET}/spp_mirror
SEC_CMD="$SEC_BIN -c $core_mask -n 4 --proc-type secondary -- --client-id $sec_id -s $SPP_CTL_IP_ADDR:$SPP_SECONDARY_SOCK_PORT"
iniset -sudo $unitfile "Unit" "Description" "Devstack $service"
iniset -sudo $unitfile "Service" "User" "root"
iniset -sudo $unitfile "Service" "ExecStart" "$SEC_CMD"
}
function build_systemd_services() {
mkdir -p $SYSTEMD_DIR
build_spp_ctl_service
build_spp_primary_service
SEC_ID=1
MAPPINGS=${DPDK_PORT_MAPPINGS//,/ }
ARRAY=( $MAPPINGS )
for map in "${ARRAY[@]}"; do
mask=`echo $map | cut -f 4 -d "#"`
build_spp_vf_service $SEC_ID $mask
SEC_ID=$(( $SEC_ID + 1 ))
done
if [[ -n "$SPP_MIRROR" ]]; then
mask=`echo $SPP_MIRROR | cut -f 2 -d "#"`
build_spp_mirror_service $SEC_ID $mask
fi
# changes to existing units sometimes need a refresh
$SYSTEMCTL daemon-reload
$SYSTEMCTL enable spp_primary.service
for ((i=1; i<=${#ARRAY[@]}; i++)); do
$SYSTEMCTL enable spp_vf-$i.service
done
}
function start_spp_services() {
# make sure ASLR off.
# DPDK primary process and secondary processes must be same address layout.
# NOTE: this may not be necessary if you use DPDK v20.05 or later
# since a bug that let it be necessary was fixed in DPDK v20.05
# (see commit 7470f845c17a).
sudo sysctl -w kernel.randomize_va_space=0
# delete unnecessary files which were left by previous run.
sudo rm -rf /var/run/dpdk/rte
NUM_SEC=0
MAPPINGS=${DPDK_PORT_MAPPINGS//,/ }
ARRAY=( $MAPPINGS )
for map in "${ARRAY[@]}"; do
NUM_SEC=$(( $NUM_SEC + 1 ))
done
MIRROR_SUPPORT=0
if [[ -n "$SPP_MIRROR" ]]; then
MIRROR_SUPPORT=1
fi
sudo $NETWORKING_SPP_DIR/devstack/start-spp-services $NUM_SEC $MIRROR_SUPPORT $SPP_CTL_IP_ADDR:$SPP_API_PORT
}
function stop_systemd_services() {
stop_process q-spp-agt
$SYSTEMCTL stop spp_ctl.service
if [[ -n "$SPP_MIRROR" ]]; then
sudo systemctl stop spp_mirror.service
fi
MAPPINGS=${DPDK_PORT_MAPPINGS//,/ }
ARRAY=( $MAPPINGS )
for ((i=1; i<=${#ARRAY[@]}; i++)); do
$SYSTEMCTL stop spp_vf-$i.service
done
$SYSTEMCTL stop spp_primary.service
}
function prepare_tempest() {
# NOTE: DEFALUT_IMAGE_NAME must be specified in local.conf explicitly.
openstack flavor create "$DEFAULT_INSTANCE_TYPE" --ram 4096 --disk 20 --vcpus 2 --public --property hw:mem_page_size=large
if [ ! -e "$NETWORKING_SPP_DIR/devstack/image/image.qcow2" ]; then
$NETWORKING_SPP_DIR/devstack/image/build_image.sh $NETWORKING_SPP_DIR
fi
openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$DEFAULT_IMAGE_NAME" --public --container-format bare --disk-format qcow2 < $NETWORKING_SPP_DIR/devstack/image/image.qcow2
}
if [[ "$1" == "stack" ]]; then
case "$2" in
pre-install)
if [ "$SPP_MODE" != "controller" ]; then
spp_pre_install
clone_spp_dpdk
fi
;;
install)
if [ "$SPP_MODE" != "controller" ]; then
build_spp_dpdk
fi
pushd $NETWORKING_SPP_DIR
sudo $PYTHON setup.py install
popd
if [ "$SPP_MODE" != "controller" ]; then
prepare_spp_dpdk
fi
;;
post-config)
if [ "$SPP_MODE" != "controller" ]; then
configure_spp_agent
fi
configure_etcd
;;
extra)
if [ "$SPP_MODE" != "controller" ]; then
build_systemd_services
# start SPP services
start_spp_services
# start spp-agent
run_process q-spp-agt "$SPP_AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
fi
if [ "$SPP_MODE" == "controller" ]; then
if is_service_enabled tempest; then
prepare_tempest
fi
fi
;;
esac
elif [[ "$1" == "unstack" ]]; then
if [ "$SPP_MODE" != "controller" ]; then
stop_systemd_services
cleanup_spp_dpdk
unconfigure_spp_agent
#TODO: more cleanup ?
fi
fi