X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif-xlate.c;h=da538b7f8d807931e0aec36131ba0a8a0c67c65f;hb=HEAD;hp=c62424a37e7de02620edf546b9db9cd3b30c24ac;hpb=1a7c0cd710e19db3ff85606dbfd5fdad964a1eea;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index c62424a37..da538b7f8 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -192,6 +192,10 @@ struct xlate_ctx { uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */ bool exit; /* No further actions should be processed. */ + bool use_recirc; /* Should generate recirc? */ + struct xlate_recirc recirc; /* Information used for generating + * recirculation actions */ + /* OpenFlow 1.1+ action set. * * 'action_set' accumulates "struct ofpact"s added by OFPACT_WRITE_ACTIONS. @@ -770,8 +774,9 @@ xport_stp_listen_state(const struct xport *xport) static bool stp_should_process_flow(const struct flow *flow, struct flow_wildcards *wc) { + /* is_stp() also checks dl_type, but dl_type is always set in 'wc'. */ memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst); - return eth_addr_equals(flow->dl_dst, eth_addr_stp); + return is_stp(flow); } static void @@ -970,9 +975,10 @@ lookup_input_bundle(const struct xbridge *xbridge, ofp_port_t in_port, return xport->xbundle; } - /* Special-case OFPP_NONE, which a controller may use as the ingress - * port for traffic that it is sourcing. */ - if (in_port == OFPP_NONE) { + /* Special-case OFPP_NONE (OF1.0) and OFPP_CONTROLLER (OF1.1+), + * which a controller may use as the ingress port for traffic that + * it is sourcing. */ + if (in_port == OFPP_CONTROLLER || in_port == OFPP_NONE) { return &ofpp_none_bundle; } @@ -1207,19 +1213,19 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, /* Partially configured bundle with no slaves. Drop the packet. */ return; } else if (!out_xbundle->bond) { - ctx->xout->use_recirc = false; + ctx->use_recirc = false; xport = CONTAINER_OF(list_front(&out_xbundle->xports), struct xport, bundle_node); } else { struct ofport_dpif *ofport; - struct xlate_recirc *xr = &ctx->xout->recirc; + struct xlate_recirc *xr = &ctx->recirc; struct flow_wildcards *wc = &ctx->xout->wc; if (ctx->xbridge->enable_recirc) { - ctx->xout->use_recirc = bond_may_recirc( + ctx->use_recirc = bond_may_recirc( out_xbundle->bond, &xr->recirc_id, &xr->hash_basis); - if (ctx->xout->use_recirc) { + if (ctx->use_recirc) { /* Only TCP mode uses recirculation. */ xr->hash_alg = OVS_HASH_ALG_L4; bond_update_post_recirc_rules(out_xbundle->bond, false); @@ -1240,7 +1246,7 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, /* If ctx->xout->use_recirc is set, the main thread will handle stats * accounting for this bond. */ - if (!ctx->xout->use_recirc) { + if (!ctx->use_recirc) { if (ctx->xin->resubmit_stats) { bond_account(out_xbundle->bond, &ctx->xin->flow, vid, ctx->xin->resubmit_stats->n_bytes); @@ -1772,11 +1778,7 @@ process_special(struct xlate_ctx *ctx, const struct flow *flow, bfd_process_packet(xport->bfd, flow, packet); /* If POLL received, immediately sends FINAL back. */ if (bfd_should_send_packet(xport->bfd)) { - if (xport->peer) { - ofproto_dpif_monitor_port_send_soon(xport->ofport); - } else { - ofproto_dpif_monitor_port_send_soon_safe(xport->ofport); - } + ofproto_dpif_monitor_port_send_soon(xport->ofport); } } return SLOW_BFD; @@ -1820,7 +1822,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, xlate_report(ctx, "OFPPC_NO_FWD set, skipping output"); return; } else if (check_stp) { - if (eth_addr_equals(ctx->base_flow.dl_dst, eth_addr_stp)) { + if (is_stp(&ctx->base_flow)) { if (!xport_stp_listen_state(xport)) { xlate_report(ctx, "STP not in listening state, " "skipping bpdu output"); @@ -1950,9 +1952,9 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, &ctx->xout->odp_actions, &ctx->xout->wc); - if (ctx->xout->use_recirc) { + if (ctx->use_recirc) { struct ovs_action_hash *act_hash; - struct xlate_recirc *xr = &ctx->xout->recirc; + struct xlate_recirc *xr = &ctx->recirc; /* Hash action. */ act_hash = nl_msg_put_unspec_uninit(&ctx->xout->odp_actions, @@ -1991,18 +1993,11 @@ static void xlate_recursively(struct xlate_ctx *ctx, struct rule_dpif *rule) { struct rule_dpif *old_rule = ctx->rule; - struct rule_actions *actions; + const struct rule_actions *actions; if (ctx->xin->resubmit_stats) { rule_dpif_credit_stats(rule, ctx->xin->resubmit_stats); } - if (ctx->xin->xcache) { - struct xc_entry *entry; - - entry = xlate_cache_add_entry(ctx->xin->xcache, XC_RULE); - entry->u.rule = rule; - rule_dpif_ref(rule); - } ctx->resubmits++; ctx->recurse++; @@ -2057,7 +2052,8 @@ xlate_table_action(struct xlate_ctx *ctx, ofp_port_t in_port, uint8_t table_id, !skip_wildcards ? &ctx->xout->wc : NULL, honor_table_miss, - &ctx->table_id, &rule, true); + &ctx->table_id, &rule, + ctx->xin->xcache != NULL); ctx->xin->flow.in_port.ofp_port = old_in_port; if (ctx->xin->resubmit_hook) { @@ -2090,12 +2086,22 @@ xlate_table_action(struct xlate_ctx *ctx, ofp_port_t in_port, uint8_t table_id, } choose_miss_rule(config, ctx->xbridge->miss_rule, - ctx->xbridge->no_packet_in_rule, &rule, true); + ctx->xbridge->no_packet_in_rule, &rule, + ctx->xin->xcache != NULL); match: if (rule) { + /* Fill in the cache entry here instead of xlate_recursively + * to make the reference counting more explicit. We take a + * reference in the lookups above if we are going to cache the + * rule. */ + if (ctx->xin->xcache) { + struct xc_entry *entry; + + entry = xlate_cache_add_entry(ctx->xin->xcache, XC_RULE); + entry->u.rule = rule; + } xlate_recursively(ctx, rule); - rule_dpif_unref(rule); } ctx->table_id = old_table_id; @@ -2653,6 +2659,8 @@ xlate_learn_action(struct xlate_ctx *ctx, entry = xlate_cache_add_entry(ctx->xin->xcache, XC_LEARN); entry->u.learn.ofproto = ctx->xin->ofproto; + /* Lookup the learned rule, taking a reference on it. The reference + * is released when this cache entry is deleted. */ rule_dpif_lookup(ctx->xbridge->ofproto, &ctx->xin->flow, NULL, &entry->u.learn.rule, true); } @@ -2678,10 +2686,11 @@ xlate_fin_timeout(struct xlate_ctx *ctx, struct xc_entry *entry; entry = xlate_cache_add_entry(ctx->xin->xcache, XC_FIN_TIMEOUT); + /* XC_RULE already holds a reference on the rule, none is taken + * here. */ entry->u.fin.rule = ctx->rule; entry->u.fin.idle = oft->fin_idle_timeout; entry->u.fin.hard = oft->fin_hard_timeout; - rule_dpif_ref(ctx->rule); } } } @@ -2717,7 +2726,7 @@ xlate_sample_action(struct xlate_ctx *ctx, static bool may_receive(const struct xport *xport, struct xlate_ctx *ctx) { - if (xport->config & (eth_addr_equals(ctx->xin->flow.dl_dst, eth_addr_stp) + if (xport->config & (is_stp(&ctx->xin->flow) ? OFPUTIL_PC_NO_RECV_STP : OFPUTIL_PC_NO_RECV)) { return false; @@ -3183,7 +3192,7 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) struct flow *flow = &xin->flow; struct rule_dpif *rule = NULL; - struct rule_actions *actions = NULL; + const struct rule_actions *actions = NULL; enum slow_path_reason special; const struct ofpact *ofpacts; struct xport *in_port; @@ -3230,7 +3239,7 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) ctx.xbridge = xbridge_lookup(xin->ofproto); if (!ctx.xbridge) { - goto out; + return; } ctx.rule = xin->rule; @@ -3259,11 +3268,12 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) ctx.orig_skb_priority = flow->skb_priority; ctx.table_id = 0; ctx.exit = false; + ctx.use_recirc = false; if (!xin->ofpacts && !ctx.rule) { ctx.table_id = rule_dpif_lookup(ctx.xbridge->ofproto, flow, !xin->skip_wildcards ? wc : NULL, - &rule, true); + &rule, ctx.xin->xcache != NULL); if (ctx.xin->resubmit_stats) { rule_dpif_credit_stats(rule, ctx.xin->resubmit_stats); } @@ -3271,13 +3281,11 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) struct xc_entry *entry; entry = xlate_cache_add_entry(ctx.xin->xcache, XC_RULE); - rule_dpif_ref(rule); entry->u.rule = rule; } ctx.rule = rule; } xout->fail_open = ctx.rule && rule_dpif_is_fail_open(ctx.rule); - xout->use_recirc = false; if (xin->ofpacts) { ofpacts = xin->ofpacts; @@ -3309,7 +3317,7 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) break; case OFPC_FRAG_DROP: - goto out; + return; case OFPC_FRAG_REASM: OVS_NOT_REACHED(); @@ -3456,9 +3464,6 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) wc->masks.tp_src &= htons(UINT8_MAX); wc->masks.tp_dst &= htons(UINT8_MAX); } - -out: - rule_dpif_unref(rule); } /* Sends 'packet' out 'ofport'. @@ -3580,9 +3585,9 @@ xlate_push_stats(struct xlate_cache *xcache, bool may_learn, struct rule_dpif *rule = entry->u.learn.rule; /* Reset the modified time for a rule that is equivalent to - * the currently cached rule. If the rule is not the exact - * rule wehave cached, update the reference that we have. */ - entry->u.learn.rule = ofproto_dpif_refresh_rule(rule); + * the currently cached rule. If the rule is not the exact + * rule we have cached, update the reference that we have. */ + entry->u.learn.rule = ofproto_dpif_refresh_rule(rule); } break; case XC_NORMAL: @@ -3651,13 +3656,15 @@ xlate_cache_clear(struct xlate_cache *xcache) mbridge_unref(entry->u.mirror.mbridge); break; case XC_LEARN: + /* 'u.learn.rule' is the learned rule. */ rule_dpif_unref(entry->u.learn.rule); break; case XC_NORMAL: free(entry->u.normal.flow); break; case XC_FIN_TIMEOUT: - rule_dpif_unref(entry->u.fin.rule); + /* 'u.fin.rule' is always already held as a XC_RULE, which + * has already released it's reference above. */ break; default: OVS_NOT_REACHED();