dpdk网络转发环境的搭建

news2024/10/2 14:27:58

文章目录

    • 前言
    • ip命令的使用
    • 配置dpdk-basicfwd需要的网络结构
    • 测试dpdk-basicfwd
    • dpdk-basicfwd代码分析
    • 附录
      • basicfwd在tcp转发时的失败抓包信息
      • DPDK的相关设置

前言

上手dpdk有两难。其一为环境搭建。被绑定之后的网卡没有IP,我如何给它发送数据呢?当然,可以通过网桥将一个正常的网卡和被绑定的网卡互相连接。但对于日常写demo实验中,这并不方便。本文尝试用vire-pair来避免使用硬件网桥,使用namespace来隔离网络。其二是,关于端口初始化。我没有搞清楚每个选项设置的必然原因,但是这里会列出端口初始化的基本流程。

最后验证,借助Basic Forwarding Sample Application — Data Plane Development Kit 23.11.0 documentation可以将网络上不相连接两个端口,可以互相ping通。但是在验证tcp转发的时候,抓包显示tcp checksum incorrect。相关报错循序见后文。此事必有蹊跷。

注:本文验证网络转发的代码来自dpdk/examples/skeleton at main · DPDK/dpdk。我将它移动到该仓库目录中。


ip命令的使用

在组建虚拟网络结构之前,我们需要先了解IP命令的使用。参考自:

  1. ip 命令 - Router Lab 实验文档
  2. ip(8) - Linux man page

ip命令的总体组成如下。

ip [ OPTIONS ] OBJECT { COMMAND | help }

OBJECT := { link | addr | addrlabel | route | rule | neigh | tunnel | maddr | mroute | monitor }

OPTIONS := { -V[ersion] | -s[tatistics] | -r[esolve] | -f[amily] { inet | inet6 | ipx | dnet | link } | -o[neline] }

ip address - protocol address management.

每个设备必须有一个IP地址,才能使用对应的协议(IPV4/IPV6)。可以通过ip address help查看使用方法。

# 列出所有网口信息和地址信息
ip address show

# 设置网络
ip addr add $addr/$prefix_len dev $interface

ip link - network device configuration

使用ip link来显示和修改网络设备的状态。具体使用方法,可以通过help查看。

# 查看设备状态
ip link show

# 创建两个虚拟以太网设备,它们之间直接相连
## ref: https://man7.org/linux/man-pages/man4/veth.4.html
### 在一对设备中的一个设备上传输的数据包会立即在其他设备上收到。当任一设备出现故障时,该对的链路状态为关闭。
### 这两个veth可以处在不同的网络命名空间中
## 如果有天希望三个veth可以互通,这似乎有点麻烦,我还没搞明白:https://superuser.com/questions/764986/howto-setup-a-veth-virtual-network
## 这里还有篇veth-pair配置的不错的介绍:https://www.cnblogs.com/bakari/p/10613710.html
ip link add $name1 type veth peer name $name2

ip route - routing table management.

操纵路由表。

# 查看路由表
ip route show

配置dpdk-basicfwd需要的网络结构

了解了ip命令的基本使用后,我们来配置下dpdk-basicfwd所需的网络结构。网络中包含:两对veth-pair, 其中veth1和veth2互连,veth3和veth4互连; veth1在名为nsA的namespace中; veth4在名为nsB的namespace中; dpdk-basicfwd将veth2收到的流量转发到veth3,veth3收到的流量转发到veth2; 网络总体结构图如下所示:

在这里插入图片描述

下面我们按照上图所示,进行网络创建。

先设置一对虚拟以太网卡,并设置IP/mask。注意此时这两者无法互相ping通,但是可以通过lo口互通的,见: Linux 虚拟网络设备 veth-pair 详解,看这一篇就够了 - bakari - 博客园

ip link add veth1 type veth peer name veth2
ip link set veth1 up
ip link set veth2 up
ip address add 10.0.0.2/24 dev veth1
ip address add 10.0.0.3/24 dev veth2

#测试下上面的配置是否可以联通。
## -l表示listen; -s表示veth2在80开启监听端口; 
## -k表示处理完一个连接后继续监听新的连接,而不是退出
#nc -k -l -s 10.0.0.3 -p 80

