From 15b3596a4105bbea82108ac251f9b19dc316e19d Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Tue, 30 Mar 2010 18:39:20 -0400 Subject: [PATCH] netdev-linux: Check notifications are for netdev-linux device. When receiving a change notification from rtnetlink we checked whether a netdev of that name existed and if so tried to handle it. This also checks that the type of the device is one handled by netdev-linux. --- lib/netdev-linux.c | 29 +++++++++++++++++++++-------- lib/netdev-provider.h | 1 + lib/netdev.c | 7 +++++++ 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 2941bf98..1b69a20d 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -157,6 +157,7 @@ static struct rtnetlink_notifier netdev_linux_poll_notifier; * additional log messages. */ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); +static int netdev_linux_init(void); static int if_up(const char *name); static int destroy_gre(const char *name); static int netdev_linux_do_ethtool(const char *name, struct ethtool_cmd *, @@ -178,21 +179,28 @@ static int set_etheraddr(const char *netdev_name, int hwaddr_family, static int get_stats_via_netlink(int ifindex, struct netdev_stats *stats); static int get_stats_via_proc(const char *netdev_name, struct netdev_stats *stats); +static bool +is_netdev_linux_class(const struct netdev_class *netdev_class) +{ + return netdev_class->init == netdev_linux_init; +} + static struct netdev_dev_linux * netdev_dev_linux_cast(const struct netdev_dev *netdev_dev) { - const char *type = netdev_dev_get_type(netdev_dev); - assert(!strcmp(type, "system") || !strcmp(type, "tap") - || !strcmp(type, "gre") || !strcmp(type, "patch")); + const struct netdev_class *netdev_class = netdev_dev_get_class(netdev_dev); + assert(is_netdev_linux_class(netdev_class)); + return CONTAINER_OF(netdev_dev, struct netdev_dev_linux, netdev_dev); } static struct netdev_linux * netdev_linux_cast(const struct netdev *netdev) { - const char *type = netdev_get_type(netdev); - assert(!strcmp(type, "system") || !strcmp(type, "tap") - || !strcmp(type, "gre") || !strcmp(type, "patch")); + struct netdev_dev *netdev_dev = netdev_get_dev(netdev); + const struct netdev_class *netdev_class = netdev_dev_get_class(netdev_dev); + assert(is_netdev_linux_class(netdev_class)); + return CONTAINER_OF(netdev, struct netdev_linux, netdev); } @@ -230,8 +238,13 @@ netdev_linux_cache_cb(const struct rtnetlink_change *change, if (change) { 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; + const struct netdev_class *netdev_class = + netdev_dev_get_class(base_dev); + + if (is_netdev_linux_class(netdev_class)) { + dev = netdev_dev_linux_cast(base_dev); + dev->cache_valid = 0; + } } } else { struct shash device_shash; diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index aac482b0..18ec1ab6 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -52,6 +52,7 @@ void netdev_dev_init(struct netdev_dev *, const char *name, const struct netdev_class *); void netdev_dev_uninit(struct netdev_dev *, bool destroy); const char *netdev_dev_get_type(const struct netdev_dev *); +const struct netdev_class *netdev_dev_get_class(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 *, diff --git a/lib/netdev.c b/lib/netdev.c index d8fd7e44..3102e6e3 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -1051,6 +1051,13 @@ 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. */ -- 2.30.2