> On Jan 5, 2017, at 5:04 PM, Ben Pfaff <b...@ovn.org> 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 <jpet...@ovn.org>

--Justin



_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to