From 46415c9085ef6b7386943b1714754150487b6cff Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Mon, 18 Jan 2010 15:05:58 -0500 Subject: [PATCH] netdev-linux: Use the netdev list of devices instead of cachemap. We previously maintained a list of open devices inside of the linux netdev. Since the netdev library now maintains this list, it is better to use that list instead of our own. --- lib/netdev-linux.c | 24 +++++++++++++++--------- lib/netdev-provider.h | 3 +++ lib/netdev.c | 27 +++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index f2a6a5d04..ccc3f845c 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -75,7 +75,7 @@ #endif static struct rtnetlink_notifier netdev_linux_cache_notifier; -static struct shash cache_map = SHASH_INITIALIZER(&cache_map); +static int cache_notifier_refcount; enum { VALID_IFINDEX = 1 << 0, @@ -220,16 +220,22 @@ netdev_linux_cache_cb(const struct rtnetlink_change *change, { struct netdev_dev_linux *dev; if (change) { - dev = shash_find_data(&cache_map, change->ifname); - if (dev) { + struct netdev_dev *base_dev = netdev_dev_from_name(change->ifname); + if (base_dev) { + dev = netdev_dev_linux_cast(base_dev); dev->cache_valid = 0; } } else { + struct shash device_shash; struct shash_node *node; - SHASH_FOR_EACH (node, &cache_map) { + + shash_init(&device_shash); + netdev_dev_get_devices(&netdev_linux_class, &device_shash); + SHASH_FOR_EACH (node, &device_shash) { dev = node->data; dev->cache_valid = 0; } + shash_destroy(&device_shash); } } @@ -573,18 +579,18 @@ netdev_linux_create_system(const char *name, const char *type UNUSED, VLOG_WARN("%s: arguments for system devices should be empty", name); } - if (shash_is_empty(&cache_map)) { + if (!cache_notifier_refcount) { error = rtnetlink_notifier_register(&netdev_linux_cache_notifier, netdev_linux_cache_cb, NULL); if (error) { return error; } } + cache_notifier_refcount++; netdev_dev = xzalloc(sizeof *netdev_dev); - netdev_dev->shash_node = shash_add(&cache_map, name, netdev_dev); - netdev_dev_init(&netdev_dev->netdev_dev, name, &netdev_linux_class); + *netdev_devp = &netdev_dev->netdev_dev; return 0; } @@ -787,9 +793,9 @@ netdev_linux_destroy(struct netdev_dev *netdev_dev_) const char *type = netdev_dev_get_type(netdev_dev_); if (!strcmp(type, "system")) { - shash_delete(&cache_map, netdev_dev->shash_node); + cache_notifier_refcount--; - if (shash_is_empty(&cache_map)) { + if (!cache_notifier_refcount) { rtnetlink_notifier_unregister(&netdev_linux_cache_notifier); } } else if (!strcmp(type, "tap")) { diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index 4148c6cfd..b009c8dc7 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -42,6 +42,9 @@ void netdev_dev_init(struct netdev_dev *, const char *name, void netdev_dev_uninit(struct netdev_dev *, bool destroy); const char *netdev_dev_get_type(const struct netdev_dev *); const char *netdev_dev_get_name(const struct netdev_dev *); +struct netdev_dev *netdev_dev_from_name(const char *name); +void netdev_dev_get_devices(const struct netdev_class *, + struct shash *device_list); static inline void netdev_dev_assert_class(const struct netdev_dev *netdev_dev, const struct netdev_class *class) diff --git a/lib/netdev.c b/lib/netdev.c index 8d243e9e7..6a95e1a4f 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -889,6 +889,33 @@ 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 '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 *class, + struct shash *device_list) +{ + struct shash_node *node; + SHASH_FOR_EACH (node, &netdev_dev_shash) { + struct netdev_dev *dev = node->data; + + if (dev->class == class) { + shash_add(device_list, node->name, node->data); + } + } +} + /* Initializes 'netdev' as a instance of the netdev_dev. * * This function adds 'netdev' to a netdev-owned linked list, so it is very -- 2.43.0