X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=e43af3c90aa42e2237c7a99e2ad560d1da164989;hb=f7eaaeba017b2442edd730b929d4713ba4375b1e;hp=bc05fdbcf70780118bd565d486c52777df33a5df;hpb=8b428d022af5848be323f6b125f896850375b8b6;p=sliver-openvswitch.git diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index bc05fdbcf..e43af3c90 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -226,6 +226,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. */ @@ -312,6 +317,7 @@ static void iface_update_cfm(struct iface *); static bool iface_refresh_cfm_stats(struct iface *iface); static void iface_update_carrier(struct 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 *); @@ -492,9 +498,7 @@ set_iface_properties(struct bridge *br OVS_UNUSED, struct iface *iface, /* Set MAC address of internal interfaces other than the local * interface. */ - if (iface->dp_ifidx != ODPP_LOCAL && !strcmp(iface->type, "internal")) { - iface_set_mac(iface); - } + iface_set_mac(iface); return true; } @@ -1195,6 +1199,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)) { @@ -1316,6 +1324,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); @@ -1730,10 +1742,14 @@ bridge_destroy(struct bridge *br) if (br) { struct port *port, *next; int error; + int i; HMAP_FOR_EACH_SAFE (port, next, hmap_node, &br->ports) { port_destroy(port); } + for (i = 0; i < MAX_MIRRORS; i++) { + mirror_destroy(br->mirrors[i]); + } list_remove(&br->node); ofproto_destroy(br->ofproto); error = dpif_delete(br->dpif); @@ -1746,6 +1762,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); } @@ -1871,22 +1888,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. @@ -4491,13 +4514,15 @@ iface_set_mac(struct iface *iface) { uint8_t ea[ETH_ADDR_LEN]; - if (iface->cfg->mac && eth_addr_from_string(iface->cfg->mac, ea)) { - if (eth_addr_is_multicast(ea)) { + if (!strcmp(iface->type, "internal") + && iface->cfg->mac && eth_addr_from_string(iface->cfg->mac, ea)) { + if (iface->dp_ifidx == ODPP_LOCAL) { + VLOG_ERR("interface %s: ignoring mac in Interface record " + "(use Bridge record to set local port's mac)", + iface->name); + } else if (eth_addr_is_multicast(ea)) { VLOG_ERR("interface %s: cannot set MAC to multicast address", iface->name); - } else if (iface->dp_ifidx == ODPP_LOCAL) { - VLOG_ERR("ignoring iface.%s.mac; use bridge.%s.mac instead", - iface->name, iface->name); } else { int error = netdev_set_etheraddr(iface->netdev, ea); if (error) { @@ -4512,7 +4537,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); } } @@ -4607,7 +4632,7 @@ iface_update_carrier(struct iface *iface) static void iface_update_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; @@ -4687,6 +4712,14 @@ iface_get_carrier(const struct iface *iface) ? netdev_get_carrier(iface->netdev) : netdev_get_miimon(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. */ @@ -4883,19 +4916,6 @@ vlan_is_mirrored(const struct mirror *m, int vlan) return false; } -static bool -port_trunks_any_mirrored_vlan(const struct mirror *m, const struct port *p) -{ - size_t i; - - for (i = 0; i < m->n_vlans; i++) { - if (port_trunks_vlan(p, m->vlans[i])) { - return true; - } - } - return false; -} - static void mirror_reconfigure_one(struct mirror *m, struct ovsrec_mirror *cfg) { @@ -4980,11 +5000,7 @@ mirror_reconfigure_one(struct mirror *m, struct ovsrec_mirror *cfg) /* Update ports. */ mirror_bit = MIRROR_MASK_C(1) << m->idx; HMAP_FOR_EACH (port, hmap_node, &m->bridge->ports) { - if (sset_contains(&m->src_ports, port->name) - || (m->n_vlans - && (!port->vlan - ? port_trunks_any_mirrored_vlan(m, port) - : vlan_is_mirrored(m, port->vlan)))) { + if (sset_contains(&m->src_ports, port->name)) { port->src_mirrors |= mirror_bit; } else { port->src_mirrors &= ~mirror_bit;