meta-flow: Correctly set destination MAC in mf_set_flow_value().
[sliver-openvswitch.git] / lib / netdev.c
index cd824f8..47c8060 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -332,31 +332,23 @@ netdev_is_open(const char *name)
     return !!shash_find_data(&netdev_dev_shash, name);
 }
 
-/*  Clears 'sset' and enumerates the names of all known network devices. */
-int
-netdev_enumerate(struct sset *sset)
+/* Parses 'netdev_name_', which is of the form [type@]name into its component
+ * pieces.  'name' and 'type' must be freed by the caller. */
+void
+netdev_parse_name(const char *netdev_name_, char **name, char **type)
 {
-    struct shash_node *node;
-    int error = 0;
+    char *netdev_name = xstrdup(netdev_name_);
+    char *separator;
 
-    netdev_initialize();
-    sset_clear(sset);
-
-    SHASH_FOR_EACH(node, &netdev_classes) {
-        const struct netdev_class *netdev_class = node->data;
-        if (netdev_class->enumerate) {
-            int retval = netdev_class->enumerate(sset);
-            if (retval) {
-                VLOG_WARN("failed to enumerate %s network devices: %s",
-                          netdev_class->type, strerror(retval));
-                if (!error) {
-                    error = retval;
-                }
-            }
-        }
+    separator = strchr(netdev_name, '@');
+    if (separator) {
+        *separator = '\0';
+        *type = netdev_name;
+        *name = xstrdup(separator + 1);
+    } else {
+        *name = netdev_name;
+        *type = xstrdup("system");
     }
-
-    return error;
 }
 
 /* Attempts to set up 'netdev' for receiving packets with netdev_recv().
@@ -510,19 +502,45 @@ netdev_get_name(const struct netdev *netdev)
  * (and received) packets, in bytes, not including the hardware header; thus,
  * this is typically 1500 bytes for Ethernet devices.
  *
- * If successful, returns 0 and stores the MTU size in '*mtup'.  Stores INT_MAX
- * in '*mtup' if 'netdev' does not have an MTU (as e.g. some tunnels do not).On
- * failure, returns a positive errno value and stores ETH_PAYLOAD_MAX (1500) in
- * '*mtup'. */
+ * If successful, returns 0 and stores the MTU size in '*mtup'.  Returns
+ * EOPNOTSUPP if 'netdev' does not have an MTU (as e.g. some tunnels do not).
+ * On other failure, returns a positive errno value.  On failure, sets '*mtup'
+ * to 0. */
 int
 netdev_get_mtu(const struct netdev *netdev, int *mtup)
 {
-    int error = netdev_get_dev(netdev)->netdev_class->get_mtu(netdev, mtup);
+    const struct netdev_class *class = netdev_get_dev(netdev)->netdev_class;
+    int error;
+
+    error = class->get_mtu ? class->get_mtu(netdev, mtup) : EOPNOTSUPP;
     if (error) {
-        VLOG_WARN_RL(&rl, "failed to retrieve MTU for network device %s: %s",
+        *mtup = 0;
+        if (error != EOPNOTSUPP) {
+            VLOG_WARN_RL(&rl, "failed to retrieve MTU for network device %s: "
+                         "%s", netdev_get_name(netdev), strerror(error));
+        }
+    }
+    return error;
+}
+
+/* Sets the MTU of 'netdev'.  The MTU is the maximum size of transmitted
+ * (and received) packets, in bytes.
+ *
+ * If successful, returns 0.  Returns EOPNOTSUPP if 'netdev' does not have an
+ * MTU (as e.g. some tunnels do not).  On other failure, returns a positive
+ * errno value. */
+int
+netdev_set_mtu(const struct netdev *netdev, int mtu)
+{
+    const struct netdev_class *class = netdev_get_dev(netdev)->netdev_class;
+    int error;
+
+    error = class->set_mtu ? class->set_mtu(netdev, mtu) : EOPNOTSUPP;
+    if (error && error != EOPNOTSUPP) {
+        VLOG_WARN_RL(&rl, "failed to set MTU for network device %s: %s",
                      netdev_get_name(netdev), strerror(error));
-        *mtup = ETH_PAYLOAD_MAX;
     }
+
     return error;
 }
 
@@ -640,7 +658,7 @@ netdev_set_advertisements(struct netdev *netdev, uint32_t advertise)
  *
  *   - EOPNOTSUPP: No IPv4 network stack attached to 'netdev'.
  *
- * 'address' or 'netmask' or both may be null, in which case the address or 
+ * 'address' or 'netmask' or both may be null, in which case the address or
  * netmask is not reported. */
 int
 netdev_get_in4(const struct netdev *netdev,
@@ -874,6 +892,15 @@ netdev_get_carrier(const struct netdev *netdev)
     return carrier;
 }
 
+/* Returns the number of times 'netdev''s carrier has changed. */
+long long int
+netdev_get_carrier_resets(const struct netdev *netdev)
+{
+    return (netdev_get_dev(netdev)->netdev_class->get_carrier_resets
+            ? netdev_get_dev(netdev)->netdev_class->get_carrier_resets(netdev)
+            : 0);
+}
+
 /* Attempts to force netdev_get_carrier() to poll 'netdev''s MII registers for
  * link status instead of checking 'netdev''s carrier.  'netdev''s MII
  * registers will be polled once ever 'interval' milliseconds.  If 'netdev'
@@ -1175,7 +1202,11 @@ netdev_get_queue_stats(const struct netdev *netdev, unsigned int queue_id,
  * Calling this function may be more efficient than calling netdev_get_queue()
  * for every queue.
  *
- * 'cb' must not modify or free the 'details' argument passed in.
+ * 'cb' must not modify or free the 'details' argument passed in.  It may
+ * delete or modify the queue passed in as its 'queue_id' argument.  It may
+ * modify but must not delete any other queue within 'netdev'.  'cb' should not
+ * add new queues because this may cause some queues to be visited twice or not
+ * at all.
  *
  * Returns 0 if successful, otherwise a positive errno value.  On error, some
  * configured queues may not have been included in the iteration. */
@@ -1223,51 +1254,6 @@ netdev_change_seq(const struct netdev *netdev)
 {
     return netdev_get_dev(netdev)->netdev_class->change_seq(netdev);
 }
-
-/* If 'netdev' is a VLAN network device (e.g. one created with vconfig(8)),
- * sets '*vlan_vid' to the VLAN VID associated with that device and returns 0.
- * Otherwise returns a errno value (specifically ENOENT if 'netdev_name' is the
- * name of a network device that is not a VLAN device) and sets '*vlan_vid' to
- * -1. */
-int
-netdev_get_vlan_vid(const struct netdev *netdev, int *vlan_vid)
-{
-    int error = (netdev_get_dev(netdev)->netdev_class->get_vlan_vid
-                 ? netdev_get_dev(netdev)->netdev_class->get_vlan_vid(netdev,
-                        vlan_vid)
-                 : ENOENT);
-    if (error) {
-        *vlan_vid = 0;
-    }
-    return error;
-}
-
-/* Returns a network device that has 'in4' as its IP address, if one exists,
- * otherwise a null pointer. */
-struct netdev *
-netdev_find_dev_by_in4(const struct in_addr *in4)
-{
-    struct netdev *netdev;
-    struct sset dev_list = SSET_INITIALIZER(&dev_list);
-    const char *name;
-
-    netdev_enumerate(&dev_list);
-    SSET_FOR_EACH (name, &dev_list) {
-        struct in_addr dev_in4;
-
-        if (!netdev_open(name, "system", &netdev)
-            && !netdev_get_in4(netdev, &dev_in4, NULL)
-            && dev_in4.s_addr == in4->s_addr) {
-            goto exit;
-        }
-        netdev_close(netdev);
-    }
-    netdev = NULL;
-
-exit:
-    sset_destroy(&dev_list);
-    return netdev;
-}
 \f
 /* Initializes 'netdev_dev' as a netdev device named 'name' of the specified
  * 'netdev_class'.  This function is ordinarily called from a netdev provider's