From: Ben Pfaff Date: Mon, 5 Oct 2009 17:29:07 +0000 (-0700) Subject: Merge "citrix" branch into "master. X-Git-Tag: v0.99.0~60 X-Git-Url: http://git.onelab.eu/?p=sliver-openvswitch.git;a=commitdiff_plain;h=4d678233e981fa319a338f6b0949e9dc625941a4 Merge "citrix" branch into "master. --- 4d678233e981fa319a338f6b0949e9dc625941a4 diff --cc vswitchd/bridge.c index 933f4afa5,36be700df..ef390f77e --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@@ -365,82 -357,6 +367,93 @@@ bridge_configure_ssl(void } #endif +/* 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 + * address and carrier status. */ +static bool +init_iface_netdev(struct bridge *br UNUSED, struct iface *iface, + void *aux UNUSED) +{ + if (iface->netdev) { + return true; + } else if (!netdev_open(iface->name, NETDEV_ETH_TYPE_NONE, + &iface->netdev)) { + netdev_get_carrier(iface->netdev, &iface->enabled); + return true; + } else { + /* If the network device can't be opened, then we're not going to try + * to do anything with this interface. */ + return false; + } +} + +static bool +check_iface_dp_ifidx(struct bridge *br, struct iface *iface, void *aux UNUSED) +{ + if (iface->dp_ifidx >= 0) { + VLOG_DBG("%s has interface %s on port %d", + dpif_name(br->dpif), + iface->name, iface->dp_ifidx); + return true; + } else { + VLOG_ERR("%s interface not in %s, dropping", + iface->name, dpif_name(br->dpif)); + return false; + } +} + +static bool - set_iface_policing(struct bridge *br UNUSED, struct iface *iface, ++set_iface_properties(struct bridge *br UNUSED, struct iface *iface, + void *aux UNUSED) +{ - int rate = cfg_get_int(0, "port.%s.ingress.policing-rate", iface->name); - int burst = cfg_get_int(0, "port.%s.ingress.policing-burst", iface->name); ++ int rate, burst; ++ ++ /* Set policing attributes. */ ++ rate = cfg_get_int(0, "port.%s.ingress.policing-rate", iface->name); ++ burst = cfg_get_int(0, "port.%s.ingress.policing-burst", iface->name); + netdev_set_policing(iface->netdev, rate, burst); ++ ++ /* Set MAC address of internal interfaces other than the local ++ * interface. */ ++ if (iface->dp_ifidx != ODPP_LOCAL ++ && iface_is_internal(br, iface->name)) { ++ iface_set_mac(iface); ++ } ++ + return true; +} + +/* Calls 'cb' for each interfaces in 'br', passing along the 'aux' argument. + * Deletes from 'br' all the interfaces for which 'cb' returns false, and then + * deletes from 'br' any ports that no longer have any interfaces. */ +static void +iterate_and_prune_ifaces(struct bridge *br, + bool (*cb)(struct bridge *, struct iface *, + void *aux), + void *aux) +{ + size_t i, j; + + for (i = 0; i < br->n_ports; ) { + struct port *port = br->ports[i]; + for (j = 0; j < port->n_ifaces; ) { + struct iface *iface = port->ifaces[j]; + if (cb(br, iface, aux)) { + j++; + } else { + iface_destroy(iface); + } + } + + if (port->n_ifaces) { + i++; + } else { + VLOG_ERR("%s port has no interfaces, dropping", port->name); + port_destroy(port); + } + } +} + void bridge_reconfigure(void) { @@@ -529,34 -459,32 +542,24 @@@ bridge_get_all_ifaces(br, &want_ifaces); svec_diff(&want_ifaces, &cur_ifaces, &add_ifaces, NULL, NULL); - next_port_no = 1; for (i = 0; i < add_ifaces.n; i++) { const char *if_name = add_ifaces.names[i]; - for (;;) { - bool internal; - int error; - - /* Add to datapath. */ - internal = iface_is_internal(br, if_name); - error = dpif_port_add(&br->dpif, if_name, next_port_no++, - internal ? ODP_PORT_INTERNAL : 0); - if (error != EEXIST) { - if (next_port_no >= 256) { - VLOG_ERR("ran out of valid port numbers on dp%u", - dpif_id(&br->dpif)); - goto out; - } - if (error) { - VLOG_ERR("failed to add %s interface to dp%u: %s", - if_name, dpif_id(&br->dpif), strerror(error)); - } - break; - } + bool internal; + int error; + - /* It's an internal interface if it's marked that way, or if - * it's a bonded interface for which we're faking up a network - * device. */ - internal = cfg_get_bool(0, "iface.%s.internal", if_name); - if (cfg_get_bool(0, "bonding.%s.fake-iface", if_name)) { - struct port *port = port_lookup(br, if_name); - if (port && port->n_ifaces > 1) { - internal = true; - } - } - + /* Add to datapath. */ ++ internal = iface_is_internal(br, if_name); + error = dpif_port_add(br->dpif, if_name, + internal ? ODP_PORT_INTERNAL : 0, NULL); + if (error == EFBIG) { + VLOG_ERR("ran out of valid port numbers on %s", + dpif_name(br->dpif)); + break; + } else if (error) { + VLOG_ERR("failed to add %s interface to %s: %s", + if_name, dpif_name(br->dpif), strerror(error)); } } - out: svec_destroy(&cur_ifaces); svec_destroy(&want_ifaces); svec_destroy(&add_ifaces); @@@ -637,13 -586,20 +640,14 @@@ LIST_FOR_EACH (br, struct bridge, node, &all_bridges) { for (i = 0; i < br->n_ports; i++) { struct port *port = br->ports[i]; + port_update_vlan_compat(port); - - for (j = 0; j < port->n_ifaces; j++) { - struct iface *iface = port->ifaces[j]; - if (iface->dp_ifidx != ODPP_LOCAL - && iface_is_internal(br, iface->name)) { - iface_set_mac(iface); - } - } + port_update_bonding(port); } } LIST_FOR_EACH (br, struct bridge, node, &all_bridges) { brstp_reconfigure(br); - iterate_and_prune_ifaces(br, set_iface_policing, NULL); ++ iterate_and_prune_ifaces(br, set_iface_properties, NULL); } } @@@ -3189,6 -3117,60 +3193,60 @@@ iface_from_dp_ifidx(const struct bridg { return port_array_get(&br->ifaces, dp_ifidx); } + + /* Returns true if 'iface' is the name of an "internal" interface on bridge + * 'br', that is, an interface that is entirely simulated within the datapath. + * The local port (ODPP_LOCAL) is always an internal interface. Other local + * interfaces are created by setting "iface..internal = true". + * + * In addition, we have a kluge-y feature that creates an internal port with + * the name of a bonded port if "bonding..fake-iface = true" is set. + * This feature needs to go away in the long term. Until then, this is one + * reason why this function takes a name instead of a struct iface: the fake + * interfaces created this way do not have a struct iface. */ + static bool + iface_is_internal(const struct bridge *br, const char *iface) + { + if (!strcmp(iface, br->name) + || cfg_get_bool(0, "iface.%s.internal", iface)) { + return true; + } + + if (cfg_get_bool(0, "bonding.%s.fake-iface", iface)) { + struct port *port = port_lookup(br, iface); + if (port && port->n_ifaces > 1) { + return true; + } + } + + return false; + } + + /* Set Ethernet address of 'iface', if one is specified in the configuration + * file. */ + static void + iface_set_mac(struct iface *iface) + { + uint64_t mac = cfg_get_mac(0, "iface.%s.mac", iface->name); + if (mac) { + static uint8_t ea[ETH_ADDR_LEN]; + + eth_addr_from_uint64(mac, ea); + 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_nodev_set_etheraddr(iface->name, ea); ++ int error = netdev_set_etheraddr(iface->netdev, ea); + if (error) { + VLOG_ERR("interface %s: setting MAC failed (%s)", + iface->name, strerror(error)); + } + } + } + } /* Port mirroring. */ diff --cc vswitchd/ovs-vswitchd.conf.5.in index e7a173971,7f989b40f..4d4bb482a --- a/vswitchd/ovs-vswitchd.conf.5.in +++ b/vswitchd/ovs-vswitchd.conf.5.in @@@ -50,18 -113,19 +113,18 @@@ configure \fBovs\-vswitchd\fR .SS "Bridge Configuration" A bridge (switch) with a given \fIname\fR is configured by specifying the names of its network devices as values for key -\fBbridge.\fIname\fB.port\fR. (The specified \fIname\fR may not begin -with \fBdp\fR or \fBnl:\fR followed by a digit.) +\fBbridge.\fIname\fB.port\fR. .PP - The names given on \fBbridge.\fIname\fB.port\fR must be the names of - existing network devices, except for ``internal ports.'' An internal - port is a simulated network device that receives traffic only - through the switch and switches any traffic sent it through the - switch. An internal port may configured with an IP address, - etc. using the usual system tools (e.g. \fBifconfig\fR, \fBip\fR). To - designate network device \fInetdev\fR as an internal port, add - \fBiface.\fInetdev\fB.internal=true\fR to the configuration file. - \fBovs\-vswitchd\fR will honor this configuration setting by automatically - creating the named internal port. + To designate network device \fInetdev\fR as an internal port, add + \fBiface.\fInetdev\fB.internal=true\fR to the configuration file, + which causes \fBovs\-vswitchd\fR to automatically creates + \fInetdev\fR, which may then be configured using the usual system + tools (e.g. \fBifconfig\fR, \fBip\fR). An internal interface by + default has a random Ethernet address, but you may configure a + specific address by setting \fBiface.\fInetdev\fB.mac\fR to a MAC + address in the format + \fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR, where each + \fIx\fR is a hex digit. .PP A bridge with a given \fIname\fR always has an internal port with the same \fIname\fR, called the ``local port.'' This network device may