目录

main.c


The RX/TX Callbacks sample application is a packet forwarding application that demonstrates the use of user defined callbacks on received and transmitted packets. The application performs a simple latency check, using callbacks, to determine the time packets spend within the application.
In the sample application a user defined callback is applied to all received packets to add a timestamp. A separate callback is applied to all packets prior to transmission to calculate the elapsed time, in CPU cycles.

RX / TX回调示例应用程序是一个数据包转发应用程序,它演示了在接收和发送的数据包上用户定义的回调的使用。 应用程序使用回调执行简单的延迟检查,以确定数据包在应用程序中花费的时间。
在示例应用程序中,将用户定义的回调应用于所有接收到的数据包以添加时间戳。 在传输之前,将单独的回调应用于所有数据包,以计算经过的时间(以CPU周期为单位)。

勘误

# make CC main.o
/opt/dpdk-20.05/examples/rxtx_callbacks-rt/main.c:223:24: 错误:expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attrib
ute__’ before ‘void’ static  __rte_noreturn void^
编译因为 -Wfatal-errors 而中止。
make[1]: *** [main.o] 错误 1
make: *** [all] 错误 2

添加

#ifndef __rte_noreturn
#define __rte_noreturn __attribute__((noreturn))
#endif

或者include对应头文件。

main.c