## 从10.0.0.2发出流量到10.0.0.3:80 端口
#echo "hello world" |  nc -s 10.0.0.2 -w 1 10.0.0.3 80

接着,我们再设置另一对虚拟以太网。

ip link add veth3 type veth peer name veth4
ip link set veth3 up
ip link set veth4 up
ip address add 172.16.0.2/24 dev veth3
ip address add 172.16.0.3/24 dev veth4

为了避免veth1和veth4通过lo口进行通信。将veth1和veth4放在不同的namespace中。

# 添加两个命名空间
ip netns add nsA
ip netns add nsB

# 将veth1加入命名空间nsA; 需要重写进行网卡信息的配置
## 此时veth1能ping通veth2了
ip link set veth1 netns nsA
ip netns exec nsA  /bin/bash
ip link set veth1 up
ip address add 10.0.0.2/24 dev veth1
ping 10.0.0.3

# 将veth4加入命名空间nsB; 然后进入命名空间,设置ip并启用
## 此时veth4能ping通veth3了
ip link set veth4 netns nsB
ip netns exec nsB  /bin/bash
ip link set veth4 up
ip address add 172.16.0.3/24 dev veth4
ping 172.16.0.2

端口配置后,还需要设置下路由:在nsA中,让访问veth4的流量,从veth1端口走。在nsB中,让访问veth1的流量,从veth4端口走。

# nsB中
ip netns exec nsB  /bin/bash
ip route add 10.0.0.2 dev veth4
# tcpdump -nn -vv -l -i veth4
# nc -k -l -s 172.16.0.3 -p 80

# nsA中
ip netns exec nsA  /bin/bash
ip route add 172.16.0.3 dev veth1
# ping 172.16.0.3
# echo "hello world" |  nc -s 10.0.0.2 -w 5 172.16.0.3 80

最终的结果:

  • veth1和veth2可以通过veth-pair跨namespcae通信。
  • veth3和veth4可以通过veth-pair跨namespcae通信。
  • 但是veth1和veth2由于不在同一个namespace,又没有veth-pair,所以相互之间无法通信。

测试dpdk-basicfwd

为什么--vdev这个参数可以呢,它是什么原理?我也不知道,照葫芦画瓢参考自:odp-dpdk/platform/linux-dpdk/README at master · OpenDataPlane/odp-dpdk

./dpdk-skeleton -l 1 -n 4 --vdev "eth_pcap0,iface=veth2" --vdev "eth_pcap1,iface=veth3"

在这里插入图片描述


dpdk-basicfwd代码分析

200行的代码,很快就能看完一遍。具体的API使用见官方文档,这里简述下流程。

首先是内存池和cpu相关的初始化,这个和存储架构相关。大体知道知道这些含义即可:NUMA node > socket > core > logical processor。相关内容见:CPU 拓扑:从 SMP 谈到 NUMA (理论篇) | 猿大白

接着是端口相关的初始化,简单的基本流程是:查看当前端口的信息->对端口进行配置->设置总共的接收/发送描述符数->每个队列可以使用的接收/发送描述符数。这部分的结构可能是这样的。

在这里插入图片描述

然后就是转发。从一个端口接收到数据,然后让另一个端口发送这部分数据。


附录

basicfwd在tcp转发时的失败抓包信息


# nsB中启动监听
nc -l -s 172.16.0.3 -p 80

# nsA中发起请求
echo "hello world" |  nc -s 10.0.0.2 -w 5 172.16.0.3 80

# nsB中抓包信息
## 可以看到 cksum 0xb643 (incorrect -> 0xfc92)
tcpdump -nn -vv -l -i veth4
tcpdump: listening on veth4, link-type EN10MB (Ethernet), capture size 262144 bytes
22:24:39.112851 IP (tos 0x0, ttl 64, id 21121, offset 0, flags [DF], proto TCP (6), length 60)
    10.0.0.2.38177 > 172.16.0.3.80: Flags [S], cksum 0xb643 (incorrect -> 0xfc92), seq 2659543870, win 64240, options [mss 1460,sackOK,TS val 3763804890 ecr 0,nop,wscale 7], length 0
