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;
/* 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;
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; }
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); }
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; }
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; } }
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; } }