这个sample是基于basicfw的。basicfw就是一个网口收到的包立即从另一个网口转发出去,非常简洁明了的程序,可以通过basicfw学习基础的DPDK发包API。RX / TX Callbacks 演示在接收和传输的数据包上使用用户定义的回调函数。

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2015 Intel Corporation
*/ #include <stdint.h>
#include <inttypes.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_cycles.h>
#include <rte_lcore.h>
#include <rte_mbuf.h> #define RX_RING_SIZE 1024
#define TX_RING_SIZE 1024 #define NUM_MBUFS 8191
#define MBUF_CACHE_SIZE 250
#define BURST_SIZE 32 static const struct rte_eth_conf port_conf_default = {
.rxmode = {
.max_rx_pkt_len = ETHER_MAX_LEN,
.ignore_offload_bitfield = 1,
},
}; static struct {
uint64_t total_cycles;
uint64_t total_pkts;
} latency_numbers; /* 回调函数的函数指针的格式设定:
一、rx
typedef uint16_t(* rte_rx_callback_fn)(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], uint16_t nb_pkts, uint16_t max_pkts, void *user_param)
参数:
1. port id
2. queue index
3. 接收的 burst pkt 所存放的 rte_mbuf 的数组
4. burst 中数据包的数量
5. 可以存储在pkts数组中的最大数据包数。
6. 最初配置回调时应用程序传入的任意用户参数 二、tx
typedef uint16_t(* rte_tx_callback_fn)(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[], uint16_t nb_pkts, void *user_param)
参数:
1. port id
2. queue index
3. rte_mbuf的数组,里面的pkt即将被发送
4. burst 中数据包的数量
5. 最初配置回调时应用程序传入的任意用户参数
*/ // rx 队列的回调函数,添加接收时刻的时间戳
static uint16_t
add_timestamps(uint16_t port __rte_unused, uint16_t qidx __rte_unused,
struct rte_mbuf **pkts, uint16_t nb_pkts,
uint16_t max_pkts __rte_unused, void *_ __rte_unused)
{
unsigned i;
uint64_t now = rte_rdtsc(); // 用来获取时间戳计数器。 for (i = 0; i < nb_pkts; i++)
pkts[i]->udata64 = now; // 8字节用户数据
return nb_pkts;
} // tx 队列的回调函数,发送时计算时延
static uint16_t
calc_latency(uint16_t port __rte_unused, uint16_t qidx __rte_unused,
struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused)
{
uint64_t cycles = 0;
uint64_t now = rte_rdtsc();
unsigned i; for (i = 0; i < nb_pkts; i++)
cycles += now - pkts[i]->udata64; // 在main.c中的全局struct中记录收到的包数量和总时延
latency_numbers.total_cycles += cycles;
latency_numbers.total_pkts += nb_pkts; if (latency_numbers.total_pkts > (100 * 1000 * 1000ULL)) { // 每十亿个包计算平均时延
printf("Latency = %"PRIu64" cycles\n",
latency_numbers.total_cycles / latency_numbers.total_pkts);
latency_numbers.total_cycles = latency_numbers.total_pkts = 0;
}
return nb_pkts;
} /*
* Initialises a given port using global settings and with the rx buffers
* coming from the mbuf_pool passed as parameter
*/
static inline int
port_init(uint16_t port, struct rte_mempool *mbuf_pool)
{
/*......*/
/*上面的部分和basicfw是一摸一样的*/ /* rte_eth_add_rx_callback() 这个API设定一个回调函数,特定 port id 和 rx queue index上每个收到的pkt(burst)都会进行突发调用。 参数四个:
1. port id
2. queue index
3. 回调函数的函数指针
4. 传递给回调函数的参数指针 返回值是一个指针,可以用于删除回调的API rte_eth_add_tx_callback()就是为 tx queue 上的发包配置回调函数。
*/ // 回调函数指针有统一的 typedef rte_eth_add_rx_callback(port, 0, add_timestamps, NULL);
rte_eth_add_tx_callback(port, 0, calc_latency, NULL); return 0;
} /*
* Main thread that does the work, reading from INPUT_PORT
* and writing to OUTPUT_PORT
*/ // lcore_main 与 basicfw 完全一样。
static __attribute__((noreturn)) void
lcore_main(void)
{
/*......*/
} /* Main function, does initialisation and calls the per-lcore functions */ // main 函数也与 basicfw 一样。
int
main(int argc, char *argv[])
{
/*......*/
}

执行情况

开了之后运行了一会,得到了输出。应该开一个外部的发包器比较好。

root@ubuntu:/home/chang/dpdk/examples/rxtx_callbacks/build# ./rxtx_callbacks -l 1 -n 4
EAL: Detected 8 lcore(s)
EAL: No free hugepages reported in hugepages-1048576kB
EAL: Multi-process socket /var/run/.rte_unix
EAL: Probing VFIO support...
EAL: PCI device 0000:02:01.0 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 8086:100f net_e1000_em
EAL: PCI device 0000:02:02.0 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 8086:100f net_e1000_em
EAL: PCI device 0000:02:03.0 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 8086:100f net_e1000_em
EAL: PCI device 0000:02:04.0 on NUMA socket -1
EAL: Invalid NUMA socket, default to 0
EAL: probe driver: 8086:100f net_e1000_em
Port 0 MAC: 00 0c 29 f7 4d 25
Port 1 MAC: 00 0c 29 f7 4d 2f Core 1 forwarding packets. [Ctrl+C to quit]
Latency = 629 cycles
Latency = 787 cycles
^C

