> On Jan 5, 2017, at 5:04 PM, Ben Pfaff <[email protected]> wrote:
>
> diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c
> index 52c1758..017fbb1 100644
> --- a/ofproto/ofproto-dpif-trace.c
> +++ b/ofproto/ofproto-dpif-trace.c
> @@ -23,165 +23,82 @@
> ...
> +struct oftrace_node *
> +oftrace_report(struct ovs_list *super, enum oftrace_node_type type,
> + const char *text)
> {
> - ds_put_char_multiple(result, '\t', level);
> - ds_put_format(result, "%s: ", title);
> - /* Do not report unchanged flows for resubmits. */
> - if ((level > 0 && flow_equal(&trace->xin.flow, &trace->flow))
> - || (level == 0 && flow_equal(&trace->xin.flow, trace->key))) {
> - ds_put_cstr(result, "unchanged");
> - } else {
> - flow_format(result, &trace->xin.flow);
> - trace->flow = trace->xin.flow;
> - }
> - ds_put_char(result, '\n');
> + struct oftrace_node *node = xmalloc(sizeof *node);
> + ovs_list_push_back(super, &node->node);
> + node->type = type;
> + node->name = xstrdup(text);
> + node->always_indent = false;
> + ovs_list_init(&node->subs);
> +
> + return node;
> }
I think it would be helpful to have a comment describing this function. Also
mentioning that the caller maintains ownership of 'text'.
I may be missing something, but is there anything that frees these
"oftrace_node"s either here or ofproto-dpif-xlate.c?
>
> static void
> +oftrace_node_print_details(struct ds *output,
> + const struct ovs_list *nodes, int level)
> {
> + const struct oftrace_node *sub;
> + LIST_FOR_EACH (sub, node, nodes) {
> + bool more = sub->node.next != nodes || sub->always_indent ||
> oftrace_node_type_is_terminal(sub->type);
This line is much longer than 80 characters.
> + bool title = sub->type == OFT_BRIDGE;
>
> ...
> + if (title) {
> + ds_put_char(output, '\n');
> + }
> + ds_put_char_multiple(output, ' ', (level + more) * 4);
It's clever, but, 'more' being a bool looks kind of weird to me seeing it used
for math.
> + switch (sub->type) {
> + case OFT_DETAIL:
> + ds_put_format(output, " -> %s\n", sub->name);
> + break;
> + case OFT_WARN:
> + ds_put_format(output, " >> %s\n", sub->name);
> + break;
> + case OFT_ERROR:
> + ds_put_format(output, " >>>> %s <<<<\n", sub->name);
> + break;
> + case OFT_BRIDGE:
> + ds_put_format(output, "%s\n", sub->name);
> + ds_put_char_multiple(output, ' ', (level + more) * 4);
> + ds_put_char_multiple(output, '-', strlen(sub->name));
> + ds_put_char(output, '\n');
> + break;
> + case OFT_TABLE:
> + case OFT_THAW:
> + case OFT_ACTION:
> + ds_put_format(output, "%s\n", sub->name);
> + break;
> }
The actions printing at a shallower depth than the rule looks a little odd to
me. I suppose that helps if there are a lot of actions. Regardless, I'm sure
I'll get used to it.
> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> index 371ced4..f96468d 100644
> --- a/ofproto/ofproto-dpif-xlate.c
> +++ b/ofproto/ofproto-dpif-xlate.c
> ...
> +static struct ovs_list * OVS_PRINTF_FORMAT(3, 4)
> +xlate_report(const struct xlate_ctx *ctx, enum oftrace_node_type type,
> + const char *format, ...)
> {
> - if (OVS_UNLIKELY(ctx->xin->report_hook)) {
> + struct ovs_list *subtrace = NULL;
> + if (OVS_UNLIKELY(ctx->xin->trace)) {
> va_list args;
> -
> va_start(args, format);
> - ctx->xin->report_hook(ctx->xin, ctx->indentation, format, args);
> + char *text = xvasprintf(format, args);
> + subtrace = &oftrace_report(ctx->xin->trace, type, text)->subs;
I think you need to free "text", since oftrace_report() makes a copy.
>
> +/* This is like xlate_report() for errors that are serious enough that we
> + * should log them even if we are not tracing. */
> +static void OVS_PRINTF_FORMAT(2, 3)
> +xlate_report_error(const struct xlate_ctx *ctx, const char *format, ...)
The next two functions in the source file have comments pointing out that
they're similar to xlate_report(), but xlate_report() doesn't have a comment
describing it. It might be nice to do that.
> +static struct ovs_list *
> +xlate_report_actions(const struct xlate_ctx *ctx, enum oftrace_node_type
> type,
> + const char *title,
> const struct ofpact *ofpacts, size_t ofpacts_len)
> {
> - if (OVS_UNLIKELY(ctx->xin->report_hook)) {
> + struct ovs_list *subtrace = NULL;
> + if (OVS_UNLIKELY(ctx->xin->trace)) {
> struct ds s = DS_EMPTY_INITIALIZER;
> + ds_put_format(&s, "%s: ", title);
> ofpacts_format(ofpacts, ofpacts_len, &s);
> - xlate_report(ctx, "%s: %s", title, ds_cstr(&s));
> + subtrace = &oftrace_report(ctx->xin->trace, type, ds_cstr(&s))->subs;
> + ds_destroy(&s);
> + }
> + return subtrace;
> +}
> +
> +static void
> +xlate_report_action_set(const struct xlate_ctx *ctx, const char *verb)
> +{
> + if (OVS_UNLIKELY(ctx->xin->trace)) {
> + struct ofpbuf action_list;
> + ofpbuf_init(&action_list, 0);
> + ofpacts_execute_action_set(&action_list, &ctx->action_set);
> + if (action_list.size) {
> + struct ds s = DS_EMPTY_INITIALIZER;
> + ofpacts_format(action_list.data, action_list.size, &s);
> + xlate_report(ctx, OFT_DETAIL, "action set %s: %s",
> + verb, ds_cstr(&s));
> + ds_destroy(&s);
> + } else {
> + xlate_report(ctx, OFT_DETAIL, "action set %s empty", verb);
> + }
> + ofpbuf_uninit(&action_list);
> + }
> +}
The difference in behavior between xlate_report_actions() and
xlate_report_action_set() seem to be more than just that one has to do with
actions and the other with action sets. It might be nice to document the
differences.
> @@ -2966,6 +3106,7 @@ compose_output_action__(struct xlate_ctx *ctx,
> ofp_port_t ofp_port,
> struct ofpbuf old_stack = ctx->stack;
> union mf_subvalue new_stack[1024 / sizeof(union mf_subvalue)];
> struct ofpbuf old_action_set = ctx->action_set;
> + struct ovs_list *old_trace = ctx->xin->trace;
> uint64_t actset_stub[1024 / 8];
>
> ofpbuf_use_stub(&ctx->stack, new_stack, sizeof new_stack);
> @@ -2980,6 +3121,8 @@ compose_output_action__(struct xlate_ctx *ctx,
> ofp_port_t ofp_port,
> flow->actset_output = OFPP_UNSET;
> ctx->conntracked = false;
> clear_conntrack(flow);
> + ctx->xin->trace = xlate_report(ctx, OFT_BRIDGE,
> + "bridge(\"%s\")",
> peer->xbridge->name);
>
> /* When the patch port points to a different bridge, then the mirrors
> * for that bridge clearly apply independently to the packet, so we
> @@ -3031,6 +3174,7 @@ compose_output_action__(struct xlate_ctx *ctx,
> ofp_port_t ofp_port,
> }
> }
>
> + ctx->xin->trace = old_trace;
> if (independent_mirrors) {
> ctx->mirrors = old_mirrors;
> }
There are a few of these "old_trace" logic blocks, and I think the memory
management and linked list processing may not be handled properly.
> @@ -5603,12 +5823,9 @@ xlate_actions(struct xlate_in *xin, struct xlate_out
> *xout)
> * was done before they were frozen and should not be redone. */
> } else if (in_port && in_port->xbundle
> && xbundle_mirror_out(xbridge, in_port->xbundle)) {
> - if (ctx.xin->packet != NULL) {
> - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> - VLOG_WARN_RL(&rl, "bridge %s: dropping packet received on port "
> - "%s, which is reserved exclusively for mirroring",
> - ctx.xbridge->name, in_port->xbundle->name);
> - }
> + xlate_report_error(&ctx, "dropping packet received on port "
> + "%s, which is reserved exclusively for mirroring",
> + in_port->xbundle->name);
This used to only log when "ctx.xin->packet" was not null. Was this
intentionally changed?
> diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
> index 51c05ac..fa2b130 100644
> --- a/ofproto/ofproto-dpif-xlate.h
> +++ b/ofproto/ofproto-dpif-xlate.h
> @@ -83,27 +83,10 @@ struct xlate_in {
> * timeouts.) */
> uint16_t tcp_flags;
>
> - /* 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.
> - *
> - * 'indentation' is the resubmit recursion depth at time of invocation,
> - * suitable for indenting the output.
> - *
> - * This is normally null so the client has to set it manually after
> - * calling xlate_in_init(). */
> - void (*resubmit_hook)(struct xlate_in *, struct rule_dpif *rule,
> - int indentation);
> -
> - /* If nonnull, flow translation calls this function to report some
> - * significant decision, e.g. to explain why OFPP_NORMAL translation
> - * dropped a packet. 'indentation' is the resubmit recursion depth at
> time
> - * of invocation, suitable for indenting the output. */
> - void (*report_hook)(struct xlate_in *, int indentation,
> - const char *format, va_list args);
> + /* If nonnull, this indicates that the translation is being traced. It
> + * points to the list of oftrace nodes to which the translation should
> add
> + * tracing information (with oftrace_node_append()). */
> + struct ovs_list *trace;
I don't believe there is a function called oftrace_node_append(). Did you mean
oftrace_report()?
Thanks for working on this. The output is much more readable now.
Acked-by: Justin Pettit <[email protected]>
--Justin
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev