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 <et...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev