This new function will provide a much simpler replacement for
netdev_monitor in the future.
---
Heres a new version of the patch with changes in netdev-provider's comments.
netdev's comments. And a type change to unsigned int.
---
lib/netdev-dummy.c | 16 ++++++++++++++++
lib/netdev-linux.c | 26 +++++++++++++++++++++++---
lib/netdev-provider.h | 16 +++++++++++++++-
lib/netdev-vport.c | 19 ++++++++++++++++++-
lib/netdev.c | 13 +++++++++++++
lib/netdev.h | 2 ++
lib/rtnetlink-link.c | 4 ++--
7 files changed, 89 insertions(+), 7 deletions(-)
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 4094f75..ea1c5fa 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -40,6 +40,7 @@ struct netdev_dev_dummy {
int mtu;
struct netdev_stats stats;
enum netdev_flags flags;
+ unsigned int change_seq;
};
struct netdev_dummy {
@@ -92,6 +93,7 @@ netdev_dummy_create(const struct netdev_class *class, const
char *name,
netdev_dev->hwaddr[5] = n;
netdev_dev->mtu = 1500;
netdev_dev->flags = 0;
+ netdev_dev->change_seq = 1;
n++;
@@ -250,6 +252,12 @@ netdev_dummy_poll_remove(struct netdev_notifier *notifier_)
free(notifier);
}
+
+static unsigned int
+netdev_dummy_change_seq(const struct netdev *netdev)
+{
+ return netdev_dev_dummy_cast(netdev_get_dev(netdev))->change_seq;
+}
/* Helper functions. */
@@ -258,6 +266,8 @@ netdev_dummy_poll_notify(const struct netdev *netdev)
{
const char *name = netdev_get_name(netdev);
struct list *list = shash_find_data(&netdev_dummy_notifiers, name);
+ struct netdev_dev_dummy *dev =
+ netdev_dev_dummy_cast(netdev_get_dev(netdev));
if (list) {
struct netdev_dummy_notifier *notifier;
@@ -267,6 +277,11 @@ netdev_dummy_poll_notify(const struct netdev *netdev)
n->cb(n);
}
}
+
+ dev->change_seq++;
+ if (!dev->change_seq) {
+ dev->change_seq++;
+ }
}
static const struct netdev_class dummy_class = {
@@ -328,6 +343,7 @@ static const struct netdev_class dummy_class = {
netdev_dummy_poll_add,
netdev_dummy_poll_remove,
+ netdev_dummy_change_seq
};
void
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index b5d3035..eda1276 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -346,6 +346,7 @@ struct netdev_dev_linux {
struct shash_node *shash_node;
unsigned int cache_valid;
+ unsigned int change_seq;
bool miimon; /* Link status of last poll. */
long long int miimon_interval; /* Miimon Poll rate. Disabled if <= 0. */
@@ -484,6 +485,16 @@ netdev_linux_wait(void)
}
static void
+netdev_dev_linux_changed(struct netdev_dev_linux *dev)
+{
+ dev->change_seq++;
+ if (!dev->change_seq) {
+ dev->change_seq++;
+ }
+ dev->cache_valid = 0;
+}
+
+static void
netdev_linux_cache_cb(const struct rtnetlink_link_change *change,
void *aux OVS_UNUSED)
{
@@ -496,7 +507,7 @@ netdev_linux_cache_cb(const struct rtnetlink_link_change
*change,
if (is_netdev_linux_class(netdev_class)) {
dev = netdev_dev_linux_cast(base_dev);
- dev->cache_valid = 0;
+ netdev_dev_linux_changed(dev);
}
}
} else {
@@ -507,7 +518,7 @@ netdev_linux_cache_cb(const struct rtnetlink_link_change
*change,
netdev_dev_get_devices(&netdev_linux_class, &device_shash);
SHASH_FOR_EACH (node, &device_shash) {
dev = node->data;
- dev->cache_valid = 0;
+ netdev_dev_linux_changed(dev);
}
shash_destroy(&device_shash);
}
@@ -537,6 +548,7 @@ netdev_linux_create(const struct netdev_class *class,
cache_notifier_refcount++;
netdev_dev = xzalloc(sizeof *netdev_dev);
+ netdev_dev->change_seq = 1;
netdev_dev_init(&netdev_dev->netdev_dev, name, args, class);
*netdev_devp = &netdev_dev->netdev_dev;
@@ -1169,6 +1181,7 @@ netdev_linux_miimon_run(void)
if (list) {
poll_notify(list);
}
+ netdev_dev_linux_changed(dev);
}
timer_set_duration(&dev->miimon_timer, dev->miimon_interval);
@@ -2318,6 +2331,12 @@ netdev_linux_poll_remove(struct netdev_notifier
*notifier_)
}
}
+static unsigned int
+netdev_linux_change_seq(const struct netdev *netdev)
+{
+ return netdev_dev_linux_cast(netdev_get_dev(netdev))->change_seq;
+}
+
#define NETDEV_LINUX_CLASS(NAME, CREATE, ENUMERATE, SET_STATS) \
{ \
NAME, \
@@ -2378,7 +2397,8 @@ netdev_linux_poll_remove(struct netdev_notifier
*notifier_)
netdev_linux_update_flags, \
\
netdev_linux_poll_add, \
- netdev_linux_poll_remove \
+ netdev_linux_poll_remove, \
+ netdev_linux_change_seq \
}
const struct netdev_class netdev_linux_class =
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 23de420..8ed3bf3 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -121,7 +121,10 @@ struct netdev_class {
void (*run)(void);
/* Arranges for poll_block() to wake up if the "run" member function needs
- * to be called. May be null if nothing is needed here. */
+ * to be called. Implementations are additionally required to wake
+ * whenever something changes in any of its netdevs which would cause their
+ * ->change_seq() function to change its result. May be null if nothing is
+ * needed here. */
void (*wait)(void);
/* Attempts to create a network device named 'name' with initial 'args' in
@@ -572,6 +575,17 @@ struct netdev_class {
/* Cancels poll notification for 'notifier'. */
void (*poll_remove)(struct netdev_notifier *notifier);
+
+ /* Returns a sequence number which indicates changes in one of 'netdev''s
+ * properties. The returned sequence number must be nonzero so that
+ * callers have a value which they may use as a reset when tracking
+ * 'netdev'.
+ *
+ * Minimally, the returned sequence number is required to change whenever
+ * 'netdev''s flags, features, ethernet address, or carrier changes. The
+ * returned sequence number is allowed to change even when 'netdev' doesn't
+ * change, although implementations should try to avoid this. */
+ unsigned int (*change_seq)(const struct netdev *netdev);
};
int netdev_register_provider(const struct netdev_class *);
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 3067323..ec67aaa 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -59,6 +59,7 @@ struct netdev_dev_vport {
struct ofpbuf *options;
int dp_ifindex; /* -1 if unknown. */
uint32_t port_no; /* UINT32_MAX if unknown. */
+ unsigned int change_seq;
};
struct netdev_vport {
@@ -242,6 +243,7 @@ netdev_vport_create(const struct netdev_class
*netdev_class, const char *name,
dev->options = options;
dev->dp_ifindex = dp_ifindex;
dev->port_no = port_no;
+ dev->change_seq = 1;
*netdev_devp = &dev->netdev_dev;
route_table_register();
@@ -538,6 +540,12 @@ netdev_vport_poll_remove(struct netdev_notifier *notifier_)
free(notifier);
}
+static unsigned int
+netdev_vport_change_seq(const struct netdev *netdev)
+{
+ return netdev_dev_vport_cast(netdev_get_dev(netdev))->change_seq;
+}
+
static void
netdev_vport_run(void)
{
@@ -581,6 +589,9 @@ netdev_vport_poll_notify(const struct netdev *netdev)
char *poll_name = make_poll_name(netdev);
struct list *list = shash_find_data(&netdev_vport_notifiers,
poll_name);
+ struct netdev_dev_vport *ndv;
+
+ ndv = netdev_dev_vport_cast(netdev_get_dev(netdev));
if (list) {
struct netdev_vport_notifier *notifier;
@@ -591,6 +602,11 @@ netdev_vport_poll_notify(const struct netdev *netdev)
}
}
+ ndv->change_seq++;
+ if (!ndv->change_seq) {
+ ndv->change_seq++;
+ }
+
free(poll_name);
}
@@ -986,7 +1002,8 @@ unparse_patch_config(const char *name OVS_UNUSED, const
char *type OVS_UNUSED,
netdev_vport_update_flags, \
\
netdev_vport_poll_add, \
- netdev_vport_poll_remove,
+ netdev_vport_poll_remove, \
+ netdev_vport_change_seq
void
netdev_vport_register(void)
diff --git a/lib/netdev.c b/lib/netdev.c
index 27ef0c3..d77f2f2 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -1223,6 +1223,19 @@ netdev_dump_queue_stats(const struct netdev *netdev,
: 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);
+}
+
/* If 'netdev' is a VLAN network device (e.g. one created with vconfig(8)),
* sets '*vlan_vid' to the VLAN VID associated with that device and returns 0.
* Otherwise returns a errno value (specifically ENOENT if 'netdev_name' is the
diff --git a/lib/netdev.h b/lib/netdev.h
index cc81e6c..547d3e7 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -205,6 +205,8 @@ typedef void netdev_dump_queue_stats_cb(unsigned int
queue_id,
int netdev_dump_queue_stats(const struct netdev *,
netdev_dump_queue_stats_cb *, void *aux);
+unsigned int netdev_change_seq(const struct netdev *netdev);
+
/* Linux stuff. */
int netdev_get_vlan_vid(const struct netdev *, int *vlan_vid);
diff --git a/lib/rtnetlink-link.c b/lib/rtnetlink-link.c
index ad83a1d..09ba954 100644
--- a/lib/rtnetlink-link.c
+++ b/lib/rtnetlink-link.c
@@ -76,8 +76,8 @@ rtnetlink_link_parse(struct ofpbuf *buf,
* caller must not modify or free.
*
* This is probably not the function that you want. You should probably be
- * using dpif_port_poll() or netdev_monitor_create(), which unlike this
- * function are not Linux-specific.
+ * using dpif_port_poll() or netdev_change_seq(), which unlike this function
+ * are not Linux-specific.
*
* Returns 0 if successful, otherwise a positive errno value. */
int
--
1.7.5.2
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev