X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=d883596de83c0e129c088974516cd4554d6495d8;hb=cc8d12f9364760456c86e92378d529c0dd9aaa66;hp=2b8b2482381f60018be980b2a1693a7ab5865ea3;hpb=f76e2dfc8a1dd2581629a0a23c40cc43a77485d3;p=openvswitch diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 2b8b2482..d883596d 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -185,6 +185,11 @@ struct bridge { /* Port mirroring. */ struct mirror *mirrors[MAX_MIRRORS]; + + /* Synthetic local port if necessary. */ + struct ovsrec_port synth_local_port; + struct ovsrec_interface synth_local_iface; + struct ovsrec_interface *synth_local_ifacep; }; /* List of all bridges. */ @@ -264,6 +269,7 @@ static void iface_update_qos(struct iface *, const struct ovsrec_qos *); static void iface_update_cfm(struct iface *); static bool iface_refresh_cfm_stats(struct iface *iface); static bool iface_get_carrier(const struct iface *); +static bool iface_is_synthetic(const struct iface *); static void shash_from_ovs_idl_map(char **keys, char **values, size_t n, struct shash *); @@ -658,6 +664,13 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) dpif_port = NULL; } if (iface) { + if (iface->port->bond) { + /* The bond has a pointer to the netdev, so remove it + * from the bond before closing the netdev. The slave + * will get added back to the bond later, after a new + * netdev is available. */ + bond_slave_unregister(iface->port->bond, iface); + } netdev_close(iface->netdev); iface->netdev = NULL; } @@ -1140,6 +1153,10 @@ iface_refresh_status(struct iface *iface) int64_t mtu_64; int error; + if (iface_is_synthetic(iface)) { + return; + } + shash_init(&sh); if (!netdev_get_status(iface->netdev, &sh)) { @@ -1282,6 +1299,10 @@ iface_refresh_stats(struct iface *iface) struct netdev_stats stats; + if (iface_is_synthetic(iface)) { + return; + } + /* Intentionally ignore return value, since errors will set 'stats' to * all-1s, and we will deal with that correctly below. */ netdev_get_stats(iface->netdev, &stats); @@ -1716,6 +1737,7 @@ bridge_destroy(struct bridge *br) hmap_destroy(&br->ifaces); hmap_destroy(&br->ports); shash_destroy(&br->iface_by_name); + free(br->synth_local_iface.type); free(br->name); free(br); } @@ -1841,22 +1863,28 @@ bridge_reconfigure_one(struct bridge *br) br->name, name); } } + if (!shash_find(&new_ports, br->name)) { + struct dpif_port dpif_port; + char *type; - /* If we have a controller, then we need a local port. Complain if the - * user didn't specify one. - * - * XXX perhaps we should synthesize a port ourselves in this case. */ - if (bridge_get_controllers(br, NULL)) { - char local_name[IF_NAMESIZE]; - int error; + VLOG_WARN("bridge %s: no port named %s, synthesizing one", + br->name, br->name); - error = dpif_port_get_name(br->dpif, ODPP_LOCAL, - local_name, sizeof local_name); - if (!error && !shash_find(&new_ports, local_name)) { - VLOG_WARN("bridge %s: controller specified but no local port " - "(port named %s) defined", - br->name, local_name); - } + dpif_port_query_by_number(br->dpif, ODPP_LOCAL, &dpif_port); + type = xstrdup(dpif_port.type ? dpif_port.type : "internal"); + dpif_port_destroy(&dpif_port); + + br->synth_local_port.interfaces = &br->synth_local_ifacep; + br->synth_local_port.n_interfaces = 1; + br->synth_local_port.name = br->name; + + br->synth_local_iface.name = br->name; + free(br->synth_local_iface.type); + br->synth_local_iface.type = type; + + br->synth_local_ifacep = &br->synth_local_iface; + + shash_add(&new_ports, br->name, &br->synth_local_port); } /* Get rid of deleted ports. @@ -2923,12 +2951,12 @@ port_reconfigure(struct port *port, const struct ovsrec_port *cfg) port->cfg = cfg; - /* 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; + const char *type; if (!sset_add(&new_ifaces, if_cfg->name)) { VLOG_WARN("port %s: %s specified twice as port interface", @@ -2937,8 +2965,18 @@ port_reconfigure(struct port *port, const struct ovsrec_port *cfg) continue; } + /* 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. */ + type = (!strcmp(if_cfg->name, port->bridge->name) ? "internal" + : if_cfg->type[0] ? if_cfg->type + : "system"); + iface = iface_lookup(port->bridge, if_cfg->name); - if (iface) { + if (!strcmp(type, "null")) { + iface_destroy(iface); + continue; + } else if (iface) { if (iface->port != port) { VLOG_ERR("bridge %s: %s interface is on multiple ports, " "removing from %s", @@ -2950,12 +2988,7 @@ port_reconfigure(struct port *port, const struct ovsrec_port *cfg) 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"); + iface->type = type; } sset_destroy(&new_ifaces); @@ -3103,11 +3136,13 @@ static void iface_reconfigure_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->dp_ifidx; @@ -3117,9 +3152,14 @@ iface_reconfigure_lacp(struct iface *iface) priority = UINT16_MAX; } + if (key < 0 || key > UINT16_MAX) { + key = 0; + } + s.name = iface->name; s.id = portid; s.priority = priority; + s.key = key; lacp_slave_register(iface->port->lacp, iface, &s); } @@ -3156,9 +3196,9 @@ port_reconfigure_lacp(struct port *port) ? 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); @@ -3225,6 +3265,8 @@ port_reconfigure_bond(struct port *port) 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) { @@ -3242,9 +3284,15 @@ port_reconfigure_bond(struct port *port) } LIST_FOR_EACH (iface, port_elem, &port->ifaces) { - uint16_t stable_id = (port->lacp - ? lacp_slave_get_port_id(port->lacp, iface) - : iface->dp_ifidx); + 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 = odp_port_to_ofp_port(iface->dp_ifidx); + } + bond_slave_register(iface->port->bond, iface, stable_id, iface->netdev); } @@ -3405,7 +3453,7 @@ iface_set_mac(struct iface *iface) static void iface_set_ofport(const struct ovsrec_interface *if_cfg, int64_t ofport) { - if (if_cfg) { + if (if_cfg && !ovsdb_idl_row_is_synthetic(&if_cfg->header_)) { ovsrec_interface_set_ofport(if_cfg, &ofport, 1); } } @@ -3565,6 +3613,14 @@ iface_get_carrier(const struct iface *iface) /* XXX */ return netdev_get_carrier(iface->netdev); } + +/* Returns true if 'iface' is synthetic, that is, if we constructed it locally + * instead of obtaining it from the database. */ +static bool +iface_is_synthetic(const struct iface *iface) +{ + return ovsdb_idl_row_is_synthetic(&iface->cfg->header_); +} /* Port mirroring. */