Looks good, thanks. Ethan
On Mon, Apr 16, 2012 at 17:19, Ben Pfaff <b...@nicira.com> wrote: > Until now, crediting statistics to OpenFlow rules due to "resubmit" actions > has required setting up a "resubmit hook" with a callback function and > auxiliary data. This commit makes it easier to do, by adding a member to > struct action_xlate_ctx that specifies statistics to credit to each > resubmitted rule. > > This commit includes one small behavioral change as an optimization. > Previously, rule_execute() translated the rule twice: once to get the ODP > actions, then a second time after executing the ODP actions to credit > statistics to the rules. After this commit, rule_execute() translates the > rule only once, crediting statistics as a side effect. The difference only > becomes visible when executing the actions fails: previously the statistics > would not be incremented, after this commit they will be. It is very > unusual for executing actions to fail (generally this indicates a bug) so > I'm not concerned about it. > > Signed-off-by: Ben Pfaff <b...@nicira.com> > --- > lib/dpif.c | 3 +- > ofproto/ofproto-dpif.c | 117 > ++++++++++++++++++++++++------------------------ > 2 files changed, 59 insertions(+), 61 deletions(-) > > diff --git a/lib/dpif.c b/lib/dpif.c > index 02b10f1..836860d 100644 > --- a/lib/dpif.c > +++ b/lib/dpif.c > @@ -674,8 +674,7 @@ dpif_port_poll_wait(const struct dpif *dpif) > } > > /* Extracts the flow stats for a packet. The 'flow' and 'packet' > - * arguments must have been initialized through a call to flow_extract(). > - */ > + * arguments must have been initialized through a call to flow_extract(). */ > void > dpif_flow_stats_extract(const struct flow *flow, const struct ofpbuf *packet, > struct dpif_flow_stats *stats) > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index 0a2c963..8eeefd3 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -105,10 +105,10 @@ static struct rule_dpif *rule_dpif_cast(const struct > rule *rule) > static struct rule_dpif *rule_dpif_lookup(struct ofproto_dpif *, > const struct flow *, uint8_t table); > > +static void rule_credit_stats(struct rule_dpif *, > + const struct dpif_flow_stats *); > static void flow_push_stats(struct rule_dpif *, const struct flow *, > - uint64_t packets, uint64_t bytes, > - long long int used); > - > + const struct dpif_flow_stats *); > static tag_type rule_calculate_tag(const struct flow *, > const struct flow_wildcards *, > uint32_t basis); > @@ -225,13 +225,23 @@ struct action_xlate_ctx { > * timeouts.) */ > uint8_t tcp_flags; > > - /* If nonnull, called just before executing a resubmit action. In > - * addition, disables logging of traces when the recursion depth is > - * exceeded. > + /* If nonnull, flow translation calls this function just before > executing a > + * resubmit or OFPP_TABLE action. In addition, disables logging of > traces > + * when the recursion depth is exceeded. > + * > + * 'rule' is the rule being submitted into. It will be null if the > + * resubmit or OFPP_TABLE action didn't find a matching rule. > * > * This is normally null so the client has to set it manually after > * calling action_xlate_ctx_init(). */ > - void (*resubmit_hook)(struct action_xlate_ctx *, struct rule_dpif *); > + void (*resubmit_hook)(struct action_xlate_ctx *, struct rule_dpif *rule); > + > + /* If nonnull, flow translation credits the specified statistics to each > + * rule reached through a resubmit or OFPP_TABLE action. > + * > + * This is normally null so the client has to set it manually after > + * calling action_xlate_ctx_init(). */ > + const struct dpif_flow_stats *resubmit_stats; > > /* xlate_actions() initializes and uses these members. The client might want > * to look at them after it returns. */ > @@ -3754,68 +3764,52 @@ facet_reset_counters(struct facet *facet) > static void > facet_push_stats(struct facet *facet) > { > - uint64_t new_packets, new_bytes; > + struct dpif_flow_stats stats; > > assert(facet->packet_count >= facet->prev_packet_count); > assert(facet->byte_count >= facet->prev_byte_count); > assert(facet->used >= facet->prev_used); > > - new_packets = facet->packet_count - facet->prev_packet_count; > - new_bytes = facet->byte_count - facet->prev_byte_count; > + stats.n_packets = facet->packet_count - facet->prev_packet_count; > + stats.n_bytes = facet->byte_count - facet->prev_byte_count; > + stats.used = facet->used; > + stats.tcp_flags = 0; > > - if (new_packets || new_bytes || facet->used > facet->prev_used) { > + if (stats.n_packets || stats.n_bytes || facet->used > facet->prev_used) { > facet->prev_packet_count = facet->packet_count; > facet->prev_byte_count = facet->byte_count; > facet->prev_used = facet->used; > > - flow_push_stats(facet->rule, &facet->flow, > - new_packets, new_bytes, facet->used); > + flow_push_stats(facet->rule, &facet->flow, &stats); > > update_mirror_stats(ofproto_dpif_cast(facet->rule->up.ofproto), > - facet->mirrors, new_packets, new_bytes); > + facet->mirrors, stats.n_packets, stats.n_bytes); > } > } > > -struct ofproto_push { > - struct action_xlate_ctx ctx; > - uint64_t packets; > - uint64_t bytes; > - long long int used; > -}; > - > static void > -push_resubmit(struct action_xlate_ctx *ctx, struct rule_dpif *rule) > +rule_credit_stats(struct rule_dpif *rule, const struct dpif_flow_stats > *stats) > { > - struct ofproto_push *push = CONTAINER_OF(ctx, struct ofproto_push, ctx); > - > - if (rule) { > - rule->packet_count += push->packets; > - rule->byte_count += push->bytes; > - ofproto_rule_update_used(&rule->up, push->used); > - } > + rule->packet_count += stats->n_packets; > + rule->byte_count += stats->n_bytes; > + ofproto_rule_update_used(&rule->up, stats->used); > } > > /* Pushes flow statistics to the rules which 'flow' resubmits into given > * 'rule''s actions and mirrors. */ > static void > flow_push_stats(struct rule_dpif *rule, > - const struct flow *flow, uint64_t packets, uint64_t bytes, > - long long int used) > + const struct flow *flow, const struct dpif_flow_stats *stats) > { > struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto); > - struct ofproto_push push; > - > - push.packets = packets; > - push.bytes = bytes; > - push.used = used; > + struct action_xlate_ctx ctx; > > - ofproto_rule_update_used(&rule->up, used); > + ofproto_rule_update_used(&rule->up, stats->used); > > - action_xlate_ctx_init(&push.ctx, ofproto, flow, flow->vlan_tci, rule, > + action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, rule, > 0, NULL); > - push.ctx.resubmit_hook = push_resubmit; > - xlate_actions_for_side_effects(&push.ctx, > - rule->up.actions, rule->up.n_actions); > + ctx.resubmit_stats = stats; > + xlate_actions_for_side_effects(&ctx, rule->up.actions, > rule->up.n_actions); > } > > /* Subfacets. */ > @@ -4249,22 +4243,24 @@ rule_execute(struct rule *rule_, const struct flow > *flow, > struct rule_dpif *rule = rule_dpif_cast(rule_); > struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto); > > - size_t size = packet->size; > + struct dpif_flow_stats stats; > > struct action_xlate_ctx ctx; > uint64_t odp_actions_stub[1024 / 8]; > struct ofpbuf odp_actions; > > + dpif_flow_stats_extract(flow, packet, &stats); > + rule_credit_stats(rule, &stats); > + > ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub); > action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, > - rule, packet_get_tcp_flags(packet, flow), packet); > + rule, stats.tcp_flags, packet); > + ctx.resubmit_stats = &stats; > xlate_actions(&ctx, rule->up.actions, rule->up.n_actions, &odp_actions); > - if (execute_odp_actions(ofproto, flow, odp_actions.data, > - odp_actions.size, packet)) { > - rule->packet_count++; > - rule->byte_count += size; > - flow_push_stats(rule, flow, 1, size, time_msec()); > - } > + > + execute_odp_actions(ofproto, flow, odp_actions.data, > + odp_actions.size, packet); > + > ofpbuf_uninit(&odp_actions); > > return 0; > @@ -4527,6 +4523,10 @@ xlate_table_action(struct action_xlate_ctx *ctx, > if (rule) { > struct rule_dpif *old_rule = ctx->rule; > > + if (ctx->resubmit_stats) { > + rule_credit_stats(rule, ctx->resubmit_stats); > + } > + > ctx->recurse++; > ctx->rule = rule; > do_xlate_actions(rule->up.actions, rule->up.n_actions, ctx); > @@ -5127,6 +5127,7 @@ action_xlate_ctx_init(struct action_xlate_ctx *ctx, > ctx->may_learn = packet != NULL; > ctx->tcp_flags = tcp_flags; > ctx->resubmit_hook = NULL; > + ctx->resubmit_stats = NULL; > } > > /* Translates the 'n_in' "union ofp_action"s in 'in' into datapath actions in > @@ -5938,28 +5939,26 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf > *packet, > ofproto->max_ports); > if (!error) { > struct odputil_keybuf keybuf; > + struct dpif_flow_stats stats; > + > struct ofpbuf key; > > + struct action_xlate_ctx ctx; > uint64_t odp_actions_stub[1024 / 8]; > struct ofpbuf odp_actions; > - struct ofproto_push push; > > ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); > odp_flow_key_from_flow(&key, flow); > > - action_xlate_ctx_init(&push.ctx, ofproto, flow, flow->vlan_tci, NULL, > - packet_get_tcp_flags(packet, flow), packet); > + dpif_flow_stats_extract(flow, packet, &stats); > > - /* Ensure that resubmits in 'ofp_actions' get accounted to their > - * matching rules. */ > - push.packets = 1; > - push.bytes = packet->size; > - push.used = time_msec(); > - push.ctx.resubmit_hook = push_resubmit; > + action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, NULL, > + packet_get_tcp_flags(packet, flow), packet); > + ctx.resubmit_stats = &stats; > > ofpbuf_use_stub(&odp_actions, > odp_actions_stub, sizeof odp_actions_stub); > - xlate_actions(&push.ctx, ofp_actions, n_ofp_actions, &odp_actions); > + xlate_actions(&ctx, ofp_actions, n_ofp_actions, &odp_actions); > dpif_execute(ofproto->dpif, key.data, key.size, > odp_actions.data, odp_actions.size, packet); > ofpbuf_uninit(&odp_actions); > -- > 1.7.9 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev