基于DPDK的VPP 插件demo代码

2024-04-08 04:20
文章标签 代码 插件 vpp demo dpdk

本文主要是介绍基于DPDK的VPP 插件demo代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

VPP的插件编写, 首先要把VPP 工程下载下来, 编译通过。

然后按照example程序的套中来编写插件。

还有一个前提, 就是测试机上已经具备了DPDK 已经可用版本。

1. 下载VPP。

可以从github上下载VPP的指定版本的zip包, 

也可以用git clone的方式直接clone到linux虚拟机上。

git clone -b stable/1801 https://github.com/FDio/vpp.git
 

2. 编译VPP 。

电脑好的话, 半小时能build出来。 内存小可能要一晚上。

cd ./vpp

./extras/vagrant/build.sh && make
编译好后会在./vpp/build-root下出现以下.deb文件 。

安装以下几个即可:

$ dpkg –i vpp-lib_18.01.2-1~g9b554f3_amd64.deb
$ dpkg –i vpp_18.01.2-1~g9b554f3_amd64.deb
$ dpkg –i vpp-dev_18.01.2-1~g9b554f3_amd64.deb
$ dpkg –i vpp-plugins_18.01.2-1~g9b554f3_amd64.deb
 

3. (假设dpdk已经可以用了)

把一个网卡加入到dpdk进行托管。

首先查一下我们有几个网卡。ifconfig

暂时用eth2吧:

lspci |grep -i ethernet 

查看对应的pci 号,

root@ubuntu:/home/king/yubo/vpp/build-root# lspci |grep -i ethernet
02:01.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
02:06.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
03:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)
0b:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)

目前还不知道 哪个是eth2

我们先把eth2 down掉, 这样dpdk才能托管。

ifconfig eth2 down.

进入dpdk的设置:

export RTE_SDK=/home/bo/dpdk_learnd/dpdk-stable-19.08.2
export RTE_TARGET=x86_64-native-linux-gcc

cd $RTE_SDK
cd usertools
ifconfig eth2 down
./dpdk-setup.sh

先选 [43] 安装一下IGB_UIO

然后[48]查看目前可用的网口

可以看到 eth2的信息如下:

然后按【49 】 把eth2 绑定到igb_uio 驱动。

再按【48】确认已经绑定成功了。

Option: 48


Network devices using DPDK-compatible driver
============================================
0000:02:01.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' drv=igb_uio unused=e1000

Network devices using kernel driver
===================================
0000:02:06.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=eth3 drv=e1000 unused=igb_uio
0000:03:00.0 'VMXNET3 Ethernet Controller 07b0' if=eth0 drv=vmxnet3 unused=igb_uio *Active*
0000:0b:00.0 'VMXNET3 Ethernet Controller 07b0' if=eth1 drv=vmxnet3 unused=igb_uio *Active*

按【60】 退出DPDK

[60] Exit Script

Option: 60

4. DPDK 准备好了,现在设置VPP 初始化配置。

vi /etc/vpp/startup.conf

修改为以下:

unix {
  interactive cli-listen 127.0.0.1:5002
  nodaemon
  log /tmp/vpp.log
  full-coredump
  cli-listen /run/vpp/cli.sock
  gid vpp
}

api-trace {
  on
}

api-segment {
  gid vpp
}

cpu {

        main-core 0

}

 dpdk {
       

        uio-driver igb_uio
        dev 0000:02:01.0       
}

然后运行VPP 确认VPP 目前工具正常了。

modprobe uio

modprobe igb_uio

echo 4 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages

echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages

vpp -c /etc/vpp/startup.conf

启动vpp , 结果启动失败, 报以下错误

## Change UIO driver used by VPP, Options are: igb_uio, vfio-pci,114,2-968%:qroot@ubuntu:/home/king/yubo/dpdk_learnd/dpdk-stable-19.08.2/usertools# vpp -c /etc/vpp/startup.conf 
vlib_plugin_early_init:356: plugin path /usr/lib/vpp_plugins
load_one_plugin:184: Loaded plugin: acl_plugin.so (Access Control Lists)
load_one_plugin:184: Loaded plugin: dpdk_plugin.so (Data Plane Development Kit (DPDK))
load_one_plugin:184: Loaded plugin: flowprobe_plugin.so (Flow per Packet)
load_one_plugin:184: Loaded plugin: gtpu_plugin.so (GTPv1-U)
load_one_plugin:184: Loaded plugin: ila_plugin.so (Identifier-locator addressing for IPv6)
load_one_plugin:184: Loaded plugin: ioam_plugin.so (Inbound OAM)
load_one_plugin:114: Plugin disabled (default): ixge_plugin.so
load_one_plugin:184: Loaded plugin: kubeproxy_plugin.so (kube-proxy data plane)
load_one_plugin:184: Loaded plugin: l2e_plugin.so (L2 Emulation)
load_one_plugin:184: Loaded plugin: lb_plugin.so (Load Balancer)
load_one_plugin:184: Loaded plugin: libsixrd_plugin.so (IPv6 Rapid Deployment on IPv4 Infrastructure (RFC5969))
load_one_plugin:184: Loaded plugin: memif_plugin.so (Packet Memory Interface (experimetal))
load_one_plugin:184: Loaded plugin: nat_plugin.so (Network Address Translation)
load_one_plugin:184: Loaded plugin: pppoe_plugin.so (PPPoE)
load_one_plugin:184: Loaded plugin: stn_plugin.so (VPP Steals the NIC for Container integration)
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/pppoe_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/gtpu_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_vxlan_gpe_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/nat_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/lb_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/flowprobe_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/acl_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/udp_ping_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/stn_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/vxlan_gpe_ioam_export_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/dpdk_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/memif_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/kubeproxy_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_pot_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_export_test_plugin.so
load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_trace_test_plugin.so
dpdk_config:1240: EAL init args: -c 1 -n 4 --huge-dir /run/vpp/hugepages --file-prefix vpp -w 0000:02:06.0 -w 0000:02:01.0 --master-lcore 0 --socket-mem 64 
EAL: 1 hugepages of size 1073741824 reserved, but no mounted hugetlbfs found for that size
EAL: VFIO support initialized
EAL:   Invalid NUMA socket, default to 0
EAL: Error reading from file descriptor 15: Input/output error
EAL: Error reading from file descriptor 15: Input/output error

这是因为dpdk 在绑定对应 网卡后, 初始化时中断功能不支持导致的,

用lspci可以看下对应的网卡驱动。

正常显示为VMXNET3 的网卡是直接 可用于DPDK的。

上边两个82545EM的就不支持。

现在把对应的网卡改成VMXNET3的驱动试下。

把虚拟机的 xx.vmx 配置文件 从左改成右边的配置:

(把e1000都 改成vmxnet3)中间可能要重启下虚拟机和物理机。

再查询发现,已经全部变成vmxnet3的网卡了。

root@ubuntu:/home/# lspci|grep -i ethernet
03:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)
0b:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)
13:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)
1b:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01)

现在再重新把VPP的流程走一下。 从DPDK 绑定开始到启动VPP。

我去, 这下就起来了撒:

查看对应网口。

show int

这样就相当于VPP 可以工作了。quit 命令可以退出VPP。

5. 准备VPP 插件文件。

在vpp/src/plugins/目录新建一个文件 夹: pktdumpme

把pktdumpme.c pktdumpme.h pktdumpme_node.c 放到这个目录下。

修改vpp/src下的文件configure.ac , 增加以下这行:

修改plugins 文件 夹下的文件 Makefile.am为以下:

在plugins文件夹下新增pktdumpme.am


# Copyright (c) 2015 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.libpktdumpme_plugin_la_SOURCES =                        \pktdumpme/pktdumpme.c                   \pktdumpme/pktdumpme_node.cnoinst_HEADERS +=                               \pktdumpme/pktdumpme.hvppplugins_LTLIBRARIES += libpktdumpme_plugin.la# vi:syntax=automake

然后回到vpp 根目录下执行:

make wipe

make build    #编译新插件

make run     #deubg 模式启动VPP

这个时候可以看到,VPP 已经把我们新写的插件启动起来了。

我们现在可以看下能不能配置一个网口, 使能Pkt dumpme功能:

现在看, VPP 已经可以把192.168.100.200 这个口收到的报文打印出来了。

6. DEMO 已经成功了, 现在分享一下代码 。

pktdumpme.h  暂时不管内容, 先这么套吧

#ifndef __included_yb_sample_h
#define __included_yb_sample_h#include <vnet/vnet.h>
#include <vnet/ip/ip.h>#include <vppinfra/hash.h>
#include <vppinfra/error.h>
#include <vppinfra/elog.h>typedef struct {u16 msg_id_base; // ???, 这玩意儿也没有用啊vnet_main_t * vnet_main; // ???
} yb_sameple_main_t;extern yb_sameple_main_t yb_sameple_main;
extern vlib_node_registration_t yb_sample_node;#define YB_SAMPLE_PLUGIN_BUILD_VER "1.0" #endif

pktdumpme.c

这个文件 主要是注册插件功能,主要涉及4 层信息:

VLIB, VNET, PLUGIN, CLI_command. 

#include <vnet/plugin/plugin.h>
#include <pktdumpme/pktdumpme.h>yb_sameple_main_t yb_sameple_main;static clib_error_t * yb_sample_command_ena_disa_fn(vlib_main_t *vm, unformat_input_t * input,vlib_cli_command_t * cmd) // not use 
{// need parse 2 argument, interface index and enable flagint interfaceIdx = -1;int enableFlag = 1; // default on// traverse all input stringswhile(unformat_check_input(input) != UNFORMAT_END_OF_INPUT){if(unformat(input, "disable")){enableFlag = 0;}else if(unformat(input, "%U", unformat_vnet_sw_interface, yb_sameple_main.vnet_main, &interfaceIdx)) // 应该是看这个输入是某一个网口, 是的话把Index存到 变量中。 后边再看下。{;			}elsebreak;}if(-1 == interfaceIdx)return clib_error_return(0, "please specify a right interface name.\n");//开始对相应接口进行设置。if(pool_is_free_index(yb_sameple_main.vnet_main->interface_main.sw_interfaces, interfaceIdx))return 0;// 调用库函数操作这个nodevnet_feature_enable_disable("ip4-unicast", "yb_sample", interfaceIdx, enableFlag, 0, 0);return 0;}// 命令行注册
VLIB_CLI_COMMAND(yb_sample_command, static)=
{.path = "pkt dumpme",.short_help = "pkt dumpme <interface-name> [disable]",.function = yb_sample_command_ena_disa_fn,
};// plugin注册
VLIB_PLUGIN_REGISTER() =
{.version = YB_SAMPLE_PLUGIN_BUILD_VER,.description = "yb sample hello world", 
};// 设置VLIB 初始化函数
static clib_error_t * yb_sample_init(vlib_main_t* vm)
{yb_sameple_main.vnet_main = vnet_get_main();return 0;
}VLIB_INIT_FUNCTION(yb_sample_init);// pktdump功能要用到网络相关的功能 , 所以要配置一下当前plugin要在nvet的指定位置运行。
// 指定yb_sample node的初始化参数, 应该是在arc "ip4-unicast" 下, node名字为 yb-sample, 
// 运行在ip4-lookup node之前。后边会指定ip4-lookup为next node中的[0]
VNET_FEATURE_INIT(yb_sample, static) =   
{.arc_name = "ip4-unicast",.node_name = "yb_sample",.runs_before = VNET_FEATURES("ip4-lookup"),
};

pktdumpme_node.c

这个就是实现报文回显的主要代码: 从frame中取出所有的packet vectore, 然后进行打印, 然后再push到下一frame中的buffer中。 这里ip4_lookup 就是下一个Node. 这个是VPP 自带的Node, 以后慢慢会熟悉。 另外关于push到下一个node还是下一个frame, 我觉得应该是一个意思, 以后学习深入了应该能确认。 注释有可能不准备, 读者自行消化,彼人也是第一次弄。

#include <vlib/vlib.h>
#include <vnet/vnet.h>
#include <vnet/pg/pg.h>
#include <vnet/ethernet/ethernet.h>
#include <vppinfra/error.h>
#include <pktdumpme/pktdumpme.h>typedef enum
{CK_SAMPLE_NEXT_IP4,CK_SAMPLE_DROP,CK_SAMPLE_NEXT_N,
} yb_sample_next_t;typedef struct
{u32 next_index;u32 sw_if_index;u8 new_src_mac[6];u8 new_dst_mac[6];
} yb_sample_trace_t;#define foreach_yb_sample_error \
_(SHOWED, "show packets processed")typedef enum
{
#define _(sym,str) SAMPLE_ERROR_##sym,foreach_yb_sample_error
#undef _SAMPLE_N_ERROR,
} yb_ssample_error_t;static char *yb_sample_error_strings[] = {
#define _(sym, str) str,foreach_yb_sample_error
#undef _
};// extern vlib_node_registration_t yb_sample_node; // 不打开 能编译过
static u8 *
format_yb_sample_trace (u8 * s, va_list * args)
{s = format(s, "To Do!\n");return s;
}// 定义打印报文的主函数
static uword yb_sample_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
{u32 n_left_in_frame, *thisDataStart, *nextNodeDataStart;u16 nextNodeIndex = 0;// 取出当前node 的数据的位置(在from中), 有多少个数据。thisDataStart = vlib_frame_vector_args(frame);n_left_in_frame = frame->n_vectors;nextNodeIndex   = node->cached_next_index;// 取出默认下一node index.// 解析所有的数据, 并push到下一个Node[0]中。while(n_left_in_frame > 0){u32 n_left_in_next;//先获取下一NODE 可以存数的信息, start, Nvlib_get_next_frame(vm, node, nextNodeIndex, nextNodeDataStart, n_left_in_next);while(n_left_in_frame > 0 && n_left_in_next > 0){// 把index指向的buffer, 转为m_buff, 然后解析, 再Push给下一node。vlib_buffer_t *bp0;u32 bi0, nextNode = 0;bi0 = thisDataStart[0];nextNodeDataStart[0] = thisDataStart[0];n_left_in_frame -= 1;n_left_in_next  -= 1;thisDataStart     += 1;nextNodeDataStart += 1;bp0 = vlib_get_buffer(vm, bi0);void* data = vlib_buffer_get_current(bp0);{   int i;for(i = 0; i <32; i++){printf("%02x ", *((u8*)data + i));}printf("\n");}vlib_validate_buffer_enqueue_x1(vm, node, nextNodeIndex, nextNodeDataStart, n_left_in_next, bi0, nextNode);}vlib_put_next_frame(vm, node, nextNodeIndex, n_left_in_next); // 应该是理解为next frame 不是next node.或者说node和frame是一对一的。}// 返回处理了多少个数据。return frame->n_vectors;  // 一定要返回这个吗?
}// 注册node.
VLIB_REGISTER_NODE(yb_sample_node) = 
{.name = "yb_sample",.function = yb_sample_node_fn,.vector_size = sizeof(u32),.format_trace = format_yb_sample_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors = ARRAY_LEN(yb_sample_error_strings),.error_strings = yb_sample_error_strings,.n_next_nodes = 2,.next_nodes = {[0] = "ip4-lookup",[1] = "error-drop",},
};

至此, 第一个demo 插件就完成了。

这篇关于基于DPDK的VPP 插件demo代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/884552

相关文章

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

D4代码AC集

贪心问题解决的步骤: (局部贪心能导致全局贪心)    1.确定贪心策略    2.验证贪心策略是否正确 排队接水 #include<bits/stdc++.h>using namespace std;int main(){int w,n,a[32000];cin>>w>>n;for(int i=1;i<=n;i++){cin>>a[i];}sort(a+1,a+n+1);int i=1

Maven(插件配置和生命周期的绑定)

1.这篇文章很好,介绍的maven插件的。 2.maven的source插件为例,可以把源代码打成包。 Goals Overview就可以查看该插件下面所有的目标。 这里我们要使用的是source:jar-no-fork。 3.查看source插件的example,然后配置到riil-collect.xml中。  <build>   <plugins>    <pl

jenkins 插件执行shell命令时,提示“Command not found”处理方法

首先提示找不到“Command not found,可能我们第一反应是查看目标机器是否已支持该命令,不过如果相信能找到这里来的朋友估计遇到的跟我一样,其实目标机器是没有问题的通过一些远程工具执行shell命令是可以执行。奇怪的就是通过jenkinsSSH插件无法执行,经一番折腾各种搜索发现是jenkins没有加载/etc/profile导致。 【解决办法】: 需要在jenkins调用shell脚

Jenkins 插件 地址证书报错问题解决思路

问题提示摘要: SunCertPathBuilderException: unable to find valid certification path to requested target...... 网上很多的解决方式是更新站点的地址,我这里修改了一个日本的地址(清华镜像也好),其实发现是解决不了上述的报错问题的,其实,最终拉去插件的时候,会提示证书的问题,几经周折找到了其中一遍博文

html css jquery选项卡 代码练习小项目

在学习 html 和 css jquery 结合使用的时候 做好是能尝试做一些简单的小功能,来提高自己的 逻辑能力,熟悉代码的编写语法 下面分享一段代码 使用html css jquery选项卡 代码练习 <div class="box"><dl class="tab"><dd class="active">手机</dd><dd>家电</dd><dd>服装</dd><dd>数码</dd><dd