[ovs-dev] [Single DP 06/15] ofproto: Add initialization function.

Justin Pettit jpettit at nicira.com
Thu Oct 18 19:51:51 UTC 2012


A future commit will make all bridges of a particular dpif share a
single backing datapath.  In order to handle restart, the datapath will
need to have some idea of what the initial state looks like.  Otherwise,
it won't know which ports belong to which bridges and orphaned ports may
never be cleaned up.

This commit introduces an initialization method to ofproto, which takes
as an argument a high-level description of the bridges and ports.  An
ofproto provider can then use this information to initialize its state.

Signed-off-by: Justin Pettit <jpettit at nicira.com>
---
 ofproto/ofproto-dpif.c     |    7 ++++++
 ofproto/ofproto-provider.h |    9 ++++++++
 ofproto/ofproto.c          |   25 ++++++++++++++--------
 ofproto/ofproto.h          |   10 +++++++++
 vswitchd/bridge.c          |   48 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 90 insertions(+), 9 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 99e9ea8..dc6cda9 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -696,6 +696,12 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 /* Factory functions. */
 
 static void
+init(const struct shash *iface_hints OVS_UNUSED)
+{
+    return;
+}
+
+static void
 enumerate_types(struct sset *types)
 {
     dp_enumerate_types(types);
@@ -7202,6 +7208,7 @@ ofp_port_to_odp_in_port(uint16_t ofp_port)
 }
 
 const struct ofproto_class ofproto_dpif_class = {
+    init,
     enumerate_types,
     enumerate_names,
     del,
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index a7ebc09..afcfe8d 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -319,6 +319,15 @@ struct ofproto_class {
 /* ## ----------------- ## */
 /* ## Factory Functions ## */
 /* ## ----------------- ## */
+    /* Iinitializes provider.  The caller may pass in 'iface_hints',
+     * which contains an shash of "iface_hint" elements indexed by the
+     * interface's name.  The provider may use these hints to describe
+     * the startup configuration in order to reinitialize its state.
+     * The caller owns the provided data, so a provider must make copies
+     * of anything required.  An ofproto provider must remove any
+     * existing state that is not described by the hint, and may choose
+     * to remove it all. */
+    void (*init)(const struct shash *iface_hints);
 
     /* Enumerates the types of all support ofproto types into 'types'.  The
      * caller has already initialized 'types' and other ofproto classes might
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 743db1f..ae01c57 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -223,14 +223,24 @@ static struct hmap all_ofprotos = HMAP_INITIALIZER(&all_ofprotos);
 
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
-static void
-ofproto_initialize(void)
+/* Must be called to initialize the ofproto library.
+ *
+ * The caller may pass in 'iface_hints', which contains an shash of
+ * "iface_hint" elements indexed by the interface's name.  The provider
+ * may use these hints to describe the startup configuration in order to
+ * reinitialize its state.  The caller owns the provided data, so a
+ * provider will make copies of anything required.  An ofproto provider
+ * will remove any existing state that is not described by the hint, and
+ * may choose to remove it all. */
+void
+ofproto_init(const struct shash *iface_hints)
 {
-    static bool inited;
+    size_t i;
+
+    ofproto_class_register(&ofproto_dpif_class);
 
-    if (!inited) {
-        inited = true;
-        ofproto_class_register(&ofproto_dpif_class);
+    for (i = 0; i < n_ofproto_classes; i++) {
+        ofproto_classes[i]->init(iface_hints);
     }
 }
 
@@ -242,7 +252,6 @@ ofproto_class_find__(const char *type)
 {
     size_t i;
 
-    ofproto_initialize();
     for (i = 0; i < n_ofproto_classes; i++) {
         const struct ofproto_class *class = ofproto_classes[i];
         struct sset types;
@@ -313,7 +322,6 @@ ofproto_enumerate_types(struct sset *types)
 {
     size_t i;
 
-    ofproto_initialize();
     for (i = 0; i < n_ofproto_classes; i++) {
         ofproto_classes[i]->enumerate_types(types);
     }
@@ -352,7 +360,6 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
 
     *ofprotop = NULL;
 
-    ofproto_initialize();
     ofproto_unixctl_init();
 
     datapath_type = ofproto_normalize_type(datapath_type);
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index 5599cd6..96dde6a 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -144,6 +144,16 @@ const char *ofproto_normalize_type(const char *);
 int ofproto_enumerate_names(const char *type, struct sset *names);
 void ofproto_parse_name(const char *name, char **dp_name, char **dp_type);
 
+/* An interface hint element, which is used by ofproto_init() to
+ * describe the caller's understanding of the startup state. */
+struct iface_hint {
+    char *br_name;              /* Name of owning bridge. */
+    char *br_type;              /* Type of owning bridge. */
+    uint16_t ofp_port;          /* OpenFlow port number. */
+};
+
+void ofproto_init(const struct shash *iface_hints);
+
 int ofproto_create(const char *datapath, const char *datapath_type,
                    struct ofproto **ofprotop);
 void ofproto_destroy(struct ofproto *);
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 8f0a143..42ac798 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -263,6 +263,48 @@ static void configure_splinter_port(struct port *);
 static void add_vlan_splinter_ports(struct bridge *,
                                     const unsigned long int *splinter_vlans,
                                     struct shash *ports);
+
+static void
+bridge_init_ofproto(const struct ovsrec_open_vswitch *cfg)
+{
+    struct shash iface_hints;
+    static bool initialized = false;
+    int i;
+
+    if (initialized) {
+        return;
+    }
+
+    shash_init(&iface_hints);
+
+    for (i = 0; i < cfg->n_bridges; i++) {
+        const struct ovsrec_bridge *br_cfg = cfg->bridges[i];
+        int j;
+
+        for (j = 0; j < br_cfg->n_ports; j++) {
+            struct ovsrec_port *port_cfg = br_cfg->ports[j];
+            int k;
+
+            for (k = 0; k < port_cfg->n_interfaces; k++) {
+                struct ovsrec_interface *if_cfg = port_cfg->interfaces[k];
+                struct iface_hint *iface_hint;
+
+                iface_hint = xmalloc(sizeof *iface_hint);
+                iface_hint->br_name = br_cfg->name;
+                iface_hint->br_type = br_cfg->datapath_type;
+                iface_hint->ofp_port = if_cfg->n_ofport_request ?
+                                       *if_cfg->ofport_request : OFPP_NONE;
+
+                shash_add(&iface_hints, if_cfg->name, iface_hint);
+            }
+        }
+    }
+
+    ofproto_init(&iface_hints);
+
+    shash_destroy_free_data(&iface_hints);
+    initialized = true;
+}
 
 /* Public functions. */
 
@@ -2077,6 +2119,12 @@ bridge_run(void)
     }
     cfg = ovsrec_open_vswitch_first(idl);
 
+    /* Initialize the ofproto library.  This only needs to run once, but
+     * it must be done after the configuration is set.  If the
+     * initialization has already occurred, bridge_init_ofproto()
+     * returns immediately. */
+    bridge_init_ofproto(cfg);
+
     /* Let each bridge do the work that it needs to do. */
     HMAP_FOR_EACH (br, node, &all_bridges) {
         ofproto_run(br->ofproto);
-- 
1.7.5.4




More information about the dev mailing list