网站建设合同甲乙双方怎么确定怎么注册深圳公司

张小明 2026/1/3 0:29:39
网站建设合同甲乙双方怎么确定,怎么注册深圳公司,建立自己网站,北京网络公司信息DPDK#xff0c;一个开源的、数据平面处理的高性能数据包处理库。核心思想是绕过操作系统内核#xff0c;在用户态直接操作网络接口卡#xff08;NIC#xff09;#xff0c;实现对硬件的直接访问和控制。这种“用户态驱动”的模式#xff0c;减少数据包在用户态和内核态之…DPDK一个开源的、数据平面处理的高性能数据包处理库。核心思想是绕过操作系统内核在用户态直接操作网络接口卡NIC实现对硬件的直接访问和控制。这种“用户态驱动”的模式减少数据包在用户态和内核态之间切换的开销避免不必要的内存拷贝提升网络数据包的处理速度和吞吐量。但是DPDK带来的高性能也伴随着一个问题DPDK接管了网卡完全在用户态处理数据包跟传统的操作系统内核网络栈之间形成了一道“鸿沟”。DPDK应用程序无法直接用内核提供的丰富网络服务也无法和依赖内核网络栈的传统应用程序进行数据交换。为了解决这一用户态与内核态协同工作的问题DPDK推出一个关键组件——Kernel Network Interface (KNI)。KNI 弥合DPDK用户态数据平面和Linux内核网络栈之间的鸿沟。让DPDK应用程序在用户态和内核态之间交换数据包实现用户态高性能网络应用与内核网络栈的互操作。通过KNIDPDK应用程序可以有选择性的把部分数据包转发给内核处理同时保留对其他数据包的高速处理能力。比如DPDK应用程序完全接管网卡后所有进出网卡的数据包都会首先被DPDK处理。但真实的情况是只关注特定类型的数据包而其他协议则希望由操作系统内核的通用协议栈来处理。在这种场景下DPDK KNI模块就是一个智能过滤器把不感兴趣的数据包发送到内核让内核去处理这些通用网络流量同时DPDK自身则专注于对特定协议进行超高速处理。这种分工合作的模式既利用了DPDK的极致性能又保留了内核网络栈的灵活性和功能完整性。注意DPDK读取网卡数据包的机制是基于共享内存的。网卡通过DMA直接内存访问技术把数据包直接映射到主机内存中的特定区域DPDK应用程序直接从这个共享内存区域读取数据避免CPU参与数据拷贝的过程。同样DPDK向内核发送数据以及从内核接收响应数据时也是通过KNI模块在共享内存中进行操作。因此rte_eth_rx_burst()和rte_eth_tx_burst()这类函数执行的是纯粹的内存操作而不是I/O操作。不涉及阻塞的概念有数据时就返回数据没有数据时也立即返回保证了DPDK数据处理的非阻塞性和高效率。二、搭建DPDK KNI开发环境在进行DPDK KNI应用程序开发之前要配置DPDK运行环境。准备DPDK源码并进入目录cd /path/to/your/dpdk/dpdk-stable-19.08.2/ # 如 dpdk/dpdk-stable-19.08.2/切换到root权限或使用sudoDPDK的某些配置和驱动加载操作需要root权限。sudo su导出DPDK环境变量设置RTE_SDK指向DPDK的根目录RTE_TARGET指定编译目标x86_64-native-linux-gcc表示64位Linux系统上的GCC编译环境。export RTE_SDK/path/to/your/dpdk/dpdk-stable-19.08.2/ export RTE_TARGETx86_64-native-linux-gcc运行DPDK配置脚本dpdk-setup.sh或较新版本中的dpdk-setup.py自动化配置和加载必要的模块。./usertools/dpdk-setup.sh按照脚本提示依次执行43) Load DPDK UIO KERNEL MODULE: 加载用户态I/OUIO模块。UIO是DPDK早期版本常用的用户态驱动框架让用户空间应用程序直接访问硬件设备。44) Load VFIO KERNEL MODULE: 加载虚拟功能I/OVFIO模块。VFIO是Linux内核提供的一种更安全、更现代的设备直通PCI Passthrough机制推荐在支持的系统上使用提供更好的隔离性和安全性。45) Load KNI KERNEL MODULE: 加载KNI内核模块。这是启用DPDK KNI功能的核心步骤会在内核中创建虚拟网卡接口用来DPDK与内核的数据交换。46) Setup 1GB Hugepages: 配置1GB大页内存。47) Setup 2MB Hugepages: 配置2MB大页内存。DPDK强烈推荐使用大页内存Hugepages。大页内存可以减少TLBTranslation Lookaside Buffer未命中减少页表查找的开销提高内存访问效率并避免频繁的页交换提升数据包处理性能。可以配置一定数量的2MB和1GB大页。49) Bind NIC to DPDK driver: 物理网卡绑定到DPDK的用户态驱动。在执行此步骤之前一定要先关闭down要绑定的网卡接口sudo ifconfig eth0 down确保其处于可用状态。提供网卡的PCI地址通过lspci -nn命令查看。绑定成功后该网卡不再被内核网络栈管理而是完全由DPDK接管。60) Exit: 退出配置脚本。三、代码实现理解了DPDK和KNI的基本概念搭建好开发环境后就可以着手编写代码了。主要目标是演示如何用KNI实现DPDK用户态应用与内核网络栈之间的数据交互从网卡接收数据包判断是否为UDP包如果是则由DPDK应用程序自行处理并可选地发送回复如果不是则通过KNI转发给内核处理。实现步骤KNI 初始化与配置在DPDK应用程序启动时要初始化KNI子系统创建和配置KNI设备。包括分配必要的内存资源、设置KNI设备的名称、MAC地址、MTU等参数注册回调函数。这是DPDK应用程序与内核建立互操作通道的第一步。使用rte_kni_init和rte_kni_alloc函数。数据交换机制KNI设备创建成功DPDK应用程序就可以通过KNI设备与内核进行数据包交换。DPDK到内核 DPDK从物理网卡接收到数据包并决定将其转发给内核时调用rte_kni_tx_burst()函数数据包从DPDK的数据平面发送到KNI设备。KNI模块随后会把这些数据包注入到内核的网络协议栈中如同从一个常规的虚拟网卡接口接收到数据一样。内核到DPDK 类似内核也可以通过KNI设备将数据包发送回DPDK。DPDK应用程序通过调用rte_kni_rx_burst()函数从KNI设备接收这些数据包。这些数据包是内核处理后需要发出的响应包或者是由内核网络栈生成的包。接收到这些包后DPDK应用程序可以决定如何处理它们可以直接通过rte_eth_tx_burst()发送到物理网卡。调度与同步在多线程或高并发场景下确保KNI设备访问的正确性很重要。要使用锁如互斥锁和信号量来保护对KNI资源的并发访问。还需要实现事件处理机制处理内核与DPDK应用程序之间的异步交互。错误处理对DPDK和KNI相关的API调用进行充分的错误检查和处理是必不可少的。dpdk_udp.c展开代码语言C自动换行AI代码解释#include rte_eal.h // DPDK Environment Abstraction Layer #include rte_ethdev.h // Ethernet Device API #include rte_mbuf.h // Memory Buffer API #include rte_kni.h // Kernel Network Interface API #include rte_ether.h // Ethernet header definitions #include rte_ip.h // IP header definitions #include rte_udp.h // UDP header definitions #include stdio.h #include arpa/inet.h #include string.h // 定义常量 #define MBUF_NUMBER 8196 // Mempool中mbuf的数量 #define MBUF_SIZE 32 // 单次burst操作中mbuf的最大数量 #define ENABLE_SEND 1 // 是否启用发送回复数据包的功能 #define ENABLE_KNI_APP 1 // 是否启用KNI功能 #define ENABLE_PROMISCUOUS 0 // 是否启用混杂模式接收所有数据包 // 全局变量 int gDpdkPortId 0; // DPDK端口ID默认为0 #if ENABLE_KNI_APP struct rte_kni *global_kni NULL; // KNI实例指针 #endif #if ENABLE_SEND // 用于构建回复包的MAC/IP/Port信息 static uint8_t gSrcMac[RTE_ETHER_ADDR_LEN]; static uint8_t gDstMac[RTE_ETHER_ADDR_LEN]; static uint32_t gSrcIp; static uint32_t gDstIp; static uint16_t gSrcPort; static uint16_t gDstPort; #endif #if ENABLE_KNI_APP /** * brief KNI回调函数配置网络接口状态 (up/down) * param port_id DPDK端口ID * param if_up 接口是否应设置为UP * return 0 on success, negative on error */ static int g_config_network_if(uint16_t port_id, uint8_t if_up) { if (!rte_eth_dev_is_valid_port(port_id)) { printf(Invalid port ID: %d\n, port_id); return -EINVAL; } int ret 0; if (if_up) { // 停止并重新启动端口以应用配置 rte_eth_dev_stop(port_id); ret rte_eth_dev_start(port_id); printf(Port %d started.\n, port_id); } else { rte_eth_dev_stop(port_id); printf(Port %d stopped.\n, port_id); } if (ret 0) { printf(Failed to %s port %d: %s\n, if_up ? start : stop, port_id, rte_strerror(-ret)); } return ret; } #endif #if ENABLE_SEND /** * brief 分配并构造一个UDP数据包 (用于发送回复) * param pool Mempool用于分配mbuf * param data UDP payload数据 * param length UDP payload长度 * return 构造好的mbuf指针 */ static struct rte_mbuf *alloc_udp_pkt(struct rte_mempool *pool, uint8_t *data, uint16_t length) { // 从mempool中分配一个mbuf struct rte_mbuf *mbuf rte_pktmbuf_alloc(pool); if (!mbuf) { rte_exit(EXIT_FAILURE, Failed to allocate mbuf for UDP packet\n); } // 计算数据包总长度 (以太网头 IP头 UDP头 Payload) uint16_t total_len length sizeof(struct rte_ipv4_hdr) sizeof(struct rte_ether_hdr); mbuf-pkt_len total_len; mbuf-data_len total_len; // 获取mbuf的数据指针 uint8_t *msg rte_pktmbuf_mtod(mbuf, uint8_t*); // 1. 构造以太网头 struct rte_ether_hdr *eth (struct rte_ether_hdr *)msg; rte_memcpy(eth-s_addr.addr_bytes, gSrcMac, RTE_ETHER_ADDR_LEN); // 源MAC rte_memcpy(eth-d_addr.addr_bytes, gDstMac, RTE_ETHER_ADDR_LEN); // 目的MAC eth-ether_type htons(RTE_ETHER_TYPE_IPV4); // 以太网类型IPv4 // 2. 构造IPv4头 struct rte_ipv4_hdr *ip (struct rte_ipv4_hdr *)(msg sizeof(struct rte_ether_hdr)); ip-version_ihl 0x45; // Version (4) and IHL (5 words) ip-type_of_service 0; ip-total_length htons(length sizeof(struct rte_ipv4_hdr)); // IP头 UDP头 Payload ip-packet_id 0; // 可以随机生成 ip-fragment_offset 0; ip-time_to_live 64; // TTL ip-next_proto_id IPPROTO_UDP; // 下层协议UDP ip-src_addr gSrcIp; // 源IP ip-dst_addr gDstIp; // 目的IP ip-hdr_checksum 0; // 计算校验和前置0 ip-hdr_checksum rte_ipv4_cksum(ip); // 计算IP头校验和 // 3. 构造UDP头 struct rte_udp_hdr *udp (struct rte_udp_hdr *)(msg sizeof(struct rte_ether_hdr) sizeof(struct rte_ipv4_hdr)); udp-src_port gSrcPort; // 源端口 udp-dst_port gDstPort; // 目的端口 udp-dgram_len htons(length); // UDP数据报长度 (UDP头 Payload) // 4. 拷贝UDP payload数据 rte_memcpy((uint8_t*)(udp 1), data, length - sizeof(struct rte_udp_hdr)); // 5. 计算UDP校验和 udp-dgram_cksum 0; // 计算校验和前置0 udp-dgram_cksum rte_ipv4_udptcp_cksum(ip, udp); // 计算UDP校验和 return mbuf; } #endif /** * brief 主函数 */ int main(int argc, char *argv[]) { // 1. EAL (Environment Abstraction Layer) 初始化 // 负责DPDK的初始化包括解析命令行参数、设置大页内存、绑定CPU核等 if (rte_eal_init(argc, argv) 0) { rte_exit(EXIT_FAILURE, Error: EAL initialization failed\n); } printf(DPDK EAL initialized successfully.\n); // 2. 创建Mempool // Mempool是DPDK中用于管理mbuf内存缓冲区的内存池。 // Mbuf是DPDK数据包处理的基本单元。 struct rte_mempool *mbuf_pool rte_pktmbuf_pool_create(mbufpool, // Mempool名称 MBUF_NUMBER, // mbuf数量 0, // 每个mbuf额外空间 0, // 每个mbuf私有数据大小 RTE_MBUF_DEFAULT_BUF_SIZE, // mbuf数据区大小 rte_socket_id()); // CPU socket ID if (!mbuf_pool) { rte_exit(EXIT_FAILURE, Error: Failed to create mbuf pool\n); } printf(Mbuf pool created successfully.\n); #if ENABLE_KNI_APP // 3. KNI 子系统初始化 // 在分配KNI设备之前需要先初始化KNI子系统。 if (rte_kni_init(gDpdkPortId) 0) { // gDpdkPortId在这里作为KNI的唯一标识 rte_exit(EXIT_FAILURE, Error: KNI subsystem initialization failed\n); } printf(KNI subsystem initialized successfully.\n); #endif // 4. 配置以太网设备 uint16_t nb_rx_queues 1; // 接收队列数量 #if ENABLE_SEND uint16_t nb_tx_queues 1; // 发送队列数量 #else uint16_t nb_tx_queues 0; #endif const struct rte_eth_conf port_conf_default { .rxmode {.max_rx_pkt_len RTE_ETHER_MAX_LEN } // 最大接收数据包长度 }; // 配置DPDK端口包括接收/发送队列数量和基本模式 int ret rte_eth_dev_configure(gDpdkPortId, nb_rx_queues, nb_tx_queues, port_conf_default); if (ret 0) { rte_exit(EXIT_FAILURE, Error: Failed to configure Ethernet device: %s\n, rte_strerror(-ret)); } printf(Ethernet device %d configured.\n, gDpdkPortId); // 5. 设置接收队列 // 设置端口的接收队列指定mbuf_pool用于接收数据包。 ret rte_eth_rx_queue_setup(gDpdkPortId, // 端口ID 0, // 队列ID 128, // 接收描述符数量 rte_eth_dev_socket_id(gDpdkPortId), // CPU socket ID NULL, // 额外配置 (NULL表示默认) mbuf_pool); // Mempool if (ret 0) { rte_exit(EXIT_FAILURE, Error: Failed to setup RX queue: %s\n, rte_strerror(-ret)); } printf(RX queue for port %d setup.\n, gDpdkPortId); #if ENABLE_SEND // 6. 设置发送队列 // 设置端口的发送队列。 ret rte_eth_tx_queue_setup(gDpdkPortId, // 端口ID 0, // 队列ID 1024, // 发送描述符数量 rte_eth_dev_socket_id(gDpdkPortId), // CPU socket ID NULL); // 额外配置 (NULL表示默认) if (ret 0) { rte_exit(EXIT_FAILURE, Error: Failed to setup TX queue: %s\n, rte_strerror(-ret)); } printf(TX queue for port %d setup.\n, gDpdkPortId); #endif // 7. 启动以太网设备 ret rte_eth_dev_start(gDpdkPortId); if (ret 0) { rte_exit(EXIT_FAILURE, Error: Failed to start Ethernet device: %s\n, rte_strerror(-ret)); } printf(Ethernet device %d started.\n, gDpdkPortId); #if ENABLE_PROMISCUOUS // 8. 启用混杂模式 (可选) // 混杂模式下网卡会接收所有经过的数据包无论目的MAC地址是否是自己。 // 在调试或特殊应用场景下可能有用。 rte_eth_promiscuous_enable(gDpdkPortId); printf(Promiscuous mode enabled for port %d.\n, gDpdkPortId); #endif #if ENABLE_KNI_APP // 9. 配置和分配KNI设备 struct rte_kni_conf conf; memset(conf, 0, sizeof(conf)); // 设置KNI设备名称通常是vEthX snprintf(conf.name, RTE_KNI_NAMESIZE, vEth%d, gDpdkPortId); conf.group_id gDpdkPortId; // KNI组ID conf.mbuf_size RTE_MBUF_DEFAULT_BUF_SIZE; // KNI内部mbuf大小 // 获取DPDK端口的MAC地址和MTU用于KNI设备的配置 struct rte_ether_addr eth_addr; rte_eth_macaddr_get(gDpdkPortId, eth_addr); rte_memcpy(conf.mac_addr, eth_addr.addr_bytes, RTE_ETHER_ADDR_LEN); uint16_t mtu; rte_eth_dev_get_mtu(gDpdkPortId, mtu); conf.mtu mtu; // 设置KNI操作回调函数 struct rte_kni_ops ops; memset(ops, 0, sizeof(ops)); ops.port_id gDpdkPortId; // 注册KNI接口的up/down回调函数当内核控制KNI接口状态时会调用 ops.config_network_if g_config_network_if; // 分配KNI设备 global_kni rte_kni_alloc(mbuf_pool, conf, ops); if (!global_kni) { rte_exit(EXIT_FAILURE, Error: Failed to allocate KNI device\n); } printf(KNI device %s allocated successfully.\n, conf.name); #endif printf(Entering main loop...\n); // 10. 主循环数据包处理 while (1) { unsigned num_recvd 0; unsigned i 0; #if ENABLE_KNI_APP // 从KNI接收数据包 (即从内核接收数据包) struct rte_mbuf *kni_burst[MBUF_SIZE]; num_recvd rte_kni_rx_burst(global_kni, kni_burst, MBUF_SIZE); if (num_recvd 0) { // 将从KNI接收到的数据包发送到物理网卡 unsigned nb_tx rte_eth_tx_burst(gDpdkPortId, 0, kni_burst, num_recvd); if (nb_tx num_recvd) { // 如果未能全部发送释放剩余的mbuf printf(Warning: Only %u/%u KNI packets sent to NIC. Freeing remaining.\n, nb_tx, num_recvd); for (i nb_tx; i num_recvd; i) { rte_pktmbuf_free(kni_burst[i]); } } } #endif // 从物理网卡接收数据包 struct rte_mbuf *mbufs[MBUF_SIZE]; num_recvd rte_eth_rx_burst(gDpdkPortId, 0, mbufs, MBUF_SIZE); if (num_recvd 0) { // 没有收到数据包继续循环 // 小心如果循环太快会占用大量CPU实际应用中会加入延时或条件等待 // rte_delay_us_block(100); // 示例可以加入短暂延时 goto handle_kni_requests; // 跳到处理KNI请求 } // 遍历接收到的数据包 for (i 0; i num_recvd; i) { struct rte_mbuf *current_mbuf mbufs[i]; struct rte_ether_hdr *ehdr rte_pktmbuf_mtod(current_mbuf, struct rte_ether_hdr *); // 检查以太网类型是否为IPv4 if (ehdr-ether_type ! rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { #if ENABLE_KNI_APP // 非IPv4数据包转发给KNI (即转发给内核) rte_kni_tx_burst(global_kni, current_mbuf, 1); // 注意这里只发送一个包如果需要发送多个需要调整数组和计数 #else // 如果没有启用KNI则直接释放非IPv4数据包 rte_pktmbuf_free(current_mbuf); #endif continue; // 处理下一个数据包 } // 解析IPv4头 struct rte_ipv4_hdr *iphdr rte_pktmbuf_mtod_offset(current_mbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); // 检查IP协议类型是否为UDP if (iphdr-next_proto_id IPPROTO_UDP) { // 是UDP数据包由DPDK应用程序处理 struct rte_udp_hdr *udphdr (struct rte_udp_hdr *)(iphdr 1); // 数据过滤只处理目的端口为8888的UDP包 (用于调试) if (ntohs(udphdr-dst_port) ! 8888) { rte_pktmbuf_free(current_mbuf); // 释放不感兴趣的UDP包 continue; } // 打印UDP数据包信息 uint16_t payload_len ntohs(udphdr-dgram_len) - sizeof(struct rte_udp_hdr); // 确保payload以null结尾以便printf打印字符串 // 注意这里直接修改mbuf内容可能影响后续处理仅为示例 if (payload_len 0 (char*)(udphdr1) payload_len (char*)rte_pktmbuf_mtod(current_mbuf, char*) current_mbuf-data_len) { *((char*) udphdr ntohs(udphdr-dgram_len)) \0; } else { // Payload长度异常或太短无法安全添加null终止符 payload_len 0; // 避免访问越界 } struct in_addr addr; addr.s_addr iphdr-src_addr; printf(RX UDP: src: %s:%d, , inet_ntoa(addr), ntohs(udphdr-src_port)); addr.s_addr iphdr-dst_addr; printf(dst: %s:%d, Payload: %s\n, inet_ntoa(addr), ntohs(udphdr-dst_port), (char *)(udphdr 1)); #if ENABLE_SEND // 构造并发送一个UDP回复包 // 交换源MAC/IP/Port和目的MAC/IP/Port rte_memcpy(gSrcMac, ehdr-d_addr.addr_bytes, RTE_ETHER_ADDR_LEN); rte_memcpy(gDstMac, ehdr-s_addr.addr_bytes, RTE_ETHER_ADDR_LEN); gSrcIp iphdr-dst_addr; gDstIp iphdr-src_addr; gSrcPort udphdr-dst_port; gDstPort udphdr-src_port; // 构造回复消息例如 Hello from DPDK! char reply_msg[] Hello from DPDK!; struct rte_mbuf *reply_mbuf alloc_udp_pkt(mbuf_pool, (uint8_t*)reply_msg, sizeof(reply_msg)); // 发送回复包 unsigned nb_tx rte_eth_tx_burst(gDpdkPortId, 0, reply_mbuf, 1); if (nb_tx 1) { printf(TX UDP: Sent reply to %s:%d\n, inet_ntoa(addr), ntohs(udphdr-src_port)); } else { printf(Failed to send UDP reply.\n); rte_pktmbuf_free(reply_mbuf); // 发送失败释放mbuf } #endif rte_pktmbuf_free(current_mbuf); // 处理完毕释放原始数据包 } else { // 非UDP的IPv4数据包 (如TCP, ICMP等)转发给KNI (即转发给内核) #if ENABLE_KNI_APP rte_kni_tx_burst(global_kni, current_mbuf, 1); #else // 如果没有启用KNI则直接释放这些数据包 rte_pktmbuf_free(current_mbuf); #endif } } handle_kni_requests: #if ENABLE_KNI_APP // 处理KNI控制请求 // KNI模块会通过此函数处理来自内核的控制请求如接口状态改变等。 rte_kni_handle_request(global_kni); #endif } // 程序退出前清理资源 (通常不会到达这里因为是无限循环) // rte_kni_release(global_kni); // rte_eth_dev_stop(gDpdkPortId); // rte_eth_dev_close(gDpdkPortId); // rte_eal_cleanup(); return 0; }Makefile支持两种编译方式用pkg-config推荐更现代或用RTE_SDK环境变量。生成共享库版本和静态库版本的可执行文件。展开代码语言Bash自动换行AI代码解释# binary name APP dpdk_udp # all source are stored in SRCS-y SRCS-y : dpdk_udp.c # Build using pkg-config variables if possible # 检查系统是否安装并配置了libdpdk的pkg-config文件 ifeq ($(shell pkg-config --exists libdpdk echo 0),0) # 如果pkg-config可用则使用其提供的编译和链接标志 all: shared # 默认构建共享库版本 .PHONY: shared static shared: build/$(APP)-shared # 目标构建共享库版本 ln -sf $(APP)-shared build/$(APP) # 创建软链接方便执行 static: build/$(APP)-static # 目标构建静态库版本 ln -sf $(APP)-static build/$(APP) # 创建软链接 # 获取pkg-config文件的路径 PKGCONFpkg-config --define-prefix PC_FILE : $(shell $(PKGCONF) --path libdpdk) # 从pkg-config获取C编译标志和链接标志 CFLAGS -O3 $(shell $(PKGCONF) --cflags libdpdk) LDFLAGS_SHARED $(shell $(PKGCONF) --libs libdpdk) LDFLAGS_STATIC -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk) # 编译共享库版本 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(CC) $(CFLAGS) $(SRCS-y) -o $ $(LDFLAGS) $(LDFLAGS_SHARED) # 编译静态库版本 build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build $(CC) $(CFLAGS) $(SRCS-y) -o $ $(LDFLAGS) $(LDFLAGS_STATIC) # 创建build目录 build: mkdir -p $ .PHONY: clean clean: rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared test -d build rmdir -p build || true # 删除build目录如果为空 else # 如果pkg-config不可用退回到使用RTE_SDK环境变量 ifeq ($(RTE_SDK),) $(error Please define RTE_SDK environment variable) # 提示用户设置RTE_SDK endif # 尝试从RTE_SDK路径推断RTE_TARGET RTE_TARGET ? $(notdir $(abspath $(dir $(firstword $(wildcard $(RTE_SDK)/*/.config))))) # 包含DPDK的通用Makefile变量和规则 include $(RTE_SDK)/mk/rte.vars.mk # 添加优化标志 CFLAGS -O3 CFLAGS $(WERROR_FLAGS) # 启用警告作为错误可选 # 包含DPDK外部应用程序的Makefile规则 include $(RTE_SDK)/mk/rte.extapp.mk endif四、编译与执行编译应用程序执行make命令。makeDPDK环境配置完成后特别是网卡已绑定到DPDK驱动且大页内存已分配以root权限运行编译好的程序。sudo ./build/dpdk_udp启动KNI虚拟网卡接口sudo ifconfig vEth0 192.168.7.26 upKNI接口的载波状态默认可能为DOWN。要手动将其设置为UP以便内核网络栈认为该接口已连接并可以传输数据。sudo sh -c echo 1 /sys/devices/virtual/net/vEth0/carrier从另一台机器或同一台机器上的其他终端ping向vEth0配置的IP地址或者向IP地址的8888端口发送UDP数据包。ping 192.168.7.26
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

