X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=ec4bb7bef57c831289751f1d48d12699d7a84368;hb=1670c579a82921fedd8b2c20818919f6b5a9c330;hp=e23ee6fcf73781738d43ef1340c005402e3ad48c;hpb=f79e673f3d3f429cd213043b054c904d23c7151a;p=sliver-openvswitch.git diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index e23ee6fcf..ec4bb7bef 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -15,59 +15,36 @@ #include #include "bridge.h" -#include "byte-order.h" #include #include -#include -#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #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" @@ -198,7 +175,8 @@ static struct port *port_lookup(const struct bridge *, const char *name); 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 *, @@ -544,10 +522,16 @@ port_configure(struct port *port) /* 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; + + LIST_FOR_EACH (iface, port_elem, &port->ifaces) { + netdev_set_miimon_interval(iface->netdev, 0); + } } /* Register. */ @@ -556,6 +540,7 @@ port_configure(struct port *port) /* Clean up. */ free(s.trunks); free(s.lacp_slaves); + free(s.bond_stable_ids); } /* Pick local port hardware address and datapath ID for 'br'. */ @@ -796,7 +781,6 @@ bridge_del_ofproto_ports(struct bridge *br) br->name, name, strerror(error)); } if (iface) { - ofproto_port_unregister(br->ofproto, ofproto_port.ofp_port); netdev_close(iface->netdev); iface->netdev = NULL; } @@ -811,7 +795,7 @@ iface_set_ofp_port(struct iface *iface, int ofp_port) 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 @@ -947,7 +931,6 @@ bridge_add_ofproto_ports(struct bridge *br) /* Already exists, nothing to do. */ ofproto_port_destroy(&ofproto_port); } - ofproto_port_destroy(&ofproto_port); } } } @@ -1416,7 +1399,7 @@ bridge_run(void) /* (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. @@ -1429,7 +1412,7 @@ bridge_run(void) 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); @@ -1650,7 +1633,11 @@ bridge_create(const struct ovsrec_bridge *br_cfg) 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); @@ -2045,7 +2032,10 @@ port_del_ifaces(struct port *port) 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. */ @@ -2071,7 +2061,8 @@ port_add_ifaces(struct port *port) 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); @@ -2183,9 +2174,10 @@ port_configure_lacp(struct port *port, struct lacp_settings *s) ? 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); @@ -2206,11 +2198,13 @@ port_configure_lacp(struct port *port, struct lacp_settings *s) 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; @@ -2220,15 +2214,24 @@ iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s) 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; + int miimon_interval; + size_t i; s->name = port->name; s->balance = BM_SLB; @@ -2239,22 +2242,24 @@ port_configure_bond(struct port *port, struct bond_settings *s) bond_mode_to_string(s->balance)); } - s->detect = BLSM_CARRIER; - detect_s = get_port_other_config(port->cfg, "bond-detect-mode", NULL); - if (detect_s && !bond_detect_mode_from_string(&s->detect, detect_s)) { - VLOG_WARN("port %s: unsupported bond-detect-mode %s, " - "defaulting to %s", - port->name, detect_s, bond_detect_mode_to_string(s->detect)); + miimon_interval = atoi(get_port_other_config(port->cfg, + "bond-miimon-interval", "0")); + if (miimon_interval <= 0) { + miimon_interval = 200; } - s->miimon_interval = atoi( - get_port_other_config(port->cfg, "bond-miimon-interval", "200")); - if (s->miimon_interval < 100) { - s->miimon_interval = 100; + detect_s = get_port_other_config(port->cfg, "bond-detect-mode", "carrier"); + if (!strcmp(detect_s, "carrier")) { + miimon_interval = 0; + } else if (strcmp(detect_s, "miimon")) { + VLOG_WARN("port %s: unsupported bond-detect-mode %s, " + "defaulting to carrier", port->name, detect_s); + miimon_interval = 0; } 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) { @@ -2262,6 +2267,20 @@ port_configure_bond(struct port *port, struct bond_settings *s) } 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; + + netdev_set_miimon_interval(iface->netdev, miimon_interval); + } } /* Interface functions. */ @@ -2470,7 +2489,7 @@ iface_delete_queues(unsigned int queue_id, 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; @@ -2672,8 +2691,6 @@ static bool 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)) { @@ -2685,7 +2702,7 @@ mirror_configure(struct mirror *m, const struct ovsrec_mirror *cfg) /* 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; @@ -2711,6 +2728,7 @@ mirror_configure(struct mirror *m, const struct ovsrec_mirror *cfg) 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;