The stats are taken before execution, but flow stats are updated only
after execution in hope that stats prefetch is complete by then.

Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 datapath/datapath.c   |   34 +++++++++++++++++++++++++++++++++-
 datapath/flow.c       |   20 +++++---------------
 datapath/flow.h       |    4 +++-
 datapath/flow_table.c |   12 ------------
 4 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index c80abe0..296e7b1 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -214,6 +214,36 @@ void ovs_dp_detach_port(struct vport *p)
        ovs_vport_del(p);
 }
 
+static void ovs_flow_stats_prefetch(const struct sw_flow *flow)
+{
+       struct flow_stats *stats;
+
+       if (!flow->stats.per_numa_mem)
+               stats = flow->stats.stat;
+       else
+               stats = &flow->stats.numa_stats[numa_node_id()];
+       spin_lock_prefetch(&stats->lock);
+}
+
+static void get_skb_stats(struct flow_stats *stat, const struct sw_flow *flow,
+                         const struct sk_buff *skb)
+{
+       ovs_flow_stats_prefetch(flow); /* Prepare for writing later. */
+
+       stat->used = jiffies;
+       stat->packet_count = 1;
+       stat->byte_count = skb->len;
+
+       if ((flow->key.eth.type == htons(ETH_P_IP) ||
+            flow->key.eth.type == htons(ETH_P_IPV6)) &&
+           flow->key.ip.proto == IPPROTO_TCP &&
+           likely(skb->len >= skb_transport_offset(skb) + sizeof(struct 
tcphdr))) {
+               stat->tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb));
+       } else {
+               stat->tcp_flags = 0;
+       }
+}
+
 /* Must be called with rcu_read_lock. */
 void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
 {
@@ -221,6 +251,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct 
sk_buff *skb)
        struct sw_flow *flow;
        struct dp_stats_percpu *stats;
        struct sw_flow_key key;
+       struct flow_stats stat;
        u64 *stats_counter;
        u32 n_mask_hit;
        int error;
@@ -252,8 +283,9 @@ void ovs_dp_process_received_packet(struct vport *p, struct 
sk_buff *skb)
        OVS_CB(skb)->flow = flow;
        OVS_CB(skb)->pkt_key = &key;
 
-       ovs_flow_stats_update(OVS_CB(skb)->flow, skb);
+       get_skb_stats(&stat, flow, skb);
        ovs_execute_actions(dp, skb);
+       ovs_flow_stats_update(flow, &stat);
        stats_counter = &stats->n_hit;
 
 out:
diff --git a/datapath/flow.c b/datapath/flow.c
index 0002759..afc7cd9 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -60,30 +60,20 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
        return cur_ms - idle_ms;
 }
 
-#define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF))
-
-void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
+void ovs_flow_stats_update(struct sw_flow *flow, const struct flow_stats *stat)
 {
        struct flow_stats *stats;
-       __be16 tcp_flags = 0;
 
        if (!flow->stats.per_numa_mem)
                stats = flow->stats.stat;
        else
                stats = &flow->stats.numa_stats[numa_node_id()];
 
-       if ((flow->key.eth.type == htons(ETH_P_IP) ||
-            flow->key.eth.type == htons(ETH_P_IPV6)) &&
-           flow->key.ip.proto == IPPROTO_TCP &&
-           likely(skb->len >= skb_transport_offset(skb) + sizeof(struct 
tcphdr))) {
-               tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb));
-       }
-
        spin_lock_bh(&stats->lock);
-       stats->used = jiffies;
-       stats->packet_count++;
-       stats->byte_count += skb->len;
-       stats->tcp_flags |= tcp_flags;
+       stats->used = stat->used;
+       stats->packet_count += stat->packet_count;
+       stats->byte_count += stat->byte_count;
+       stats->tcp_flags |= stat->tcp_flags;
        spin_unlock_bh(&stats->lock);
 }
 
diff --git a/datapath/flow.h b/datapath/flow.h
index 14ea93f..008c92c 100644
--- a/datapath/flow.h
+++ b/datapath/flow.h
@@ -67,6 +67,8 @@ static inline void ovs_flow_tun_key_init(struct 
ovs_key_ipv4_tunnel *tun_key,
               sizeof(*tun_key) - OVS_TUNNEL_KEY_SIZE);
 }
 
+#define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF))
+
 struct sw_flow_key {
        struct ovs_key_ipv4_tunnel tun_key;  /* Encapsulating tunnel key. */
        struct {
@@ -191,7 +193,7 @@ struct arp_eth_header {
        unsigned char       ar_tip[4];          /* target IP address        */
 } __packed;
 
-void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb);
+void ovs_flow_stats_update(struct sw_flow *flow, const struct flow_stats 
*stat);
 void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *stats,
                        unsigned long *used, __be16 *tcp_flags);
 void ovs_flow_stats_clear(struct sw_flow *flow);
diff --git a/datapath/flow_table.c b/datapath/flow_table.c
index aec96cb..417c57b 100644
--- a/datapath/flow_table.c
+++ b/datapath/flow_table.c
@@ -435,17 +435,6 @@ bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
        return cmp_key(&flow->unmasked_key, key, key_start, key_end);
 }
 
-static void ovs_flow_stats_prefetch(struct sw_flow *flow)
-{
-       struct flow_stats *stats;
-
-       if (!flow->stats.per_numa_mem)
-               stats = flow->stats.stat;
-       else
-               stats = &flow->stats.numa_stats[numa_node_id()];
-       spin_lock_prefetch(&stats->lock);
-}
-
 static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
                                          const struct sw_flow_key *unmasked,
                                          struct sw_flow_mask *mask)
@@ -464,7 +453,6 @@ static struct sw_flow *masked_flow_lookup(struct 
table_instance *ti,
                if (flow->mask == mask && flow->hash == hash &&
                    flow_cmp_masked_key(flow, &masked_key,
                                        key_start, key_end)) {
-                       ovs_flow_stats_prefetch(flow);
                        return flow;
                }
        }
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to