[ovs-dev] [monitor 1/4] netdev: New Function netdev_change_seq().

Ethan Jackson ethan at nicira.com
Thu May 26 22:27:49 UTC 2011


This new function will provide a much simpler replacement for
netdev_monitor in the future.
---
 lib/netdev-dummy.c    |   16 ++++++++++++++++
 lib/netdev-linux.c    |   26 +++++++++++++++++++++++---
 lib/netdev-provider.h |    6 ++++++
 lib/netdev-vport.c    |   19 ++++++++++++++++++-
 lib/netdev.c          |   10 ++++++++++
 lib/netdev.h          |    2 ++
 lib/rtnetlink-link.c  |    4 ++--
 7 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 4094f75..92965e9 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;
+    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 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..fb1abd7 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;
+    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 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..51d82b6 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -572,6 +572,12 @@ struct netdev_class {
 
     /* Cancels poll notification for 'notifier'. */
     void (*poll_remove)(struct netdev_notifier *notifier);
+
+    /* Returns a nonzero sequence number which indicates changes in 'netdev'.
+     * The returned sequence number is guaranteed to change if 'netdev' has
+     * changed.  However, a change in the returned sequence number does not
+     * necessarily guarantee that 'netdev' has changed. */
+    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..df072bb 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. */
+    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 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..3b8a950 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -1223,6 +1223,16 @@ netdev_dump_queue_stats(const struct netdev *netdev,
             : EOPNOTSUPP);
 }
 
+/* Returns a nonzero sequence number which indicates changes in 'netdev'.  The
+ * returned sequence number is guaranteed to change if 'netdev' has changed.
+ * However, a change in the returned sequence number does not necessarily
+ * guarantee that 'netdev' has changed. */
+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..a4f5dca 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);
 
+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




More information about the dev mailing list