X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=040c7f382de42564ed97b0c170f9333be8e26a66;hb=95440284bdf8ac9a94c3e119d011d76acab577a7;hp=d7f4d32893fbed64a630e42b62b243e5bf3e4fd0;hpb=e9e2856e084383b4f93b371dfba8320b51d4cd03;p=openvswitch diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index d7f4d328..040c7f38 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -247,7 +247,8 @@ static bool vlan_is_mirrored(const struct mirror *m UNUSED, int vlan UNUSED) } #endif -static struct iface *iface_create(struct port *, const char *name); +static struct iface *iface_create(struct port *port, + const struct ovsrec_interface *if_cfg); static void iface_destroy(struct iface *); static struct iface *iface_lookup(const struct bridge *, const char *name); static struct iface *iface_from_dp_ifidx(const struct bridge *, @@ -421,24 +422,12 @@ set_up_iface(const struct ovsrec_interface *iface_cfg, bool create) return error; } -static int -create_iface(const struct ovsrec_interface *iface_cfg) -{ - return set_up_iface(iface_cfg, true); -} - static int reconfigure_iface(const struct ovsrec_interface *iface_cfg) { return set_up_iface(iface_cfg, false); } -static void -destroy_iface(const char *iface_name) -{ - netdev_destroy(iface_name); -} - /* iterate_and_prune_ifaces() callback function that opens the network device * for 'iface', if it is not already open, and retrieves the interface's MAC @@ -528,6 +517,7 @@ iterate_and_prune_ifaces(struct bridge *br, void bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) { + struct ovsdb_idl_txn *txn; struct shash old_br, new_br; struct shash_node *node; struct bridge *br, *next; @@ -535,6 +525,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) COVERAGE_INC(bridge_reconfigure); + txn = ovsdb_idl_txn_create(ovs_cfg->header_.table->idl); + /* Collect old and new bridges. */ shash_init(&old_br); shash_init(&new_br); @@ -602,7 +594,6 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) p->devname, dpif_name(br->dpif), strerror(retval)); } - destroy_iface(p->devname); } } shash_destroy(&want_ifaces); @@ -642,17 +633,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) bool internal; int error; - /* Attempt to create the network interface in case it - * doesn't exist yet. */ - error = iface ? create_iface(iface->cfg) : 0; - if (error) { - VLOG_WARN("could not create iface %s: %s\n", if_name, - strerror(error)); - continue; - } - /* Add to datapath. */ - internal = !iface || iface_is_internal(br, if_name); + internal = iface_is_internal(br, if_name); error = dpif_port_add(br->dpif, if_name, internal ? ODP_PORT_INTERNAL : 0, NULL); if (error == EFBIG) { @@ -673,6 +655,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) uint64_t dpid; struct iface *local_iface; struct iface *hw_addr_iface; + char *dpid_string; bridge_fetch_dp_ifaces(br); iterate_and_prune_ifaces(br, init_iface_netdev, NULL); @@ -695,6 +678,10 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) dpid = bridge_pick_datapath_id(br, ea, hw_addr_iface); ofproto_set_datapath_id(br->ofproto, dpid); + dpid_string = xasprintf("%012"PRIx64, dpid); + ovsrec_bridge_set_datapath_id(br->cfg, dpid_string); + free(dpid_string); + /* Set NetFlow configuration on this bridge. */ if (br->cfg->netflow) { struct ovsrec_netflow *nf_cfg = br->cfg->netflow; @@ -766,19 +753,39 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) LIST_FOR_EACH (br, struct bridge, node, &all_bridges) { iterate_and_prune_ifaces(br, set_iface_properties, NULL); } + + ovsrec_open_vswitch_set_cur_cfg(ovs_cfg, ovs_cfg->next_cfg); + + ovsdb_idl_txn_commit(txn); + ovsdb_idl_txn_destroy(txn); /* XXX */ +} + +static const char * +bridge_get_other_config(const struct ovsrec_bridge *br_cfg, const char *key) +{ + size_t i; + + for (i = 0; i < br_cfg->n_other_config; i++) { + if (!strcmp(br_cfg->key_other_config[i], key)) { + return br_cfg->value_other_config[i]; + } + } + return NULL; } static void bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN], struct iface **hw_addr_iface) { + const char *hwaddr; size_t i, j; int error; *hw_addr_iface = NULL; /* Did the user request a particular MAC? */ - if (br->cfg->hwaddr && eth_addr_from_string(br->cfg->hwaddr, ea)) { + hwaddr = bridge_get_other_config(br->cfg, "hwaddr"); + if (hwaddr && eth_addr_from_string(hwaddr, ea)) { if (eth_addr_is_multicast(ea)) { VLOG_ERR("bridge %s: cannot set MAC address to multicast " "address "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(ea)); @@ -789,9 +796,8 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN], } } - /* Otherwise choose the minimum MAC address among all of the interfaces. - * (Xen uses FE:FF:FF:FF:FF:FF for virtual interfaces so this will get the - * MAC of the physical interface in such an environment.) */ + /* Otherwise choose the minimum non-local MAC address among all of the + * interfaces. */ memset(ea, 0xff, sizeof ea); for (i = 0; i < br->n_ports; i++) { struct port *port = br->ports[i]; @@ -832,11 +838,8 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN], } /* The local port doesn't count (since we're trying to choose its - * MAC address anyway). Other internal ports don't count because - * we really want a physical MAC if we can get it, and internal - * ports typically have randomly generated MACs. */ - if (iface->dp_ifidx == ODPP_LOCAL - || !strcmp(iface->cfg->type, "internal")) { + * MAC address anyway). */ + if (iface->dp_ifidx == ODPP_LOCAL) { continue; } @@ -852,6 +855,7 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN], /* Compare against our current choice. */ if (!eth_addr_is_multicast(iface_ea) && + !eth_addr_is_local(iface_ea) && !eth_addr_is_reserved(iface_ea) && !eth_addr_is_zero(iface_ea) && memcmp(iface_ea, ea, ETH_ADDR_LEN) < 0) @@ -860,7 +864,7 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN], *hw_addr_iface = iface; } } - if (eth_addr_is_multicast(ea) || eth_addr_is_vif(ea)) { + if (eth_addr_is_multicast(ea)) { memcpy(ea, br->default_ea, ETH_ADDR_LEN); *hw_addr_iface = NULL; VLOG_WARN("bridge %s: using default bridge Ethernet " @@ -893,10 +897,11 @@ bridge_pick_datapath_id(struct bridge *br, * stable from one run to the next, so that policy set on a datapath * "sticks". */ + const char *datapath_id; uint64_t dpid; - if (br->cfg->datapath_id - && dpid_from_string(br->cfg->datapath_id, &dpid)) { + datapath_id = bridge_get_other_config(br->cfg, "datapath-id"); + if (datapath_id && dpid_from_string(datapath_id, &dpid)) { return dpid; } @@ -1253,14 +1258,21 @@ bridge_reconfigure_one(const struct ovsrec_open_vswitch *ovs_cfg, br->name, name); } } + + /* 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_controller(ovs_cfg, br)) { char local_name[IF_NAMESIZE]; int error; error = dpif_port_get_name(br->dpif, ODPP_LOCAL, local_name, sizeof local_name); - if (!error) { - shash_add_once(&new_ports, local_name, NULL); + 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); } } @@ -1528,6 +1540,13 @@ bridge_fetch_dp_ifaces(struct bridge *br) port_array_set(&br->ifaces, p->port, iface); iface->dp_ifidx = p->port; } + + if (iface->cfg) { + int64_t ofport = (iface->dp_ifidx >= 0 + ? odp_port_to_ofp_port(iface->dp_ifidx) + : -1); + ovsrec_interface_set_ofport(iface->cfg, &ofport, 1); + } } } free(dpif_ports); @@ -3002,12 +3021,11 @@ port_reconfigure(struct port *port, const struct ovsrec_port *cfg) } SHASH_FOR_EACH (node, &new_ifaces) { const struct ovsrec_interface *if_cfg = node->data; - const char *if_name = node->name; struct iface *iface; - iface = shash_find_data(&old_ifaces, if_name); + iface = shash_find_data(&old_ifaces, if_cfg->name); if (!iface) { - iface = iface_create(port, if_name); + iface = iface_create(port, if_cfg); } iface->cfg = if_cfg; } @@ -3290,9 +3308,11 @@ port_update_vlan_compat(struct port *port) /* Interface functions. */ static struct iface * -iface_create(struct port *port, const char *name) +iface_create(struct port *port, const struct ovsrec_interface *if_cfg) { struct iface *iface; + char *name = if_cfg->name; + int error; iface = xzalloc(sizeof *iface); iface->port = port; @@ -3312,6 +3332,14 @@ iface_create(struct port *port, const char *name) port->bridge->has_bonded_ports = true; } + /* Attempt to create the network interface in case it + * doesn't exist yet. */ + error = set_up_iface(if_cfg, true); + if (error) { + VLOG_WARN("could not create iface %s: %s\n", iface->name, + strerror(error)); + } + VLOG_DBG("attached network device %s to port %s", iface->name, port->name); bridge_flush(port->bridge); @@ -3336,8 +3364,6 @@ iface_destroy(struct iface *iface) del->port_ifidx = iface->port_ifidx; netdev_close(iface->netdev); - free(iface->name); - free(iface); if (del_active) { ofproto_revalidate(port->bridge->ofproto, port->active_iface_tag); @@ -3345,6 +3371,10 @@ iface_destroy(struct iface *iface) bond_send_learning_packets(port); } + netdev_destroy(iface->name); + free(iface->name); + free(iface); + bridge_flush(port->bridge); } }