It seems odd to me that we call it 'may_add_flows' in facet_account, and 'do_learn_action' in action_xlate_ctx. I'd be inclined to call both of them the same thing. It strikes me, that an appropriate name for the flag may be "may_flow_mod" as that's the behavior we actually care about. If we add actions in the future which flow_mod, this flag would still be applicable.
Am I correct that this patch prevents leftover packets in the datapath from updating the timeouts in learned actions in some cases? e.g. if you change the actions of a rule, packets which applied to the old rule may not be properly accounted? This seems like a fine trade-off, just wanted to make sure I understand it. Looks good, thanks. Ethan On Tue, Mar 20, 2012 at 15:44, Ben Pfaff <b...@nicira.com> wrote: > "ovs-ofctl del-flows <bridge>" can result in the following call path: > > delete_flows_loose() in ofproto.c > -> collect_rules_loose() -- uses 'ofproto_node' inside 'struct rule' > -> rule_destruct() in ofproto-dpif.c > -> facet_revalidate() > -> facet_remove() > -> facet_flush_stats() > -> facet_account() > -> xlate_actions() > -> xlate_learn_action() > -> ofproto_flow_mod() back in ofproto.c > -> modify_flow_strict() > -> collect_rules_strict() -- also uses 'ofproto_node' > > which goes "boom" when we fall back up the call chain because the nested > use of ofproto_node steps on the outer use of ofproto_node. > > This commit fixes the problem by refusing to translate "learn" actions > within facet_flush_stats(), breaking the doubled use. > > Another possible approach would be to switch to another way to keep track > of rules in the flow_mod implementations, so that there'd be no fighting > over 'ofproto_node'. But then "ovs-ofctl del-flows" might still leave some > flows around (ones created by "learn" actions as flows are accounted as > facets get deleted), which would be surprising behavior. And it seems in > general a bad idea to allow recursive flow_mods; the consequences have not > been carefully thought through. > > Before this commit, one can reproduce the problem by running an "hping3" > between a couple of VMs plus the following commands on OVS in the middle. > Sometimes you have to run them a few times: > > ovs-ofctl del-flows br0 > ovs-ofctl add-flow br0 "table=0 actions=learn(table=1, \ > idle_timeout=600, NXM_OF_VLAN_TCI[0..11], \ > NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \ > output:NXM_OF_IN_PORT[], fin_idle_timeout=10), resubmit(,1)" > ovs-ofctl add-flow br0 "table=1 priority=0 actions=flood" > > Bug #10184. > Reported-by: Michael Mao <m...@nicira.com> > Signed-off-by: Ben Pfaff <b...@nicira.com> > --- > ofproto/ofproto-dpif.c | 34 +++++++++++++++++++++------------- > 1 files changed, 21 insertions(+), 13 deletions(-) > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index 200846b..0ffc4e8 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -209,11 +209,17 @@ struct action_xlate_ctx { > * revalidating without a packet to refer to. */ > const struct ofpbuf *packet; > > - /* Should OFPP_NORMAL MAC learning and NXAST_LEARN actions execute? We > - * want to execute them if we are actually processing a packet, or if we > - * are accounting for packets that the datapath has processed, but not if > - * we are just revalidating. */ > - bool may_learn; > + /* Should OFPP_NORMAL update the MAC learning table? We want to update > it > + * if we are actually processing a packet, or if we are accounting for > + * packets that the datapath has processed, but not if we are just > + * revalidating. */ > + bool do_learn_macs; > + > + /* Should "learn" actions update the flow table? We want to update it if > + * we are actually processing a packet, or in most cases if we are > + * accounting for packets that the datapath has processed, but not if we > + * are just revalidating. */ > + bool do_learn_action; > > /* The rule that we are currently translating, or NULL. */ > struct rule_dpif *rule; > @@ -346,7 +352,7 @@ static void facet_flush_stats(struct facet *); > static void facet_update_time(struct facet *, long long int used); > static void facet_reset_counters(struct facet *); > static void facet_push_stats(struct facet *); > -static void facet_account(struct facet *); > +static void facet_account(struct facet *, bool may_add_flows); > > static bool facet_is_controller_flow(struct facet *); > > @@ -2989,7 +2995,7 @@ update_stats(struct ofproto_dpif *p) > facet->tcp_flags |= stats->tcp_flags; > > subfacet_update_time(subfacet, stats->used); > - facet_account(facet); > + facet_account(facet, true); > facet_push_stats(facet); > } else { > if (!VLOG_DROP_WARN(&rl)) { > @@ -3241,7 +3247,7 @@ facet_remove(struct facet *facet) > } > > static void > -facet_account(struct facet *facet) > +facet_account(struct facet *facet, bool may_add_flows) > { > struct ofproto_dpif *ofproto = ofproto_dpif_cast(facet->rule->up.ofproto); > uint64_t n_bytes; > @@ -3267,7 +3273,8 @@ facet_account(struct facet *facet) > action_xlate_ctx_init(&ctx, ofproto, &facet->flow, > facet->flow.vlan_tci, > facet->rule, facet->tcp_flags, NULL); > - ctx.may_learn = true; > + ctx.do_learn_macs = true; > + ctx.do_learn_action = may_add_flows; > ofpbuf_delete(xlate_actions(&ctx, facet->rule->up.actions, > facet->rule->up.n_actions)); > } > @@ -3341,7 +3348,7 @@ facet_flush_stats(struct facet *facet) > } > > facet_push_stats(facet); > - facet_account(facet); > + facet_account(facet, false); > > if (ofproto->netflow && !facet_is_controller_flow(facet)) { > struct ofexpired expired; > @@ -4964,7 +4971,7 @@ do_xlate_actions(const union ofp_action *in, size_t > n_in, > > case OFPUTIL_NXAST_LEARN: > ctx->has_learn = true; > - if (ctx->may_learn) { > + if (ctx->do_learn_action) { > xlate_learn_action(ctx, (const struct nx_action_learn *) ia); > } > break; > @@ -5017,7 +5024,8 @@ action_xlate_ctx_init(struct action_xlate_ctx *ctx, > ctx->base_flow.vlan_tci = initial_tci; > ctx->rule = rule; > ctx->packet = packet; > - ctx->may_learn = packet != NULL; > + ctx->do_learn_macs = packet != NULL; > + ctx->do_learn_action = packet != NULL; > ctx->tcp_flags = tcp_flags; > ctx->resubmit_hook = NULL; > } > @@ -5645,7 +5653,7 @@ xlate_normal(struct action_xlate_ctx *ctx) > } > > /* Learn source MAC. */ > - if (ctx->may_learn) { > + if (ctx->do_learn_macs) { > update_learning_table(ctx->ofproto, &ctx->flow, vlan, in_bundle); > } > > -- > 1.7.2.5 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev