dpdk版本、网卡驱动版本、网卡固件版本、网卡型号之间有着强依赖的关系。特别是一些新网卡,容易出现一些版本不匹配的问题。我们可以先通过ethtool -i eth0命令和lspci -vvv -s [bus-info] | grep -i product命令来查看网卡的型号和固件版本。然后到mlx官网查看ofed各版本支持的网卡型号,如ofed-5.0只支持较低版本的cx6 dx固件。
对于cx6 dx网卡,建议还是使用ofed-5.4版本,不然可能会出现各种各样的问题。确定好ofed版本之后,再去dpdk官网确定dpdk版本即可。特别需要注意的是dpdk-19.11开始支持cx6 dx网卡,所以如果用小于19.11的版本部署在cx6网卡上,dpdk将无法接管网卡。
所以理论上,cx6 dx网卡搭配ofed-5.4和dpdk19.11就可以了,但是实际上咨询过mlx官方人员,建议ofed-5.4搭配dpdk-20.11使用,可能是19.11有一些bug吧。dpdk-20.11编译方式跟之前的版本差别挺大的,20.11编译需要使用meson和ninja,meson需要python3.5以上的版本,3.7当然也可以,我准备使用python3.7,由于线上环境复杂,我想实现一个自动化脚本,可以从python3开始自动化编译dpdk,实现过程中遇到了很多坑,在这里记录一下。
- 编译python3.7.8之后,使用pip3会报pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available,原因是python3.7和低版本的openssl不兼容,需要更新openssl到1.1以上
- 安装新版本的openssl后,执行openssl version报version `OPENSSL_1_1_1’ not found (required by openssl),原因是openssl动态库找不到了,需要将LD_LIBRARY_PATH重新指向新编译的openssl库。
- 编译python3.7之前,需要安装apt-get install libffi-dev,否则python3后面使用的时候会报No module named ‘_ctypes’ when using Value from module multiprocessing
#! /bin/bash
set -x
DPDK_VERSION=20.11.1
HOME_DIR=/root/
DPDK_XZ=dpdk-${DPDK_VERSION}.tar.xz
DPDK_TAR=dpdk-${DPDK_VERSION}.tar
DPDK_DIR=dpdk-stable-${DPDK_VERSION}
OPENSSL_TAR=OpenSSL_1_1_1d.tar.gz
OPENSSL_DIR=openssl-OpenSSL_1_1_1d
PY3_VERSION=3.7.8
PY3_XZ=Python-${PY3_VERSION}.tar.xz
PY3_TAR=Python-${PY3_VERSION}.tar
PY3_DIR=Python-${PY3_VERSION}
log_path="/var/log/build.log"
function logger() {
local msg=$1
local DATE=`date +"%F %T"`
echo -e "[DPDK] ${DATE}: ${msg}" >> ${log_path}
echo "[DPDK] ${DATE}: ${msg}"
}
function download_pkg() {
# 可以把安装包上传到公司内部的存储服务器上
}
function install_openssl() {
download_pkg ${OPENSSL_TAR}
cd ${HOME_DIR}
yes | rm -f ${OPENSSL_DIR}
tar zxvf ${OPENSSL_TAR}
cd ${OPENSSL_DIR}
./config --prefix=/usr/local/openssl
make && make install
yes | mv /usr/bin/openssl /usr/bin/openssl.old
yes | mv /usr/lib64/openssl /usr/lib64/openssl.old
yes | mv /usr/lib64/libssl.so /usr/lib64/libssl.so.old
ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl
ln -s /usr/local/openssl/include/openssl /usr/include/openssl
ln -s /usr/local/openssl/lib/libssl.so /usr/lib64/libssl.so
echo "/usr/local/openssl/lib" >> /etc/ld.so.conf
ldconfig -v
echo "export LD_LIBRARY_PATH=/usr/local/openssl/lib:$LD_LIBRARY_PATH" >> ~/.bashrc
export LD_LIBRARY_PATH=/usr/local/openssl/lib:$LD_LIBRARY_PATH
openssl_v=`openssl version | grep OpenSSL | awk '{print $2}'`
if [[ ${openssl_v} != "1.1.1d" ]]; then
logger "install openssl failed"
exit 1
fi
}
function install_py3() {
openssl_v=`openssl version | grep OpenSSL | awk '{print $2}'`
if [[ ${openssl_v} < "1.1.1d" ]]; then
logger "openssl is older than 1.1.1d"
install_openssl
else
logger "openssl is newer than 1.1.1d"
fi
download_pkg ${PY3_XZ}
apt-get install -y libffi-dev
cd ${HOME_DIR}
xz -d ${PY3_XZ}
tar -xf ${PY3_TAR}
cd ${PY3_DIR}
yes | mv /usr/local/bin/python3 /usr/local/bin/python3.bak
yes | mv /usr/local/bin/pip3 /usr/local/bin/pip3.bak
./configure --prefix=/usr/local/python3.7 --with-openssl=/usr/local/openssl
make && make install
ln -s /usr/local/python3.7/bin/python3 /usr/local/bin/python3
ln -s /usr/local/python3.7/bin/pip3 /usr/local/bin/pip3
pip3 install pyelftools
py3_version=`/usr/local/python3.7/bin/python3 -V | grep 'Python' | awk '{print $2}'`
if [[ ${py3_version} == "3.7.8" ]]; then
logger "install py3 success"
else
logger "install py3 fail"
exit 1
fi
}
function install_ninja_meson() {
pip3 install meson
yes | mv /usr/local/bin/meson /usr/local/bin/meson.bak
ln -s /usr/local/python3.7/bin/meson /usr/local/bin/meson
pip3 install ninja
yes | mv /usr/local/bin/ninja /usr/local/bin/ninja.bak
ln -s /usr/local/python3.7/bin/ninja /usr/local/bin/ninja
}
function install_dpdk() {
cd ${HOME_DIR}
download_pkg ${DPDK_XZ}
cd ${HOME_DIR}
yes | rm -rf ${DPDK_DIR}
xz -d ${DPDK_XZ}
tar -xf ${DPDK_TAR}
cd ${DPDK_DIR}
meson build --prefix=/root/dpdk-stable-20.11.1/mydpdk -Denable_kmods=true
ninja -C build install
echo "/root/dpdk-stable-20.11.1/mydpdk/lib/x86_64-linux-gnu/" >> /etc/ld.so.conf
/sbin/ldconfig
}
function main() {
py3_version=`/usr/local/bin/python3 -V | grep 'Python' | awk '{print $2}'`
if [[ ${py3_version} < "3.7.0" ]]; then
logger "py3 version older than 3.7.0"
install_py3
fi
apt-get install -y libnuma-dev build-essential
install_ninja_meson
install_dpdk
}
main
遇到的很多坑其实还是python3.7的环境问题,估计使用python3.5的话问题会少很多。秉承着用新不用旧的原则,本来还想编译dpdk-22-11的,但是遇到了更负责的环境问题,只好作罢。果然,在使用开源软件方面,还是要用老的稳定版本,这样坑就少一些。事实上cx6 dx网卡使用dpdk-19.11也可以,19版本可以使用make编译,在我的环境上会简单很多。只需要解压后,修改config/common_base,打开mlx5编译开关:CONFIG_RTE_LIBRTE_MLX5_PMD=y,执行make install T=x86_64-native-linuxapp-gcc -j16编译dpdk就可以了。
编译dpdk前其实还有些前置步骤,就是安装ofed和配置大页内存,在我的debian操作系统中我也实现了自动化,安装ofed就不谈了,主要是在安装完后需要执行rm -rf /lib/udev/rules.d/82-net-setup-link.rules再重启,不然网卡名会变;配置大业内存的脚本如下,仅供参考,不建议使用。
function update_grub() {
MEM=$(cat /proc/meminfo |grep MemTotal |awk '{print $2}')
mem=$((${MEM} / 1024 / 1024))
threshold=$((${mem} / 2))
if [ ${threshold} -gt "64" ]; then
hugepages=64
else
hugepages=${threshold}
fi
GRUB_LINE=`grep '^GRUB_CMDLINE_LINUX_DEFAULT' /etc/default/grub`
grub_line=`echo ${GRUB_LINE} | awk -F '"' '{print $2}'`
logger "grub_line: ${grub_line}"
g_default_hugepagesz=`echo ${grub_line} | awk -F 'default_hugepagesz=' '{print $2}' | awk '{print $1}'`
if [ -n ${g_default_hugepagesz} ]; then
sed -i "s/default_hugepagesz=${g_default_hugepagesz}//" /etc/default/grub
fi
g_hugepagesz=`echo ${grub_line} | awk -F 'hugepagesz=' '{print $2}' | awk '{print $1}'`
if [ -n ${g_hugepagesz} ]; then
sed -i "s/hugepagesz=${g_hugepagesz}//" /etc/default/grub
fi
g_hugepages=`echo ${grub_line} | awk -F 'hugepages=' '{print $2}' | awk '{print $1}'`
if [ -n ${g_hugepages} ]; then
sed -i "s/hugepages=${g_hugepages}//" /etc/default/grub
fi
grub_line=`grep '^GRUB_CMDLINE_LINUX_DEFAULT' /etc/default/grub | awk -F '"' '{print $2}'`
new_line="default_hugepagesz=1G hugepagesz=1G hugepages=${hugepages}G"
sed -i "s/${grub_line}/${grub_line} ${new_line}/g" /etc/default/grub
/usr/sbin/update-grub
}
由于安装ofed后配置大页内存之后,需要重启机器,所以建议使用ansible playbook来实现完整的自动化部署,playbook脚本中可以通过notify handler wait_for_connection来控制机器重启,具体就不赘述了,谷歌即可。