Merge "citrix" branch into "master.
authorBen Pfaff <blp@nicira.com>
Mon, 5 Oct 2009 17:29:07 +0000 (10:29 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 5 Oct 2009 17:29:07 +0000 (10:29 -0700)
1  2 
lib/shash.c
ofproto/ofproto.c
vswitchd/bridge.c
vswitchd/ovs-vswitchd.conf.5.in
xenserver/etc_init.d_vswitch

diff --cc lib/shash.c
Simple merge
Simple merge
@@@ -365,82 -357,6 +367,93 @@@ bridge_configure_ssl(void
  }
  #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);
      }
  }
  
@@@ -3189,6 -3117,60 +3193,60 @@@ iface_from_dp_ifidx(const struct bridg
  {
      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. */
  
@@@ -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
Simple merge