参考

sample guide:https://doc.dpdk.org/guides/sample_app_ug/rxtx_callbacks.html

API:ethdev, mbuf

DPDK RX / TX Callbacks 源码阅读的更多相关文章

  1. 【原】SDWebImage源码阅读(三)

    [原]SDWebImage源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1.SDWebImageDownloader中的downloadImageWithURL 我们 ...

  2. ng2048源码阅读

    ng2048源码阅读 Tutorial: http://www.ng-newsletter.com/posts/building-2048-in-angularjs.html Github: http ...

  3. jQuery.Callbacks 源码解读二

    一.参数标记 /* * once: 确保回调列表仅只fire一次 * unique: 在执行add操作中,确保回调列表中不存在重复的回调 * stopOnFalse: 当执行回调返回值为false,则 ...

  4. 【 js 基础 】【 源码学习 】backbone 源码阅读(一)

    最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...

  5. Spring源码阅读笔记

    前言 作为一个Java开发者,工作了几年后,越发觉力有点不从心了,技术的世界实在是太过于辽阔了,接触的东西越多,越感到前所未有的恐慌. 每天捣鼓这个捣鼓那个,结果回过头来,才发现这个也不通,那个也不精 ...

  6. Pytorch版本yolov3源码阅读

    目录 Pytorch版本yolov3源码阅读 1. 阅读test.py 1.1 参数解读 1.2 data文件解析 1.3 cfg文件解析 1.4 根据cfg文件创建模块 1.5 YOLOLayer ...

  7. Flume-NG源码阅读之SourceRunner,及选择器selector和拦截器interceptor的执行

    在AbstractConfigurationProvider类中loadSources方法会将所有的source进行封装成SourceRunner放到了Map<String, SourceRun ...

  8. Sping学习笔记(一)----Spring源码阅读环境的搭建

    idea搭建spring源码阅读环境 安装gradle Github下载Spring源码 新建学习spring源码的项目 idea搭建spring源码阅读环境 安装gradle 在官网中下载gradl ...

  9. Spring源码阅读 之 配置的读取,解析

    在上文中我们已经知道了Spring如何从我们给定的位置加载到配置文件,并将文件包装成一个Resource对象.这篇文章我们将要探讨的就是,如何从这个Resouce对象中加载到我们的容器?加载到容器后又 ...

随机推荐

  1. PHP代码优化—array_push

    PHP中数组插入数据通常有这么几种: 定义的时候直接赋值 $arr = array('apple', 'banana'); 使用数组变量操作 $arr = array(); $arr[] = 'app ...

  2. 深入虚拟内存(Virtual Memory,VM)

    我们应该知道物理内存(Physical Memory)指的是硬件上的内存,即 RAM.它通常指的是插在主板上的内存条,给进程提供临时数据存储的设备.因为 CPU 可以直接从物理内存中读取数据和指令,所 ...

  3. VB6 red write DB using Microsoft DAO 3.6 Object Library

    ' -----------------------------read db Private Sub Form_Load() 'MsgBox App.Path & "\wgscd.m ...

  4. 关于DFS与BFS

    DFS(深度优先搜索)   为无向图 DFS的过程类似于树的先序遍历. 请看图: DFS此图的过程为: 1.首先任意找一个未被便利过的顶点,例如从V1开始,由于率先访问了它,所以需要标记V1即已经访问 ...

  5. P4284 [SHOI2014]概率充电器

    P4284 [SHOI2014]概率充电器 今天上课讲到的题orz,第一次做这种上下搞两次dp的题. g[i]表示i的子树(包括i)不给i充电的概率. f[i]表示i的父亲不给i充电的概率. g[]可 ...

  6. 【SoDiaoEditor电子病历编辑器更新啦】--谨以献给那些还在医疗行业奋斗的小伙伴们

    为什么推荐的人这么少~~~~   更新(2017-4-18): 截止目前已知的已有2个三甲医院在使用该编辑器,容我内心澎湃以下,O(∩_∩)O哈哈~   先放github地址:https://gith ...

  7. STM8S——Flash program memory and data EEPROM

    1.简介 STM8S内部的FLASH程序存储器和数据EEPROM是由一组通用寄存器来控制的:所以我们可以通过这些通用寄存器来编程或擦除存储器的内容.设置写保护.或者配置特定的低功耗模式.我们也可以自己 ...

  8. Session里存的密码或其他信息如何获取。

    1.首先找到登陆界面,看给session里存的是什么,是以什么格式去存的(个人这边是commonAction): 2.其次在需要的界面进行获取,拿出想要的密码或其余值.(密码可能是加密过的,如想做密码 ...

  9. curl命令实现上网认证登录

    为了想让组里的服务器连外网下数据,需要命令行上网登录.与很多高校的上网方式一样,大气所上网采用的是用户帐号登录验证的方法.上网需要需要先开浏览器,然后打开网页输入帐号密码登录.参考了前人的一些帖子,最 ...

  10. 怎样注册Docker Hub账号

    Docker Hub是Docker的远程镜像仓库,类似于GitHub;如果没有搭建本地私有仓库,Docker会默认去Docker Hub拉镜像. 访问Docker Hub官网https://hub.d ...