* 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)
{
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++;
memset(&options, 0, sizeof options);
options.name = name;
- options.ethertype = NETDEV_ETH_TYPE_NONE;
return netdev_open(&options, netdevp);
}
}
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);
}
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
* (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
}
}
+/* 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