Handle implicit recirculation explicitly for each action type, so that it is easier to follow what is happening.
Signed-off-by: Jarno Rajahalme <ja...@ovn.org> --- ofproto/ofproto-dpif-xlate.c | 164 +++++++++++++++++++++++++------------------ 1 file changed, 97 insertions(+), 67 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 1edc1b0..54ee73f 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -354,12 +354,6 @@ ctx_trigger_recirculation(struct xlate_ctx *ctx) ctx->recirc_action_offset = ctx->action_set.size; } -static bool -ctx_first_recirculation_action(const struct xlate_ctx *ctx) -{ - return ctx->recirc_action_offset == ctx->action_set.size; -} - static inline bool exit_recirculates(const struct xlate_ctx *ctx) { @@ -4247,16 +4241,6 @@ recirc_unroll_actions(const struct ofpact *ofpacts, size_t ofpacts_len, } } -#define CHECK_MPLS_RECIRCULATION() \ - if (ctx->was_mpls) { \ - ctx_trigger_recirculation(ctx); \ - break; \ - } -#define CHECK_MPLS_RECIRCULATION_IF(COND) \ - if (COND) { \ - CHECK_MPLS_RECIRCULATION(); \ - } - static void put_ct_mark(const struct flow *flow, struct flow *base_flow, struct ofpbuf *odp_actions, struct flow_wildcards *wc) @@ -4413,12 +4397,20 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc) } static void +xlate_implicit_recirculation(const struct ofpact *ofpacts, size_t ofpacts_len, + struct xlate_ctx *ctx) +{ + ctx_trigger_recirculation(ctx); + recirc_unroll_actions(ofpacts, ofpacts_len, ctx); +} + +static void do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, struct xlate_ctx *ctx) { struct flow_wildcards *wc = ctx->wc; struct flow *flow = &ctx->xin->flow; - const struct ofpact *a; + const struct ofpact *a, * const end = ofpact_end(ofpacts, ofpacts_len); if (ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) { tnl_neigh_snoop(flow, wc, ctx->xbridge->name); @@ -4426,6 +4418,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, /* dl_type already in the mask, not set below. */ OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { + size_t rem_len = (uint8_t *)end - (uint8_t *)a; struct ofpact_controller *controller; const struct ofpact_metadata *metadata; const struct ofpact_set_field *set_field; @@ -4436,13 +4429,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, } if (ctx->exit) { - /* Check if need to store the remaining actions for later - * execution. */ if (exit_recirculates(ctx)) { - recirc_unroll_actions(a, OFPACT_ALIGN(ofpacts_len - - ((uint8_t *)a - - (uint8_t *)ofpacts)), - ctx); + /* Remaining actions must be executed after recirculation. */ + recirc_unroll_actions(a, rem_len, ctx); } break; } @@ -4451,6 +4440,10 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_OUTPUT: xlate_output_action(ctx, ofpact_get_OUTPUT(a)->port, ofpact_get_OUTPUT(a)->max_len, true); + if (exit_recirculates(ctx)) { + /* OUTPUT needs recirculation before it can be translated. */ + recirc_unroll_actions(a, rem_len, ctx); + } break; case OFPACT_GROUP: @@ -4515,7 +4508,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_SET_IPV4_SRC: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } if (flow->dl_type == htons(ETH_TYPE_IP)) { memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src); flow->nw_src = ofpact_get_SET_IPV4_SRC(a)->ipv4; @@ -4523,7 +4518,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_SET_IPV4_DST: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } if (flow->dl_type == htons(ETH_TYPE_IP)) { memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst); flow->nw_dst = ofpact_get_SET_IPV4_DST(a)->ipv4; @@ -4531,7 +4528,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_SET_IP_DSCP: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } if (is_ip_any(flow)) { wc->masks.nw_tos |= IP_DSCP_MASK; flow->nw_tos &= ~IP_DSCP_MASK; @@ -4540,7 +4539,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_SET_IP_ECN: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } if (is_ip_any(flow)) { wc->masks.nw_tos |= IP_ECN_MASK; flow->nw_tos &= ~IP_ECN_MASK; @@ -4549,7 +4550,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_SET_IP_TTL: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } if (is_ip_any(flow)) { wc->masks.nw_ttl = 0xff; flow->nw_ttl = ofpact_get_SET_IP_TTL(a)->ttl; @@ -4557,7 +4560,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_SET_L4_SRC_PORT: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } if (is_ip_any(flow) && !(flow->nw_frag & FLOW_NW_FRAG_LATER)) { memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src); @@ -4566,7 +4571,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_SET_L4_DST_PORT: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } if (is_ip_any(flow) && !(flow->nw_frag & FLOW_NW_FRAG_LATER)) { memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst); @@ -4594,11 +4601,10 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, * the resubmit to the post-recirculation actions. */ if (ctx->was_mpls) { - ctx_trigger_recirculation(ctx); - break; + return xlate_implicit_recirculation(a, rem_len, ctx); } xlate_ofpact_resubmit(ctx, ofpact_get_RESUBMIT(a)); - continue; + break; case OFPACT_SET_TUNNEL: flow->tunnel.tun_id = htonll(ofpact_get_SET_TUNNEL(a)->tun_id); @@ -4617,15 +4623,19 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_REG_MOVE: - CHECK_MPLS_RECIRCULATION_IF( - mf_is_l3_or_higher(ofpact_get_REG_MOVE(a)->dst.field) || - mf_is_l3_or_higher(ofpact_get_REG_MOVE(a)->src.field)); + if (ctx->was_mpls && + (mf_is_l3_or_higher(ofpact_get_REG_MOVE(a)->dst.field) || + mf_is_l3_or_higher(ofpact_get_REG_MOVE(a)->src.field))) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } nxm_execute_reg_move(ofpact_get_REG_MOVE(a), flow, wc); break; case OFPACT_SET_FIELD: - CHECK_MPLS_RECIRCULATION_IF( - mf_is_l3_or_higher(ofpact_get_SET_FIELD(a)->field)); + if (ctx->was_mpls && + mf_is_l3_or_higher(ofpact_get_SET_FIELD(a)->field)) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } set_field = ofpact_get_SET_FIELD(a); mf = set_field->field; @@ -4651,15 +4661,19 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_STACK_PUSH: - CHECK_MPLS_RECIRCULATION_IF( - mf_is_l3_or_higher(ofpact_get_STACK_PUSH(a)->subfield.field)); + if (ctx->was_mpls && + mf_is_l3_or_higher(ofpact_get_STACK_PUSH(a)->subfield.field)) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } nxm_execute_stack_push(ofpact_get_STACK_PUSH(a), flow, wc, &ctx->stack); break; case OFPACT_STACK_POP: - CHECK_MPLS_RECIRCULATION_IF( - mf_is_l3_or_higher(ofpact_get_STACK_POP(a)->subfield.field)); + if (ctx->was_mpls && + mf_is_l3_or_higher(ofpact_get_STACK_POP(a)->subfield.field)) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } nxm_execute_stack_pop(ofpact_get_STACK_POP(a), flow, wc, &ctx->stack); break; @@ -4670,43 +4684,57 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, * action converted it to IP. In this case recirculating should * reveal the IP TTL which is used as the basis for a new MPLS * LSE. */ - CHECK_MPLS_RECIRCULATION_IF( - !flow_count_mpls_labels(flow, wc) + if (ctx->was_mpls + && !flow_count_mpls_labels(flow, wc) && flow->nw_ttl == 0 - && is_ip_any(flow)); + && is_ip_any(flow)) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } compose_mpls_push_action(ctx, ofpact_get_PUSH_MPLS(a)); break; case OFPACT_POP_MPLS: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } compose_mpls_pop_action(ctx, ofpact_get_POP_MPLS(a)->ethertype); break; case OFPACT_SET_MPLS_LABEL: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } compose_set_mpls_label_action( ctx, ofpact_get_SET_MPLS_LABEL(a)->label); break; case OFPACT_SET_MPLS_TC: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } compose_set_mpls_tc_action(ctx, ofpact_get_SET_MPLS_TC(a)->tc); break; case OFPACT_SET_MPLS_TTL: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } compose_set_mpls_ttl_action(ctx, ofpact_get_SET_MPLS_TTL(a)->ttl); break; case OFPACT_DEC_MPLS_TTL: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } if (compose_dec_mpls_ttl_action(ctx)) { return; } break; case OFPACT_DEC_TTL: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } wc->masks.nw_ttl = 0xff; if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL(a))) { return; @@ -4718,12 +4746,16 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_MULTIPATH: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } multipath_execute(ofpact_get_MULTIPATH(a), flow, wc); break; case OFPACT_BUNDLE: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } xlate_bundle_action(ctx, ofpact_get_BUNDLE(a)); break; @@ -4732,7 +4764,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_LEARN: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } xlate_learn_action(ctx, ofpact_get_LEARN(a)); break; @@ -4759,7 +4793,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; } case OFPACT_FIN_TIMEOUT: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); xlate_fin_timeout(ctx, ofpact_get_FIN_TIMEOUT(a)); break; @@ -4789,6 +4825,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, ovs_assert(ctx->table_id < ogt->table_id); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } xlate_table_action(ctx, ctx->xin->flow.in_port.ofp_port, ogt->table_id, true, true); break; @@ -4799,7 +4838,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_CT: - CHECK_MPLS_RECIRCULATION(); + if (ctx->was_mpls) { + return xlate_implicit_recirculation(a, rem_len, ctx); + } compose_conntrack_action(ctx, ofpact_get_CT(a)); break; @@ -4810,17 +4851,6 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_DEBUG_RECIRC: ctx_trigger_recirculation(ctx); - a = ofpact_next(a); - break; - } - - /* Check if need to store this and the remaining actions for later - * execution. */ - if (!ctx->error && ctx->exit && ctx_first_recirculation_action(ctx)) { - recirc_unroll_actions(a, OFPACT_ALIGN(ofpacts_len - - ((uint8_t *)a - - (uint8_t *)ofpacts)), - ctx); break; } } -- 2.1.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev