[ovs-dev] [RFC PATCH 4/4] datapath: Update flow stats after execute_actions.

Jarno Rajahalme jrajahalme at nicira.com
Thu Jan 9 00:15:48 UTC 2014


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 <jrajahalme at 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




More information about the dev mailing list