#include "meta-flow.h"
#include "netdev.h"
#include "ofp-print.h"
+#include "ofp-util.h"
#include "ofpbuf.h"
#include "ofproto/ofproto.h"
#include "poll-loop.h"
static void iface_configure_lacp(struct iface *, struct lacp_slave_settings *);
static bool iface_create(struct bridge *, struct if_cfg *, int ofp_port);
+static bool iface_is_internal(const struct ovsrec_interface *iface,
+ const struct ovsrec_bridge *br);
static const char *iface_get_type(const struct ovsrec_interface *,
const struct ovsrec_bridge *);
static void iface_destroy(struct iface *);
static void iface_refresh_stats(struct iface *);
static void iface_refresh_status(struct iface *);
static bool iface_is_synthetic(const struct iface *);
+static int64_t iface_pick_ofport(const struct ovsrec_interface *);
/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
*
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;
+ iface_hint->ofp_port = iface_pick_ofport(if_cfg);
shash_add(&iface_hints, if_cfg->name, iface_hint);
}
free(dpid_string);
}
+/* Returns a bitmap of "enum ofputil_protocol"s that are allowed for use with
+ * 'br'. */
+static uint32_t
+bridge_get_allowed_versions(struct bridge *br)
+{
+ if (!br->cfg->n_protocols)
+ return 0;
+
+ return ofputil_versions_from_strings(br->cfg->protocols,
+ br->cfg->n_protocols);
+}
+
/* Set NetFlow configuration on 'br'. */
static void
bridge_configure_netflow(struct bridge *br)
* configured as the user requested, so we must destroy it. */
return false;
} else {
- /* It's the right type and configured correctly. keep it. */
+ /* It's the right type and configured correctly. Keep it. */
iface_set_ofp_port(iface, ofp_port);
return true;
}
br->name, iface_cfg->name, *ofp_portp);
}
- if (port_cfg->vlan_mode && !strcmp(port_cfg->vlan_mode, "splinter")) {
+ if ((port_cfg->vlan_mode && !strcmp(port_cfg->vlan_mode, "splinter"))
+ || iface_is_internal(iface_cfg, br->cfg)) {
netdev_turn_flags_on(netdev, NETDEV_UP, true);
}
error = iface_do_create(br, if_cfg, &ofp_port, &netdev);
bridge_run_fast();
if (error) {
+ iface_set_ofport(iface_cfg, -1);
iface_clear_db_record(iface_cfg);
ok = false;
goto done;
if_cfg->cfg = cfg;
if_cfg->parent = parent;
- if_cfg->ofport = cfg->n_ofport_request ? *cfg->ofport_request : OFPP_NONE;
+ if_cfg->ofport = iface_pick_ofport(cfg);
hmap_insert(&br->if_cfg_todo, &if_cfg->hmap_node,
hash_string(if_cfg->cfg->name, 0));
}
n_ocs++;
}
- ofproto_set_controllers(br->ofproto, ocs, n_ocs, 0);
+ ofproto_set_controllers(br->ofproto, ocs, n_ocs,
+ bridge_get_allowed_versions(br));
free(ocs[0].target); /* From bridge_ofproto_controller_for_mgmt(). */
free(ocs);
\f
/* Interface functions. */
+static bool
+iface_is_internal(const struct ovsrec_interface *iface,
+ const struct ovsrec_bridge *br)
+{
+ /* The local port and "internal" ports are always "internal". */
+ return !strcmp(iface->type, "internal") || !strcmp(iface->name, br->name);
+}
+
/* Returns the correct network device type for interface 'iface' in bridge
* 'br'. */
static const char *
iface_get_type(const struct ovsrec_interface *iface,
const struct ovsrec_bridge *br)
{
- /* The local port always has type "internal" unless the bridge is of
- * type "dummy". Other ports take their type from the database and
- * default to "system" if none is specified. */
- if (!strcmp(iface->name, br->name)) {
- return !strcmp(br->datapath_type, "dummy") ? "dummy" : "internal";
+ const char *type;
+
+ /* The local port always has type "internal". Other ports take
+ * their type from the database and default to "system" if none is
+ * specified. */
+ if (iface_is_internal(iface, br)) {
+ type = "internal";
} else {
- return iface->type[0] ? iface->type : "system";
+ type = iface->type[0] ? iface->type : "system";
}
+
+ return ofproto_port_open_type(br->datapath_type, type);
}
static void
iface_clear_db_record(const struct ovsrec_interface *if_cfg)
{
if (!ovsdb_idl_row_is_synthetic(&if_cfg->header_)) {
- iface_set_ofport(if_cfg, -1);
ovsrec_interface_set_status(if_cfg, NULL);
ovsrec_interface_set_admin_state(if_cfg, NULL);
ovsrec_interface_set_duplex(if_cfg, NULL);
return ovsdb_idl_row_is_synthetic(&iface->cfg->header_);
}
+static int64_t
+iface_pick_ofport(const struct ovsrec_interface *cfg)
+{
+ int64_t ofport = cfg->n_ofport ? *cfg->ofport : OFPP_NONE;
+ return cfg->n_ofport_request ? *cfg->ofport_request : ofport;
+}
+
\f
/* Port mirroring. */