【OVS2.5.0源码分析】enqueue action精确流表生成过程分析

1、xlate_actions函数

  openflow流表匹配完成后,调用do_xlate_actions函数把openflow action转化为精确流表的action;


2、do_xlate_actions函数

        case OFPACT_ENQUEUE:
            memset(&wc->masks.skb_priority, 0xff,
                   sizeof wc->masks.skb_priority);
            xlate_enqueue_action(ctx, ofpact_get_ENQUEUE(a));
            break;

3、xlate_queue_action函数

    /* Translate queue to priority. */
    error = dpif_queue_to_priority(ctx->xbridge->dpif, queue_id, &priority);  <span style="color:#ff0000;">//queue id转化为priority</span>
    if (error) {
        /* Fall back to ordinary output action. */
        xlate_output_action(ctx, enqueue->port, 0, false);
        return;
    }

    /* Check output port. */
    if (ofp_port == OFPP_IN_PORT) {
        ofp_port = ctx->xin->flow.in_port.ofp_port;
    } else if (ofp_port == ctx->xin->flow.in_port.ofp_port) {
        return;
    }

    /* Add datapath actions. */
    flow_priority = ctx->xin->flow.skb_priority;   //保存skb_priority
    ctx->xin->flow.skb_priority = priority;        //设置该值,使得最终在output action之前会生成set action
    compose_output_action(ctx, ofp_port, NULL);   //构建output action
    ctx->xin->flow.skb_priority = flow_priority;

4、compose_output_action函数

    if (out_port != ODPP_NONE) {
        xlate_commit_actions(ctx);          //构建set action

        if (xr) {
            struct ovs_action_hash *act_hash;

            /* Hash action. */
            act_hash = nl_msg_put_unspec_uninit(ctx->odp_actions,
                                                OVS_ACTION_ATTR_HASH,
                                                sizeof *act_hash);
            act_hash->hash_alg = xr->hash_alg;
            act_hash->hash_basis = xr->hash_basis;

            /* Recirc action. */
            nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_RECIRC,
                           xr->recirc_id);
        } else {

            if (tnl_push_pop_send) {
                build_tunnel_send(ctx, xport, flow, odp_port);
                flow->tunnel = flow_tnl; /* Restore tunnel metadata */
            } else {
                odp_port_t odp_tnl_port = ODPP_NONE;

                /* XXX: Write better Filter for tunnel port. We can use inport
                * int tunnel-port flow to avoid these checks completely. */
                if (ofp_port == OFPP_LOCAL &&
                    ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) {

                    odp_tnl_port = tnl_port_map_lookup(flow, wc);
                }

                if (odp_tnl_port != ODPP_NONE) {
                    nl_msg_put_odp_port(ctx->odp_actions,
                                        OVS_ACTION_ATTR_TUNNEL_POP,
                                        odp_tnl_port);
                } else {
                    /* Tunnel push-pop action is not compatible with
                     * IPFIX action. */
                    compose_ipfix_action(ctx, out_port);
                    nl_msg_put_odp_port(ctx->odp_actions,
                                        OVS_ACTION_ATTR_OUTPUT,     //构建output action
                                        out_port);
               }
           }
        }

        ctx->sflow_odp_port = odp_port;
        ctx->sflow_n_outputs++;
        ctx->nf_output_iface = ofp_port;
    }

5、xlate_commit_actions函数

static void
xlate_commit_actions(struct xlate_ctx *ctx)
{
    bool use_masked = ctx->xbridge->support.masked_set_action;

    ctx->xout->slow |= <span style="color:#ff0000;"><strong>commit_odp_actions</strong></span>(&ctx->xin->flow, &ctx->base_flow,
                                          ctx->odp_actions, ctx->wc,
                                          use_masked);
}

6、commit_odp_actions函数

enum slow_path_reason
commit_odp_actions(const struct flow *flow, struct flow *base,
                   struct ofpbuf *odp_actions, struct flow_wildcards *wc,
                   bool use_masked)
{
    enum slow_path_reason slow1, slow2;

    commit_set_ether_addr_action(flow, base, odp_actions, wc, use_masked);
    slow1 = commit_set_nw_action(flow, base, odp_actions, wc, use_masked);
    commit_set_port_action(flow, base, odp_actions, wc, use_masked);
    slow2 = commit_set_icmp_action(flow, base, odp_actions, wc);
    commit_mpls_action(flow, base, odp_actions);
    commit_vlan_action(flow->vlan_tci, base, odp_actions, wc);
    commit_set_priority_action(flow, base, odp_actions, wc, use_masked);
    commit_set_pkt_mark_action(flow, base, odp_actions, wc, use_masked);

    return slow1 ? slow1 : slow2;
}

7、commit_set_priority_action函数

static void
commit_set_priority_action(const struct flow *flow, struct flow *base_flow,
                           struct ofpbuf *odp_actions,
                           struct flow_wildcards *wc,
                           bool use_masked)
{
    uint32_t key, mask, base;

    key = flow->skb_priority;
    base = base_flow->skb_priority;
    mask = wc->masks.skb_priority;
    if (commit(OVS_KEY_ATTR_PRIORITY, use_masked, &key, &base, &mask,    //因为flow和base_flow不同,添加set action
               sizeof key, odp_actions)) {
        base_flow->skb_priority = base;
        wc->masks.skb_priority = mask;
    }
}

8、commit函数

static bool
commit(enum ovs_key_attr attr, bool use_masked_set,
       const void *key, void *base, void *mask, size_t size,
       struct ofpbuf *odp_actions)
{
    if (memcmp(key, base, size)) {
        bool fully_masked = odp_mask_is_exact(attr, mask, size);

        if (use_masked_set && !fully_masked) {
            commit_masked_set_action(odp_actions, attr, key, mask, size);
        } else {
            if (!fully_masked) {
                memset(mask, 0xff, size);
            }
            commit_set_action(odp_actions, attr, key, size);   //生成action
        }
        memcpy(base, key, size);
        return true;
    } else {
        /* Mask bits are set when we have either read or set the corresponding
         * values.  Masked bits will be exact-matched, no need to set them
         * if the value did not actually change. */
        return false;
    }
}


你可能感兴趣的:(网络)