您的位置:首页 > 产品设计 > UI/UE

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

2016-08-10 21:04 507 查看
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;
}
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络