- const char *netdev_name = netdev_get_name(netdev);
- int error = 0;
- if (!shash_find(&monitor->polled_netdevs, netdev_name)
- && netdev->class->poll_add)
- {
- struct netdev_notifier *notifier;
- error = netdev->class->poll_add(netdev, netdev_monitor_cb, monitor,
- ¬ifier);
- if (!error) {
- assert(notifier->netdev == netdev);
- shash_add(&monitor->polled_netdevs, netdev_name, notifier);
- }
+ const struct netdev_class *class = netdev_get_dev(netdev)->netdev_class;
+ return (class->dump_queue_stats
+ ? class->dump_queue_stats(netdev, cb, aux)
+ : EOPNOTSUPP);
+}
+
+/* Returns a sequence number which indicates changes in one of 'netdev''s
+ * properties. The returned sequence will be nonzero so that callers have a
+ * value which they may use as a reset when tracking 'netdev'.
+ *
+ * The returned sequence number will change whenever 'netdev''s flags,
+ * features, ethernet address, or carrier changes. It may change for other
+ * reasons as well, or no reason at all. */
+unsigned int
+netdev_change_seq(const struct netdev *netdev)
+{
+ return netdev_get_dev(netdev)->netdev_class->change_seq(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
+ * 'create' function.
+ *
+ * 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);
+
+ if (destroy) {
+ netdev_dev->netdev_class->destroy(netdev_dev);