On Wed, Jun 21, 2017 at 1:02 PM, Joe Stringer <[email protected]> wrote:
> On 21 June 2017 at 11:06, Yi-Hung Wei <[email protected]> wrote:
>> Previous patch enables ofproto/trace to automatically trace a flow
>> that involves multiple recirculation on conntrack. However, it always
>> sets the ct_state to trk|est when it processes recirculated conntrack flows.
>> With this patch, users can customize the expected next ct_state in the
>> aforementioned use case.
>>
>> Signed-off-by: Yi-Hung Wei <[email protected]>
>> ---
>> NEWS | 2 +
>> ofproto/ofproto-dpif-trace.c | 111
>> ++++++++++++++++++++++++++++++++++++-------
>> ofproto/ofproto-dpif-trace.h | 6 +++
>> ofproto/ofproto-unixctl.man | 54 +++++++++++++++++++--
>> tests/completion.at | 8 ++--
>> tests/ofproto-dpif.at | 33 +++++++++----
>> 6 files changed, 182 insertions(+), 32 deletions(-)
>>
>> diff --git a/NEWS b/NEWS
>> index 4ea7e628e1fc..1824ec9de744 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -58,6 +58,8 @@ Post-v2.7.0
>> - Fedora Packaging:
>> * OVN services are no longer restarted automatically after upgrade.
>> - Add --cleanup option to command 'ovs-appctl exit' (see
>> ovs-vswitchd(8)).
>> + - Add --ct-next option to command 'ovs-appctl ofprot/trace' (see
>
> ofproto/trace.
Fixed in v3.
>
>> + ovs-vswitchd(8)).
>> - L3 tunneling:
>> * Add "layer3" options for tunnel ports that support non-Ethernet (L3)
>> payload (GRE, VXLAN-GPE).
>> diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c
>> index d8cdd92493cf..e75c62d464eb 100644
>> --- a/ofproto/ofproto-dpif-trace.c
>> +++ b/ofproto/ofproto-dpif-trace.c
>> @@ -18,6 +18,7 @@
>>
>> #include "ofproto-dpif-trace.h"
>>
>> +#include "conntrack.h"
>> #include "dpif.h"
>> #include "ofproto-dpif-xlate.h"
>> #include "openvswitch/ofp-parse.h"
>> @@ -26,7 +27,7 @@
>> static void ofproto_trace(struct ofproto_dpif *, struct flow *,
>> const struct dp_packet *packet,
>> const struct ofpact[], size_t ofpacts_len,
>> - struct ds *);
>> + struct ds *, struct ovs_list *next_ct_states);
>> static void oftrace_node_destroy(struct oftrace_node *);
>>
>> /* Creates a new oftrace_node, populates it with the given 'type' and a
>> copy of
>> @@ -119,6 +120,17 @@ oftrace_recirc_node_destroy(struct oftrace_recirc_node
>> *node)
>> free(node);
>> }
>>
>> +static uint32_t
>> +oftrace_next_ct_state(struct ovs_list *next_ct_states)
>> +{
>> + struct oftrace_next_ct_state *next_ct_state;
>> + ASSIGN_CONTAINER(next_ct_state, ovs_list_pop_front(next_ct_states),
>> node);
>> + uint32_t state = next_ct_state->state;
>> + free(next_ct_state);
>
> It wouldn't hurt to expand this a bit for improved readability,
> declaring the variables first, then getting the ovs_list_pop_front()
> pointer, then assigning the container, getting state and freeing.
Sure.
>
>> +
>> + return state;
>> +}
>> +
>> static void
>> oftrace_node_print_details(struct ds *output,
>> const struct ovs_list *nodes, int level)
>> @@ -160,18 +172,47 @@ oftrace_node_print_details(struct ds *output,
>> }
>> }
>>
>> +static char * OVS_WARN_UNUSED_RESULT
>> +parse_oftrace_options(int argc, const char *argv[],
>> + struct ovs_list *next_ct_states)
>> +{
>> + char *error = NULL;
>> + int k;
>> +
>> + for (k = 0; k < argc; k++) {
>> + if (!strncmp(argv[k], "--ct-next", 9)) {
>> + if (k + 1 > argc) {
>> + error = xasprintf("Missing argument for option %s",
>> argv[k]);
>> + return error;
>
> I guess these could just be return xasprintf(...) ?
Sure.
>
>> + }
>> +
>> + uint32_t ct_state = parse_ct_state(argv[++k], 0);
>
> I'm a bit concerned that parse_oftrace_options() may be called from
> ovs-vswitchd, and parse_ct_state() may, on parse failure, exit in a
> fatal manner. If this is the case, perhaps we should refactor
> parse_ct_state() into a version that should exit fatally for
> commandline execution, and the version run from the main vswitchd
> thread.
This is a good point. I break parse_ct_state() into parse_ct_state()
and validate_ct_sate(), and move the ovs_fatal() logic into the caller
of parse_ct_state(). Later on if ovs-vswitchd needs to use
parse_ct_state() it will not necessarily trigger ovs_fatal().
>
>> + struct oftrace_next_ct_state *next_state =
>> + xmalloc(sizeof *next_state);
>> + next_state->state = ct_state;
>> + ovs_list_push_back(next_ct_states, &next_state->node);
>
> You might consider refactoring the above into a function like
> oftrace_push_ct_state(next_ct_states, ct_state). Then the malloc/free
> operations would be matched between this new function and the above
> oftrace_next_ct_state().. which you may also consider renaming
> something like oftrace_pop_ct_state(...).
Thanks, that will be more clean. I refactor that in v2.
>
>> + } else {
>> + error = xasprintf("Invalid option %s", argv[k]);
>> + return error;
>
> Same as above xasprintf comment.
Yes.
>
>> + }
>> + }
>> +
>> + return error;
>> +}
>> +
>> /* Parses the 'argc' elements of 'argv', ignoring argv[0]. The following
>> * forms are supported:
>> *
>> - * - [dpname] odp_flow [-generate | packet]
>> - * - bridge br_flow [-generate | packet]
>> + * - [dpname] odp_flow [OPTIONS] [-generate | packet]
>> + * - bridge br_flow [OPTIONS] [-generate | packet]
>> *
>> * On success, initializes '*ofprotop' and 'flow' and returns NULL. On
>> failure
>> * returns a nonnull malloced error message. */
>> static char * OVS_WARN_UNUSED_RESULT
>> parse_flow_and_packet(int argc, const char *argv[],
>> struct ofproto_dpif **ofprotop, struct flow *flow,
>> - struct dp_packet **packetp)
>> + struct dp_packet **packetp,
>> + struct ovs_list *next_ct_states)
>> {
>> const struct dpif_backer *backer = NULL;
>> const char *error = NULL;
>> @@ -180,6 +221,7 @@ parse_flow_and_packet(int argc, const char *argv[],
>> struct dp_packet *packet;
>> struct ofpbuf odp_key;
>> struct ofpbuf odp_mask;
>> + int first_option;
>>
>> ofpbuf_init(&odp_key, 0);
>> ofpbuf_init(&odp_mask, 0);
>> @@ -199,6 +241,25 @@ parse_flow_and_packet(int argc, const char *argv[],
>> error = NULL;
>> }
>>
>> + /* Parse options. */
>> + if (argc >= 4) {
>> + if (!strncmp(argv[2], "--", 2)) {
>> + first_option = 2;
>> + } else if (!strncmp(argv[3], "--", 2)) {
>> + first_option = 3;
>> + } else {
>> + error = "Syntax error";
>
> Could you expand on this a bit? It can be confusing for users to get
> stonewalled with "Syntax error" and not know why the syntax was wrong.
> (I realise there's other examples later in the function where this
> error is used, it'd be nice to improve that as well).
I replace it with "Syntax error: invalid option"
>
> Thanks!
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev