diff mbox

[ovs-dev] ovn-controller: Persist desired conntrack groups.

Message ID 1469593387-28419-1-git-send-email-rmoats@us.ibm.com
State Changes Requested
Headers show

Commit Message

Ryan Moats July 27, 2016, 4:23 a.m. UTC
[1] indicates that with incremental processing of logical flows
desired conntrack groups are not being persisted.  This patch
adds this capability, with the side effect of adding a ds_copy
method that this capability leverages.

[1] http://openvswitch.org/pipermail/dev/2016-July/076320.html

Signed-off-by: Ryan Moats <rmoats@us.ibm.com>
---
 include/openvswitch/dynamic-string.h |  1 +
 lib/dynamic-string.c                 |  8 ++++++++
 ovn/controller/lflow.c               |  4 +++-
 ovn/controller/ofctrl.c              | 33 +++++++++++++++++++++++----------
 ovn/controller/ofctrl.h              |  3 +++
 ovn/lib/actions.c                    | 11 ++++++++---
 ovn/lib/actions.h                    |  9 +++++++--
 tests/test-ovn.c                     |  5 ++++-
 8 files changed, 57 insertions(+), 17 deletions(-)

Comments

Ben Pfaff July 28, 2016, 6:02 a.m. UTC | #1
On Wed, Jul 27, 2016 at 04:23:07AM +0000, Ryan Moats wrote:
> [1] indicates that with incremental processing of logical flows
> desired conntrack groups are not being persisted.  This patch
> adds this capability, with the side effect of adding a ds_copy
> method that this capability leverages.
> 
> [1] http://openvswitch.org/pipermail/dev/2016-July/076320.html

Thanks for the fix!  Would you mind transforming the above to use
Reported-at, Reported-by, and Fixes?

> Signed-off-by: Ryan Moats <rmoats@us.ibm.com>

> +void
> +ds_copy(struct ds *dst, struct ds *source)
> +{
> +    dst->length = source->length;
> +    dst->allocated = source->allocated;
> +    dst->string = xmemdup(source->string, source->allocated + 1);
> +}

In the case where allocate is much bigger than length, the above is
pretty wasteful.  Would you mind doing separate xmalloc() and memcpy()
steps?

We tend to use the term "clone" for operations that initialize and copy
in one step; "copy" tend to imply copying into an already-initialized
destination.  So I would be more likely to call this ds_clone().

The actions_parse() function has a pretty clear explanatory comment, but
it doesn't hint at what the new uuid parameter means.  Also, should the
new parameter be part of action_params?  It's where most of the
parameters related to parsing go.

Thanks,

Ben.
Ryan Moats July 28, 2016, 12:56 p.m. UTC | #2
Ben Pfaff <blp@ovn.org> wrote on 07/28/2016 01:02:47 AM:

> From: Ben Pfaff <blp@ovn.org>
> To: Ryan Moats/Omaha/IBM@IBMUS
> Cc: dev@openvswitch.org
> Date: 07/28/2016 01:03 AM
> Subject: Re: [ovs-dev] [PATCH] ovn-controller: Persist desired
> conntrack groups.
>
> On Wed, Jul 27, 2016 at 04:23:07AM +0000, Ryan Moats wrote:
> > [1] indicates that with incremental processing of logical flows
> > desired conntrack groups are not being persisted.  This patch
> > adds this capability, with the side effect of adding a ds_copy
> > method that this capability leverages.
> >
> > [1] http://openvswitch.org/pipermail/dev/2016-July/076320.html
>
> Thanks for the fix!  Would you mind transforming the above to use
> Reported-at, Reported-by, and Fixes?

Sure, I can do that...

> > Signed-off-by: Ryan Moats <rmoats@us.ibm.com>
>
> > +void
> > +ds_copy(struct ds *dst, struct ds *source)
> > +{
> > +    dst->length = source->length;
> > +    dst->allocated = source->allocated;
> > +    dst->string = xmemdup(source->string, source->allocated + 1);
> > +}
>
> In the case where allocate is much bigger than length, the above is
> pretty wasteful.  Would you mind doing separate xmalloc() and memcpy()
> steps?

I went back and forth on this one between keeping it *as is* and doing
xmalloc + memcpy, so I ended up mentally flipping a coin
(and of course, got it wrong), so sure, I can do that.

> We tend to use the term "clone" for operations that initialize and copy
> in one step; "copy" tend to imply copying into an already-initialized
> destination.  So I would be more likely to call this ds_clone().