22:24:40.136180 IP (tos 0x0, ttl 64, id 21122, offset 0, flags [DF], proto TCP (6), length 60)
    10.0.0.2.38177 > 172.16.0.3.80: Flags [S], cksum 0xb643 (incorrect -> 0xf893), seq 2659543870, win 64240, options [mss 1460,sackOK,TS val 3763805913 ecr 0,nop,wscale 7], length 0
22:24:42.232702 IP (tos 0x0, ttl 64, id 21123, offset 0, flags [DF], proto TCP (6), length 60)
    10.0.0.2.38177 > 172.16.0.3.80: Flags [S], cksum 0xb643 (incorrect -> 0xf05f), seq 2659543870, win 64240, options [mss 1460,sackOK,TS val 3763808013 ecr 0,nop,wscale 7], length 0
22:24:44.140469 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.16.0.3 tell 10.0.0.2, length 28
22:24:44.140480 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.16.0.3 is-at 8a:06:58:68:ec:d8, length 2

DPDK的相关设置

绑定网卡

ip命令创建的虚拟以太网卡,dpdk-devbind.py是无法绑定的。如果绑定真实的网卡,需要先有驱动,然后进行绑定。

# 包管理器方式下载驱动
## ubuntu
sudo apt install dpdk-igb-uio-dkms

# 源码编译的方式生成驱动
# 编译igb_uio驱动; 在wsl中会编译失败,需要在linux环境中编译
git clone git://dpdk.org/dpdk-kmods
cd dpdk-kmods/linux 
make

# 绑定网卡
## 先停止网卡
ip link set enp0s3  down
## 然后安装驱动模块
modprobe igb_uio
## 然后绑定网卡
./dpdk-devbind.py --bind=igb_uio enp0s3
## 查看绑定后的信息
./dpdk-devbind.py --status

dpdk源码编译

关于编译参数,自行参考官方手册和源码。

git clone git@github.com:DPDK/dpdk.git

# 初学还是不要直接用dev分支的代码比较好。
## 我踩了一个坑:ALLOW_EXPERIMENTAL_API这个宏,在dev中是默认开启的,但是在发布的tag中是关闭的
git checkout v23.11

# cpu_instruction_set还是设置为corei7吧。
## 如果不设置这个选项,在dev分支中,debug版本调试的时候,会出现crash,提示指令相关的报错
meson setup -Dcpu_instruction_set=corei7 -Dbuildtype=debug -Dexamples=all -Dprefix=/home/dacao/work/3rdlib/dpdk build
cd build
ninja 
ninja install

在cmake中链接dpdk库

自行编写的dpdk程序链接dpdk库的时候,要加上--whole-archive。否则不会将pmd相关的库不会打包到程序中。在CmakeLists中使用pkgconfig, 不会带上--whole-archive这个参数。原因我不知道到。我还没有去查阅pkgconfig的文件格式和cmake对其的使用。可以使用下面的配置。

cmake_minimum_required(VERSION 3.11)

project(dpdk-skeleton)

# arch的参数和编译dpdk时的cpu_instruction_set参数保持一致
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=corei7")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=corei7")

find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBDPDK REQUIRED libdpdk)
include_directories(${LIBDPDK_STATIC_INCLUDE_DIRS})
# link_directories(${LIBDPDK_STATIC_LIBRARY_DIRS})
# message(STATUS "LIBDPDK_STATIC_LIBRARIES: ${LIBDPDK_STATIC_LIBRARIES}")
# message(STATUS "LIBDPDK_STATIC_INCLUDE_DIRS: ${LIBDPDK_STATIC_INCLUDE_DIRS}")
message(STATUS "LIBDPDK_LIBDIR: ${LIBDPDK_LIBDIR}")

add_custom_target(compress_dpdk_libraries
    COMMAND rm -rf libdpdks.a
    COMMAND sh -c "ar crsT libdpdks.a ./librte*.a"
    WORKING_DIRECTORY ${LIBDPDK_LIBDIR}
    COMMENT "Compressing static libraries"
)

find_library(M_LIB m)
add_library(libdpdk STATIC IMPORTED GLOBAL)
add_dependencies(libdpdk compress_dpdk_libraries)
set_target_properties(libdpdk PROPERTIES
    IMPORTED_LOCATION ${M_LIB}
    INTERFACE_LINK_LIBRARIES "-Wl,--whole-archive;${LIBDPDK_LIBDIR}/libdpdks.a;-Wl,--no-whole-archive;rt;m;numa;fdt;atomic;mlx5;ibverbs;crypto;z;jansson;mlx4;pcap;isal;elf;pthread;dl;bsd"
)

add_executable(${PROJECT_NAME} basicfwd.c)
target_link_libraries(${PROJECT_NAME} PRIVATE libdpdk)

多台虚拟机之间组网

上面是在一台虚拟机中进行组网测试。如果不想这么做,想让两台虚拟机之间的网卡通过网桥互连。可以参考下面的做法(应该可行,但是我没测试过):不同组的网卡使用不同名称的网络适配器机进行网络隔离。

  • 在VirtualBox上搭建DPDK数据包转发运行环境 - 黑牛2008的个人空间 - OSCHINA - 中文开源技术交流社区
  • dpdk l3fwd/l2fwd实验-CSDN博客
  • 2.VMware三种网络模式 - certainTao - 博客园

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1402246.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动物免疫(羊驼免疫)-泰克生物

在过去几十年里,抗体研究和应用的领域已经经历了革命性的变化。在这个进程中,一种特殊来源的抗体 —— 来自骆驼科动物(包括羊驼)的单链抗体(也称纳米抗体)引起了全球科学家的广泛关注。 羊驼等骆驼科动物…

vectorCast添加边界值分析测试用例

1.1创建项目成功后会自动生成封装好的函数,在这些封装好的函数上点击右键,添加边界值分析测试用例,如下图所示。 1.2生成的用例模版是不可以直接运行的,需要我们分别点击它们,让它们自动生成相应测试用例。如下图所示,分别为变化前和变化后。 1.3点击选中生成的测试用例,…

家庭教育小知识青春期孩子如何教育?

孩子进入青春期后,很多家长都纷纷感叹,与孩子相处太难了。那个曾经乖巧、黏人的孩子,好像一夜之间浑身长满刺,变得叛逆、敏感、暴躁、将父母拒之门外、甚至是辱骂、羞辱父母。 让父母更挫败的是,曾经通过说教、讲道理…

sqlmap使用教程(1)

一、sqlmap简介 sqlmap是一个自动化SQL注入测试工具,它支持的数据库有MySQL、MSSQL、Oracle、PostgreSQL、Access、IBM DB2、SQLite、Firebird、Sybase和SAP MaxDB。sqlmap默认使用以下5种SQL注入技术: 基于布尔的盲注:根据返回页面判断条件…

flink基本概念

1. Flink关键组件: 这里首先要说明一下“客户端”。其实客户端并不是处理系统的一部分,它只负责作业的提交。具体来说,就是调用程序的 main 方法,将代码转换成“数据流图”(Dataflow Graph),并最终生成作业…

Kotlin 尾递归函数

函数式编程中,重要的概念 尾递归: 当一个函数 在最后调用 自身,称为 尾递归,是一种特殊的递归函数。 Kotlin 使用 tailrec 声明尾递归函数,可以避免 StackOverflowError 的风险。 原理是:通过编译器优化 …

BACnet网关BL121BN 实现稳定可靠、低成本、简单的楼宇自控协议BACnet转OPC UA解决方案

随着楼宇自控系统的迅猛发展,人们深刻认识到在楼宇暖通行业中,实时、可靠、安全的数据传输至关重要。在此背景下,高性能的楼宇暖通数据传输解决方案——协议转换网关应运而生,广泛应用于楼宇自控和暖通空调系统应用中。 钡铼技术…

Linux:动静态库的概念制作和底层工作原理

文章目录 动静态库基础认知动静态库基本概念静态库的制作库的概念包的概念 静态库的使用第三方库小结 动态库的制作动态库的使用动态库如何找到内容?小结 动态库加载库和程序都要加载可执行程序的地址问题地址问题逻辑地址和平坦模式绝对编址和相对编址与位置无关码…

Lombok工具包

Lombok已经集成springboot项目中因此在依赖中引入Lombok不需要指定版本号。 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId> </dependency> Lombok中各种注释的含义

51单片机电子密码锁Proteus仿真+程序+视频+报告

