dpdk网络转发环境的搭建

文章目录

    • 前言
    • 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 - 博客园

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

全国各省市上市公司数量数据,Shp、excel格式,含上市企业数量、行政区划中心点位经纬度等字段

基本信息. 数据名称: 全国各省市上市公司数量数据 数据格式: Shp、excel 数据时间: 2023年1月 数据几何类型: 面 数据坐标系: WGS84 数据来源:网络公开数据 数据字段: 序号字段名称字段说明1province省份名称2provin_dm省份代码3city城市名…

学习CANopen --- [12] Abort报文

当我们使用SDO进行读写操作时,有时device会返回abort报文,意味着本次SDO读写失败。本文使用例子来讲解Abort报文,以及如何解读失败原因。 一 Device例子 下面是device的python代码,文件名叫device.py,device的CANopen…

02. VBA从入门到精通——基础语法

数据类型 常用数据类型 Integer:整数,-32,768到32,767之间的整数 Long:较长长整数,-2,147,483,648到2,147,483,647之间的整数 Single:浮点数,它可以存储大约:6到7位小数的精度。 Double:较长浮…

免费的WordPress插件大全

在当今数字化的时代,拥有一个强大的在线存在变得至关重要。而对于使用WordPress建站的用户来说,插件是提高网站功能的关键。在这篇文章中,我们将为您推荐三款免费的WordPress插件,它们不仅是147SEO软件中的佼佼者,而且…

【Leetcode】接雨水(双指针、单调栈)

目录 &#x1f4a1;题目描述 &#x1f4a1;双指针解法 &#x1f4a1;单调栈解法 &#x1f4a1;题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 提示&#xff1a; n height.length1 < n…

this.$set的用法

作用&#xff1a; 在data里面绑定的数据具有响应式的效果,也就是我们说的V-Model 数据更新视图,视图也能更新数据&#xff0c;如果不是data里面的数据如何添加响应式呢&#xff1f; this.$Set这个方法能够实现 用法&#xff1a; this.$Set(要添加的对象,要添加的属性’,要添…

为什么C++17要引入std::string_view?

目录 1.引言 2.原理分析 2.1.结构 2.2.构造函数 2.3.成员函数 2.4.std::string_view字面量 3.实例 3.1.std::string_view和std::string的运算符操作 3.2.查找函数使用 3.3.std::string_view和临时字符串 4.总结 1.引言 在C/C日常编程中&#xff0c;我们常进行数据的…

Offer必备算法_双指针_八道力扣OJ题详解(由浅到深)

目录 双指针算法原理 ①力扣283. 移动零 解析代码 ②力扣1089. 复写零 解析代码 ③力扣202. 快乐数 解析代码 ④力扣11. 盛最多水的容器 解析代码 ⑤力扣611. 有效三角形的个数 解析代码 ⑥剑指 Offer 57. 和为s的两个数字 解析代码&#xff1a; ⑦力扣15. 三数之…

最通俗易懂的JVM内存管理与对象创建原理

前言 对于Java程序员来说&#xff0c;在虚拟机自动内存管理机制的帮助下&#xff0c;不再需要像 C/C程序为每一个new操作去写配对 的delete/free代码&#xff0c;不容易出现内存泄漏和内存溢出问题。也正是因为Java程序员把控制内存的权力交给了Java虚拟机&#xff0c;一旦出现…

SpringMVC基础知识学习笔记

Universe Infinity Inc. 目录 一、学习SpringMVC主要是学什么1、SpringMVC的基本原理2、SpringMVC学习串联 二、快速体验SpringMVC的开发1、新建项目&#xff0c;转成web项目2、引入依赖3、编写Spring的配置类4、配置web启动类&#xff0c;替代web.xml5、编写Handler&#xff…

都在卷鸿蒙开发,那就推荐 几个鸿蒙开源项目

如果要问2024年最火的技术是什么,那鸿蒙开发必须占据一些位置,HarmonyOS是华为自主研发的物联网操作系统,自2019年8月正式发布以来便受到了广大开发者的追崇。为了方便大家学习鸿蒙开发,本文分享 12 个开源的鸿蒙实战项目,希望能从这些项目中获得启发和实用经验。 小狐浏…

IDEA的database使用

一、数据据库 在使用database之前&#xff0c;首先你的电脑要安装好了数据库并且启动。 MySQL卸载手册 链接&#xff1a;https://pan.baidu.com/doc/share/AVXW5SG6T76puBOWnPegmw-602323264797863 提取码&#xff1a;hlgf MySQL安装图解 链接&#xff1a;https://pan.baidu.…

Win10/11中VMware Workstation设置网络桥接模式

文章目录 一、添加VMware Bridge Protocol服务二、配置桥接参数1.启用系统Device Install Service服务2.配置VMware 需要确认物理网卡是否有添加VMware Bridge Protocol服务 添加VMware Bridge Protocol服务 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参…

艾比森的“增长炼金术”:从四力驱动到三层面增长

在技术驱动的LED显示行业&#xff0c;产品迭代快、周期波动大&#xff0c;企业经营时时承压。 但是&#xff0c;市场上总不乏打破“传统”的个例。根据2023年业绩预告&#xff0c;艾比森预计2023年实现归母净利润3.10亿-3.50亿元&#xff0c;同比增长52.70%-72.40%&#xff1b…

HttpServletRequest getServerPort()、getLocalPort() 、getRemotePort() 区别

getRemotePort() 、getServerPort()、getLocalPort() request.getServerPort()、request.getLocalPort() 和 request.getRemotePort() 这三个方法都是获取与HTTP请求相关的端口信息的 客户端(如浏览器)通过某个随机分配的网络连接端口(7070) 向服务器发送HTTP请求( http://exam…

【Docker】未来已来 | Docker技术在云计算、边缘计算领域的应用前景

欢迎来到英杰社区&#xff1a; https://bbs.csdn.net/topics/617804998 欢迎来到阿Q社区&#xff1a; https://bbs.csdn.net/topics/617897397 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff…

[小程序]向服务器上传图片和从服务器下载图片

本例的服务器基于flask&#xff0c;配置flask可以参见[Flask]上传多个文件到服务器https://blog.csdn.net/weixin_37878740/article/details/128435136?ops_request_misc%257B%2522request%255Fid%2522%253A%2522170581653516800185854860%2522%252C%2522scm%2522%253A%252220…

【iOS】UICollectionView的基本使用

使用UITableView作为表格来展示数据完全没有问题&#xff0c;但仍有许多局限性&#xff0c;对于一些更加复杂的布局样式&#xff0c;就有些力不从心了 比如&#xff0c;UITableView只允许表格每一行只能显示一个cell&#xff0c;而不能在一行中显示多个cell&#xff0c;对于这…

项目管理该考哪个证书❓NPDP还是软考❓

有小伙伴在纠结是要考NPDP认证呢还是考软考呢❓ 今天小编要给大家好好说说NPDP认证❗️ &#x1f4a1;NPDP全称New Product Development Professional&#xff0c;也就是产品经理国际资格认证。 &#x1f525;NPDP是国际公认的为一的新产品开发专业认证&#xff0c;是集理论、方…

【神经网络】火箭点火发射-诠释一场数据与学习的奇妙之旅

火箭点火发射来理解神经网络的故事细节 在一个充满科技气息的研究室里&#xff0c;一群科学家们正在忙碌地准备着一次重要的火箭点火发射。这次发射不仅是一次航天探索的壮丽征程&#xff0c;更是一场利用神经网络处理数据的智慧之旅。 在火箭发射的背后&#xff0c;神经网络…