diff mbox

[ovs-dev,v9,04/10] Persist ports simap in logical_datapath

Message ID 1457730385-28923-5-git-send-email-rmoats@us.ibm.com
State Changes Requested
Headers show

Commit Message

Ryan Moats March 11, 2016, 9:06 p.m. UTC
From: RYAN D. MOATS <rmoats@us.ibm.com>

Persist across runs so that a change to this simap can be used
as a trigger for resetting incremental processing.
---
 ovn/controller/lflow.c |  125 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 115 insertions(+), 10 deletions(-)

Comments

Ben Pfaff March 22, 2016, 9:57 p.m. UTC | #1
On Fri, Mar 11, 2016 at 03:06:19PM -0600, Ryan Moats wrote:
> From: RYAN D. MOATS <rmoats@us.ibm.com>
> 
> Persist across runs so that a change to this simap can be used
> as a trigger for resetting incremental processing.

This makes a lot of sense but it will have to be ported to the new
abstraction in ovn/controller/lport.h (which will probably make it
cleaner anyhow).

Thanks,

Ben.
Ryan Moats March 23, 2016, 1:40 p.m. UTC | #2
Ben Pfaff <blp@ovn.org> wrote on 03/22/2016 04:57:18 PM:

> From: Ben Pfaff <blp@ovn.org>
> To: Ryan Moats/Omaha/IBM@IBMUS
> Cc: dev@openvswitch.org
> Date: 03/22/2016 04:57 PM
> Subject: Re: [ovs-dev,v9,04/10] Persist ports simap in logical_datapath
>
> On Fri, Mar 11, 2016 at 03:06:19PM -0600, Ryan Moats wrote:
> > From: RYAN D. MOATS <rmoats@us.ibm.com>
> >
> > Persist across runs so that a change to this simap can be used
> > as a trigger for resetting incremental processing.
>
> This makes a lot of sense but it will have to be ported to the new
> abstraction in ovn/controller/lport.h (which will probably make it
> cleaner anyhow).
>
> Thanks,
>
> Ben.
>

Yes, this got completely reworked during the current rebase...

Ryan (regXboi)
diff mbox

Patch

diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index a66dcd0..4856362 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -1,4 +1,4 @@ 
-/* Copyright (c) 2015 Nicira, Inc.
+/*te Copyright (c) 2016 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -226,28 +226,133 @@  ldp_free(struct logical_datapath *ldp)
     free(ldp);
 }
 
+/* Whether a particular port has been seen or not
+ *
+ * the hmap_node is based on the name string, while the logical
+ * datapath pointer handles back cleanup */
+struct ldp_port {
+    struct hmap_node hmap_node; /* Indexed on 'ins_seqno'. */
+    uint32_t ins_seqno;
+    char *name;
+    struct logical_datapath *ldp;   /* Associated logical datapath */
+};
+
+struct hmap ldp_ports = HMAP_INITIALIZER(&ldp_ports);
+
+void
+ldp_port_create(uint32_t ins_seqno, char *name, struct logical_datapath *ldp)
+{
+    struct ldp_port *psp;
+
+    psp = xmalloc(sizeof *psp);
+    psp->ins_seqno = ins_seqno;
+    psp->name = xmemdup(name, strlen(name));
+    psp->ldp = ldp;
+    psp->hmap_node.hash = hash_int(ins_seqno, 0);
+    hmap_insert(&ldp_ports, &psp->hmap_node, psp->hmap_node.hash);
+}
+
+static struct ldp_port *
+ldp_port_lookup(uint32_t ins_seqno)
+{
+    struct ldp_port *psp;
+    HMAP_FOR_EACH_IN_BUCKET (psp, hmap_node, hash_int(ins_seqno, 0),
+                             &ldp_ports) {
+        if (ins_seqno == psp->ins_seqno) {
+            return psp;
+        }
+    }
+    return NULL;
+}
+
+void
+ldp_port_update(uint32_t ins_seqno, char *name, struct logical_datapath *ldp)
+{
+    struct ldp_port *ldpp = ldp_port_lookup(ins_seqno);
+    if (!ldpp) {
+        ldp_port_create(ins_seqno, name, ldp);
+    }
+}
+
+static void
+ldp_port_free(struct ldp_port *psp)
+{
+    if (psp->name) {
+        free(psp->name);
+    }
+    free(psp);
+}
+
 /* Iterates through all of the records in the Port_Binding table, updating the
  * table of logical_datapaths to match the values found in active
  * Port_Bindings. */
 static void
 ldp_run(struct controller_ctx *ctx)
 {
-    struct logical_datapath *ldp;
-    HMAP_FOR_EACH (ldp, hmap_node, &logical_datapaths) {
-        simap_clear(&ldp->ports);
-    }
+    struct logical_datapath *ldp = NULL;
 
     const struct sbrec_port_binding *binding;
-    SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
-        struct logical_datapath *ldp = ldp_lookup_or_create(binding->datapath);
+    SBREC_PORT_BINDING_FOR_EACH_TRACKED (binding, ctx->ovnsb_idl) {
+        unsigned int del_seqno = sbrec_port_binding_row_get_seqno(binding,
+            OVSDB_IDL_CHANGE_DELETE);
+        unsigned int ins_seqno = sbrec_port_binding_row_get_seqno(binding,
+            OVSDB_IDL_CHANGE_INSERT);
+
+        /* if the row has a del_seqno > 0, then trying to process the row
+         * isn't going to work (as it has already been freed). */
+        if (del_seqno > 0) {
+            struct ldp_port *oldp = ldp_port_lookup(ins_seqno);
+            if (oldp) {
+                struct simap_node *old = simap_find(&oldp->ldp->ports,
+                                                    oldp->name);
+                if (old) {
+                    simap_delete(&oldp->ldp->ports, old);
+                }
+                hmap_remove(&ldp_ports, &oldp->hmap_node);
+                ldp_port_free(oldp);
+            }
+            continue;
+        }
 
-        simap_put(&ldp->ports, binding->logical_port, binding->tunnel_key);
+        struct logical_datapath *ldp = ldp_lookup_or_create(binding->datapath);
+        struct simap_node *old = simap_find(&ldp->ports,
+                                            binding->logical_port);
+        if (!old || old->data != binding->tunnel_key) {
+            simap_put(&ldp->ports, binding->logical_port, binding->tunnel_key);
+        }
+       
+        ldp_port_update(ins_seqno, binding->logical_port, ldp);
     }
 
     const struct sbrec_multicast_group *mc;
-    SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->ovnsb_idl) {
+    SBREC_MULTICAST_GROUP_FOR_EACH_TRACKED (mc, ctx->ovnsb_idl) {
+        unsigned int del_seqno = sbrec_multicast_group_row_get_seqno(mc,
+            OVSDB_IDL_CHANGE_DELETE);
+        unsigned int ins_seqno = sbrec_multicast_group_row_get_seqno(mc,
+            OVSDB_IDL_CHANGE_INSERT);
+
+        /* if the row has a del_seqno > 0, then trying to process the row
+         * isn't going to work (as it has already been freed). */
+        if (del_seqno > 0) {
+            struct ldp_port *oldp = ldp_port_lookup(ins_seqno);
+            if (oldp) {
+                struct simap_node *old = simap_find(&oldp->ldp->ports,
+                                                    oldp->name);
+                if (old) {
+                    simap_delete(&oldp->ldp->ports, old);
+                }
+                hmap_remove(&ldp_ports, &oldp->hmap_node);
+                ldp_port_free(oldp);
+            }
+            continue;
+        }
+
         struct logical_datapath *ldp = ldp_lookup_or_create(mc->datapath);
-        simap_put(&ldp->ports, mc->name, mc->tunnel_key);
+        struct simap_node *old = simap_find(&ldp->ports, mc->name);
+        if (!old || old->data != mc->tunnel_key) {
+            simap_put(&ldp->ports, mc->name, mc->tunnel_key);
+        }
+        ldp_port_update(ins_seqno, mc->name, ldp);
     }
 
     struct logical_datapath *next_ldp;