上文写到:
//调用netdev的硬件卸载流表接口ret = netdev_flow_put(port, &offload->match,
CONST_CAST(struct nlattr *, offload->actions),
offload->actions_len, &flow->mega_ufid, &info,
NULL);
lib
etdev-offload-dpdk.c:
//入口函数
static int
netdev_offload_dpdk_flow_put(struct netdev *netdev, struct match *match,
struct nlattr *actions, size_t actions_len,
const ovs_u128 *ufid, struct offload_info *info,
struct dpif_flow_stats *stats)
{
struct ufid_to_rte_flow_data *rte_flow_data;
struct dpif_flow_stats old_stats;
bool modification = false;
int ret;
do_context_delayed_release();
/*
* If an old rte_flow exists, it means it's a flow modification.
* Here destroy the old rte flow first before adding a new one.
* Keep the stats for the newly created rule.
*/
//根据mega_ufid找是否已经存在rte_flow_data
rte_flow_data = ufid_to_rte_flow_data_find(ufid);
if (rte_flow_data) {
old_stats = rte_flow_data->stats;
modification = true;
//存在先删除
ret = netdev_offload_dpdk_remove_flows(netdev, ufid,
&rte_flow_data->flows);
if (ret < 0) {
return ret;
}
}
rte_flow_data = netdev_offload_dpdk_add_flow(netdev, match, actions,
actions_len, ufid, info);
if (!rte_flow_data) {
return -1;
}
if (modification) {
rte_flow_data->stats = old_stats;
}
if (stats) {
*stats = rte_flow_data->stats;
}
return 0;
}
//解析match和action,如果action解析不成功就只卸载match,如果成功就全卸载,关联mega_ufid和rte_flow_data
static struct ufid_to_rte_flow_data *
netdev_offload_dpdk_add_flow(struct netdev *netdev,
struct match *match,
struct nlattr *nl_actions,
size_t actions_len,
const ovs_u128 *ufid,
struct offload_info *info)
{
struct act_resources act_resources = { .flow_id = info->flow_mark };
struct flow_patterns patterns = { .items = NULL, .cnt = 0 };
struct flows_handle flows = { .items = NULL, .cnt = 0 };
struct act_vars act_vars = { .vport = ODPP_NONE };
struct flow_item flow_item = { .devargs = NULL };
struct ufid_to_rte_flow_data *flows_data = NULL;
bool actions_offloaded = true;
int ret;
//解析match,转成rte_flow的pattern
ret = parse_flow_match(netdev, &patterns, match, &act_resources,
&act_vars);
if (ret) {
goto out;
}
//解析action,转成rte_flow的action
ret = netdev_offload_dpdk_actions(netdev, &patterns, nl_actions,
actions_len, ufid, &act_resources,
&act_vars, &flows);
if (ret) {
/* If we failed to offload the rule actions fallback to MARK+RSS
* actions.
*/
actions_offloaded = false;
flow_item.rte_flow[0] = act_resources.self_table_id == 0 ?
netdev_offload_dpdk_mark_rss(&patterns, netdev, info->flow_mark) :
NULL;
ret = flow_item.rte_flow[0] ? 0 : -1;
if (ret) {
goto out;
}
VLOG_DBG_RL(&rl, "%s: installed flow %p by ufid "UUID_FMT"
",
netdev_get_name(netdev), flow_item.rte_flow[0],
UUID_ARGS((struct uuid *)ufid));
add_flow_item(&flows, &flow_item);
}
if (ret) {
goto out;
}
//关联mega_ufid和rte_flow_data
flows_data = ufid_to_rte_flow_associate(ufid, &flows, actions_offloaded,
&act_resources);
out:
if (ret) {
put_action_resources(netdev, &act_resources);
}
free_flow_patterns(&patterns);
return flows_data;
}
//如果netdev是vport(vxlan),就寻找他属于的dpdk netdev;找到dpdk netdev,调用netdev_offload_dpdk_flow_create
static int
create_offload_flow(struct netdev *netdev,
struct rte_flow_attr *attr,
const struct rte_flow_item *items,
const struct rte_flow_action *actions,
const ovs_u128 *ufid,
struct act_resources *act_resources,
struct act_vars *act_vars,
struct flows_handle *flows)
{
struct flow_item flow_item = { .devargs = NULL };
struct rte_flow_error error;
int ret;
if (netdev_vport_is_vport_class(netdev->netdev_class)) {
ret = netdev_offload_dpdk_create_tnl_flows(netdev, attr, items, actions,
ufid, act_resources,
act_vars, flows);
} else {
ret = netdev_offload_dpdk_flow_create(netdev, attr, items, actions,
&error, act_resources, act_vars,
&flow_item);
if (ret) {
goto out;
}
if (act_vars->explicit_netdev) {
flow_item.devargs = netdev_dpdk_get_port_devargs(netdev);
}
VLOG_DBG_RL(&rl, "%s: installed flow %p/%p by ufid "UUID_FMT"
",
netdev_get_name(netdev), flow_item.rte_flow[0],
flow_item.rte_flow[1],
UUID_ARGS((struct uuid *)ufid));
add_flow_item(flows, &flow_item);
}
out:
return ret;
}
static int
netdev_offload_dpdk_flow_create(struct netdev *netdev,
const struct rte_flow_attr *attr,
const struct rte_flow_item *items,
const struct rte_flow_action *actions,
struct rte_flow_error *error,
struct act_resources *act_resources,
struct act_vars *act_vars,
struct flow_item *fi)
{
switch (act_vars->ct_mode) {
case CT_MODE_NONE:
fi->has_count[0] = true;
return create_rte_flow(netdev, attr, items, actions, error, fi, 0);
case CT_MODE_CT:
/* fallthrough */
case CT_MODE_CT_NAT:
return create_pre_post_ct(netdev, attr, items, actions, error,
act_resources, act_vars, fi);
case CT_MODE_CT_CONN:
return create_ct_conn(netdev, items, actions, error, act_resources,
act_vars, fi);
default:
OVS_NOT_REACHED();
}
}