文章目录
- 前言
- 基本概念
- 示例代码说明
- 最后
前言
本文介绍dpdk flow api的简单使用。
dpdk flow 的使用过程和 iptables 差不多。即,数据包匹配上指定的规则后,执行对应的动作。
本文示例代码来自Basic RTE Flow Filtering Sample Application。
这篇内容还是“水”了点。随手笔记吧。
基本概念
总的来说:dpdk flow 可以对数据包的协议头等进行匹配。可能执行的动作是丢弃流量,将流量转移到指定队列等。
dpdk flow 有这些基本概念:
Attributes
: 数据流规则的属性,如其方向(入口或出口)和优先级。(这里面还有个group属性。 group 0是默认必经过的。如果想到其他group,需要执行JUMP操作。其他group中有不同的action。这些group可能被物理设备支持,或者以虚拟的方式支持。示例代码中没有显示使用group,可以暂时不管)Pattern item
: 描述匹配的样式。即,什么样的包会命中样式。Actions
: 当数据包与样式匹配时,执行的操作。
示例代码说明
下面这个示例代码来自“前言”中的链接。含义是,当port_id
端口进入的数据包,满足src_ip/mask -> dst_ip/mask
的pattern时,将其转移到rx_q
队列上。
代码还是比较简单的。我简单介绍下。
Attributes
在dpdk中的结构体是rte_flow_attr
。attr.ingress = 1;
表示 Pattern 将应用在入站流量上。Pattern
在dpdk中的结构是rte_flow_item
。代码中填充了一个src_ip/mask -> dst_ip/mask
样式。Actions
在dpdk中的结构是rte_flow_action
。代码中填充了一个将流量转移到指定队列的动作。- 相关函数:
rte_flow_create
则是在指定端口上,创建一个flow rule。
/*** create a flow rule that sends packets with matching src and dest ip* to selected queue.** @param port_id* The selected port.* @param rx_q* The selected target queue.* @param src_ip* The src ip value to match the input packet.* @param src_mask* The mask to apply to the src ip.* @param dest_ip* The dest ip value to match the input packet.* @param dest_mask* The mask to apply to the dest ip.* @param[out] error* Perform verbose error reporting if not NULL.** @return* A flow if the rule could be created else return NULL.*//* Function responsible for creating the flow rule. 8< */
struct rte_flow *generate_ipv4_flow(uint16_t port_id, uint16_t rx_q,uint32_t src_ip, uint32_t src_mask,uint32_t dest_ip, uint32_t dest_mask,struct rte_flow_error *error) {/* Declaring structs being used. 8< */struct rte_flow_attr attr;struct rte_flow_item pattern[MAX_PATTERN_NUM];struct rte_flow_action action[MAX_ACTION_NUM];struct rte_flow *flow = NULL;struct rte_flow_action_queue queue = {.index = rx_q};struct rte_flow_item_ipv4 ip_spec;struct rte_flow_item_ipv4 ip_mask;/* >8 End of declaring structs being used. */int res;memset(pattern, 0, sizeof(pattern));memset(action, 0, sizeof(action));/* Set the rule attribute, only ingress packets will be checked. 8< */memset(&attr, 0, sizeof(struct rte_flow_attr));attr.ingress = 1;/* >8 End of setting the rule attribute. *//** create the action sequence.* one action only, move packet to queue*/action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;action[0].conf = &queue;action[1].type = RTE_FLOW_ACTION_TYPE_END;/** set the first level of the pattern (ETH).* since in this example we just want to get the* ipv4 we set this level to allow all.*//* Set this level to allow all. 8< */pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;/* >8 End of setting the first level of the pattern. *//** setting the second level of the pattern (IP).* in this example this is the level we care about* so we set it according to the parameters.*//* Setting the second level of the pattern. 8< */memset(&ip_spec, 0, sizeof(struct rte_flow_item_ipv4));memset(&ip_mask, 0, sizeof(struct rte_flow_item_ipv4));ip_spec.hdr.dst_addr = htonl(dest_ip);ip_mask.hdr.dst_addr = dest_mask;ip_spec.hdr.src_addr = htonl(src_ip);ip_mask.hdr.src_addr = src_mask;pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;pattern[1].spec = &ip_spec;pattern[1].mask = &ip_mask;/* >8 End of setting the second level of the pattern. *//* The final level must be always type end. 8< */pattern[2].type = RTE_FLOW_ITEM_TYPE_END;/* >8 End of final level must be always type end. *//* Validate the rule and create it. 8< */res = rte_flow_validate(port_id, &attr, pattern, action, error);if (!res)flow = rte_flow_create(port_id, &attr, pattern, action, error);/* >8 End of validation the rule and create it. */return flow;
}
/* >8 End of function responsible for creating the flow rule. */
最后
我们现在已经了解了 dpdk flow 最简单的使用了。难度大概是 “1+1=2”。
如果想要在日常工作中使用dpdk flow, 难度大概是解二元一次方程,需要看更多的示例代码。