[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