X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fnetdev.c;h=b8592c19f9e3e1760734a593d26f933b441be380;hb=09eda55c4a3ef0215fea797c73cc2ba5778af8ca;hp=d77f2f25e5742e3bd72db1646d60bed28cea6b30;hpb=ac4d3bcb46fa0acd0b63f79449432df28569f74f;p=openvswitch diff --git a/lib/netdev.c b/lib/netdev.c index d77f2f25..b8592c19 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -243,7 +243,7 @@ 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); @@ -289,7 +289,7 @@ netdev_set_config(struct netdev *netdev, const struct shash *args) } 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); } @@ -1382,6 +1382,19 @@ netdev_dev_get_devices(const struct netdev_class *netdev_class, } } +/* 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 @@ -1431,148 +1444,6 @@ netdev_get_dev(const struct netdev *netdev) { return netdev->netdev_dev; } - -/* Initializes 'notifier' as a netdev notifier for 'netdev', for which - * notification will consist of calling 'cb', with auxiliary data 'aux'. */ -void -netdev_notifier_init(struct netdev_notifier *notifier, struct netdev *netdev, - void (*cb)(struct netdev_notifier *), void *aux) -{ - notifier->netdev = netdev; - notifier->cb = cb; - notifier->aux = aux; -} - -/* Tracks changes in the status of a set of network devices. */ -struct netdev_monitor { - struct shash polled_netdevs; - struct sset changed_netdevs; -}; - -/* Creates and returns a new structure for monitor changes in the status of - * network devices. */ -struct netdev_monitor * -netdev_monitor_create(void) -{ - struct netdev_monitor *monitor = xmalloc(sizeof *monitor); - shash_init(&monitor->polled_netdevs); - sset_init(&monitor->changed_netdevs); - return monitor; -} - -/* Destroys 'monitor'. */ -void -netdev_monitor_destroy(struct netdev_monitor *monitor) -{ - if (monitor) { - struct shash_node *node; - - SHASH_FOR_EACH (node, &monitor->polled_netdevs) { - struct netdev_notifier *notifier = node->data; - netdev_get_dev(notifier->netdev)->netdev_class->poll_remove( - notifier); - } - - shash_destroy(&monitor->polled_netdevs); - sset_destroy(&monitor->changed_netdevs); - free(monitor); - } -} - -static void -netdev_monitor_cb(struct netdev_notifier *notifier) -{ - struct netdev_monitor *monitor = notifier->aux; - const char *name = netdev_get_name(notifier->netdev); - sset_add(&monitor->changed_netdevs, name); -} - -/* Attempts to add 'netdev' as a netdev monitored by 'monitor'. Returns 0 if - * successful, otherwise a positive errno value. - * - * Adding a given 'netdev' to a monitor multiple times is equivalent to adding - * it once. */ -int -netdev_monitor_add(struct netdev_monitor *monitor, struct netdev *netdev) -{ - const char *netdev_name = netdev_get_name(netdev); - int error = 0; - if (!shash_find(&monitor->polled_netdevs, netdev_name) - && netdev_get_dev(netdev)->netdev_class->poll_add) - { - struct netdev_notifier *notifier; - error = netdev_get_dev(netdev)->netdev_class->poll_add(netdev, - netdev_monitor_cb, monitor, ¬ifier); - if (!error) { - assert(notifier->netdev == netdev); - shash_add(&monitor->polled_netdevs, netdev_name, notifier); - } - } - return error; -} - -/* Removes 'netdev' from the set of netdevs monitored by 'monitor'. (This has - * no effect if 'netdev' is not in the set of devices monitored by - * 'monitor'.) */ -void -netdev_monitor_remove(struct netdev_monitor *monitor, struct netdev *netdev) -{ - const char *netdev_name = netdev_get_name(netdev); - struct shash_node *node; - - node = shash_find(&monitor->polled_netdevs, netdev_name); - if (node) { - /* Cancel future notifications. */ - struct netdev_notifier *notifier = node->data; - netdev_get_dev(netdev)->netdev_class->poll_remove(notifier); - shash_delete(&monitor->polled_netdevs, node); - - /* Drop any pending notification. */ - sset_find_and_delete(&monitor->changed_netdevs, netdev_name); - } -} - -/* Checks for changes to netdevs in the set monitored by 'monitor'. If any of - * the attributes (Ethernet address, carrier status, speed or peer-advertised - * speed, flags, etc.) of a network device monitored by 'monitor' has changed, - * sets '*devnamep' to the name of a device that has changed and returns 0. - * The caller is responsible for freeing '*devnamep' (with free()). - * - * If no devices have changed, sets '*devnamep' to NULL and returns EAGAIN. */ -int -netdev_monitor_poll(struct netdev_monitor *monitor, char **devnamep) -{ - if (sset_is_empty(&monitor->changed_netdevs)) { - *devnamep = NULL; - return EAGAIN; - } else { - *devnamep = sset_pop(&monitor->changed_netdevs); - return 0; - } -} - -/* Clears all notifications from 'monitor'. May be called instead of - * netdev_monitor_poll() by clients which don't care specifically which netdevs - * have changed. */ -void -netdev_monitor_flush(struct netdev_monitor *monitor) -{ - sset_clear(&monitor->changed_netdevs); -} - -/* Registers with the poll loop to wake up from the next call to poll_block() - * when netdev_monitor_poll(monitor) would indicate that a device has - * changed. */ -void -netdev_monitor_poll_wait(const struct netdev_monitor *monitor) -{ - if (!sset_is_empty(&monitor->changed_netdevs)) { - poll_immediate_wake(); - } else { - /* XXX Nothing needed here for netdev_linux, but maybe other netdev - * classes need help. */ - } -} /* Restore the network device flags on 'netdev' to those that were active * before we changed them. Returns 0 if successful, otherwise a positive