#include <config.h>
#include "bridge.h"
-#include "byte-order.h"
#include <assert.h>
#include <errno.h>
-#include <arpa/inet.h>
-#include <ctype.h>
#include <inttypes.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <openflow/openflow.h>
-#include <signal.h>
#include <stdlib.h>
-#include <strings.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
#include "bitmap.h"
#include "bond.h"
#include "cfm.h"
-#include "classifier.h"
#include "coverage.h"
#include "daemon.h"
#include "dirs.h"
#include "dynamic-string.h"
-#include "flow.h"
#include "hash.h"
#include "hmap.h"
#include "jsonrpc.h"
#include "lacp.h"
#include "list.h"
-#include "mac-learning.h"
#include "netdev.h"
-#include "netlink.h"
-#include "odp-util.h"
#include "ofp-print.h"
#include "ofpbuf.h"
-#include "ofproto/netflow.h"
#include "ofproto/ofproto.h"
-#include "ovsdb-data.h"
-#include "packets.h"
#include "poll-loop.h"
-#include "process.h"
#include "sha1.h"
#include "shash.h"
#include "socket-util.h"
#include "stream-ssl.h"
#include "sset.h"
-#include "svec.h"
#include "system-stats.h"
#include "timeval.h"
#include "util.h"
#include "unixctl.h"
-#include "vconn.h"
#include "vswitchd/vswitch-idl.h"
#include "xenserver.h"
#include "vlog.h"
static void port_configure(struct port *);
static struct lacp_settings *port_configure_lacp(struct port *,
struct lacp_settings *);
-static void port_configure_bond(struct port *, struct bond_settings *);
+static void port_configure_bond(struct port *, struct bond_settings *,
+ uint32_t *bond_stable_ids);
static void bridge_configure_mirrors(struct bridge *);
static struct mirror *mirror_create(struct bridge *,
/* Get bond settings. */
if (s.n_slaves > 1) {
- port_configure_bond(port, &bond_settings);
s.bond = &bond_settings;
+ s.bond_stable_ids = xmalloc(s.n_slaves * sizeof *s.bond_stable_ids);
+ port_configure_bond(port, &bond_settings, s.bond_stable_ids);
} else {
s.bond = NULL;
+ s.bond_stable_ids = NULL;
}
/* Register. */
/* Clean up. */
free(s.trunks);
free(s.lacp_slaves);
+ free(s.bond_stable_ids);
}
/* Pick local port hardware address and datapath ID for 'br'. */
br->name, name, strerror(error));
}
if (iface) {
- ofproto_port_unregister(br->ofproto, ofproto_port.ofp_port);
netdev_close(iface->netdev);
iface->netdev = NULL;
}
assert(iface->ofp_port < 0 && ofp_port >= 0);
iface->ofp_port = ofp_port;
hmap_insert(&br->ifaces, &iface->ofp_port_node, hash_int(ofp_port, 0));
-
+ iface_set_ofport(iface->cfg, ofp_port);
}
static void
/* Already exists, nothing to do. */
ofproto_port_destroy(&ofproto_port);
}
- ofproto_port_destroy(&ofproto_port);
}
}
}
/* (Re)configure if necessary. */
database_changed = ovsdb_idl_run(idl);
cfg = ovsrec_open_vswitch_first(idl);
-#ifdef HAVE_OPENSSL
+
/* Re-configure SSL. We do this on every trip through the main loop,
* instead of just when the database changes, because the contents of the
* key and certificate files can change without the database changing.
stream_ssl_set_key_and_cert(ssl->private_key, ssl->certificate);
stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert);
}
-#endif
+
if (database_changed || datapath_destroyed) {
if (cfg) {
struct ovsdb_idl_txn *txn = ovsdb_idl_txn_create(idl);
br->name = xstrdup(br_cfg->name);
br->type = xstrdup(ofproto_normalize_type(br_cfg->datapath_type));
br->cfg = br_cfg;
- eth_addr_nicira_random(br->default_ea);
+
+ /* Derive the default Ethernet address from the bridge's UUID. This should
+ * be unique and it will be stable between ovs-vswitchd runs. */
+ memcpy(br->default_ea, &br_cfg->header_.uuid, ETH_ADDR_LEN);
+ eth_addr_mark_random(br->default_ea);
hmap_init(&br->ports);
hmap_init(&br->ifaces);
sset_init(&new_ifaces);
for (i = 0; i < port->cfg->n_interfaces; i++) {
const char *name = port->cfg->interfaces[i]->name;
- sset_add(&new_ifaces, name);
+ const char *type = port->cfg->interfaces[i]->name;
+ if (strcmp(type, "null")) {
+ sset_add(&new_ifaces, name);
+ }
}
/* Get rid of deleted interfaces. */
shash_init(&new_ifaces);
for (i = 0; i < port->cfg->n_interfaces; i++) {
const struct ovsrec_interface *cfg = port->cfg->interfaces[i];
- if (!shash_add_once(&new_ifaces, cfg->name, cfg)) {
+ if (strcmp(cfg->type, "null")
+ && !shash_add_once(&new_ifaces, cfg->name, cfg)) {
VLOG_WARN("port %s: %s specified twice as port interface",
port->name, cfg->name);
iface_set_ofport(cfg, -1);
? priority
: UINT16_MAX - !list_is_short(&port->ifaces));
- s->strict = !strcmp(get_port_other_config(port->cfg, "lacp-strict",
- "false"),
- "true");
+ s->heartbeat = !strcmp(get_port_other_config(port->cfg,
+ "lacp-heartbeat",
+ "false"), "true");
+
lacp_time = get_port_other_config(port->cfg, "lacp-time", "slow");
custom_time = atoi(lacp_time);
static void
iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s)
{
- int priority, portid;
+ int priority, portid, key;
portid = atoi(get_interface_other_config(iface->cfg, "lacp-port-id", "0"));
priority = atoi(get_interface_other_config(iface->cfg,
"lacp-port-priority", "0"));
+ key = atoi(get_interface_other_config(iface->cfg, "lacp-aggregation-key",
+ "0"));
if (portid <= 0 || portid > UINT16_MAX) {
portid = iface->ofp_port;
priority = UINT16_MAX;
}
+ if (key < 0 || key > UINT16_MAX) {
+ key = 0;
+ }
+
s->name = iface->name;
s->id = portid;
s->priority = priority;
+ s->key = key;
}
static void
-port_configure_bond(struct port *port, struct bond_settings *s)
+port_configure_bond(struct port *port, struct bond_settings *s,
+ uint32_t *bond_stable_ids)
{
const char *detect_s;
+ struct iface *iface;
+ size_t i;
s->name = port->name;
s->balance = BM_SLB;
s->up_delay = MAX(0, port->cfg->bond_updelay);
s->down_delay = MAX(0, port->cfg->bond_downdelay);
+ s->basis = atoi(get_port_other_config(port->cfg, "bond-hash-basis", "0"));
s->rebalance_interval = atoi(
get_port_other_config(port->cfg, "bond-rebalance-interval", "10000"));
if (s->rebalance_interval < 1000) {
}
s->fake_iface = port->cfg->bond_fake_iface;
+
+ i = 0;
+ LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+ long long stable_id;
+
+ stable_id = atoll(get_interface_other_config(iface->cfg,
+ "bond-stable-id", "0"));
+ if (stable_id <= 0 || stable_id >= UINT32_MAX) {
+ stable_id = iface->ofp_port;
+ }
+ bond_stable_ids[i++] = stable_id;
+ }
}
\f
/* Interface functions. */
static void
iface_configure_qos(struct iface *iface, const struct ovsrec_qos *qos)
{
- if (!qos || qos->type[0] == '\0') {
+ if (!qos || qos->type[0] == '\0' || qos->n_queues < 1) {
netdev_set_qos(iface->netdev, NULL, NULL);
} else {
struct iface_delete_queues_cbdata cbdata;
mirror_configure(struct mirror *m, const struct ovsrec_mirror *cfg)
{
struct ofproto_mirror_settings s;
- struct port *out_port;
- struct port *port;
/* Set name. */
if (strcmp(cfg->name, m->name)) {
/* Get output port or VLAN. */
if (cfg->output_port) {
s.out_bundle = port_lookup(m->bridge, cfg->output_port->name);
- if (!out_port) {
+ if (!s.out_bundle) {
VLOG_ERR("bridge %s: mirror %s outputs to port not on bridge",
m->bridge->name, m->name);
return false;
if (cfg->select_all) {
size_t n_ports = hmap_count(&m->bridge->ports);
void **ports = xmalloc(n_ports * sizeof *ports);
+ struct port *port;
size_t i;
i = 0;