[ovs-dev] [thread-safety 06/11] netdev-vport: Make statistics thread safe.

Ethan Jackson ethan at nicira.com
Sat Jul 27 01:07:07 UTC 2013


Statistics are the only part of netdev-vport which need to be
manipulated by multiple threads.  This patch makes them thread safe.

Signed-off-by: Ethan Jackson <ethan at nicira.com>
---
 lib/netdev-vport.c |   12 +++++++++++-
 lib/netdev-vport.h |   16 +++++++++++-----
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 4214b38..578fff1 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -50,7 +50,9 @@ struct netdev_vport {
     struct netdev up;
     unsigned int change_seq;
     uint8_t etheraddr[ETH_ADDR_LEN];
-    struct netdev_stats stats;
+
+    struct netdev_stats stats OVS_GUARDED;
+    struct ovs_mutex stats_mutex;
 
     /* Tunnels. */
     struct netdev_tunnel_config tnl_cfg;
@@ -165,6 +167,7 @@ netdev_vport_create(const struct netdev_class *netdev_class, const char *name,
     netdev_init(&dev->up, name, netdev_class);
     dev->change_seq = 1;
     eth_addr_random(dev->etheraddr);
+    ovs_mutex_init(&dev->stats_mutex, NULL);
 
     *netdevp = &dev->up;
     route_table_register();
@@ -177,6 +180,7 @@ netdev_vport_destroy(struct netdev *netdev_)
 {
     struct netdev_vport *netdev = netdev_vport_cast(netdev_);
 
+    ovs_mutex_destroy(&netdev->stats_mutex);
     route_table_unregister();
     free(netdev->peer);
     free(netdev);
@@ -559,8 +563,10 @@ netdev_vport_inc_rx(const struct netdev *netdev,
 {
     if (is_vport_class(netdev_get_class(netdev))) {
         struct netdev_vport *dev = netdev_vport_cast(netdev);
+        ovs_mutex_lock(&dev->stats_mutex);
         dev->stats.rx_packets += stats->n_packets;
         dev->stats.rx_bytes += stats->n_bytes;
+        ovs_mutex_unlock(&dev->stats_mutex);
     }
 }
 
@@ -570,8 +576,10 @@ netdev_vport_inc_tx(const struct netdev *netdev,
 {
     if (is_vport_class(netdev_get_class(netdev))) {
         struct netdev_vport *dev = netdev_vport_cast(netdev);
+        ovs_mutex_lock(&dev->stats_mutex);
         dev->stats.tx_packets += stats->n_packets;
         dev->stats.tx_bytes += stats->n_bytes;
+        ovs_mutex_unlock(&dev->stats_mutex);
     }
 }
 
@@ -619,7 +627,9 @@ static int
 get_stats(const struct netdev *netdev, struct netdev_stats *stats)
 {
     struct netdev_vport *dev = netdev_vport_cast(netdev);
+    ovs_mutex_lock(&dev->stats_mutex);
     memcpy(stats, &dev->stats, sizeof *stats);
+    ovs_mutex_unlock(&dev->stats_mutex);
     return 0;
 }
 
diff --git a/lib/netdev-vport.h b/lib/netdev-vport.h
index 5394966..7941525 100644
--- a/lib/netdev-vport.h
+++ b/lib/netdev-vport.h
@@ -20,6 +20,13 @@
 #include <stdbool.h>
 #include <stddef.h>
 
+/* Thread-safety
+ * =============
+ *
+ * Only netdev_vport_inc_rx() and and netdev_vport_inc_tx() are thread safe.
+ * All other functions are expected to be called exclusively from the main
+ * thread. */
+
 struct dpif_linux_vport;
 struct dpif_flow_stats;
 struct netdev;
@@ -33,11 +40,6 @@ bool netdev_vport_is_patch(const struct netdev *);
 
 const char *netdev_vport_patch_peer(const struct netdev *netdev);
 
-void netdev_vport_inc_rx(const struct netdev *,
-                         const struct dpif_flow_stats *);
-void netdev_vport_inc_tx(const struct netdev *,
-                         const struct dpif_flow_stats *);
-
 const char *netdev_vport_class_get_dpif_port(const struct netdev_class *);
 
 enum { NETDEV_VPORT_NAME_BUFSIZE = 16 };
@@ -45,4 +47,8 @@ const char *netdev_vport_get_dpif_port(const struct netdev *,
                                        char namebuf[], size_t bufsize);
 char *netdev_vport_get_dpif_port_strdup(const struct netdev *);
 
+void netdev_vport_inc_rx(const struct netdev *,
+                         const struct dpif_flow_stats *);
+void netdev_vport_inc_tx(const struct netdev *,
+                         const struct dpif_flow_stats *);
 #endif /* netdev-vport.h */
-- 
1.7.9.5




More information about the dev mailing list