static void bridge_configure_datapath_id(struct bridge *);
static void bridge_configure_flow_eviction_threshold(struct bridge *);
static void bridge_configure_netflow(struct bridge *);
+static void bridge_configure_forward_bpdu(struct bridge *);
static void bridge_configure_sflow(struct bridge *, int *sflow_bridge_number);
static void bridge_configure_remotes(struct bridge *,
const struct sockaddr_in *managers,
static void iface_set_ofport(const struct ovsrec_interface *, int64_t ofport);
static void iface_configure_qos(struct iface *, const struct ovsrec_qos *);
static void iface_configure_cfm(struct iface *);
-static bool iface_refresh_cfm_stats(struct iface *);
+static void iface_refresh_cfm_stats(struct iface *);
static void iface_refresh_stats(struct iface *);
static void iface_refresh_status(struct iface *);
static bool iface_get_carrier(const struct iface *);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_ofport);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_statistics);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_status);
+ ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_fault);
+ ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_mpids);
+ ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_lacp_current);
ovsdb_idl_omit(idl, &ovsrec_interface_col_external_ids);
ovsdb_idl_omit_alert(idl, &ovsrec_controller_col_is_connected);
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);
bridge_configure_netflow(br);
bridge_configure_sflow(br, &sflow_bridge_number);
/* Open the netdev. */
if (!iface->netdev) {
- struct netdev_options options;
- options.name = iface->name;
- options.type = iface->type;
- error = netdev_open(&options, &iface->netdev);
+ error = netdev_open(iface->name, iface->type, &iface->netdev);
if (error) {
VLOG_WARN("could not open network device %s (%s)",
iface->name, strerror(error));
if (port_is_bond_fake_iface(port)) {
if (ofproto_port_query_by_name(br->ofproto, port->name,
&ofproto_port)) {
- struct netdev_options options;
struct netdev *netdev;
int error;
- options.name = port->name;
- options.type = "internal";
- error = netdev_open(&options, &netdev);
+ error = netdev_open(port->name, "internal", &netdev);
if (!error) {
ofproto_port_add(br->ofproto, netdev, NULL);
netdev_close(netdev);
ofproto_set_flow_eviction_threshold(br->ofproto, threshold);
}
+/* Set forward BPDU option. */
+static void
+bridge_configure_forward_bpdu(struct bridge *br)
+{
+ const char *forward_bpdu_str;
+ bool forward_bpdu = false;
+
+ forward_bpdu_str = bridge_get_other_config(br->cfg, "forward-bpdu");
+ if (forward_bpdu_str && !strcmp(forward_bpdu_str, "true")) {
+ forward_bpdu = true;
+ }
+ ofproto_set_forward_bpdu(br->ofproto, forward_bpdu);
+}
+
static void
bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
struct iface **hw_addr_iface)
{
const char *hwaddr;
struct port *port;
+ bool found_addr = false;
int error;
*hw_addr_iface = NULL;
/* Otherwise choose the minimum non-local MAC address among all of the
* interfaces. */
- memset(ea, 0xff, ETH_ADDR_LEN);
HMAP_FOR_EACH (port, hmap_node, &br->ports) {
uint8_t iface_ea[ETH_ADDR_LEN];
struct iface *candidate;
!eth_addr_is_local(iface_ea) &&
!eth_addr_is_reserved(iface_ea) &&
!eth_addr_is_zero(iface_ea) &&
- eth_addr_compare_3way(iface_ea, ea) < 0)
+ (!found_addr || eth_addr_compare_3way(iface_ea, ea) < 0))
{
memcpy(ea, iface_ea, ETH_ADDR_LEN);
*hw_addr_iface = iface;
+ found_addr = true;
}
}
- if (eth_addr_is_multicast(ea)) {
+ if (found_addr) {
+ VLOG_DBG("bridge %s: using bridge Ethernet address "ETH_ADDR_FMT,
+ br->name, ETH_ADDR_ARGS(ea));
+ } else {
memcpy(ea, br->default_ea, ETH_ADDR_LEN);
*hw_addr_iface = NULL;
VLOG_WARN("bridge %s: using default bridge Ethernet "
"address "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(ea));
- } else {
- VLOG_DBG("bridge %s: using bridge Ethernet address "ETH_ADDR_FMT,
- br->name, ETH_ADDR_ARGS(ea));
}
}
iface_get_carrier(iface) ? "up" : "down");
error = netdev_get_mtu(iface->netdev, &mtu);
- if (!error && mtu != INT_MAX) {
+ if (!error) {
mtu_64 = mtu;
ovsrec_interface_set_mtu(iface->cfg, &mtu_64, 1);
}
/* Writes 'iface''s CFM statistics to the database. Returns true if anything
* changed, false otherwise. */
-static bool
+static void
iface_refresh_cfm_stats(struct iface *iface)
{
const struct ovsrec_interface *cfg = iface->cfg;
- bool changed = false;
- int fault;
+ int fault, error;
+ const uint64_t *rmps;
+ size_t n_rmps;
fault = ofproto_port_get_cfm_fault(iface->port->bridge->ofproto,
iface->ofp_port);
-
- if (fault < 0) {
- return false;
- }
-
- if (cfg->n_cfm_fault != 1 || cfg->cfm_fault[0] != fault) {
+ if (fault >= 0) {
bool fault_bool = fault;
ovsrec_interface_set_cfm_fault(cfg, &fault_bool, 1);
- changed = true;
+ } else {
+ ovsrec_interface_set_cfm_fault(cfg, NULL, 0);
}
- return changed;
+ error = ofproto_port_get_cfm_remote_mpids(iface->port->bridge->ofproto,
+ iface->ofp_port, &rmps, &n_rmps);
+ if (error >= 0) {
+ ovsrec_interface_set_cfm_remote_mpids(cfg, (const int64_t *)rmps,
+ n_rmps);
+ } else {
+ ovsrec_interface_set_cfm_remote_mpids(cfg, NULL, 0);
+ }
}
static bool
ofproto_free_ofproto_controller_info(&info);
}
+static void
+refresh_cfm_stats(void)
+{
+ static struct ovsdb_idl_txn *txn = NULL;
+
+ if (!txn) {
+ struct bridge *br;
+
+ txn = ovsdb_idl_txn_create(idl);
+
+ HMAP_FOR_EACH (br, node, &all_bridges) {
+ struct iface *iface;
+
+ HMAP_FOR_EACH (iface, name_node, &br->iface_by_name) {
+ iface_refresh_cfm_stats(iface);
+ }
+ }
+ }
+
+ if (ovsdb_idl_txn_commit(txn) != TXN_INCOMPLETE) {
+ ovsdb_idl_txn_destroy(txn);
+ txn = NULL;
+ }
+}
+
void
bridge_run(void)
{
struct iface *iface;
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
- changed = iface_refresh_cfm_stats(iface) || changed;
+ /* XXX: Eventually we need to remove the lacp_current flag
+ * from the database so that we can completely get rid of
+ * this rate limiter code. */
changed = iface_refresh_lacp_stats(iface) || changed;
}
}
ovsdb_idl_txn_commit(txn);
ovsdb_idl_txn_destroy(txn);
}
+
+ refresh_cfm_stats();
}
void
iface_configure_cfm(struct iface *iface)
{
const struct ovsrec_interface *cfg = iface->cfg;
+ const char *extended_str;
struct cfm_settings s;
- uint16_t remote_mpid;
- if (!cfg->n_cfm_mpid || !cfg->n_cfm_remote_mpid) {
+ if (!cfg->n_cfm_mpid) {
ofproto_port_clear_cfm(iface->port->bridge->ofproto, iface->ofp_port);
return;
}
s.mpid = *cfg->cfm_mpid;
- remote_mpid = *cfg->cfm_remote_mpid;
- s.remote_mpids = &remote_mpid;
- s.n_remote_mpids = 1;
-
s.interval = atoi(get_interface_other_config(iface->cfg, "cfm_interval",
"0"));
if (s.interval <= 0) {
s.interval = 1000;
}
+ extended_str = get_interface_other_config(iface->cfg, "cfm_extended",
+ "false");
+ s.extended = !strcasecmp("true", extended_str);
+
ofproto_port_set_cfm(iface->port->bridge->ofproto, iface->ofp_port, &s);
}