searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

ovs+dpdk硬件卸载流表添加流程-2

2023-07-25 08:16:12
140
0

上文写到:
//调用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();
    }
}
0条评论
作者已关闭评论
郑****理
4文章数
0粉丝数
郑****理
4 文章 | 0 粉丝
郑****理
4文章数
0粉丝数
郑****理
4 文章 | 0 粉丝
原创

ovs+dpdk硬件卸载流表添加流程-2

2023-07-25 08:16:12
140
0

上文写到:
//调用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();
    }
}
文章来自个人专栏
ovs-dpdk卸载
4 文章 | 1 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0