netdev: Clean up and refactor packet receive interface.
[sliver-openvswitch.git] / lib / netdev.c
index 1f0b764..9954929 100644 (file)
@@ -204,12 +204,8 @@ update_device_args(struct netdev_dev *dev, const struct shash *args)
  * to the new network device, otherwise to null.
  *
  * If this is the first time the device has been opened, then create is called
- * before opening.  The device is created using the given type and arguments.
- *
- * '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. */
+ * before opening.  The device is created using the given type and
+ * arguments. */
 int
 netdev_open(struct netdev_options *options, struct netdev **netdevp)
 {
@@ -243,15 +239,14 @@ netdev_open(struct netdev_options *options, struct netdev **netdevp)
         assert(netdev_dev->netdev_class == class);
 
     } else if (!shash_is_empty(options->args) &&
-               !smap_equal(&netdev_dev->args, options->args)) {
+               !netdev_dev_args_equal(netdev_dev, options->args)) {
 
         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,
-                netdevp);
+    error = netdev_dev->netdev_class->open(netdev_dev, netdevp);
 
     if (!error) {
         netdev_dev->ref_cnt++;
@@ -271,7 +266,6 @@ netdev_open_default(const char *name, struct netdev **netdevp)
 
     memset(&options, 0, sizeof options);
     options.name = name;
-    options.ethertype = NETDEV_ETH_TYPE_NONE;
 
     return netdev_open(&options, netdevp);
 }
@@ -289,7 +283,7 @@ netdev_set_config(struct netdev *netdev, const struct shash *args)
     }
 
     if (netdev_dev->netdev_class->set_config) {
-        if (!smap_equal(&netdev_dev->args, args)) {
+        if (!netdev_dev_args_equal(netdev_dev, args)) {
             update_device_args(netdev_dev, args);
             return netdev_dev->netdev_class->set_config(netdev_dev, args);
         }
@@ -387,6 +381,19 @@ netdev_enumerate(struct sset *sset)
     return error;
 }
 
+/* Attempts to set up 'netdev' for receiving packets with netdev_recv().
+ * Returns 0 if successful, otherwise a positive errno value.  EOPNOTSUPP
+ * indicates that the network device does not implement packet reception
+ * through this interface. */
+int
+netdev_listen(struct netdev *netdev)
+{
+    int (*listen)(struct netdev *);
+
+    listen = netdev_get_dev(netdev)->netdev_class->listen;
+    return listen ? (listen)(netdev) : EOPNOTSUPP;
+}
+
 /* Attempts to receive a packet from 'netdev' into 'buffer', which the caller
  * must have initialized with sufficient room for the packet.  The space
  * required to receive any packet is ETH_HEADER_LEN bytes, plus VLAN_HEADER_LEN
@@ -394,6 +401,9 @@ netdev_enumerate(struct sset *sset)
  * (Some devices do not allow for a VLAN header, in which case VLAN_HEADER_LEN
  * need not be included.)
  *
+ * This function can only be expected to return a packet if ->listen() has
+ * been called successfully.
+ *
  * If a packet is successfully retrieved, returns 0.  In this case 'buffer' is
  * guaranteed to contain at least ETH_TOTAL_MIN bytes.  Otherwise, returns a
  * positive errno value.  Returns EAGAIN immediately if no packet is ready to
@@ -1382,6 +1392,19 @@ netdev_dev_get_devices(const struct netdev_class *netdev_class,
     }
 }
 
+/* Returns true if 'args' is equivalent to the "args" field in
+ * 'netdev_dev', otherwise false. */
+bool
+netdev_dev_args_equal(const struct netdev_dev *netdev_dev,
+                      const struct shash *args)
+{
+    if (netdev_dev->netdev_class->config_equal) {
+        return netdev_dev->netdev_class->config_equal(netdev_dev, args);
+    } else {
+        return smap_equal(&netdev_dev->args, args);
+    }
+}
+
 /* Initializes 'netdev' as a instance of the netdev_dev.
  *
  * This function adds 'netdev' to a netdev-owned linked list, so it is very