rte_flow的创建流程
DPDK通过rte_flow
提供的流控制功能,通过dpdk example中的flow_filtering实例,可以看到rte_flow的简单应用。实例实现的功能为:针对指定目的IP的报文,进入指定的网卡rx队列。实现步骤如下:
- 创建
struct rte_flow_attr
,指定匹配报文的方向。 - 创建
struct rte_flow_action
,指定动作类型为报文通过特定rx队列接收。 - 创建
struct rte_flow_item
,指定匹配报文的IP地址。 - 调用
rte_flow_validate
校验创建flow的参数是否合理。 - 调用
rte_flow_create
创建flow,并下发配置到网卡。
源码如下:
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)
{
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;
int res;
memset(pattern, 0, sizeof(pattern));
memset(action, 0, sizeof(action));
memset(&attr, 0, sizeof(struct rte_flow_attr));
attr.ingress = 1;//过滤入方向
//rte_flow_action的type指定动作类型,conf指定动作对象
//RTE_FLOW_ACTION_TYPE_QUEUE : 动作类型:将流发给指定队列
//conf : 动作对象:指定的队列号
//action数组RTE_FLOW_ACTION_TYPE_END结束
action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
action[0].conf = &queue;
action[1].type = RTE_FLOW_ACTION_TYPE_END;
//pattern[0] : eth header不做限制
pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
//pattern[1] : 针对IP header,匹配指定src dst地址
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;
//pattern数组必须使用RTE_FLOW_ITEM_TYPE_END结束
pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
//flow校验
res = rte_flow_validate(port_id, &attr, pattern, action, error);
printf("err after rte_flow_validate : %s\n", error->message);
//在指定的port上创建flow
//if (!res) {
flow = rte_flow_create(port_id, &attr, pattern, action, error);
printf("err after rte_flow_create : %s\n", error->message);
//}
return flow;
}
流规则创建相关API
rte_flow_item_ipv4
使用dpdk提供的rte_flow_item_ipv4
记录IP头部信息。
struct rte_flow_item_ipv4 {
struct ipv4_hdr hdr; /**< IPv4 header definition. */
};
rte_flow_validate
用于校验指定网口是否有能力创建指定的流规则。
int
rte_flow_validate(uint16_t port_id,
const struct rte_flow_attr *attr,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error);
- 返回值 : 校验成功返回0,失败返回负数
- port_id : 网卡ID
- attr : 流规则属性
- pattern : 流规则模式
- actions : 流规则动作
- error : 发生错误时的错误信息,通过error->message打印
rte_flow_create
创建流规则,并将流规则下发到网卡。
struct rte_flow *
rte_flow_create(uint16_t port_id,
const struct rte_flow_attr *attr,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error)
- 返回值 : 返回rte_flow类型实例
- port_id : 网卡ID
- attr : 流规则属性
- pattern : 流规则模式
- actions : 流规则动作
- error : 发生错误时的错误信息,通过error->message打印
rte_flow_destroy
删除指定port上的一条指定流规则。
int rte_flow_destroy(uint8_t port_id,
struct rte_flow* flow,
struct rte_flow_error* error);
- 返回值 : 成功返回0,失败返回负数
- port_id : 网卡ID
- flow : 待删除的流规则
- error : 发生错误时的错误信息,通过error->message打印
rte_flow_flush
清除port上的所有流规则
int
rte_flow_flush(uint16_t port_id,
struct rte_flow_error *error)
- 返回值 : 成功返回0,失败返回负数
- port_id : 网卡ID
- error : 发生错误时的错误信息,通过error->message打印
rte_flow_query
查询流规则是否存在
int rte_flow_query(uint8_t port_id,
struct rte_flow *flow,
enum rte_flow_action_type action,
void *data,
struct rte_flow_error *error);
- 返回值 : 成功返回0,失败返回负数