\f
/* Factory functions. */
+static void
+init(const struct shash *iface_hints OVS_UNUSED)
+{
+}
+
static void
enumerate_types(struct sset *types)
{
}
\f
const struct ofproto_class ofproto_dpif_class = {
+ init,
enumerate_types,
enumerate_names,
del,
/* ## Factory Functions ## */
/* ## ----------------- ## */
+ /* Initializes provider. The caller may pass in 'iface_hints',
+ * which contains an shash of "struct 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
* already have added names to it. */
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);
}
}
{
size_t i;
- ofproto_initialize();
for (i = 0; i < n_ofproto_classes; i++) {
const struct ofproto_class *class = ofproto_classes[i];
struct sset types;
{
size_t i;
- ofproto_initialize();
for (i = 0; i < n_ofproto_classes; i++) {
ofproto_classes[i]->enumerate_types(types);
}
*ofprotop = NULL;
- ofproto_initialize();
ofproto_unixctl_init();
datapath_type = ofproto_normalize_type(datapath_type);
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 *);
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;
+}
\f
/* Public functions. */
}
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);