目录 视频 设计分析 系统结构 仿真图 资料内容 资料下载地址&#xff1a;51单片机电子密码锁Proteus仿真程序视频报告 视频 单片机电子密码锁Proteus仿真程序视频 设计分析 (1)能够从键盘中输入密码&#xff0c;并相应地在显示器上显示‘*’&#xff1b; (2)能够判断密码…

什么是碳结算电能表?

引言 近年来&#xff0c;我国加速推进碳达峰碳中和标准计量体系建设&#xff0c;但随着各地区、各领域、各行业对碳排放核算数据的需求显著提升&#xff0c;当前碳排放核算体系数据更新偏慢、核算口径不一、基础排放因子滞后等一系列问题也开始凸显。新形势下对碳排放统计核算…

Android OpenGL EGL使用——自定义相机

如果要使用OpenGl来自定义相机&#xff0c;EGL还是需要了解下的。 可能大多数开发者使用过OpengGL但是不知道EGL是什么&#xff1f;EGL的作用是什么&#xff1f;这其实一点都不奇怪&#xff0c;因为Android中的GlSurfaceView已经将EGL环境都给配置好了&#xff0c;你一直在使用…

【机器学习】调配师:咖啡的完美预测

有一天&#xff0c;小明带着一脸期待找到了你这位数据分析大师。他掏出手机&#xff0c;屏幕上展示着一份详尽的Excel表格。“看&#xff0c;这是我咖啡店过去一年的数据。”他滑动着屏幕&#xff0c;“每个月的销售量、广告投入&#xff0c;还有当月的气温&#xff0c;我都记录…

踏上职业征程的第一步——选择理想城市迎接大学生求职新起点

概要&#x1f481;&#x1f3fb; "嘿&#xff0c;这个话题我早就想聊聊了。感觉现在好多同学在找工作时&#xff0c;签约和工作地点的选择都有点盲目。很少有人主动考虑自己喜欢哪个城市&#xff0c;所以我想说说这个。当然&#xff0c;纯属个人看法&#xff0c;大家随便吐…

模型的 PSI(Population Stability Index)

PSI&#xff08;Population Stability Index&#xff09;是一种用于评估两个数据集或时间点之间的分布变化的指标。它常用于监测模型在不同时间段或不同群体上的稳定性。PSI的计算基于两个分布的累积分布函数&#xff08;CDF&#xff09;之间的差异。 在模型监测和评估的背景下…

Django(九)

1. 用户登录-Cookie和Session 什么是cookie和session&#xff1f; 发送HTTP请求或者HTTPS请求(无状态&短连接) http://127.0.0.1:8000/admin/list/ https://127.0.0.1:8000/admin/list/http无状态短连接&#xff1a;一次请求响应之后断开连接&#xff0c;再发请求重新连…

Keepalived实现nfs高可用

Keepalived实现nfs高可用 Nfs_master服务器&#xff1a;172.20.26.167 &#xff08;keepalived、nfs、sersync、rsync&#xff09; Nfs_salve服务器&#xff1a;172.20.26.198 &#xff08;keepalived、nfs、rsync&#xff09; Nfs_client服务器&#xff1a;172.20.26.24 …

LeetCode面试题05.06

美好的一天&#xff0c;从力扣开始 王子公主请看题 整数转换。编写一个函数&#xff0c;确定需要改变几个位才能将整数A转成整数B。 示例1: 输入&#xff1a;A 29 &#xff08;或者0b11101&#xff09;, B 15&#xff08;或者0b01111&#xff09;输出&#xff1a;2示例2: 输…

Python爬虫--5

1、异步爬虫 异步爬虫的方式&#xff1a; &#xff08;1&#xff09;多线程&#xff0c;多进程&#xff08;不建议使用&#xff09; 好处&#xff1a;可以为相关阻塞的操作单独开启线程或者进程&#xff0c;阻塞操作就可以异步执行。 弊端&#xff1a;无法无限制的开启多线程…

Docker安装配置OnlyOffice

OnlyOffice 是一款强大的办公套件&#xff0c;你可以通过 Docker 轻松安装和部署它。本文将指导你完成安装过程。 步骤 1&#xff1a;拉取 OnlyOffice Docker 镜像 首先&#xff0c;使用以下命令从 Docker Hub 拉取 OnlyOffice Document Server 镜像&#xff1a; sudo docke…