vpp


难度 中等

概述

VPP(Vector Packet Processing )(向量包处理)库。

VPP向量报文处理是与传统的标量报文处理相对而言的。传统报文处理方式,同时也是人类常用的逻辑思维方式,即:报文是按照到达先后顺序来处理,第一个报文处理完,处理第二个,依次类推;A callsB calls C….return return return,函数会频繁嵌套调用,并最终返回。

由此可见,传统标量报文处理有如下缺陷:

  1. I-cache 抖动(cache时间局限性和空间局限性特点)

  2. I-cache misses

  3. 除了扩大cache外,没有变更方案

相比较而言,向量报文处理则是一次处理多个报文,也相当于一次处理一个报文数组。VPP把一批底层硬件队列Rx ring收到的包,组成一个Packet Vector或者是一组包,借助于报文处理图Packet Processing graph来实现处理流程,图节点graph node把整个过程分解为一个个先后连接的服务node。这一组包(packet vector)被第一个graph node节点的任务处理,然后依次被第二个graph node节点的任务处理,依次类推。

向量报文处理解决了标量处理的主要性能缺陷,并有具有如下优点:

  1. 解决了I-cache抖动问题
  2. 向量报文进行预取缓解了读时延问题,高性能并且更加稳定

技术特色

  • 服务的易插件化

    VPP平台的图节点graph node组织方式,使用户可以根据需求,通过plugin方式插入新的图节点或者重新排列图节点,扩展非常方便,也不会影响原有核心处理流程。

  • 丰富的基础功能

    • ipv4
    • ipv6
  • 良好的扩展性

    VPP平台是通过graph node串联起来形成一条datapath来处理报文,类似于freebsd的netgraph。通过插件的形式引入新的graph node或者重新排列报文的graph node。将插件添加到插件目录中,运行程序的时候就会自动加载插件。另外插件也可以根据硬件情况通过某个node直接连接硬件进行加速。将插件添加到插件目录中,运行程序的时候就会自动加载插件。另外插件也可以根据硬件情况通过某个node直接连接硬件进行加速。VPP平台可以用于构建任何类型的报文处理应用。比如负载均衡、防火墙、IDS、主机栈。也可以是一个组合,比如给负载均衡添加一个vSwitch。

    通过创建插件,可以任意扩展如下功能:

    • 自定义新的graph node。
    • 重新排列graph node。
    • 添加底层API。

架构

源码架构

  • 基础架构层:包括vppinfra,vlib,svm和二进制api库
  • 通用网络协议栈层:vnet
  • 应用程序shell:vpp

编译

x86

  • openssl
./Configure linux-aarch64 --prefix=/home/duanyingshou/code/openssl/build_linux_native_x86/openssl shared
make -j 8
make install
  • dpdk
make config T=x86_64-native-linuxapp-gcc EXTRA_CFLAGS='-g -Ofast -fPIC -ftls-model=local-dynamic'
make T=x86_64-native-linuxapp-gcc  -j 8 EXTRA_CFLAGS='-g -Ofast -fPIC -ftls-model=local-dynamic' install 
  • vpp
export DPDK_PATH=/home/duanyingshou/code/dpdk/x86_64-native-linuxapp-gcc
#export OPENSSL_PATH=/home/duanyingshou/code/openssl/build_linux_native_x86/
export PLATFORM=vpp
make wipe
make build-release

arm64

  • openssl
export CC=aarch64-linux-gnu-gcc
#./Configure linux-aarch64 --prefix=/opt/cross/sysroots/x86_64-fslsdk-linux/usr shared
./Configure linux-aarch64 --prefix=/home/duanyingshou/code/openssl/build_linux_aarch64/openssl shared
make -j 8
make install
  • dpdk
export CROSS=aarch64-linux-gnu-
make config T=arm64-dpaa2-linuxapp-gcc
make T=arm64-dpaa-linuxapp-gcc install CONFIG_RTE_KNI_KMOD=n CONFIG_RTE_EAL_IGB_UIO=n -j 8
  • vpp

