-/* Expires all MAC learning entries associated with 'port' and forces ofproto
- * to revalidate every flow. */
-static void
-port_flush_macs(struct port *port)
-{
- struct bridge *br = port->bridge;
- struct mac_learning *ml = br->ml;
- struct mac_entry *mac, *next_mac;
-
- bridge_flush(br);
- LIST_FOR_EACH_SAFE (mac, next_mac, lru_node, &ml->lrus) {
- if (mac->port.p == port) {
- mac_learning_expire(ml, mac);
- }
- }
-}
-
-static void
-port_reconfigure(struct port *port, const struct ovsrec_port *cfg)
-{
- const char *detect_mode;
- struct sset new_ifaces;
- long long int next_rebalance, miimon_next_update, lacp_priority;
- bool need_flush = false;
- unsigned long *trunks;
- int vlan;
- size_t i;
-
- port->cfg = cfg;
-
- /* Update settings. */
- port->updelay = cfg->bond_updelay;
- if (port->updelay < 0) {
- port->updelay = 0;
- }
- port->downdelay = cfg->bond_downdelay;
- if (port->downdelay < 0) {
- port->downdelay = 0;
- }
- port->bond_rebalance_interval = atoi(
- get_port_other_config(cfg, "bond-rebalance-interval", "10000"));
- if (port->bond_rebalance_interval < 1000) {
- port->bond_rebalance_interval = 1000;
- }
- next_rebalance = time_msec() + port->bond_rebalance_interval;
- if (port->bond_next_rebalance > next_rebalance) {
- port->bond_next_rebalance = next_rebalance;
- }
-
- detect_mode = get_port_other_config(cfg, "bond-detect-mode",
- "carrier");
-
- netdev_monitor_destroy(port->monitor);
- port->monitor = NULL;
-
- if (strcmp(detect_mode, "miimon")) {
- port->monitor = netdev_monitor_create();
-
- if (strcmp(detect_mode, "carrier")) {
- VLOG_WARN("port %s: unsupported bond-detect-mode %s, "
- "defaulting to carrier", port->name, detect_mode);
- }
- }
-
- port->miimon_interval = atoi(
- get_port_other_config(cfg, "bond-miimon-interval", "200"));
- if (port->miimon_interval < 100) {
- port->miimon_interval = 100;
- }
- miimon_next_update = time_msec() + port->miimon_interval;
- if (port->miimon_next_update > miimon_next_update) {
- port->miimon_next_update = miimon_next_update;
- }
-
- if (!port->cfg->bond_mode ||
- !strcmp(port->cfg->bond_mode, bond_mode_to_string(BM_SLB))) {
- port->bond_mode = BM_SLB;
- } else if (!strcmp(port->cfg->bond_mode, bond_mode_to_string(BM_AB))) {
- port->bond_mode = BM_AB;
- } else if (!strcmp(port->cfg->bond_mode, bond_mode_to_string(BM_TCP))) {
- port->bond_mode = BM_TCP;
- } else {
- port->bond_mode = BM_SLB;
- VLOG_WARN("port %s: unknown bond_mode %s, defaulting to %s",
- port->name, port->cfg->bond_mode,
- bond_mode_to_string(port->bond_mode));
- }
-
- /* Add new interfaces and update 'cfg' member of existing ones. */
- sset_init(&new_ifaces);
- for (i = 0; i < cfg->n_interfaces; i++) {
- const struct ovsrec_interface *if_cfg = cfg->interfaces[i];
- struct iface *iface;
-
- if (!sset_add(&new_ifaces, if_cfg->name)) {
- VLOG_WARN("port %s: %s specified twice as port interface",
- port->name, if_cfg->name);
- iface_set_ofport(if_cfg, -1);
- continue;
- }
-
- iface = iface_lookup(port->bridge, if_cfg->name);
- if (iface) {
- if (iface->port != port) {
- VLOG_ERR("bridge %s: %s interface is on multiple ports, "
- "removing from %s",
- port->bridge->name, if_cfg->name, iface->port->name);
- continue;
- }
- iface->cfg = if_cfg;
- } else {
- iface = iface_create(port, if_cfg);
- }
-
- /* Determine interface type. The local port always has type
- * "internal". Other ports take their type from the database and
- * default to "system" if none is specified. */
- iface->type = (!strcmp(if_cfg->name, port->bridge->name) ? "internal"
- : if_cfg->type[0] ? if_cfg->type
- : "system");
-
- lacp_priority =
- atoi(get_interface_other_config(if_cfg, "lacp-port-priority",
- "0"));
-
- if (lacp_priority <= 0 || lacp_priority > UINT16_MAX) {
- iface->lacp_priority = UINT16_MAX;
- } else {
- iface->lacp_priority = lacp_priority;
- }
- }
- sset_destroy(&new_ifaces);
-
- port->lacp_fast = !strcmp(get_port_other_config(cfg, "lacp-time", "slow"),
- "fast");
-
- lacp_priority =
- atoi(get_port_other_config(cfg, "lacp-system-priority", "0"));
-
- if (lacp_priority <= 0 || lacp_priority > UINT16_MAX) {
- /* Prefer bondable links if unspecified. */
- port->lacp_priority = port->n_ifaces > 1 ? UINT16_MAX - 1 : UINT16_MAX;
- } else {
- port->lacp_priority = lacp_priority;
- }
-
- if (!port->cfg->lacp) {
- /* XXX when LACP implementation has been sufficiently tested, enable by
- * default and make active on bonded ports. */
- lacp_destroy(port->lacp);
- port->lacp = NULL;
- } else if (!strcmp(port->cfg->lacp, "off")) {
- lacp_destroy(port->lacp);
- port->lacp = NULL;
- } else if (!strcmp(port->cfg->lacp, "active")) {
- if (!port->lacp) {
- port->lacp = lacp_create();
- }
- port->lacp_active = true;
- } else if (!strcmp(port->cfg->lacp, "passive")) {
- if (!port->lacp) {
- port->lacp = lacp_create();
- }
- port->lacp_active = false;
- } else {
- VLOG_WARN("port %s: unknown LACP mode %s",
- port->name, port->cfg->lacp);
- lacp_destroy(port->lacp);
- port->lacp = NULL;
- }
-
- /* Get VLAN tag. */
- vlan = -1;
- if (cfg->tag) {
- if (port->n_ifaces < 2) {
- vlan = *cfg->tag;
- if (vlan >= 0 && vlan <= 4095) {
- VLOG_DBG("port %s: assigning VLAN tag %d", port->name, vlan);
- } else {
- vlan = -1;
- }
- } else {
- /* It's possible that bonded, VLAN-tagged ports make sense. Maybe
- * they even work as-is. But they have not been tested. */
- VLOG_WARN("port %s: VLAN tags not supported on bonded ports",
- port->name);
- }
- }
- if (port->vlan != vlan) {
- port->vlan = vlan;
- need_flush = true;
- }
-
- /* Get trunked VLANs. */
- trunks = NULL;
- if (vlan < 0 && cfg->n_trunks) {
- size_t n_errors;
-
- trunks = bitmap_allocate(4096);
- n_errors = 0;
- for (i = 0; i < cfg->n_trunks; i++) {
- int trunk = cfg->trunks[i];
- if (trunk >= 0) {
- bitmap_set1(trunks, trunk);
- } else {
- n_errors++;
- }
- }
- if (n_errors) {
- VLOG_ERR("port %s: invalid values for %zu trunk VLANs",
- port->name, cfg->n_trunks);
- }
- if (n_errors == cfg->n_trunks) {
- VLOG_ERR("port %s: no valid trunks, trunking all VLANs",
- port->name);
- bitmap_free(trunks);
- trunks = NULL;
- }
- } else if (vlan >= 0 && cfg->n_trunks) {
- VLOG_ERR("port %s: ignoring trunks in favor of implicit vlan",
- port->name);
- }
- if (trunks == NULL
- ? port->trunks != NULL
- : port->trunks == NULL || !bitmap_equal(trunks, port->trunks, 4096)) {
- need_flush = true;
- }
- bitmap_free(port->trunks);
- port->trunks = trunks;
-
- if (need_flush) {
- port_flush_macs(port);
- }
-}
-