东莞网站制作建设公司深汕特别合作区公共事业局

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 请比较传统手动创建docsify项目需要:1.初始化项目 2.配置webpack 3.编写markdown 4.设置主题 5.添加插件等步骤。然后展示如何使用本平台一键生成包含所有这些要素的完整…

张小明 2026/1/1 13:00:16 网站建设

校园网站建设与管理问题分析互联网黄页是什么

多智能体系统在竞争优势分析中的应用:寻找护城河关键词:多智能体系统、竞争优势分析、护城河、复杂系统、博弈论摘要:本文聚焦于多智能体系统在竞争优势分析中的应用,旨在探讨如何利用多智能体系统这一强大工具来寻找企业或组织的…

张小明 2026/1/1 15:20:21 网站建设

网站咨询窗口怎么做网站建设项目经理

在系统开发和硬件监控领域,快速准确地获取硬件信息一直是个技术难点。hwinfo作为一款优秀的跨平台C硬件信息库,为开发者提供了统一、高效的硬件数据访问方案。无论您是在Linux服务器上部署应用,还是在Windows桌面开发工具,亦或是m…

张小明 2025/12/31 3:40:46 网站建设

电子商务公司网站建设flashfxp上传多个网站

PHP:服务器端脚本语言的全面指南 1. PHP简介 PHP 是一种服务器端脚本语言,由 Rasmus Lerdorf 在 1995 年创建,最初被称为 PHP/FI。它通常通过表单使用 GET 或 POST 方法发送信息来访问脚本。 在很长一段时间里,PHP3 和 PHP4 这两个主要版本并存。如今,我们有了 PHP5,它…

张小明 2025/12/23 13:14:51 网站建设

站长工具永久it项目外包网

3小时完成千份文档迁移:自动化工具彻底改变飞书知识库备份方式 【免费下载链接】feishu-doc-export 项目地址: https://gitcode.com/gh_mirrors/fe/feishu-doc-export 在数字化转型浪潮中,企业知识库的迁移与备份已成为每个组织必须面对的挑战。…

张小明 2026/1/2 14:05:35 网站建设

1.网站建设基本流程是什么wordpress模板文件是那个文件

Kotaemon框架的绿色节能计算实践 在大语言模型(LLM)席卷各行各业的今天,企业部署智能对话系统已不再局限于“能不能用”,而是越来越关注“值不值得用”——尤其是当一个看似聪明的AI助手背后,是高昂的GPU电费账单、频繁…

张小明 2025/12/23 13:10:49 网站建设