dpaa2

需要使用专门的交叉工具编译,交叉编译工具文件为fsl-qoriq-glibc-x86_64-fsl-toolchain-aarch64-toolchain-2.5.sh,使用如下命令安装:

fsl-qoriq-glibc-x86_64-fsl-toolchain-aarch64-toolchain-2.5.sh -d /opt/cross

若/opt/cross已存在该交叉编译工具无需安装。

注:暂时只能以该交叉工具编译vpp,且openssl、dpdk、vpp都需要以该工具链编译。

交叉编译工具链中包含的openssl库可以用来编译fastup,暂时先不用编译opens数量。

  • openssl
#编译openssl
git checkout OpenSSL_1_1_0g
export CROSS=/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-
export CC=aarch64-fsl-linux-gcc
#./Configure linux-aarch64 --prefix=/opt/cross/sysroots/x86_64-fslsdk-linux/usr shared
./Configure linux-aarch64 --prefix=/home/duanyingshou/code/openssl/build_linux_aarch64/ shared
make depend
make CC="/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-gcc --sysroot=/opt/cross/sysroots/aarch64-fsl-linux -fPIC" LD="/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-ld" AR="/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-ar rv " EXTRA_CFLAGS='-g -Ofast -fPIC -ftls-model=local-dynamic' -j 8
make install
  1. 编译时打包/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-ar失败

    解决方法添加rv参数

  2. 编译openssl成功,但在编译vpp时openssl报错找不到符号表

    解决方法添加LD=”/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-ld”

  • dpdk
# 编译dpdk
export CROSS=/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-
make config T=arm64-dpaa2-linuxapp-gcc CROSS=aarch64-fsl-linux- CROSS_COMPILE="aarch64-fsl-linux-" CC="/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-gcc --sysroot=/opt/cross/sysroots/aarch64-fsl-linux -fPIC -g"  EXTRA_CFLAGS='-g -Ofast -fPIC -ftls-model=local-dynamic'
make T=arm64-dpaa2-linuxapp-gcc CC="/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-gcc --sysroot=/opt/cross/sysroots/aarch64-fsl-linux -fPIC" EXTRA_CFLAGS='-g -Ofast -fPIC -ftls-model=local-dynamic' CONFIG_RTE_KNI_KMOD=n CONFIG_RTE_EAL_IGB_UIO=n install -j 8
# support kni
export CROSS=/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-
export RTE_KERNELDIR=/home/duanyingshou/linux
make config T=arm64-dpaa2-linuxapp-gcc CROSS=aarch64-fsl-linux- CROSS_COMPILE="aarch64-fsl-linux-"
CC="/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-gcc --sysroot=/opt/cross/sysroots/aarch64-fsl-linux -fPIC -g"  EXTRA_CFLAGS='-g -Ofast -fPIC -ftls-model=local-dynamic'
make T=arm64-dpaa2-linuxapp-gcc CC="/opt/cross/sysroots/x86_64-fslsdk-linux/usr/bin/aarch64-fsl-linux/aarch64-fsl-linux-gcc --sysroot=/opt/cross/sysroots/aarch64-fsl-linux -fPIC" EXTRA_CFLAGS='-g -Ofast -fPIC -ftls-model=local-dynamic -I/opt/cross/sysroots/aarch64-fsl-linux/usr/include' CONFIG_RTE_KNI_KMOD=y CONFIG_RTE_EAL_IGB_UIO=n install -j 32
  • vpp

修改vpp下的toolchain.cmake的20和21行如下:

set(CMAKE_C_COMPILER ${toolchain}/usr/bin/$ENV{CROSS_PREFIX}/$ENV{CROSS_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${toolchain}/usr/bin/$ENV{CROSS_PREFIX}/$ENV{CROSS_PREFIX}-g++)
#编译vpp
export PLATFORM=dpaa
export DPDK_PATH=/home/duanyingshou/code/dpdk/arm64-dpaa2-linuxapp-gcc
#export OPENSSL_PATH=/home/duanyingshou/code/openssl/build_linux_aarch64/
export CROSS_TOOLCHAIN=/opt/cross/sysroots/x86_64-fslsdk-linux
export CROSS_PREFIX=aarch64-fsl-linux
export CROSS_SYSROOT=/opt/cross/sysroots/aarch64-fsl-linux/
export PATH=$CROSS_TOOLCHAIN/bin:$CROSS_TOOLCHAIN/usr/bin/aarch64-fsl-linux:$PATH
cd build-root
make distclean
#TAG可以使用dpaa_debug,编译时不会优化,方便debug,详见 vpp/build-data/platforms/dpaa.mk
make V=0 PLATFORM=dpaa TAG=dpaa 

执行

vpp环境准备

  • 打包
# x86
cp ~/code/fastup_nxp/src/fastuplibs/libup/lib/x86/*  ~/code/fastup_nxp/build-root/install-vpp_debug-native/vpp/lib
cp ~/code/fastup_nxp/src/fastuplibs/libutils/lib/x86/* ~/code/fastup_nxp/build-root/install-vpp_debug-native/vpp/lib
cd ~/code/fastup_nxp/build-root/install-vpp_debug-native/
tar zcvf ~/package/vpp_x86.tar.gz vpp
# arm
cp ~/code/fastup_nxp/src/fastuplibs/libup/lib/arm64/*  ~/code/fastup_nxp/build-root/install-dpaa-aarch64/vpp/lib
cp ~/code/fastup_nxp/src/fastuplibs/libutils/lib/arm64/* ~/code/fastup_nxp/build-root/install-dpaa-aarch64/vpp/lib
cd ~/code/fastup_nxp/build-root/install-dpaa-aarch64/
tar zcvf ~/package/vpp_arm64.tar.gz vpp
  • 指明lib路径
# x86
export LD_LIBRARY_PATH=../lib
# dpaa2
export LD_LIBRARY_PATH=/mnt/emmc2/vpp/lib
export PATH=/mnt/emmc2/vpp/bin:$PATH

vpp可以通过配置文件startup.conf进行启动,startup.conf可配置插件等参数。

  • 配置
$ cat /etc/vpp/startup.conf
unix {
  interactive
}

api-trace {
  on
}
  • 启动

startup.conf实际配置如下

heapsize 256M
plugin_path /mnt/emmc2/vpp/lib/vpp_plugins

unix {
  interactive
  #nodaemon
  gid vpp
  log /tmp/vpp.log
  full-coredump
  cli-listen /run/vpp/cli.sock
  #startup-config /mnt/vpp/interface.txt
}

api-trace {
  on
}

api-segment {
  gid vpp
}

session {
  evt_qs_memfd_seg
}

socksvr {
  socket-name /tmp/vpp-api.sock
}

cpu {
  main-core 1
}

dpdk {
        ## Change default settings for all intefaces
        huge-dir /mnt/hugepages
        no-pci
        num-mem-channels 1
         dev default {
                ## Number of receive queues, enables RSS
                ## Default is 1
                num-rx-queues 1

                # rss { ipv4 }

                ## Number of transmit queues, Default is equal
                ## to number of worker threads or 1 if no workers treads
                num-tx-queues 1
  }
  proc-type primary
        #log-level  8
}

plugins {
        ## Adjusting the plugin path depending on where the VPP plugins are
        path /mnt/emmc2/vpp/lib/vpp_plugins
        vat-path /mnt/emmc2/vpp/lib/vpp_api_test_plugins

        plugin default { enable }
        plugin gtpu_plugin.so { disable }
        plugin fastgtpu_plugin.so { disable }

}
./dynamic_dpl.sh dpmac.4
groupadd -f -r vpp
vpp -c startup.conf
  • 配置
set int state TenGigabitEthernet0 up
set int ip address TenGigabitEthernet0 192.168.8.24/24
set int ip address TenGigabitEthernet0 192.168.9.24/24
set interface mac address TenGigabitEthernet0 42:4b:54:ae:6e:05
set int mtu 1500 TenGigabitEthernet0
set ip arp static TenGigabitEthernet0 192.168.8.25 90:e2:ba:8d:02:f0
vpp# show interface
              Name               Idx    State  MTU (L3/IP4/IP6/MPLS)     Counter          Count
TenGigabitEthernet0               1     down         9000/0/0/0
local0                            0     down          0/0/0/0
vpp#set int state TenGigabitEthernet0 up

配置详解

  • unix
  • api-trace
  • api-segment
  • socksvr
  • cpu
  • buffer
  • dpdk
  • plugins
  • statseg
  • heapsize

vpp插件机制

vpp通过插件机制来开发自定义node,进而实现用户定义的行为。一般情况下会在插件中加入一些node节点去实现相关功能

vpp node详解

vpp 把一个包的处理流程划分成多个阶段,每个阶段只做一部分处理工作,报文经过所有的阶段处理后完成报文的处理。一个阶段称为 node(中文叫做节点),即一个报文从某个口收上来后会经过一系列的 node 处理,然后从某个口发送出去。

node结构

node之间的关系

报文在节点之间转移方式:

  • 报文类型

    mac层将报文转到ipv4、ipv6

  • 预定义规则

各node组合成了一张图。

node类型

  • INTERNAl

    为 node 图中的 node

  • INPUT

    为 node 图提供报文输入的 node,这类 node 在收包线程中每次循环都被调用,比如收包node,每次循环都被调用以从网卡收包;

  • PRE_INPUT

    为在 INPUT 类型的 node 之前需要被调用的 node;

  • PORCESS

    为可以被挂起和重新被执行的 node。

    process 和一般的 node 相比具有以下特点:

    • 只能在 thread0 上执行,即在 main 核上执行,不能在 worker 线程上执行,多个 process 共享main 的时钟
    • 能被挂起和恢复执行,恢复执行的时候要从被挂起的地方接着执行,因此需要给 process 创建单独的栈用来在被挂起时保存现场,被恢复执行时恢复现场

node注册

node 的注册,即在 node 图中添加一个新的 node,vpp 提供宏 VLIB_REGISTER_NODE 用来注册node。

node调度

由于 process 本身的特点,process 和其他类型的 node 的调度方式不一样,实现上为两个不同的函数,分别为:dispatch_process 和 dispatch_node,但 node 使用统一的状态,只是各自有独立的 flags。

node有如下几种状态:

  • POLLING:轮询方式,每次循环都会被调度
  • INTERRUPT:中断方式,只有收到中断信号之后才会被调度
  • DISABLED:只有非 INTERNAL 类型的 node 才会设置该状态,如果设置了 DISABLE 状态表示不再会被调度

vpp与dpdk的关系

dpdk是vpp的一个插件,是vpp中的一个输入节点。负责从网卡接收包到vpp。

  • DPDK 的定位是基础组件, 提供的是基于X86平台的高效L2包转发方案. 这个方案包含一些最重要的底层组件,PMD/内存管理/初始化/etc.这些组件大多是为了使能硬件,优化硬件的用例.
  • VPP 的定位是解决方案. VPP 并不依赖特定的包转发框架, 当然在X86平台下, VPP集成DPDK的L2 包转发组件是一个明智选择.但VPP 更接近面向最终产品化的解决方案,尤其是对各类协议的支持更为完善. 调试框架,控制平面的接口都更加完备
  • DPDK支持 Run To Completation/Pipe Line 两种模型, 当然取决于开发者怎么使用
  • VPP 只支持 Run To Completation, 在IPSEC一些用例中会有比较难以处理的情况(e.g esn processing), 更加依赖网卡的 RSS功能
  • VPP 有Honeycomb这样的控制平面接口, 支持netconf/yang. 这个对于产品化是非常重要的.DPDK 没有对应的组件

reference

  1. https://www.sohu.com/a/134745174_468741
  2. https://www.cnblogs.com/mysky007/p/12348129.html
  3. https://turbock79.cn/?p=855
  4. https://blog.csdn.net/turbock/article/details/105076800
  5. https://zhuanlan.zhihu.com/p/28324999
  6. https://segmentfault.com/a/1190000019613730
  7. https://fd.io/docs/vpp/v2009/gettingstarted/users/configuring/startup.html
  8. https://www.cnblogs.com/sunnypoem/p/11368500.html
  9. http://www.manongjc.com/detail/10-hpsehamtgobvwtz.html

文章作者: growdu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 growdu !
  目录
分类导航
随笔3 AI29 计算机基础13 算法1 博客搭建7 ChatGPT2 集群63 计算机通信1 数据库59 数据库深入93 数据库93 Docker11 DPDK26 编辑工具4 Elasticsearch4 FAQ1 Go Web1 hometown2 编程语言16 人生11 网络9 Linux38 OPC1 openGauss4 页面12 PostgreSQL54 程序员自我修养1 协议11 stock1 存储5 成长之路1 工具20 视频作品1 VPP18 Vue13 Web1 代码示例11 BenchmarkSQL1 PostgreSQL 源码修炼之路14
最热文章
1
PostgreSQL 逻辑复制全链路:以一个真实事务为例,从 `INSERT` 到 `apply` 的源码级旅程
数据库🔥 2162
2
PostgreSQL 逻辑复制 Stream 执行逻辑源码级拆解:从 reorderbuffer 触发到订阅端落盘回放
数据库🔥 1765
3
PostgreSQL 行锁机制源码级深度拆解:4 种锁模式 + xmax + MultiXact 的完整链路
数据库🔥 1656
4
PostgreSQL reorderbuffer.c 函数级源码全集:5615 行 / 95 个函数的逐函数解析
数据库深入🔥 1650
5
PostgreSQL 目录快照源码级深度拆解:系统表读取的 MVCC 真相与失效机制
数据库🔥 1604
6
13 逻辑复制深入
数据库深入🔥 1570
7
0 Postgresql存储、索引及系统优化、主备切换
PostgreSQL🔥 1495
8
PostgreSQL 读一行数据源码级深度拆解:MVCC 在每个环节的落点
数据库🔥 1464
9
PostgreSQL WAL 记录类型完全指南:21 个 RMGR × 80+ 种记录的源码级拆解
数据库🔥 1431
10
一文读懂openguass dcf网络模块
集群🔥 1420
11
PostgreSQL 元数据存储机制:从磁盘文件到内存缓存,`pg_class` 撑起的整个系统表体系
数据库🔥 1411
12
openGauss 并行解码设计原理深度拆解:reader + 多 worker + CSN 三层架构的源码级剖析
数据库深入🔥 1344
13
逻辑复制源码分析
数据库深入🔥 1327
14
PostgreSQL 逻辑复制:catalog 改动、可见性判定与 xmin/xmax 推进全景
数据库深入🔥 1317
15
自托管服务全家桶:从原文方案到可复制实操手册
人生🔥 1278
16
PostgreSQL CREATE_REPLICATION_SLOT 端到端源码分析:从 SQL 到 snapbuild 状态机的完整链路(每个函数每个参数)
数据库深入🔥 1277
17
PostgreSQL syscache 模块源码深度拆解:CatCache 数据结构、LRU 哈希表、cache invalidation 全链路
数据库深入🔥 1216
18
PostgreSQL 18 内核数据结构全景:RangeVar 与 20+ 个核心数据结构源码级拆解
数据库🔥 1158
19
PostgreSQL 逻辑复制里 `RUNNING_XACTS` 写入机制与快照 `xmin / xmax / xip` 的演化:源码级深度拆解
数据库🔥 1119
20
PostgreSQL 分区表:从一行 `PARTITION BY` 到路由热路径的全链路拆解
数据库🔥 1094