温馨提示:这篇文章已超过381天没有更新,请注意相关的内容是否还可用!
摘要:本篇内容主要介绍了DPDK常用API合集四的相关信息。DPDK是一套针对高性能网络数据包处理的库和驱动程序的集合,其API接口广泛应用于网络数据处理领域。本文总结了DPDK中的一些常用API,包括其功能、使用方法等,对于开发者来说具有重要的参考意义。通过学习和掌握这些API,可以更加高效地进行网络数据处理开发。
dpdk-lib
- librte_lpm
- 1.1 librte_lpm 简介
- 1.2 rte_lpm.h
- 1.3 rte_lpm_create
- 1.3.1 参数说明:
- 1.3.2 返回值:
- 1.3.3 示例代码:
- 1.4 rte_lpm_add
- 1.4.1 函数介绍
- 1.4.2 参数说明
- 1.4.3 实例
- 1.5 rte_lpm_delete
- 1.5.1 函数介绍
- 1.5.2 参数说明
- 1.5.3 实例
- 1.6 rte_lpm_lookup
- 1.6.1 函数介绍
- 1.6.2 参数说明
- 1.6.3 实例
- 1.7 rte_lpm_is_rule_present
- 1.7.1 函数介绍
- 1.7.2 参数说明
- 1.7.3 实例
- 1.8 rte_lpm_free
- 1.8.1 实例
- 2.1 rte_lpm6.h
- 2.2 rte_lpm6_create
- 2.2.1 函数介绍
- 2.2.2 参数说明
- 2.2.3 实例
- 2.3 rte_lpm6_add
- 2.3.1 函数介绍
- 2.3.2 参数说明
- 2.3.3 实例
- 2.4 rte_lpm6_delete
- 2.4.1 函数介绍
- 2.4.2 参数说明
- 2.4.3 实例
- 2.5 rte_lpm6_lookup
- 2.5.1 函数介绍
- 2.5.2 参数说明
- 2.5.3 实例
- 2.6 rte_lpm6_is_rule_present
- 2.6.1 函数介绍
- 2.6.2 参数说明
- 2.6.3 实例
- 2.7 rte_lpm6_free
- 2.7.1 函数介绍
- 2.7.2 参数说明
- 2.7.3 实例
librte_lpm
1.1 librte_lpm 简介
librte_lpm是DPDK(Data Plane Development Kit)中的一个库,用于实现长网址前缀匹配(Longest Prefix Match)算法,通常用于高性能网络应用中的路由表查找。
(图片来源网络,侵删)功能:
实现了高效的长网址前缀匹配算法,用于快速查找路由表中最长匹配的前缀。支持IPv4和IPv6地址。
(图片来源网络,侵删)数据结构:
路由表(Routing Table):librte_lpm使用路由表来存储网络地址前缀及其对应的下一跳信息。
节点表(Node Table):librte_lpm内部使用一个节点表来组织路由表,以便快速查找最长匹配的前缀。
主要函数:
rte_lpm_create():创建一个新的长网址前缀匹配实例,并初始化相关数据结构。
rte_lpm_add():向已创建的长网址前缀匹配实例中添加一个前缀及其对应的下一跳信息。
rte_lpm_lookup():在已创建的长网址前缀匹配实例中查找一个目标地址的最长匹配前缀,并返回其对应的下一跳信息。
rte_lpm_delete():从已创建的长网址前缀匹配实例中删除一个前缀。
rte_lpm_free():释放一个长网址前缀匹配实例所占用的内存空间。
性能优化:
librte_lpm通过使用树状结构以及优化的查找算法来实现高效的路由表查找。
在内部实现中,通常使用二叉树或者Trie树等数据结构来组织路由表,以便快速查找最长匹配的前缀。
适用场景:
librte_lpm适用于需要高性能路由表查找的网络应用,例如路由器、防火墙、负载均衡器等。
由于其高效的实现和优化,特别适用于需要处理大量数据包的高速网络环境
1.2 rte_lpm.h
#ifndef _RTE_LPM_H_ #define _RTE_LPM_H_ /** * @file * RTE Longest Prefix Match (LPM) */ #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** LPM名称中的最大字符数 */ #define RTE_LPM_NAMESIZE 32 /** IPv4 LPM的最大深度值 */ #define RTE_LPM_MAX_DEPTH 32 /** @internal tbl24表中的总条目数 */ #define RTE_LPM_TBL24_NUM_ENTRIES (1 \ if (cond) return (retval); \ } while (0) #else #define RTE_LPM_RETURN_IF_TRUE(cond, retval) #endif /** @internal 具有有效和valid_group字段的位掩码 */ #define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x03000000 /** 用于指示成功查找的位掩码 */ #define RTE_LPM_LOOKUP_SUCCESS 0x01000000 /** @internal 默认的RCU延迟队列中的条目数量 */ #define RTE_LPM_RCU_DQ_RECLAIM_MAX 16 /** RCU回收模式 */ enum rte_lpm_qsbr_mode { /** 创建延迟队列以进行回收 */ RTE_LPM_QSBR_MODE_DQ = 0, /** 使用阻塞模式回收,不创建延迟队列 */ RTE_LPM_QSBR_MODE_SYNC }; #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN /** @internal tbl24条目结构 */ __extension__ struct rte_lpm_tbl_entry { /** * 存储下一个跳点(当valid_group未设置时为tbl8或tbl24,或当valid_group设置时为tbl24) * 或指向tbl8结构的group_index(仅tbl24,当valid_group设置时) */ uint32_t next_hop :24; /* 使用单个uint8_t存储3个值 */ uint32_t valid :1; /** 8); uint32_t tbl_entry; const uint32_t *ptbl; /* 调试:检查用户输入参数 */ RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL); /* 复制tbl24条目 */ ptbl = (const uint32_t *)(&lpm->tbl24[tbl24_index]); tbl_entry = *ptbl; /* 在查找中不需要内存顺序。因为存在数据流依赖性, * 编译器或硬件无法重新排序操作。 */ /* 复制tbl8条目(仅在需要时) */ if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { unsigned tbl8_index = (uint8_t)ip + (((uint32_t)tbl_entry & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES); ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index]; tbl_entry = *ptbl; } *next_hop = ((uint32_t)tbl_entry & 0x00FFFFFF); return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT; } /** * 在LPM表中查找多个IP地址。这可能作为宏实现,因此不应使用函数的地址。 * * @param lpm * LPM对象句柄 * @param ips * 要在LPM表中查找的IP数组 * @param next_hops * IP的最特定规则的下一跳(仅在查找命中时有效)。 * 这是一个包含两个字节值的数组。每个值的最高字节表示查找是否成功(设置了位掩码 * RTE_LPM_LOOKUP_SUCCESS)。最低字节是实际的下一跳。 * @param n * 要查找的ips数组中的元素数量。这应该是一个编译时常量,并且对于性能最好, * 应该能够被8整除。 * @return * -EINVAL表示参数不正确,否则为0 */ #define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \ rte_lpm_lookup_bulk_func(lpm, ips, next_hops, n) static inline int rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t *ips, uint32_t *next_hops, const unsigned n) { unsigned i; unsigned tbl24_indexes[n]; const uint32_t *ptbl; /* 调试:检查用户输入参数 */ RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) || (next_hops == NULL)), -EINVAL); for (i = 0; i > 8; } for (i = 0; i tbl24[tbl24_indexes[i]]; next_hops[i] = *ptbl; /* 如果需要,覆盖输出以获取tbl8条目 */ if (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { unsigned tbl8_index = (uint8_t)ips[i] + (((uint32_t)next_hops[i] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES); ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index]; next_hops[i] = *ptbl; } } return 0; } /* 屏蔽四个结果。 */ #define RTE_LPM_MASKX4_RES UINT64_C(0x00ffffff00ffffff) /** * 在LPM表中查找四个IP地址。 * * @param lpm * LPM对象句柄 * @param ip * 要在LPM表中查找的四个IP * @param hop * IP的最特定规则的下一跳(仅在查找命中时有效)。这是一个包含四个元素的数组。 * 如果对给定IP的查找成功,则相应元素的最低有效字节是实际的下一跳,最高有效字节为零。 * 如果给定IP的查找失败,则相应元素将包含默认值,请参阅下一个参数的描述。 * @param defv * 如果查找失败,则将默认值填充到hop[]数组的相应元素中。 */ static inline void rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4], uint32_t defv); #if defined(RTE_ARCH_ARM) #ifdef RTE_HAS_SVE_ACLE #include "rte_lpm_sve.h" #undef rte_lpm_lookup_bulk #define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \ __rte_lpm_lookup_vec(lpm, ips, next_hops, n) #endif #include "rte_lpm_neon.h" #elif defined(RTE_ARCH_PPC_64) #include "rte_lpm_altivec.h" #elif defined(RTE_ARCH_X86) #include "rte_lpm_sse.h" #else #include "rte_lpm_scalar.h" #endif #ifdef __cplusplus } #endif #endif /* _RTE_LPM_H_ */
1.3 rte_lpm_create
创建一个LPM对象
struct rte_lpm * rte_lpm_create(const char *name, int socket_id, const struct rte_lpm_config *config);
1.3.1 参数说明:
name:指定长网址前缀匹配实例的名称。
socket_id:指定长网址前缀匹配实例所在的NUMA节点。
config:指定长网址前缀匹配实例的配置信息,包括最大表项数量和最大深度等。
1.3.2 返回值:
如果创建成功,则返回指向新创建的长网址前缀匹配实例的指针。
如果创建失败,则返回NULL。
1.3.3 示例代码:
#include #include #define MAX_RULES 1024 #define SOCKET_ID 0 int main() { struct rte_lpm *lpm; struct rte_lpm_config config; const char *lpm_name = "example_lpm"; uint32_t ip[MAX_RULES] = {0}; // Example IP addresses uint8_t depth[MAX_RULES] = {0}; // Example prefix depths uint8_t next_hop[MAX_RULES] = {0}; // Example next hop values // Initialize configuration config.max_rules = MAX_RULES; config.number_tbl8s = MAX_RULES / RTE_LPM_TBL8_GROUP_NUM; config.flags = 0; // Create LPM instance lpm = rte_lpm_create(lpm_name, SOCKET_ID, &config); if (lpm == NULL) { printf("Error: Unable to create LPM instance\n"); return -1; } // Add example routing table entries for (int i = 0; i
在上面的示例代码中,我们首先初始化了一个rte_lpm_config结构体作为rte_lpm_create()函数的配置参数。然后,使用rte_lpm_create()函数创建了一个名为example_lpm的长网址前缀匹配实例。接着,我们使用rte_lpm_add()函数向该实例中添加了一些路由表项。最后,在使用完实例后,通过rte_lpm_free()函数释放了其所占用的内存空间。
1.4 rte_lpm_add
1.4.1 函数介绍
函数用于向 Longest Prefix Match (LPM) 表中添加一条规则。这个函数的作用是将给定的 IP 地址和前缀长度与相应的下一跳信息关联起来,以便后续的查找操作可以使用这些规则进行路由。
int rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint32_t next_hop);
1.4.2 参数说明
lpm: 指向已经创建的 LPM 对象的指针,用于添加规则。
ip: 要添加的 IP 地址(IPv4),以 32 位无符号整数表示。
depth: IP 地址的前缀长度,以位为单位。例如,对于 192.168.1.0/24,前缀长度为 24。
next_hop: 下一跳信息,即与给定 IP 地址匹配时应采取的操作(通常是下一个路由器的 IP 地址)。
函数返回值为整数,表示操作是否成功。如果成功添加规则,则返回 0;如果失败,则返回负值,同时设置 rte_errno 以指示失败原因。
1.4.3 实例
#include #include int main() { // 创建一个 LPM 对象 struct rte_lpm_config config = { .max_rules = 1024, .number_tbl8s = 1024, .flags = 0 }; struct rte_lpm *lpm = rte_lpm_create("example_lpm", 0, &config); if (lpm == NULL) { printf("Failed to create LPM object.\n"); return -1; } // 添加规则到 LPM 表 uint32_t ip = rte_ipv4_to_uint32(192, 168, 1, 0); // IP 地址转换为 32 位整数 uint8_t depth = 24; // 前缀长度为 24 uint32_t next_hop = rte_ipv4_to_uint32(1, 2, 3, 4); // 下一跳 IP 地址 int ret = rte_lpm_add(lpm, ip, depth, next_hop); if (ret
1.5 rte_lpm_delete
1.5.1 函数介绍
函数用于从 Longest Prefix Match (LPM) 表中删除指定的规则。这个函数的作用是移除与给定的 IP 地址和前缀长度相对应的规则
int rte_lpm_delete(struct rte_lpm *lpm, uint32_t ip, uint8_t depth);
1.5.2 参数说明
lpm: 指向已经创建的 LPM 对象的指针,从中删除规则。
ip: 要删除的 IP 地址(IPv4),以 32 位无符号整数表示。
depth: IP 地址的前缀长度,以位为单位。例如,对于 192.168.1.0/24,前缀长度为 24。
1.5.3 实例
#include #include int main() { // 创建一个 LPM 对象 struct rte_lpm_config config = { .max_rules = 1024, .number_tbl8s = 1024, .flags = 0 }; struct rte_lpm *lpm = rte_lpm_create("example_lpm", 0, &config); if (lpm == NULL) { printf("Failed to create LPM object.\n"); return -1; } // 添加规则到 LPM 表 uint32_t ip = rte_ipv4_to_uint32(192, 168, 1, 0); // IP 地址转换为 32 位整数 uint8_t depth = 24; // 前缀长度为 24 uint32_t next_hop = rte_ipv4_to_uint32(1, 2, 3, 4); // 下一跳 IP 地址 int ret = rte_lpm_add(lpm, ip, depth, next_hop); if (ret
1.6 rte_lpm_lookup
1.6.1 函数介绍
rte_lpm_lookup 函数用于在 Longest Prefix Match (LPM) 表中查找给定的 IP 地址,并返回与之最匹配的规则的下一跳信息。这个函数的作用是根据输入的 IP 地址在 LPM 表中进行前缀匹配,并返回匹配到的规则的下一跳信息
int rte_lpm_lookup(const struct rte_lpm *lpm, uint32_t ip, uint32_t *next_hop);
1.6.2 参数说明
lpm: 指向已经创建的 LPM 对象的指针,从中进行查找。
ip: 要查找的 IP 地址(IPv4),以 32 位无符号整数表示。
next_hop: 指向存储下一跳信息的指针。如果查找成功,则该指针将被赋值为与给定 IP 地址最匹配的规则的下一跳信息。
函数返回值为整数,表示操作是否成功。如果成功找到匹配的规则,则返回 0,并将下一跳信息存储在 next_hop 中;如果未找到匹配的规则,则返回负值,同时设置 rte_errno 以指示失败原因。
1.6.3 实例
#include #include int main() { // 创建一个 LPM 对象 struct rte_lpm_config config = { .max_rules = 1024, .number_tbl8s = 1024, .flags = 0 }; struct rte_lpm *lpm = rte_lpm_create("example_lpm", 0, &config); if (lpm == NULL) { printf("Failed to create LPM object.\n"); return -1; } // 添加规则到 LPM 表 uint32_t ip = rte_ipv4_to_uint32(192, 168, 1, 0); // IP 地址转换为 32 位整数 uint8_t depth = 24; // 前缀长度为 24 uint32_t next_hop = rte_ipv4_to_uint32(1, 2, 3, 4); // 下一跳 IP 地址 int ret = rte_lpm_add(lpm, ip, depth, next_hop); if (ret > 24) & 0xFF, (lookup_ip >> 16) & 0xFF, (lookup_ip >> 8) & 0xFF, lookup_ip & 0xFF, (lookup_next_hop >> 24) & 0xFF, (lookup_next_hop >> 16) & 0xFF, (lookup_next_hop >> 8) & 0xFF, lookup_next_hop & 0xFF); } // 释放 LPM 对象 rte_lpm_free(lpm); return 0; }
1.7 rte_lpm_is_rule_present
1.7.1 函数介绍
rte_lpm_is_rule_present 函数用于检查指定的 IP 地址和前缀长度是否存在于 Longest Prefix Match (LPM) 表中,并提供其下一跳信息。感觉和上面的rte_lpm_lookup类似,实际我也是用的rte_lpm_lookup函数。
int rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint32_t *next_hop);
1.7.2 参数说明
lpm: 指向已经创建的 LPM 对象的指针,从中进行规则检查。
ip: 要检查的 IP 地址(IPv4),以 32 位无符号整数表示。
depth: IP 地址的前缀长度,以位为单位。例如,对于 192.168.1.0/24,前缀长度为 24。
next_hop: 如果规则存在,则存储与给定 IP 地址和前缀长度匹配的规则的下一跳信息。
函数返回值为整数,表示操作的结果。如果规则存在,则返回 1,并将下一跳信息存储在 next_hop 中;如果规则不存在,则返回 0;如果出现错误,则返回负值,同时设置 rte_errno 以指示失败原因。
1.7.3 实例
#include #include int main() { // 创建一个 LPM 对象 struct rte_lpm_config config = { .max_rules = 1024, .number_tbl8s = 1024, .flags = 0 }; struct rte_lpm *lpm = rte_lpm_create("example_lpm", 0, &config); if (lpm == NULL) { printf("Failed to create LPM object.\n"); return -1; } // 添加规则到 LPM 表 uint32_t ip = rte_ipv4_to_uint32(192, 168, 1, 0); // IP 地址转换为 32 位整数 uint8_t depth = 24; // 前缀长度为 24 uint32_t next_hop = rte_ipv4_to_uint32(1, 2, 3, 4); // 下一跳 IP 地址 int ret = rte_lpm_add(lpm, ip, depth, next_hop); if (ret > 24) & 0xFF, (lookup_ip >> 16) & 0xFF, (lookup_ip >> 8) & 0xFF, lookup_ip & 0xFF, lookup_depth); printf("Next hop: %d.%d.%d.%d\n", (lookup_next_hop >> 24) & 0xFF, (lookup_next_hop >> 16) & 0xFF, (lookup_next_hop >> 8) & 0xFF, lookup_next_hop & 0xFF); } else { printf("Rule for IP address %d.%d.%d.%d with prefix length %d does not exist.\n", (lookup_ip >> 24) & 0xFF, (lookup_ip >> 16) & 0xFF, (lookup_ip >> 8) & 0xFF, lookup_ip & 0xFF, lookup_depth); } // 释放 LPM 对象 rte_lpm_free(lpm); return 0; }
1.8 rte_lpm_free
函数用于释放之前创建的 Longest Prefix Match (LPM) 对象及其占用的资源。当你不再需要使用 LPM 对象时,应该调用该函数来释放内存并清理资源,以避免内存泄漏。
1.8.1 实例
#include #include int main() { // 创建一个 LPM 对象 struct rte_lpm_config config = { .max_rules = 1024, .number_tbl8s = 1024, .flags = 0 }; struct rte_lpm *lpm = rte_lpm_create("example_lpm", 0, &config); if (lpm == NULL) { printf("Failed to create LPM object.\n"); return -1; } // 使用 LPM 对象进行一些操作... // 当不再需要使用 LPM 对象时,释放资源 rte_lpm_free(lpm); return 0; }
2.1 rte_lpm6.h
#ifndef _RTE_LPM6_H_ #define _RTE_LPM6_H_ /** * @file * IPv6(LPM6)的RTE最长前缀匹配 */ #include #ifdef __cplusplus extern "C" { #endif #define RTE_LPM6_MAX_DEPTH 128 #define RTE_LPM6_IPV6_ADDR_SIZE 16 /** 最大LPM名称中的字符数。 */ #define RTE_LPM6_NAMESIZE 32 /** LPM结构。 */ struct rte_lpm6; /** LPM配置结构。 */ struct rte_lpm6_config { uint32_t max_rules; /**
2.2 rte_lpm6_create
2.2.1 函数介绍
函数用于创建一个 IPv6 的最长前缀匹配(Longest Prefix Match, LPM)对象。
struct rte_lpm6 *rte_lpm6_create(const char *name, int socket_id, const struct rte_lpm6_config *config);
2.2.2 参数说明
name:LPM 对象的名称。
socket_id:用于 LPM 表内存分配的 NUMA 套接字 ID。
config:包含 LPM 配置的结构体指针。
如果创建成功,则返回指向新创建的 LPM 对象的指针。
如果创建失败,则返回 NULL,并设置 rte_errno 以指示错误原因。可能的错误包括:
E_RTE_NO_CONFIG:无法获取指向 rte_config 结构的指针。
E_RTE_SECONDARY:函数从次要进程实例调用。
EINVAL:传递给函数的参数无效。
ENOSPC:已经分配了最大数量的内存区域。
EEXIST:具有相同名称的内存区域已存在。
ENOMEM:未找到适当的内存区域来创建内存区域。
2.2.3 实例
#include #include #define LPM_NAME "example_lpm6" #define SOCKET_ID 0 #define MAX_RULES 1024 #define NUM_TBL8S 1024 int main() { // 创建 LPM 配置结构 struct rte_lpm6_config config = { .max_rules = MAX_RULES, .number_tbl8s = NUM_TBL8S, .flags = 0 // 此字段当前未使用 }; // 创建 IPv6 LPM 对象 struct rte_lpm6 *lpm = rte_lpm6_create(LPM_NAME, SOCKET_ID, &config); if (lpm == NULL) { printf("Failed to create LPM object\n"); return -1; } // 使用 LPM 对象进行其他操作(添加规则、查询、删除等) // 释放 LPM 对象 rte_lpm6_free(lpm); return 0; }
2.3 rte_lpm6_add
2.3.1 函数介绍
函数用于向 IPv6 的最长前缀匹配(Longest Prefix Match, LPM)表中添加规则
int rte_lpm6_add(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth, uint32_t next_hop);
2.3.2 参数说明
lpm:指向要添加规则的 IPv6 LPM 对象的指针。
ip:要添加到 LPM 表中的 IPv6 地址的字节流表示形式,以 uint8_t 数组形式传递。
depth:要添加的规则的前缀长度。
next_hop:与匹配的规则相关联的下一跳信息。
如果成功添加规则,则返回 0。
如果添加规则失败,则返回负值,表示错误的原因。
2.3.3 实例
#include #include #include #define LPM_NAME "example_lpm6" #define SOCKET_ID 0 #define MAX_RULES 1024 #define NUM_TBL8S 1024 int main() { // 创建 LPM 配置结构 struct rte_lpm6_config config = { .max_rules = MAX_RULES, .number_tbl8s = NUM_TBL8S, .flags = 0 // 此字段当前未使用 }; // 创建 IPv6 LPM 对象 struct rte_lpm6 *lpm = rte_lpm6_create(LPM_NAME, SOCKET_ID, &config); if (lpm == NULL) { printf("Failed to create LPM object\n"); return -1; } // 添加规则 uint8_t ip[] = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; // IPv6地址 uint8_t depth = 64; // 前缀长度 uint32_t next_hop = 1; // 下一跳信息 int ret = rte_lpm6_add(lpm, ip, depth, next_hop); if (ret != 0) { printf("Failed to add rule to LPM\n"); rte_lpm6_free(lpm); return -1; } // 使用 LPM 对象进行其他操作(添加规则、查询、删除等) // 释放 LPM 对象 rte_lpm6_free(lpm); return 0; }
在上面的示例中,我们首先创建了一个 IPv6 LPM 对象,并添加了一个规则。我们定义了一个 IPv6 地址作为规则的前缀,并指定了前缀的长度和与规则关联的下一跳信息。然后,我们检查了规则添加操作的结果,并在结束时释放了创建的 LPM 对象。
2.4 rte_lpm6_delete
2.4.1 函数介绍
函数用于从 IPv6 的最长前缀匹配(Longest Prefix Match, LPM)表中删除规则。
int rte_lpm6_delete(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth);
2.4.2 参数说明
lpm:指向要从中删除规则的 IPv6 LPM 对象的指针。
ip:要从 LPM 表中删除的 IPv6 地址的字节流表示形式,以 uint8_t 数组形式传递。
depth:要删除的规则的前缀长度
如果成功删除规则,则返回 0。
如果删除规则失败,则返回负值,表示错误的原因。
2.4.3 实例
#include #include #include #define LPM_NAME "example_lpm6" #define SOCKET_ID 0 #define MAX_RULES 1024 #define NUM_TBL8S 1024 int main() { // 创建 LPM 配置结构 struct rte_lpm6_config config = { .max_rules = MAX_RULES, .number_tbl8s = NUM_TBL8S, .flags = 0 // 此字段当前未使用 }; // 创建 IPv6 LPM 对象 struct rte_lpm6 *lpm = rte_lpm6_create(LPM_NAME, SOCKET_ID, &config); if (lpm == NULL) { printf("Failed to create LPM object\n"); return -1; } // 添加规则 uint8_t ip[] = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; // IPv6地址 uint8_t depth = 64; // 前缀长度 uint32_t next_hop = 1; // 下一跳信息 int ret = rte_lpm6_add(lpm, ip, depth, next_hop); if (ret != 0) { printf("Failed to add rule to LPM\n"); rte_lpm6_free(lpm); return -1; } // 删除规则 ret = rte_lpm6_delete(lpm, ip, depth); if (ret != 0) { printf("Failed to delete rule from LPM\n"); rte_lpm6_free(lpm); return -1; } // 使用 LPM 对象进行其他操作(添加规则、查询、删除等) // 释放 LPM 对象 rte_lpm6_free(lpm); return 0; }
2.5 rte_lpm6_lookup
2.5.1 函数介绍
函数用于在 IPv6 的最长前缀匹配(Longest Prefix Match, LPM)表中查找给定的 IPv6 地址,并提供与匹配规则关联的下一跳信息
int rte_lpm6_lookup(const struct rte_lpm6 *lpm, const uint8_t *ip, uint32_t *next_hop);
2.5.2 参数说明
lpm:指向要查询的 IPv6 LPM 对象的指针。
ip:要查找的 IPv6 地址的字节流表示形式,以 uint8_t 数组形式传递。
next_hop:用于存储查找到的下一跳信息的指针。
如果查找成功并找到匹配的规则,则返回 0。
如果查找失败,即未找到匹配的规则,则返回负值,表示错误的原因。
2.5.3 实例
#include #include #include #define LPM_NAME "example_lpm6" #define SOCKET_ID 0 #define MAX_RULES 1024 #define NUM_TBL8S 1024 int main() { // 创建 LPM 配置结构 struct rte_lpm6_config config = { .max_rules = MAX_RULES, .number_tbl8s = NUM_TBL8S, .flags = 0 // 此字段当前未使用 }; // 创建 IPv6 LPM 对象 struct rte_lpm6 *lpm = rte_lpm6_create(LPM_NAME, SOCKET_ID, &config); if (lpm == NULL) { printf("Failed to create LPM object\n"); return -1; } // 添加规则 uint8_t ip[] = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; // IPv6地址 uint8_t depth = 64; // 前缀长度 uint32_t next_hop = 1; // 下一跳信息 int ret = rte_lpm6_add(lpm, ip, depth, next_hop); if (ret != 0) { printf("Failed to add rule to LPM\n"); rte_lpm6_free(lpm); return -1; } // 查找规则 uint32_t found_next_hop; ret = rte_lpm6_lookup(lpm, ip, &found_next_hop); if (ret == 0) { printf("Next hop found: %u\n", found_next_hop); } else { printf("Rule not found in LPM\n"); } // 使用 LPM 对象进行其他操作(添加规则、删除规则等) // 释放 LPM 对象 rte_lpm6_free(lpm); return 0; }
2.6 rte_lpm6_is_rule_present
2.6.1 函数介绍
函数用于检查指定的 IPv6 地址是否存在于 IPv6 的最长前缀匹配(Longest Prefix Match, LPM)表中,并提供与该规则关联的下一跳信息。
int rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth, uint32_t *next_hop);
2.6.2 参数说明
lpm:指向要查询的 IPv6 LPM 对象的指针。
ip:要查询的 IPv6 地址的字节流表示形式,以 uint8_t 数组形式传递。
depth:要查询的规则的前缀长度。
next_hop:用于存储查找到的下一跳信息的指针。
如果规则存在并且成功找到,则返回 1。
如果规则不存在,则返回 0。
如果发生错误,则返回负值,表示错误的原因。
2.6.3 实例
#include #include #include #define LPM_NAME "example_lpm6" #define SOCKET_ID 0 #define MAX_RULES 1024 #define NUM_TBL8S 1024 int main() { // 创建 LPM 配置结构 struct rte_lpm6_config config = { .max_rules = MAX_RULES, .number_tbl8s = NUM_TBL8S, .flags = 0 // 此字段当前未使用 }; // 创建 IPv6 LPM 对象 struct rte_lpm6 *lpm = rte_lpm6_create(LPM_NAME, SOCKET_ID, &config); if (lpm == NULL) { printf("Failed to create LPM object\n"); return -1; } // 添加规则 uint8_t ip[] = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; // IPv6地址 uint8_t depth = 64; // 前缀长度 uint32_t next_hop = 1; // 下一跳信息 int ret = rte_lpm6_add(lpm, ip, depth, next_hop); if (ret != 0) { printf("Failed to add rule to LPM\n"); rte_lpm6_free(lpm); return -1; } // 检查规则是否存在 uint32_t found_next_hop; ret = rte_lpm6_is_rule_present(lpm, ip, depth, &found_next_hop); if (ret == 1) { printf("Rule is present, next hop: %u\n", found_next_hop); } else if (ret == 0) { printf("Rule is not present in LPM\n"); } else { printf("Error checking rule presence\n"); } // 使用 LPM 对象进行其他操作(添加规则、删除规则等) // 释放 LPM 对象 rte_lpm6_free(lpm); return 0; }
2.7 rte_lpm6_free
2.7.1 函数介绍
函数用于释放 IPv6 最长前缀匹配(Longest Prefix Match, LPM)对象所占用的资源,并将其销毁。
void rte_lpm6_free(struct rte_lpm6 *lpm);
2.7.2 参数说明
lpm:要释放的 IPv6 LPM 对象的指针。
2.7.3 实例
#include #include #define LPM_NAME "example_lpm6" #define SOCKET_ID 0 #define MAX_RULES 1024 #define NUM_TBL8S 1024 int main() { // 创建 LPM 配置结构 struct rte_lpm6_config config = { .max_rules = MAX_RULES, .number_tbl8s = NUM_TBL8S, .flags = 0 // 此字段当前未使用 }; // 创建 IPv6 LPM 对象 struct rte_lpm6 *lpm = rte_lpm6_create(LPM_NAME, SOCKET_ID, &config); if (lpm == NULL) { printf("Failed to create LPM object\n"); return -1; } // 使用 LPM 对象进行其他操作(添加规则、删除规则等) // 释放 LPM 对象 rte_lpm6_free(lpm); return 0; }
还没有评论,来说两句吧...