#include "dynamic-string.h"
#include "hash.h"
#include "hmap.h"
+#include "hmapx.h"
#include "jsonrpc.h"
#include "lacp.h"
#include "list.h"
HMAP_FOR_EACH (br, node, &all_bridges) {
struct port *port;
+ /* We need the datapath ID early to allow LACP ports to use it as the
+ * default system ID. */
+ bridge_configure_datapath_id(br);
+
HMAP_FOR_EACH (port, hmap_node, &br->ports) {
struct iface *iface;
}
}
bridge_configure_mirrors(br);
- bridge_configure_datapath_id(br);
bridge_configure_flow_eviction_threshold(br);
bridge_configure_forward_bpdu(br);
bridge_configure_remotes(br, managers, n_managers);
/* Get VLAN tag. */
s.vlan = -1;
- if (cfg->tag) {
- if (list_is_short(&port->ifaces)) {
- if (*cfg->tag >= 0 && *cfg->tag <= 4095) {
- s.vlan = *cfg->tag;
- }
- } else {
- /* It's possible that bonded, VLAN-tagged ports make sense. Maybe
- * they even work as-is. But they have not been tested. */
- VLOG_WARN("port %s: VLAN tags not supported on bonded ports",
- port->name);
- }
+ if (cfg->tag && *cfg->tag >= 0 && *cfg->tag <= 4095) {
+ s.vlan = *cfg->tag;
}
/* Get VLAN trunks. */
bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
struct iface **hw_addr_iface)
{
+ struct hmapx mirror_output_ports;
const char *hwaddr;
struct port *port;
bool found_addr = false;
int error;
+ int i;
*hw_addr_iface = NULL;
}
}
+ /* Mirror output ports don't participate in picking the local hardware
+ * address. ofproto can't help us find out whether a given port is a
+ * mirror output because we haven't configured mirrors yet, so we need to
+ * accumulate them ourselves. */
+ hmapx_init(&mirror_output_ports);
+ for (i = 0; i < br->cfg->n_mirrors; i++) {
+ struct ovsrec_mirror *m = br->cfg->mirrors[i];
+ if (m->output_port) {
+ hmapx_add(&mirror_output_ports, m->output_port);
+ }
+ }
+
/* Otherwise choose the minimum non-local MAC address among all of the
* interfaces. */
HMAP_FOR_EACH (port, hmap_node, &br->ports) {
struct iface *iface;
/* Mirror output ports don't participate. */
- if (ofproto_is_mirror_output_bundle(br->ofproto, port)) {
+ if (hmapx_contains(&mirror_output_ports, port->cfg)) {
continue;
}
VLOG_WARN("bridge %s: using default bridge Ethernet "
"address "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(ea));
}
+
+ hmapx_destroy(&mirror_output_ports);
}
/* Choose and returns the datapath ID for bridge 'br' given that the bridge
static struct lacp_settings *
port_configure_lacp(struct port *port, struct lacp_settings *s)
{
- const char *lacp_time;
+ const char *lacp_time, *system_id;
long long int custom_time;
int priority;
}
s->name = port->name;
- memcpy(s->id, port->bridge->ea, ETH_ADDR_LEN);
+
+ system_id = get_port_other_config(port->cfg, "lacp-system-id", NULL);
+ if (!system_id
+ || sscanf(system_id, ETH_ADDR_SCAN_FMT,
+ ETH_ADDR_SCAN_ARGS(s->id)) != ETH_ADDR_SCAN_COUNT) {
+ memcpy(s->id, port->bridge->ea, ETH_ADDR_LEN);
+ }
+
+ if (eth_addr_is_zero(s->id)) {
+ VLOG_WARN("port %s: Invalid zero LACP system ID.", port->name);
+ return NULL;
+ }
/* Prefer bondable links if unspecified. */
priority = atoi(get_port_other_config(port->cfg, "lacp-system-priority",
"lacp-heartbeat",
"false"), "true");
-
lacp_time = get_port_other_config(port->cfg, "lacp-time", "slow");
custom_time = atoi(lacp_time);
if (!strcmp(lacp_time, "fast")) {
struct bridge *br;
size_t i;
+ /* Free space allocated for synthesized ports and interfaces, since we're
+ * in the process of reconstructing all of them. */
+ free_registered_blocks();
+
splinter_vlans = NULL;
sset_init(&splinter_ifaces);
for (i = 0; i < ovs_cfg->n_bridges; i++) {
{
size_t i;
- free_registered_blocks();
-
/* We iterate through 'br->cfg->ports' instead of 'ports' here because
* we're modifying 'ports'. */
for (i = 0; i < br->cfg->n_ports; i++) {