I also went back and forth on "copy" vs "clone" in the name, with the
same mental coin flip/result as above (in case anybody is wondering,
I don't play games of chance for obvious reasons).

> The actions_parse() function has a pretty clear explanatory comment, but
> it doesn't hint at what the new uuid parameter means...

I can certainly fix this.

> Also, should the
> new parameter be part of action_params?  It's where most of the
> parameters related to parsing go.

Since I see that have to do a rebase as well, I'm willing to see about
putting this in the action_params and see how it goes...

Ryan
diff mbox

Patch

diff --git a/include/openvswitch/dynamic-string.h b/include/openvswitch/dynamic-string.h
index dfe2688..398e41a 100644
--- a/include/openvswitch/dynamic-string.h
+++ b/include/openvswitch/dynamic-string.h
@@ -73,6 +73,7 @@  void ds_swap(struct ds *, struct ds *);
 
 int ds_last(const struct ds *);
 bool ds_chomp(struct ds *, int c);
+void ds_copy(struct ds *, struct ds *);
 
 /* Inline functions. */
 
diff --git a/lib/dynamic-string.c b/lib/dynamic-string.c
index 1f17a9f..692468f 100644
--- a/lib/dynamic-string.c
+++ b/lib/dynamic-string.c
@@ -456,3 +456,11 @@  ds_chomp(struct ds *ds, int c)
         return false;
     }
 }
+
+void
+ds_copy(struct ds *dst, struct ds *source)
+{
+    dst->length = source->length;
+    dst->allocated = source->allocated;
+    dst->string = xmemdup(source->string, source->allocated + 1);
+}
diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index 42c9055..67b702c 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -383,6 +383,7 @@  add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports,
 
     if (full_flow_processing) {
         ovn_flow_table_clear();
+        ovn_group_table_clear(group_table, false);
         full_logical_flow_processing = true;
         full_neighbor_flow_processing = true;
         full_flow_processing = false;
@@ -522,7 +523,8 @@  consider_logical_flow(const struct lport_index *lports,
         .output_ptable = output_ptable,
         .arp_ptable = OFTABLE_MAC_BINDING,
     };
-    error = actions_parse_string(lflow->actions, &ap, &ofpacts, &prereqs);
+    error = actions_parse_string(lflow->actions, &ap, &ofpacts, &prereqs,
+                                 &lflow->header_.uuid);
     if (error) {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
         VLOG_WARN_RL(&rl, "error parsing actions \"%s\": %s",
diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c
index f0451b7..40591c7 100644
--- a/ovn/controller/ofctrl.c
+++ b/ovn/controller/ofctrl.c
@@ -118,9 +118,6 @@  static enum mf_field_id mff_ovn_geneve;
 
 static void ovn_flow_table_destroy(void);
 
-static void ovn_group_table_clear(struct group_table *group_table,
-                                  bool existing);
-
 static void ofctrl_recv(const struct ofp_header *, enum ofptype);
 
 static struct hmap match_flow_table = HMAP_INITIALIZER(&match_flow_table);
@@ -630,6 +627,16 @@  ofctrl_remove_flows(const struct uuid *uuid)
             ovn_flow_destroy(f);
         }
     }
+
+    /* Remove any group_info information created by this logical flow. */
+    struct group_info *g, *next_g;
+    HMAP_FOR_EACH_SAFE (g, next_g, hmap_node, &groups->desired_groups) {
+        if (uuid_equals(&g->lflow_uuid, uuid)) {
+            hmap_remove(&groups->desired_groups, &g->hmap_node);
+            ds_destroy(&g->group);
+            free(g);
+        }
+    }
 }
 
 /* Shortcut to remove all flows matching the supplied UUID and add this
@@ -777,6 +784,15 @@  queue_flow_mod(struct ofputil_flow_mod *fm)
 
 /* group_table. */
 
+static struct group_info *
+group_info_clone(struct group_info *source) {
+    struct group_info *clone = xmalloc(sizeof *clone);
+    ds_copy(&clone->group, &source->group);
+    clone->group_id = source->group_id;
+    clone->hmap_node.hash = source->hmap_node.hash;
+    return clone;
+}
+
 /* Finds and returns a group_info in 'existing_groups' whose key is identical
  * to 'target''s key, or NULL if there is none. */
 static struct group_info *
@@ -795,7 +811,7 @@  ovn_group_lookup(struct hmap *exisiting_groups,
 }
 
 /* Clear either desired_groups or existing_groups in group_table. */
-static void
+void
 ovn_group_table_clear(struct group_table *group_table, bool existing)
 {
     struct group_info *g, *next;
@@ -1000,13 +1016,10 @@  ofctrl_put(struct group_table *group_table)
     /* Move the contents of desired_groups to existing_groups. */
     HMAP_FOR_EACH_SAFE(desired, next_group, hmap_node,
                        &group_table->desired_groups) {
-        hmap_remove(&group_table->desired_groups, &desired->hmap_node);
         if (!ovn_group_lookup(&group_table->existing_groups, desired)) {
-            hmap_insert(&group_table->existing_groups, &desired->hmap_node,
-                        desired->hmap_node.hash);
-        } else {
-            ds_destroy(&desired->group);
-            free(desired);
+            struct group_info *clone = group_info_clone(desired);
+            hmap_insert(&group_table->existing_groups, &clone->hmap_node,
+                        clone->hmap_node.hash);
         }
     }
 }
diff --git a/ovn/controller/ofctrl.h b/ovn/controller/ofctrl.h
index 49b95b0..a6fffec 100644
--- a/ovn/controller/ofctrl.h
+++ b/ovn/controller/ofctrl.h
@@ -53,4 +53,7 @@  void ofctrl_flow_table_clear(void);
 
 void ovn_flow_table_clear(void);
 
+void ovn_group_table_clear(struct group_table *group_table,
+                           bool existing);
+
 #endif /* ovn/ofctrl.h */
diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
index 6e2bf93..64a9de8 100644
--- a/ovn/lib/actions.c
+++ b/ovn/lib/actions.c
@@ -42,6 +42,7 @@  struct action_context {
     char *error;                /* Error, if any, otherwise NULL. */
     struct ofpbuf *ofpacts;     /* Actions. */
     struct expr *prereqs;       /* Prerequisites to apply to match. */
+    struct uuid lflow_uuid;     /* Parent lflow UUID (for group removal). */
 };
 
 static bool parse_action(struct action_context *);
@@ -761,6 +762,7 @@  parse_ct_lb_action(struct action_context *ctx)
         group_info = xmalloc(sizeof *group_info);
         group_info->group = ds;
         group_info->group_id = group_id;
+        group_info->lflow_uuid = ctx->lflow_uuid;
         group_info->hmap_node.hash = hash;
 
         hmap_insert(&ctx->ap->group_table->desired_groups,
@@ -1120,7 +1122,8 @@  parse_actions(struct action_context *ctx)
   */
 char * OVS_WARN_UNUSED_RESULT
 actions_parse(struct lexer *lexer, const struct action_params *ap,
-              struct ofpbuf *ofpacts, struct expr **prereqsp)
+              struct ofpbuf *ofpacts, struct expr **prereqsp,
+              const struct uuid *uuid)
 {
     size_t ofpacts_start = ofpacts->size;
 
@@ -1130,6 +1133,7 @@  actions_parse(struct lexer *lexer, const struct action_params *ap,
         .error = NULL,
         .ofpacts = ofpacts,
         .prereqs = NULL,
+        .lflow_uuid = *uuid,
     };
     parse_actions(&ctx);
 
@@ -1147,14 +1151,15 @@  actions_parse(struct lexer *lexer, const struct action_params *ap,
 /* Like actions_parse(), but the actions are taken from 's'. */
 char * OVS_WARN_UNUSED_RESULT
 actions_parse_string(const char *s, const struct action_params *ap,
-                     struct ofpbuf *ofpacts, struct expr **prereqsp)
+                     struct ofpbuf *ofpacts, struct expr **prereqsp,
+                     const struct uuid *uuid)
 {
     struct lexer lexer;
     char *error;
 
     lexer_init(&lexer, s);
     lexer_get(&lexer);
-    error = actions_parse(&lexer, ap, ofpacts, prereqsp);
+    error = actions_parse(&lexer, ap, ofpacts, prereqsp, uuid);
     lexer_destroy(&lexer);
 
     return error;
diff --git a/ovn/lib/actions.h b/ovn/lib/actions.h
index 114c71e..72efa95 100644
--- a/ovn/lib/actions.h
+++ b/ovn/lib/actions.h
@@ -22,7 +22,9 @@ 
 #include "compiler.h"
 #include "openvswitch/hmap.h"
 #include "openvswitch/dynamic-string.h"
+#include "openvswitch/uuid.h"
 #include "util.h"
+#include "uuid.h"
 
 struct expr;
 struct lexer;
@@ -43,6 +45,7 @@  struct group_table {
 struct group_info {
     struct hmap_node hmap_node;
     struct ds group;
+    struct uuid lflow_uuid;
     uint32_t group_id;
 };
 
@@ -132,10 +135,12 @@  struct action_params {
 };
 
 char *actions_parse(struct lexer *, const struct action_params *,
-                    struct ofpbuf *ofpacts, struct expr **prereqsp)
+                    struct ofpbuf *ofpacts, struct expr **prereqsp,
+                    const struct uuid *uuid)
     OVS_WARN_UNUSED_RESULT;
 char *actions_parse_string(const char *s, const struct action_params *,
-                           struct ofpbuf *ofpacts, struct expr **prereqsp)
+                           struct ofpbuf *ofpacts, struct expr **prereqsp,
+                           const struct uuid *uuid)
     OVS_WARN_UNUSED_RESULT;
 
 #endif /* ovn/actions.h */
diff --git a/tests/test-ovn.c b/tests/test-ovn.c
index 26055bb..afd7b31 100644
--- a/tests/test-ovn.c
+++ b/tests/test-ovn.c
@@ -1319,7 +1319,10 @@  test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED)
             .output_ptable = 64,
             .arp_ptable = 65,
         };
-        error = actions_parse_string(ds_cstr(&input), &ap, &ofpacts, &prereqs);
+        struct uuid uuid;
+        uuid_zero(&uuid);
+        error = actions_parse_string(ds_cstr(&input), &ap, &ofpacts, &prereqs,
+                                     &uuid);
         if (!error) {
             struct ds output;