}
#endif
- set_iface_policing(struct bridge *br UNUSED, struct iface *iface,
+/* 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
- 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);
++set_iface_properties(struct bridge *br UNUSED, struct iface *iface,
+ void *aux UNUSED)
+{
++ 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)
{
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);
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);
}
}
{
return port_array_get(&br->ifaces, dp_ifidx);
}
- int error = netdev_nodev_set_etheraddr(iface->name, ea);
+
+ /* 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.<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.<bondname>.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_set_etheraddr(iface->netdev, ea);
+ if (error) {
+ VLOG_ERR("interface %s: setting MAC failed (%s)",
+ iface->name, strerror(error));
+ }
+ }
+ }
+ }
\f
/* Port mirroring. */
.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