-/* Copyright (c) 2008, 2009 Nicira Networks
+/* Copyright (c) 2008, 2009, 2010 Nicira Networks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "sha1.h"
#include "shash.h"
#include "socket-util.h"
+#include "stream-ssl.h"
#include "svec.h"
#include "timeval.h"
#include "util.h"
#include "unixctl.h"
#include "vconn.h"
-#include "vconn-ssl.h"
#include "vswitchd/vswitch-idl.h"
#include "xenserver.h"
#include "xtoxll.h"
}
#endif
-static struct iface *iface_create(struct port *, const char *name);
+static struct iface *iface_create(struct port *port,
+ const struct ovsrec_interface *if_cfg);
static void iface_destroy(struct iface *);
static struct iface *iface_lookup(const struct bridge *, const char *name);
static struct iface *iface_from_dp_ifidx(const struct bridge *,
}
if (config_string_change(ssl->private_key, &private_key_file)) {
- vconn_ssl_set_private_key_file(private_key_file);
+ stream_ssl_set_private_key_file(private_key_file);
}
if (config_string_change(ssl->certificate, &certificate_file)) {
- vconn_ssl_set_certificate_file(certificate_file);
+ stream_ssl_set_certificate_file(certificate_file);
}
/* We assume that even if the filename hasn't changed, if the CA cert
* restarted. We may want to address this in vconn's SSL library. */
if (config_string_change(ssl->ca_cert, &cacert_file)
|| (cacert_file && stat(cacert_file, &s) && errno == ENOENT)) {
- vconn_ssl_set_ca_cert_file(cacert_file, ssl->bootstrap_ca_cert);
+ stream_ssl_set_ca_cert_file(cacert_file, ssl->bootstrap_ca_cert);
}
}
#endif
return error;
}
-static int
-create_iface(const struct ovsrec_interface *iface_cfg)
-{
- return set_up_iface(iface_cfg, true);
-}
-
static int
reconfigure_iface(const struct ovsrec_interface *iface_cfg)
{
return set_up_iface(iface_cfg, false);
}
-static void
-destroy_iface(const char *iface_name)
-{
- netdev_destroy(iface_name);
-}
-
/* iterate_and_prune_ifaces() callback function that opens the network device
* for 'iface', if it is not already open, and retrieves the interface's MAC
void
bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
{
+ struct ovsdb_idl_txn *txn;
struct shash old_br, new_br;
struct shash_node *node;
struct bridge *br, *next;
COVERAGE_INC(bridge_reconfigure);
+ txn = ovsdb_idl_txn_create(ovs_cfg->header_.table->idl);
+
/* Collect old and new bridges. */
shash_init(&old_br);
shash_init(&new_br);
const struct ovsrec_bridge *br_cfg = node->data;
if (!shash_find_data(&old_br, br_name)) {
br = bridge_create(br_name);
- br->cfg = br_cfg;
+ if (br) {
+ br->cfg = br_cfg;
+ }
}
}
shash_destroy(&old_br);
p->devname, dpif_name(br->dpif),
strerror(retval));
}
- destroy_iface(p->devname);
}
}
shash_destroy(&want_ifaces);
bool internal;
int error;
- /* Attempt to create the network interface in case it
- * doesn't exist yet. */
- error = iface ? create_iface(iface->cfg) : 0;
- if (error) {
- VLOG_WARN("could not create iface %s: %s\n", if_name,
- strerror(error));
- continue;
- }
-
/* Add to datapath. */
- internal = !iface || iface_is_internal(br, if_name);
+ internal = iface_is_internal(br, if_name);
error = dpif_port_add(br->dpif, if_name,
internal ? ODP_PORT_INTERNAL : 0, NULL);
if (error == EFBIG) {
uint64_t dpid;
struct iface *local_iface;
struct iface *hw_addr_iface;
+ char *dpid_string;
bridge_fetch_dp_ifaces(br);
iterate_and_prune_ifaces(br, init_iface_netdev, NULL);
dpid = bridge_pick_datapath_id(br, ea, hw_addr_iface);
ofproto_set_datapath_id(br->ofproto, dpid);
+ dpid_string = xasprintf("%012"PRIx64, dpid);
+ ovsrec_bridge_set_datapath_id(br->cfg, dpid_string);
+ free(dpid_string);
+
/* Set NetFlow configuration on this bridge. */
if (br->cfg->netflow) {
struct ovsrec_netflow *nf_cfg = br->cfg->netflow;
if (!opts.active_timeout) {
opts.active_timeout = -1;
} else if (opts.active_timeout < 0) {
- opts.active_timeout = 0;
+ VLOG_WARN("bridge %s: active timeout interval set to negative "
+ "value, using default instead (%d seconds)", br->name,
+ NF_ACTIVE_TIMEOUT_DEFAULT);
+ opts.active_timeout = -1;
}
opts.add_id_to_iface = nf_cfg->add_id_to_interface;
LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
iterate_and_prune_ifaces(br, set_iface_properties, NULL);
}
+
+ ovsrec_open_vswitch_set_cur_cfg(ovs_cfg, ovs_cfg->next_cfg);
+
+ ovsdb_idl_txn_commit(txn);
+ ovsdb_idl_txn_destroy(txn); /* XXX */
+}
+
+static const char *
+bridge_get_other_config(const struct ovsrec_bridge *br_cfg, const char *key)
+{
+ size_t i;
+
+ for (i = 0; i < br_cfg->n_other_config; i++) {
+ if (!strcmp(br_cfg->key_other_config[i], key)) {
+ return br_cfg->value_other_config[i];
+ }
+ }
+ return NULL;
}
static void
bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
struct iface **hw_addr_iface)
{
+ const char *hwaddr;
size_t i, j;
int error;
*hw_addr_iface = NULL;
/* Did the user request a particular MAC? */
- if (br->cfg->hwaddr && eth_addr_from_string(br->cfg->hwaddr, ea)) {
+ hwaddr = bridge_get_other_config(br->cfg, "hwaddr");
+ if (hwaddr && eth_addr_from_string(hwaddr, ea)) {
if (eth_addr_is_multicast(ea)) {
VLOG_ERR("bridge %s: cannot set MAC address to multicast "
"address "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(ea));
}
}
- /* Otherwise choose the minimum MAC address among all of the interfaces.
- * (Xen uses FE:FF:FF:FF:FF:FF for virtual interfaces so this will get the
- * MAC of the physical interface in such an environment.) */
+ /* Otherwise choose the minimum non-local MAC address among all of the
+ * interfaces. */
memset(ea, 0xff, sizeof ea);
for (i = 0; i < br->n_ports; i++) {
struct port *port = br->ports[i];
}
/* The local port doesn't count (since we're trying to choose its
- * MAC address anyway). Other internal ports don't count because
- * we really want a physical MAC if we can get it, and internal
- * ports typically have randomly generated MACs. */
- if (iface->dp_ifidx == ODPP_LOCAL
- || !strcmp(iface->cfg->type, "internal")) {
+ * MAC address anyway). */
+ if (iface->dp_ifidx == ODPP_LOCAL) {
continue;
}
/* Compare against our current choice. */
if (!eth_addr_is_multicast(iface_ea) &&
+ !eth_addr_is_local(iface_ea) &&
!eth_addr_is_reserved(iface_ea) &&
!eth_addr_is_zero(iface_ea) &&
memcmp(iface_ea, ea, ETH_ADDR_LEN) < 0)
*hw_addr_iface = iface;
}
}
- if (eth_addr_is_multicast(ea) || eth_addr_is_vif(ea)) {
+ if (eth_addr_is_multicast(ea)) {
memcpy(ea, br->default_ea, ETH_ADDR_LEN);
*hw_addr_iface = NULL;
VLOG_WARN("bridge %s: using default bridge Ethernet "
* stable from one run to the next, so that policy set on a datapath
* "sticks".
*/
+ const char *datapath_id;
uint64_t dpid;
- if (br->cfg->datapath_id
- && dpid_from_string(br->cfg->datapath_id, &dpid)) {
+ datapath_id = bridge_get_other_config(br->cfg, "datapath-id");
+ if (datapath_id && dpid_from_string(datapath_id, &dpid)) {
return dpid;
}
br->name, name);
}
}
+
+ /* If we have a controller, then we need a local port. Complain if the
+ * user didn't specify one.
+ *
+ * XXX perhaps we should synthesize a port ourselves in this case. */
if (bridge_get_controller(ovs_cfg, br)) {
char local_name[IF_NAMESIZE];
int error;
error = dpif_port_get_name(br->dpif, ODPP_LOCAL,
local_name, sizeof local_name);
- if (!error) {
- shash_add_once(&new_ports, local_name, NULL);
+ if (!error && !shash_find(&new_ports, local_name)) {
+ VLOG_WARN("bridge %s: controller specified but no local port "
+ "(port named %s) defined",
+ br->name, local_name);
}
}
rate_limit = c->controller_rate_limit ? *c->controller_rate_limit : 0;
burst_limit = c->controller_burst_limit ? *c->controller_burst_limit : 0;
ofproto_set_rate_limit(br->ofproto, rate_limit, burst_limit);
-
- ofproto_set_remote_execution(br->ofproto, NULL, NULL); /* XXX */
} else {
union ofp_action action;
flow_t flow;
port_array_set(&br->ifaces, p->port, iface);
iface->dp_ifidx = p->port;
}
+
+ if (iface->cfg) {
+ int64_t ofport = (iface->dp_ifidx >= 0
+ ? odp_port_to_ofp_port(iface->dp_ifidx)
+ : -1);
+ ovsrec_interface_set_ofport(iface->cfg, &ofport, 1);
+ }
}
}
free(dpif_ports);
}
SHASH_FOR_EACH (node, &new_ifaces) {
const struct ovsrec_interface *if_cfg = node->data;
- const char *if_name = node->name;
struct iface *iface;
- iface = shash_find_data(&old_ifaces, if_name);
+ iface = shash_find_data(&old_ifaces, if_cfg->name);
if (!iface) {
- iface = iface_create(port, if_name);
+ iface = iface_create(port, if_cfg);
}
iface->cfg = if_cfg;
}
/* Interface functions. */
static struct iface *
-iface_create(struct port *port, const char *name)
+iface_create(struct port *port, const struct ovsrec_interface *if_cfg)
{
struct iface *iface;
+ char *name = if_cfg->name;
+ int error;
iface = xzalloc(sizeof *iface);
iface->port = port;
port->bridge->has_bonded_ports = true;
}
+ /* Attempt to create the network interface in case it
+ * doesn't exist yet. */
+ error = set_up_iface(if_cfg, true);
+ if (error) {
+ VLOG_WARN("could not create iface %s: %s\n", iface->name,
+ strerror(error));
+ }
+
VLOG_DBG("attached network device %s to port %s", iface->name, port->name);
bridge_flush(port->bridge);
del->port_ifidx = iface->port_ifidx;
netdev_close(iface->netdev);
- free(iface->name);
- free(iface);
if (del_active) {
ofproto_revalidate(port->bridge->ofproto, port->active_iface_tag);
bond_send_learning_packets(port);
}
+ netdev_destroy(iface->name);
+ free(iface->name);
+ free(iface);
+
bridge_flush(port->bridge);
}
}
}
port = port_lookup(br, if_name);
- if (port->n_ifaces > 1 && port->cfg->bond_fake_iface) {
+ if (port && port->n_ifaces > 1 && port->cfg->bond_fake_iface) {
return true;
}
return false;