netdev-vport: Use vport set_stats instead of internal dev.
[openvswitch] / lib / netdev.c
index 99b5d243a5304b3dbd05d057984906378ac16069..a15315a79019ca5062a07b7796d0ff3476fad97f 100644 (file)
 #include "vlog.h"
 
 static const struct netdev_class *base_netdev_classes[] = {
+#ifdef HAVE_NETLINK
     &netdev_linux_class,
     &netdev_tap_class,
+    &netdev_patch_class,
     &netdev_gre_class,
+#endif
 };
 
 static struct shash netdev_classes = SHASH_INITIALIZER(&netdev_classes);
@@ -262,12 +265,6 @@ create_device(struct netdev_options *options, struct netdev_dev **netdev_devp)
 {
     struct netdev_class *netdev_class;
 
-    if (!options->may_create) {
-        VLOG_WARN("attempted to create a device that may not be created: %s",
-                  options->name);
-        return ENODEV;
-    }
-
     if (!options->type || strlen(options->type) == 0) {
         /* Default to system. */
         options->type = "system";
@@ -294,15 +291,7 @@ create_device(struct netdev_options *options, struct netdev_dev **netdev_devp)
  * 'ethertype' may be a 16-bit Ethernet protocol value in host byte order to
  * capture frames of that type received on the device.  It may also be one of
  * the 'enum netdev_pseudo_ethertype' values to receive frames in one of those
- * categories.
- *
- * If the 'may_create' flag is set then this is allowed to be the first time
- * the device is opened (i.e. the refcount will be 1 after this call).  It
- * may be set to false if the device should have already been created.
- *
- * If the 'may_open' flag is set then the call will succeed even if another
- * caller has already opened it.  It may be to false if the device should not
- * currently be open. */
+ * categories. */
 
 int
 netdev_open(struct netdev_options *options, struct netdev **netdevp)
@@ -327,18 +316,12 @@ netdev_open(struct netdev_options *options, struct netdev **netdevp)
         }
         update_device_args(netdev_dev, options->args);
 
-    } else if (options->may_open) {
-        if (!shash_is_empty(options->args) &&
-            !compare_device_args(netdev_dev, options->args)) {
+    } else if (!shash_is_empty(options->args) &&
+               !compare_device_args(netdev_dev, options->args)) {
 
-            VLOG_WARN("%s: attempted to open already created netdev with "
-                      "different arguments", options->name);
-            return EINVAL;
-        }
-    } else {
-        VLOG_WARN("%s: attempted to create a netdev device with bound name",
-                  options->name);
-        return EEXIST;
+        VLOG_WARN("%s: attempted to open already open netdev with "
+                  "different arguments", options->name);
+        return EINVAL;
     }
 
     error = netdev_dev->netdev_class->open(netdev_dev, options->ethertype, 
@@ -361,11 +344,8 @@ netdev_open_default(const char *name, struct netdev **netdevp)
     struct netdev_options options;
 
     memset(&options, 0, sizeof options);
-
     options.name = name;
     options.ethertype = NETDEV_ETH_TYPE_NONE;
-    options.may_create = true;
-    options.may_open = true;
 
     return netdev_open(&options, netdevp);
 }
@@ -434,6 +414,14 @@ netdev_exists(const char *name)
     }
 }
 
+/* Returns true if a network device named 'name' is currently opened,
+ * otherwise false. */
+bool
+netdev_is_open(const char *name)
+{
+    return !!shash_find_data(&netdev_dev_shash, name);
+}
+
 /*  Clears 'svec' and enumerates the names of all known network devices. */
 int
 netdev_enumerate(struct svec *svec)
@@ -620,23 +608,37 @@ netdev_get_mtu(const struct netdev *netdev, int *mtup)
  * value should be unique within a host and remain stable at least until
  * reboot.  SNMP says an ifindex "ranges between 1 and the value of ifNumber"
  * but many systems do not follow this rule anyhow.
+ *
+ * Some network devices may not implement support for this function.  In such
+ * cases this function will always return -EOPNOTSUPP.
  */
 int
 netdev_get_ifindex(const struct netdev *netdev)
 {
-    return netdev_get_dev(netdev)->netdev_class->get_ifindex(netdev);
+    int (*get_ifindex)(const struct netdev *);
+
+    get_ifindex = netdev_get_dev(netdev)->netdev_class->get_ifindex;
+
+    return get_ifindex ? get_ifindex(netdev) : -EOPNOTSUPP;
 }
 
 /* Stores the features supported by 'netdev' into each of '*current',
  * '*advertised', '*supported', and '*peer' that are non-null.  Each value is a
  * bitmap of "enum ofp_port_features" bits, in host byte order.  Returns 0 if
  * successful, otherwise a positive errno value.  On failure, all of the
- * passed-in values are set to 0. */
+ * passed-in values are set to 0.
+ *
+ * Some network devices may not implement support for this function.  In such
+ * cases this function will always return EOPNOTSUPP.
+ */
 int
 netdev_get_features(struct netdev *netdev,
                     uint32_t *current, uint32_t *advertised,
                     uint32_t *supported, uint32_t *peer)
 {
+    int (*get_features)(struct netdev *netdev,
+                        uint32_t *current, uint32_t *advertised,
+                        uint32_t *supported, uint32_t *peer);
     uint32_t dummy[4];
     int error;
 
@@ -653,8 +655,10 @@ netdev_get_features(struct netdev *netdev,
         peer = &dummy[3];
     }
 
-    error = netdev_get_dev(netdev)->netdev_class->get_features(netdev, current,
-            advertised, supported, peer);
+    get_features = netdev_get_dev(netdev)->netdev_class->get_features;
+    error = get_features
+                    ? get_features(netdev, current, advertised, supported, peer)
+                    : EOPNOTSUPP;
     if (error) {
         *current = *advertised = *supported = *peer = 0;
     }
@@ -933,6 +937,19 @@ netdev_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
     return error;
 }
 
+/* Attempts to change the stats for 'netdev' to those provided in 'stats'.
+ * Returns 0 if successful, otherwise a positive errno value.
+ *
+ * This will probably fail for most network devices.  Some devices might only
+ * allow setting their stats to 0. */
+int
+netdev_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
+{
+    return (netdev_get_dev(netdev)->netdev_class->set_stats
+             ? netdev_get_dev(netdev)->netdev_class->set_stats(netdev, stats)
+             : EOPNOTSUPP);
+}
+
 /* Attempts to set input rate limiting (policing) policy, such that up to
  * 'kbits_rate' kbps of traffic is accepted, with a maximum accumulative burst
  * size of 'kbits' kb. */
@@ -1042,6 +1059,13 @@ netdev_dev_get_type(const struct netdev_dev *netdev_dev)
     return netdev_dev->netdev_class->type;
 }
 
+/* Returns the class associated with 'netdev_dev'. */
+const struct netdev_class *
+netdev_dev_get_class(const struct netdev_dev *netdev_dev)
+{
+    return netdev_dev->netdev_class;
+}
+
 /* Returns the name of 'netdev_dev'.
  *
  * The caller must not free the returned value. */