#include "port-array.h"
#include "proc-net-compat.h"
#include "process.h"
+#include "shash.h"
#include "socket-util.h"
#include "stp.h"
#include "svec.h"
#include "unixctl.h"
#include "vconn.h"
#include "vconn-ssl.h"
+#include "vswitchd/vswitch-idl.h"
#include "xenserver.h"
#include "xtoxll.h"
static struct bridge *bridge_create(const char *name);
static void bridge_destroy(struct bridge *);
static struct bridge *bridge_lookup(const char *name);
-static void bridge_unixctl_dump_flows(struct unixctl_conn *, const char *);
+static unixctl_cb_func bridge_unixctl_dump_flows;
static int bridge_run_one(struct bridge *);
static void bridge_reconfigure_one(struct bridge *);
static void bridge_reconfigure_controller(struct bridge *);
static struct iface *bridge_get_local_iface(struct bridge *);
static uint64_t dpid_from_hash(const void *, size_t nbytes);
-static void bridge_unixctl_fdb_show(struct unixctl_conn *, const char *args);
+static unixctl_cb_func bridge_unixctl_fdb_show;
static void bond_init(void);
static void bond_run(struct bridge *);
struct svec dpif_names;
size_t i;
- unixctl_command_register("fdb/show", bridge_unixctl_fdb_show);
+ unixctl_command_register("fdb/show", bridge_unixctl_fdb_show, NULL);
svec_init(&dpif_names);
dp_enumerate(&dpif_names);
}
svec_destroy(&dpif_names);
- unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows);
+ unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows,
+ NULL);
bond_init();
bridge_reconfigure();
}
#endif
+/* Attempt to create the network device 'iface_name' through the netdev
+ * library. */
+static int
+set_up_iface(const char *iface_name, bool create)
+{
+ const char *type;
+ const char *arg;
+ struct svec arg_svec;
+ struct shash args;
+ int error;
+ size_t i;
+
+ /* If a type is not explicitly declared, then assume it's an existing
+ * "system" device. */
+ type = cfg_get_string(0, "iface.%s.type", iface_name);
+ if (!type || !strcmp(type, "system")) {
+ return 0;
+ }
+
+ svec_init(&arg_svec);
+ cfg_get_subsections(&arg_svec, "iface.%s.args", iface_name);
+
+ shash_init(&args);
+ SVEC_FOR_EACH (i, arg, &arg_svec) {
+ const char *value;
+
+ value = cfg_get_string(0, "iface.%s.args.%s", iface_name, arg);
+ if (value) {
+ shash_add(&args, arg, xstrdup(value));
+ }
+ }
+
+ if (create) {
+ error = netdev_create(iface_name, type, &args);
+ } else {
+ /* xxx Check to make sure that the type hasn't changed. */
+ error = netdev_reconfigure(iface_name, &args);
+ }
+
+ svec_destroy(&arg_svec);
+ shash_destroy(&args);
+
+ return error;
+}
+
+static int
+create_iface(const char *iface_name)
+{
+ return set_up_iface(iface_name, true);
+}
+
+static int
+reconfigure_iface(const char *iface_name)
+{
+ return set_up_iface(iface_name, 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
* address and carrier status. */
p->devname, dpif_name(br->dpif),
strerror(retval));
}
+ destroy_iface(p->devname);
}
}
svec_destroy(&want_ifaces);
bridge_get_all_ifaces(br, &want_ifaces);
svec_diff(&want_ifaces, &cur_ifaces, &add_ifaces, NULL, NULL);
+ for (i = 0; i < cur_ifaces.n; i++) {
+ const char *if_name = cur_ifaces.names[i];
+ reconfigure_iface(if_name);
+ }
+
for (i = 0; i < add_ifaces.n; i++) {
const char *if_name = add_ifaces.names[i];
bool internal;
int error;
+ /* Attempt to create the network interface in case it
+ * doesn't exist yet. */
+ error = create_iface(if_name);
+ if (error) {
+ VLOG_WARN("could not create iface %s: %s\n", if_name,
+ strerror(error));
+ continue;
+ }
+
/* Add to datapath. */
internal = iface_is_internal(br, if_name);
error = dpif_port_add(br->dpif, if_name,
\f
/* Bridge unixctl user interface functions. */
static void
-bridge_unixctl_fdb_show(struct unixctl_conn *conn, const char *args)
+bridge_unixctl_fdb_show(struct unixctl_conn *conn,
+ const char *args, void *aux UNUSED)
{
struct ds ds = DS_EMPTY_INITIALIZER;
const struct bridge *br;
int error;
assert(!bridge_lookup(name));
- br = xcalloc(1, sizeof *br);
+ br = xzalloc(sizeof *br);
- error = dpif_create(name, &br->dpif);
- if (error == EEXIST || error == EBUSY) {
- error = dpif_open(name, &br->dpif);
- if (error) {
- VLOG_ERR("datapath %s already exists but cannot be opened: %s",
- name, strerror(error));
- free(br);
- return NULL;
- }
- dpif_flow_flush(br->dpif);
- } else if (error) {
- VLOG_ERR("failed to create datapath %s: %s", name, strerror(error));
+ error = dpif_create_and_open(name, &br->dpif);
+ if (error) {
free(br);
return NULL;
}
+ dpif_flow_flush(br->dpif);
error = ofproto_create(name, &bridge_ofhooks, br, &br->ofproto);
if (error) {
/* Handle requests for a listing of all flows known by the OpenFlow
* stack, including those normally hidden. */
static void
-bridge_unixctl_dump_flows(struct unixctl_conn *conn, const char *args)
+bridge_unixctl_dump_flows(struct unixctl_conn *conn,
+ const char *args, void *aux UNUSED)
{
struct bridge *br;
struct ds results;
/* Bonding unixctl user interface functions. */
static void
-bond_unixctl_list(struct unixctl_conn *conn, const char *args UNUSED)
+bond_unixctl_list(struct unixctl_conn *conn,
+ const char *args UNUSED, void *aux UNUSED)
{
struct ds ds = DS_EMPTY_INITIALIZER;
const struct bridge *br;
}
static void
-bond_unixctl_show(struct unixctl_conn *conn, const char *args)
+bond_unixctl_show(struct unixctl_conn *conn,
+ const char *args, void *aux UNUSED)
{
struct ds ds = DS_EMPTY_INITIALIZER;
const struct port *port;
}
static void
-bond_unixctl_migrate(struct unixctl_conn *conn, const char *args_)
+bond_unixctl_migrate(struct unixctl_conn *conn, const char *args_,
+ void *aux UNUSED)
{
char *args = (char *) args_;
char *save_ptr = NULL;
}
static void
-bond_unixctl_set_active_slave(struct unixctl_conn *conn, const char *args_)
+bond_unixctl_set_active_slave(struct unixctl_conn *conn, const char *args_,
+ void *aux UNUSED)
{
char *args = (char *) args_;
char *save_ptr = NULL;
}
static void
-bond_unixctl_enable_slave(struct unixctl_conn *conn, const char *args)
+bond_unixctl_enable_slave(struct unixctl_conn *conn, const char *args,
+ void *aux UNUSED)
{
enable_slave(conn, args, true);
}
static void
-bond_unixctl_disable_slave(struct unixctl_conn *conn, const char *args)
+bond_unixctl_disable_slave(struct unixctl_conn *conn, const char *args,
+ void *aux UNUSED)
{
enable_slave(conn, args, false);
}
static void
-bond_unixctl_hash(struct unixctl_conn *conn, const char *args)
+bond_unixctl_hash(struct unixctl_conn *conn, const char *args,
+ void *aux UNUSED)
{
uint8_t mac[ETH_ADDR_LEN];
uint8_t hash;
static void
bond_init(void)
{
- unixctl_command_register("bond/list", bond_unixctl_list);
- unixctl_command_register("bond/show", bond_unixctl_show);
- unixctl_command_register("bond/migrate", bond_unixctl_migrate);
+ unixctl_command_register("bond/list", bond_unixctl_list, NULL);
+ unixctl_command_register("bond/show", bond_unixctl_show, NULL);
+ unixctl_command_register("bond/migrate", bond_unixctl_migrate, NULL);
unixctl_command_register("bond/set-active-slave",
- bond_unixctl_set_active_slave);
- unixctl_command_register("bond/enable-slave", bond_unixctl_enable_slave);
- unixctl_command_register("bond/disable-slave", bond_unixctl_disable_slave);
- unixctl_command_register("bond/hash", bond_unixctl_hash);
+ bond_unixctl_set_active_slave, NULL);
+ unixctl_command_register("bond/enable-slave", bond_unixctl_enable_slave,
+ NULL);
+ unixctl_command_register("bond/disable-slave", bond_unixctl_disable_slave,
+ NULL);
+ unixctl_command_register("bond/hash", bond_unixctl_hash, NULL);
}
\f
/* Port functions. */
{
struct port *port;
- port = xcalloc(1, sizeof *port);
+ port = xzalloc(sizeof *port);
port->bridge = br;
port->port_idx = br->n_ports;
port->vlan = -1;
{
struct iface *iface;
- iface = xcalloc(1, sizeof *iface);
+ iface = xzalloc(sizeof *iface);
iface->port = port;
iface->port_ifidx = port->n_ifaces;
iface->name = xstrdup(name);
VLOG_INFO("created port mirror %s on bridge %s", name, br->name);
bridge_flush(br);
- br->mirrors[i] = m = xcalloc(1, sizeof *m);
+ br->mirrors[i] = m = xzalloc(sizeof *m);
m->bridge = br;
m->idx = i;
m->name = xstrdup(name);