+/* Initializes 'netdev_dev' as a netdev device named 'name' of the
+ * specified 'netdev_class'.
+ *
+ * This function adds 'netdev_dev' to a netdev-owned shash, so it is
+ * very important that 'netdev_dev' only be freed after calling
+ * the refcount drops to zero. */
+void
+netdev_dev_init(struct netdev_dev *netdev_dev, const char *name,
+ const struct netdev_class *netdev_class)
+{
+ assert(!shash_find(&netdev_dev_shash, name));
+
+ memset(netdev_dev, 0, sizeof *netdev_dev);
+ netdev_dev->netdev_class = netdev_class;
+ netdev_dev->name = xstrdup(name);
+ netdev_dev->node = shash_add(&netdev_dev_shash, name, netdev_dev);
+}
+
+/* Undoes the results of initialization.
+ *
+ * Normally this function does not need to be called as netdev_close has
+ * the same effect when the refcount drops to zero.
+ * However, it may be called by providers due to an error on creation
+ * that occurs after initialization. It this case netdev_close() would
+ * never be called. */
+void
+netdev_dev_uninit(struct netdev_dev *netdev_dev, bool destroy)
+{
+ char *name = netdev_dev->name;
+
+ assert(!netdev_dev->ref_cnt);
+
+ shash_delete(&netdev_dev_shash, netdev_dev->node);
+ update_device_args(netdev_dev, NULL);
+
+ if (destroy) {
+ netdev_dev->netdev_class->destroy(netdev_dev);
+ }
+ free(name);
+}
+
+/* Returns the class type of 'netdev_dev'.
+ *
+ * The caller must not free the returned value. */
+const char *
+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. */
+const char *
+netdev_dev_get_name(const struct netdev_dev *netdev_dev)
+{
+ return netdev_dev->name;
+}
+
+/* Returns the netdev_dev with 'name' or NULL if there is none.
+ *
+ * The caller must not free the returned value. */
+struct netdev_dev *
+netdev_dev_from_name(const char *name)
+{
+ return shash_find_data(&netdev_dev_shash, name);
+}
+
+/* Fills 'device_list' with devices that match 'netdev_class'.
+ *
+ * The caller is responsible for initializing and destroying 'device_list'
+ * but the contained netdev_devs must not be freed. */
+void
+netdev_dev_get_devices(const struct netdev_class *netdev_class,
+ struct shash *device_list)
+{
+ struct shash_node *node;
+ SHASH_FOR_EACH (node, &netdev_dev_shash) {
+ struct netdev_dev *dev = node->data;
+
+ if (dev->netdev_class == netdev_class) {
+ shash_add(device_list, node->name, node->data);
+ }
+ }
+}
+
+/* Initializes 'netdev' as a instance of the netdev_dev.