#include "vswitchd/vswitch-idl.h"
#include "xenserver.h"
#include "xtoxll.h"
+#include "sflow_api.h"
#define THIS_MODULE VLM_bridge
#include "vlog.h"
/* Maximum number of datapaths. */
enum { DP_MAX = 256 };
-static struct bridge *bridge_create(const char *name);
+static struct bridge *bridge_create(const struct ovsrec_bridge *br_cfg);
static void bridge_destroy(struct bridge *);
static struct bridge *bridge_lookup(const char *name);
static unixctl_cb_func bridge_unixctl_dump_flows;
static int bridge_run_one(struct bridge *);
+static const struct ovsrec_controller *bridge_get_controller(
+ const struct ovsrec_open_vswitch *ovs_cfg,
+ const struct bridge *br);
static void bridge_reconfigure_one(const struct ovsrec_open_vswitch *,
struct bridge *);
static void bridge_reconfigure_controller(const struct ovsrec_open_vswitch *,
bridge_init(const struct ovsrec_open_vswitch *cfg)
{
struct svec bridge_names;
- struct svec dpif_names;
+ struct svec dpif_names, dpif_types;
size_t i;
unixctl_command_register("fdb/show", bridge_unixctl_fdb_show, NULL);
svec_sort(&bridge_names);
svec_init(&dpif_names);
- dp_enumerate(&dpif_names);
- for (i = 0; i < dpif_names.n; i++) {
- const char *dpif_name = dpif_names.names[i];
+ svec_init(&dpif_types);
+ dp_enumerate_types(&dpif_types);
+ for (i = 0; i < dpif_types.n; i++) {
struct dpif *dpif;
int retval;
+ size_t j;
- retval = dpif_open(dpif_name, &dpif);
- if (!retval) {
- struct svec all_names;
- size_t j;
+ dp_enumerate_names(dpif_types.names[i], &dpif_names);
- svec_init(&all_names);
- dpif_get_all_names(dpif, &all_names);
- for (j = 0; j < all_names.n; j++) {
- if (svec_contains(&bridge_names, all_names.names[j])) {
- goto found;
+ for (j = 0; j < dpif_names.n; j++) {
+ retval = dpif_open(dpif_names.names[j], dpif_types.names[i], &dpif);
+ if (!retval) {
+ struct svec all_names;
+ size_t k;
+
+ svec_init(&all_names);
+ dpif_get_all_names(dpif, &all_names);
+ for (k = 0; k < all_names.n; k++) {
+ if (svec_contains(&bridge_names, all_names.names[k])) {
+ goto found;
+ }
}
+ dpif_delete(dpif);
+ found:
+ svec_destroy(&all_names);
+ dpif_close(dpif);
}
- dpif_delete(dpif);
- found:
- svec_destroy(&all_names);
- dpif_close(dpif);
}
}
svec_destroy(&dpif_names);
+ svec_destroy(&dpif_types);
unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows,
NULL);
}
static bool
-check_iface_netdev(struct bridge *br UNUSED, struct iface *iface,
- void *aux UNUSED)
+check_iface_netdev(struct bridge *br OVS_UNUSED, struct iface *iface,
+ void *aux OVS_UNUSED)
{
if (!iface->netdev) {
int error = set_up_iface(iface->cfg, iface, true);
}
static bool
-check_iface_dp_ifidx(struct bridge *br, struct iface *iface, void *aux UNUSED)
+check_iface_dp_ifidx(struct bridge *br, struct iface *iface,
+ void *aux OVS_UNUSED)
{
if (iface->dp_ifidx >= 0) {
VLOG_DBG("%s has interface %s on port %d",
}
static bool
-set_iface_properties(struct bridge *br UNUSED, struct iface *iface,
- void *aux UNUSED)
+set_iface_properties(struct bridge *br OVS_UNUSED, struct iface *iface,
+ void *aux OVS_UNUSED)
{
/* Set policing attributes. */
netdev_set_policing(iface->netdev,
struct shash_node *node;
struct bridge *br, *next;
size_t i;
+ int sflow_bridge_number;
COVERAGE_INC(bridge_reconfigure);
SHASH_FOR_EACH (node, &new_br) {
const char *br_name = node->name;
const struct ovsrec_bridge *br_cfg = node->data;
- if (!shash_find_data(&old_br, br_name)) {
- br = bridge_create(br_name);
- if (br) {
- br->cfg = br_cfg;
+ br = shash_find_data(&old_br, br_name);
+ if (br) {
+ /* If the bridge datapath type has changed, we need to tear it
+ * down and recreate. */
+ if (strcmp(br->cfg->datapath_type, br_cfg->datapath_type)) {
+ bridge_destroy(br);
+ bridge_create(br_cfg);
}
+ } else {
+ bridge_create(br_cfg);
}
}
shash_destroy(&old_br);
shash_destroy(&cur_ifaces);
shash_destroy(&want_ifaces);
}
+ sflow_bridge_number = 0;
LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
uint8_t ea[8];
uint64_t dpid;
dpif_get_netflow_ids(br->dpif, &opts.engine_type, &opts.engine_id);
if (nf_cfg->engine_type) {
- opts.engine_type = nf_cfg->engine_type;
+ opts.engine_type = *nf_cfg->engine_type;
}
if (nf_cfg->engine_id) {
- opts.engine_id = nf_cfg->engine_id;
+ opts.engine_id = *nf_cfg->engine_id;
}
opts.active_timeout = nf_cfg->active_timeout;
ofproto_set_netflow(br->ofproto, NULL);
}
+ /* Set sFlow configuration on this bridge. */
+ if (br->cfg->sflow) {
+ const struct ovsrec_sflow *sflow_cfg = br->cfg->sflow;
+ const struct ovsrec_controller *ctrl;
+ struct ofproto_sflow_options oso;
+
+ memset(&oso, 0, sizeof oso);
+
+ oso.targets.n = sflow_cfg->n_targets;
+ oso.targets.names = sflow_cfg->targets;
+
+ oso.sampling_rate = SFL_DEFAULT_SAMPLING_RATE;
+ if (sflow_cfg->sampling) {
+ oso.sampling_rate = *sflow_cfg->sampling;
+ }
+
+ oso.polling_interval = SFL_DEFAULT_POLLING_INTERVAL;
+ if (sflow_cfg->polling) {
+ oso.polling_interval = *sflow_cfg->polling;
+ }
+
+ oso.header_len = SFL_DEFAULT_HEADER_SIZE;
+ if (sflow_cfg->header) {
+ oso.header_len = *sflow_cfg->header;
+ }
+
+ oso.sub_id = sflow_bridge_number++;
+ oso.agent_device = sflow_cfg->agent;
+
+ ctrl = bridge_get_controller(ovs_cfg, br);
+ oso.control_ip = ctrl ? ctrl->local_ip : NULL;
+ ofproto_set_sflow(br->ofproto, &oso);
+
+ svec_destroy(&oso.targets);
+ } else {
+ ofproto_set_sflow(br->ofproto, NULL);
+ }
+
/* Update the controller and related settings. It would be more
* straightforward to call this from bridge_reconfigure_one(), but we
* can't do it there for two reasons. First, and most importantly, at
/* Bridge unixctl user interface functions. */
static void
bridge_unixctl_fdb_show(struct unixctl_conn *conn,
- const char *args, void *aux UNUSED)
+ const char *args, void *aux OVS_UNUSED)
{
struct ds ds = DS_EMPTY_INITIALIZER;
const struct bridge *br;
\f
/* Bridge reconfiguration functions. */
static struct bridge *
-bridge_create(const char *name)
+bridge_create(const struct ovsrec_bridge *br_cfg)
{
struct bridge *br;
int error;
- assert(!bridge_lookup(name));
+ assert(!bridge_lookup(br_cfg->name));
br = xzalloc(sizeof *br);
- error = dpif_create_and_open(name, &br->dpif);
+ error = dpif_create_and_open(br_cfg->name, br_cfg->datapath_type,
+ &br->dpif);
if (error) {
free(br);
return NULL;
}
dpif_flow_flush(br->dpif);
- error = ofproto_create(name, &bridge_ofhooks, br, &br->ofproto);
+ error = ofproto_create(br_cfg->name, br_cfg->datapath_type, &bridge_ofhooks,
+ br, &br->ofproto);
if (error) {
- VLOG_ERR("failed to create switch %s: %s", name, strerror(error));
+ VLOG_ERR("failed to create switch %s: %s", br_cfg->name,
+ strerror(error));
dpif_delete(br->dpif);
dpif_close(br->dpif);
free(br);
return NULL;
}
- br->name = xstrdup(name);
+ br->name = xstrdup(br_cfg->name);
+ br->cfg = br_cfg;
br->ml = mac_learning_create();
br->sent_config_request = false;
- eth_addr_random(br->default_ea);
+ eth_addr_nicira_random(br->default_ea);
port_array_init(&br->ifaces);
* stack, including those normally hidden. */
static void
bridge_unixctl_dump_flows(struct unixctl_conn *conn,
- const char *args, void *aux UNUSED)
+ const char *args, void *aux OVS_UNUSED)
{
struct bridge *br;
struct ds results;
struct svec listeners, old_listeners;
struct svec snoops, old_snoops;
struct shash_node *node;
- uint64_t mgmt_id;
size_t i;
/* Collect old ports. */
}
}
- dpid_from_string(ovs_cfg->management_id, &mgmt_id);
- ofproto_set_mgmt_id(br->ofproto, mgmt_id);
-
/* Get rid of deleted ports and add new ports. */
SHASH_FOR_EACH (node, &old_ports) {
if (!shash_find(&new_ports, node->name)) {
local_iface = bridge_get_local_iface(br);
if (local_iface && c->local_ip && inet_aton(c->local_ip, &ip)) {
struct netdev *netdev = local_iface->netdev;
- struct in_addr ip, mask, gateway;
+ struct in_addr mask, gateway;
if (!c->local_netmask || !inet_aton(c->local_netmask, &mask)) {
mask.s_addr = 0;
return dst - dsts;
}
-static void UNUSED
+static void OVS_UNUSED
print_dsts(const struct dst *dsts, size_t n)
{
for (; n--; dsts++) {
static void
bond_unixctl_list(struct unixctl_conn *conn,
- const char *args UNUSED, void *aux UNUSED)
+ const char *args OVS_UNUSED, void *aux OVS_UNUSED)
{
struct ds ds = DS_EMPTY_INITIALIZER;
const struct bridge *br;
static void
bond_unixctl_show(struct unixctl_conn *conn,
- const char *args, void *aux UNUSED)
+ const char *args, void *aux OVS_UNUSED)
{
struct ds ds = DS_EMPTY_INITIALIZER;
const struct port *port;
static void
bond_unixctl_migrate(struct unixctl_conn *conn, const char *args_,
- void *aux UNUSED)
+ void *aux OVS_UNUSED)
{
char *args = (char *) args_;
char *save_ptr = NULL;
static void
bond_unixctl_set_active_slave(struct unixctl_conn *conn, const char *args_,
- void *aux UNUSED)
+ void *aux OVS_UNUSED)
{
char *args = (char *) args_;
char *save_ptr = NULL;
static void
bond_unixctl_enable_slave(struct unixctl_conn *conn, const char *args,
- void *aux UNUSED)
+ void *aux OVS_UNUSED)
{
enable_slave(conn, args, true);
}
static void
bond_unixctl_disable_slave(struct unixctl_conn *conn, const char *args,
- void *aux UNUSED)
+ void *aux OVS_UNUSED)
{
enable_slave(conn, args, false);
}
static void
bond_unixctl_hash(struct unixctl_conn *conn, const char *args,
- void *aux UNUSED)
+ void *aux OVS_UNUSED)
{
uint8_t mac[ETH_ADDR_LEN];
uint8_t hash;
iface = shash_find_data(&old_ifaces, if_cfg->name);
if (!iface) {
- iface = iface_create(port, if_cfg);
+ iface_create(port, if_cfg);
} else {
iface->cfg = if_cfg;
}
}
}
- /* Update learning disabled vlans (for RSPAN). */
+ /* Update flooded vlans (for RSPAN). */
rspan_vlans = NULL;
if (br->cfg->n_flood_vlans) {
rspan_vlans = bitmap_allocate(4096);
}
}
}
- if (mac_learning_set_disabled_vlans(br->ml, rspan_vlans)) {
+ if (mac_learning_set_flood_vlans(br->ml, rspan_vlans)) {
bridge_flush(br);
}
}
size_t n_vlans;
size_t i;
- *vlans = xmalloc(sizeof *vlans * cfg->n_select_vlan);
+ *vlans = xmalloc(sizeof **vlans * cfg->n_select_vlan);
n_vlans = 0;
for (i = 0; i < cfg->n_select_vlan; i++) {
int64_t vlan = cfg->select_vlan[i];