/* SPDX-License-Identifier: BSD-3-Clause* Copyright(c) 2010-2015 Intel Corporation*/
//RX / TX回调示例应用程序是一个数据包转发应用程序,
//它演示了在接收和发送的数据包上用户定义的回调的使用。
//应用程序使用回调执行简单的延迟检查,以确定数据包在应用程序中花费的时间。
//在示例应用程序中,将用户定义的回调应用于所有接收到的数据包以添加时间戳。
//在传输之前,将单独的回调应用于所有数据包,以计算经过的时间(以CPU周期为单位)。#include <stdint.h>
#include <inttypes.h>
#include <getopt.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 32static const char usage[] ="%s EAL_ARGS -- [-t]\n";static const struct rte_eth_conf port_conf_default = {.rxmode = {.max_rx_pkt_len = RTE_ETHER_MAX_LEN,},
};static struct {uint64_t total_cycles;uint64_t total_queue_cycles;uint64_t total_pkts;
} latency_numbers;int hw_timestamping;#define TICKS_PER_CYCLE_SHIFT 16
static uint64_t ticks_per_cycle_mult;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;return nb_pkts;
}static uint16_t
calc_latency(uint16_t port, uint16_t qidx __rte_unused,struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused)
{/* 计算时延 */uint64_t cycles = 0;uint64_t queue_ticks = 0;uint64_t now = rte_rdtsc();uint64_t ticks;unsigned i;if (hw_timestamping)rte_eth_read_clock(port, &ticks);for (i = 0; i < nb_pkts; i++) {cycles += now - pkts[i]->udata64;if (hw_timestamping)queue_ticks += ticks - pkts[i]->timestamp;}latency_numbers.total_cycles += cycles;if (hw_timestamping)latency_numbers.total_queue_cycles += (queue_ticks* ticks_per_cycle_mult) >> TICKS_PER_CYCLE_SHIFT;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);if (hw_timestamping) {printf("Latency from HW = %"PRIu64" cycles\n",latency_numbers.total_queue_cycles/ latency_numbers.total_pkts);}latency_numbers.total_cycles = 0;latency_numbers.total_queue_cycles = 0;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)
{struct rte_eth_conf port_conf = port_conf_default;const uint16_t rx_rings = 1, tx_rings = 1;uint16_t nb_rxd = RX_RING_SIZE;uint16_t nb_txd = TX_RING_SIZE;int retval;uint16_t q;struct rte_eth_dev_info dev_info;struct rte_eth_rxconf rxconf;struct rte_eth_txconf txconf;if (!rte_eth_dev_is_valid_port(port))return -1;retval = rte_eth_dev_info_get(port, &dev_info);if (retval != 0) {printf("Error during getting device (port %u) info: %s\n",port, strerror(-retval));return retval;}if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)port_conf.txmode.offloads |=DEV_TX_OFFLOAD_MBUF_FAST_FREE;/* 如果有时间戳选项 */if (hw_timestamping) {if (!(dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TIMESTAMP)) {printf("\nERROR: Port %u does not support hardware timestamping\n", port);return -1;}port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_TIMESTAMP;}/* 配置设备 */retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);if (retval != 0)return retval;/* 调控 */retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd);if (retval != 0)return retval;rxconf = dev_info.default_rxconf;/* 初始化接收队列 */for (q = 0; q < rx_rings; q++) {retval = rte_eth_rx_queue_setup(port, q, nb_rxd,rte_eth_dev_socket_id(port), &rxconf, mbuf_pool);if (retval < 0)return retval;}txconf = dev_info.default_txconf;txconf.offloads = port_conf.txmode.offloads;/* 初始化发送队列 */for (q = 0; q < tx_rings; q++) {retval = rte_eth_tx_queue_setup(port, q, nb_txd,rte_eth_dev_socket_id(port), &txconf);if (retval < 0)return retval;}/* 启动网卡 */retval  = rte_eth_dev_start(port);if (retval < 0)return retval;/* 如果时间戳开启 */if (hw_timestamping && ticks_per_cycle_mult  == 0) {uint64_t cycles_base = rte_rdtsc();uint64_t ticks_base;retval = rte_eth_read_clock(port, &ticks_base);if (retval != 0)return retval;rte_delay_ms(100);uint64_t cycles = rte_rdtsc();uint64_t ticks;rte_eth_read_clock(port, &ticks);uint64_t c_freq = cycles - cycles_base;uint64_t t_freq = ticks - ticks_base;double freq_mult = (double)c_freq / t_freq;printf("TSC Freq ~= %" PRIu64"\nHW Freq ~= %" PRIu64"\nRatio : %f\n",c_freq * 10, t_freq * 10, freq_mult);/* TSC will be faster than internal ticks so freq_mult is > 0* We convert the multiplication to an integer shift & mult*/ticks_per_cycle_mult = (1 << TICKS_PER_CYCLE_SHIFT) / freq_mult;}struct rte_ether_addr addr;/* 获取MAC地址并输出 */retval = rte_eth_macaddr_get(port, &addr);if (retval < 0) {printf("Failed to get MAC address on port %u: %s\n",port, rte_strerror(-retval));return retval;}printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",(unsigned)port,addr.addr_bytes[0], addr.addr_bytes[1],addr.addr_bytes[2], addr.addr_bytes[3],addr.addr_bytes[4], addr.addr_bytes[5]);retval = rte_eth_promiscuous_enable(port);if (retval != 0)return retval;/* 发送添加时间戳 */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*/
#ifndef __rte_noreturn
#define __rte_noreturn __attribute__((noreturn))
#endif
static  __rte_noreturn void
lcore_main(void)
{uint16_t port;/* 轮询所有port */RTE_ETH_FOREACH_DEV(port)if (rte_eth_dev_socket_id(port) > 0 &&rte_eth_dev_socket_id(port) !=(int)rte_socket_id())printf("WARNING, port %u is on remote NUMA node to ""polling thread.\n\tPerformance will ""not be optimal.\n", port);printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n",rte_lcore_id());/* 开始 *//*  */for (;;) {RTE_ETH_FOREACH_DEV(port) {struct rte_mbuf *bufs[BURST_SIZE];const uint16_t nb_rx = rte_eth_rx_burst(port, 0,bufs, BURST_SIZE);if (unlikely(nb_rx == 0))continue;const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,bufs, nb_rx);if (unlikely(nb_tx < nb_rx)) {uint16_t buf;for (buf = nb_tx; buf < nb_rx; buf++)rte_pktmbuf_free(bufs[buf]);}printf("RX = %d, port %d vs TX = %d, port %d\n", nb_rx, port, nb_tx, port ^ 1);}}
}/* Main function, does initialisation and calls the per-lcore functions */
int
main(int argc, char *argv[])
{struct rte_mempool *mbuf_pool;uint16_t nb_ports;uint16_t portid;struct option lgopts[] = {{ NULL,  0, 0, 0 }};int opt, option_index;/* init EAL *//* 初始化EAL */int ret = rte_eal_init(argc, argv);if (ret < 0)rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");argc -= ret;argv += ret;/* 获取命令行 */while ((opt = getopt_long(argc, argv, "t", lgopts, &option_index))!= EOF)switch (opt) {case 't':hw_timestamping = 1;break;default:printf(usage, argv[0]);return -1;}optind = 1; /* reset getopt lib *//* 可用设备个数 */nb_ports = rte_eth_dev_count_avail();if (nb_ports < 2 || (nb_ports & 1))rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");/* 创建池 */mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL",NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0,RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());if (mbuf_pool == NULL)rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");/* initialize all ports *//* 轮询设备 */RTE_ETH_FOREACH_DEV(portid)if (port_init(portid, mbuf_pool) != 0)rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8"\n",portid);/* lcore大于1,告警 */if (rte_lcore_count() > 1)printf("\nWARNING: Too much enabled lcores - ""App uses only 1 lcore\n");/* call lcore_main on master core only */lcore_main();/* core主函数 */return 0;
}

DPDK examples rxtx_callbacks完全注释相关推荐

  1. DPDK examples cmdline完全注释(添加quit功能)

    目录 main.c 添加的quit部分代码 DPDK版本:20.05 main.c /* SPDX-License-Identifier: BSD-3-Clause* Copyright(c) 201 ...

  2. DPDK examples ethtool-app完全注释

    目录 main.c ethapp.h ethapp.c The Ethtool sample application shows an implementation of an ethtool-lik ...

  3. ethtool 原理介绍和解决网卡丢包排查思路(附ethtool源码下载)

    Table of Contents 1. 了解接收数据包的流程 将网卡收到的数据包转移到主机内存(NIC 与驱动交互) 通知系统内核处理(驱动与 Linux 内核交互) 2. ifconfig 解释 ...

  4. DPDK - 通过源码安装dpdk并运行examples (by quqi99)

    作者:张华 发表于:2021-08-11 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 前言 2016年通过源码安装过dpdk,但过时了,见: https:/ ...

  5. DPDK之makefile编译选项修改和gdb调试(三)

    摘要 intel dpdk 的makefile 写的很好,该好好学习他的这种架构,但在调试程序时候发现,它的编译选项优化级别很高:怎样去修改intel dpdk中的编译选项,达到自己一个一个满意的程度 ...

  6. DPDK flow_classify 源码阅读

    代码部分 /* SPDX-License-Identifier: BSD-3-Clause* Copyright(c) 2017 Intel Corporation*/#include <std ...

  7. l3fwd 是什么_服务器DPDK l3fwd性能测试

    1.测试背景 由于项目中需要用到dpdk,当时在服务器平台选型上有如下2种不同配置可供选择,为了理解老的Xeon处理器和Xeon金牌处理器对DPDK转发性能的影响,需要在两台服务器上分别进行DPDK ...

  8. DPDK helloworld 源码阅读

    在 DPDK Programmer's Guides 中的 EAL 一篇中有一个图可以很清晰地看到一个DPDK的应用程序的大致执行思路: 初始化检查CPU支持.微架构配置等完成后,执行main()函数 ...

  9. DPDK技术系统学习一(接收,发送,arp,icmp功能测试)

    如何技术不去手动做练习实践,就总有一种无从下手的感觉 文末附上小编总结的DPDK学习路线图以及我的学习资料. 0:准备环境并启动,使用dpdk接管其中一个网卡. ubuntu虚拟机环境配置多队列网卡, ...

最新文章

  1. 【camera】基于深度学习的车牌检测与识别系统实现(课程设计)
  2. java 在线监测 trace_JDK自带的性能调优监测工具使用示例
  3. 一次DB2数据库连接失败(SQLSTATE=08001)的解决方法
  4. 数据结构:哈希表函数构造和冲突解决方法
  5. .NET 跨平台服务端资料
  6. 字符串之数组中两个字符串的最小距离
  7. JavaFX缺少的功能调查:CSS
  8. linux msgrcv阻塞接收_linux下高并发服务器实现
  9. 关于用css实现的文字超出部分显示省略号
  10. 【万字长文】创业公司就应该技术选型 Spring Cloud Alibaba , 开箱即用
  11. elementUI响应式布局@media:基于断点的隐藏类
  12. python如何加载图片_python如何导入图片
  13. HDFS的JAVA客户端编写
  14. html设置隐藏窗口,html – 在窗口大小调整时逐个隐藏菜单项
  15. 软件构造过程与配置管理
  16. python处理word页码_word——插入页码
  17. 机器学习教程 之 半监督学习 Co-training 协同训练 (论文、算法、数据集、代码)
  18. opengl绘制太阳系:地球+卫星+行星
  19. sklearn中FastICA接口的使用方法
  20. java 数据类型的基本类型

热门文章

  1. 新买的服务器怎么安装Linux,买了新服务器,如何从头开始配置?Ubuntu系统安装+新建用户名+挂...
  2. leetcode题解26-删除数组的重复项
  3. Spring Bean的实例化时机与ApplicationContext中单例bean的延迟初始化
  4. Java开发人员常用网站收录
  5. 2019.7.20十道js题目
  6. 线程的创建 锁 Threading模块 事件 条件 定时器 队列 线程池 回调函数
  7. express中的错误处理
  8. Unity3D之Mecanim动画系统学习笔记(五):Animator Controller
  9. (转载)UI设计还远没有满足客户的需求
  10. 9-Mybatis 多表查询之一对多