datapath: Remove 5-tuple optimization.
[sliver-openvswitch.git] / datapath / flow.c
index 510bb87..f40cddb 100644 (file)
@@ -64,11 +64,14 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
 
 void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
 {
-       struct sw_flow_stats *stats = &flow->stats[smp_processor_id()];
+       struct flow_stats *stats;
        __be16 tcp_flags = 0;
 
+       stats = this_cpu_ptr(flow->stats);
+
        if ((flow->key.eth.type == htons(ETH_P_IP) ||
             flow->key.eth.type == htons(ETH_P_IPV6)) &&
+           flow->key.ip.frag != OVS_FRAG_TYPE_LATER &&
            flow->key.ip.proto == IPPROTO_TCP &&
            likely(skb->len >= skb_transport_offset(skb) + sizeof(struct tcphdr))) {
                tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb));
@@ -82,32 +85,65 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
        spin_unlock(&stats->lock);
 }
 
-void ovs_flow_stats_get(struct sw_flow *flow, struct sw_flow_stats *res)
+static void stats_read(struct flow_stats *stats, bool lock_bh,
+                      struct ovs_flow_stats *ovs_stats,
+                      unsigned long *used, __be16 *tcp_flags)
+{
+       if (lock_bh)
+               spin_lock_bh(&stats->lock);
+       else
+               spin_lock(&stats->lock);
+
+       if (time_after(stats->used, *used))
+               *used = stats->used;
+       *tcp_flags |= stats->tcp_flags;
+       ovs_stats->n_packets += stats->packet_count;
+       ovs_stats->n_bytes += stats->byte_count;
+
+       if (lock_bh)
+               spin_unlock_bh(&stats->lock);
+       else
+               spin_unlock(&stats->lock);
+}
+
+void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats,
+                       unsigned long *used, __be16 *tcp_flags)
 {
        int cpu, cur_cpu;
 
-       memset(res, 0, sizeof(*res));
+       *used = 0;
+       *tcp_flags = 0;
+       memset(ovs_stats, 0, sizeof(*ovs_stats));
 
        cur_cpu = get_cpu();
+
        for_each_possible_cpu(cpu) {
-               struct sw_flow_stats *stats = &flow->stats[cpu];
+               struct flow_stats *stats;
+               bool lock_bh;
 
-               if (cpu == cur_cpu)
-                       local_bh_disable();
+               stats = per_cpu_ptr(flow->stats, cpu);
+               lock_bh = (cpu == cur_cpu);
+               stats_read(stats, lock_bh, ovs_stats, used, tcp_flags);
+       }
+       put_cpu();
+}
 
+static void stats_reset(struct flow_stats *stats, bool lock_bh)
+{
+       if (lock_bh)
+               spin_lock_bh(&stats->lock);
+       else
                spin_lock(&stats->lock);
-               if (time_after(stats->used, res->used))
-                       res->used = stats->used;
-               res->packet_count += stats->packet_count;
-               res->byte_count += stats->byte_count;
-               res->tcp_flags |= stats->tcp_flags;
-               spin_unlock(&stats->lock);
 
-               if (cpu == cur_cpu)
-                       local_bh_enable();
+       stats->used = 0;
+       stats->packet_count = 0;
+       stats->byte_count = 0;
+       stats->tcp_flags = 0;
 
-       }
-       put_cpu();
+       if (lock_bh)
+               spin_unlock_bh(&stats->lock);
+       else
+               spin_unlock(&stats->lock);
 }
 
 void ovs_flow_stats_clear(struct sw_flow *flow)
@@ -115,21 +151,12 @@ void ovs_flow_stats_clear(struct sw_flow *flow)
        int cpu, cur_cpu;
 
        cur_cpu = get_cpu();
-       for_each_possible_cpu(cpu) {
-               struct sw_flow_stats *stats = &flow->stats[cpu];
-
-               if (cpu == cur_cpu)
-                       local_bh_disable();
 
-               spin_lock(&stats->lock);
-               stats->used = 0;
-               stats->packet_count = 0;
-               stats->byte_count = 0;
-               stats->tcp_flags = 0;
-               spin_unlock(&stats->lock);
+       for_each_possible_cpu(cpu) {
+               bool lock_bh;
 
-               if (cpu == cur_cpu)
-                       local_bh_enable();
+               lock_bh = (cpu == cur_cpu);
+               stats_reset(per_cpu_ptr(flow->stats, cpu), lock_bh);
        }
        put_cpu();
 }
@@ -482,6 +509,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
                                struct tcphdr *tcp = tcp_hdr(skb);
                                key->ipv4.tp.src = tcp->source;
                                key->ipv4.tp.dst = tcp->dest;
+                               key->ipv4.tp.flags = TCP_FLAGS_BE16(tcp);
                        }
                } else if (key->ip.proto == IPPROTO_UDP) {
                        if (udphdr_ok(skb)) {
@@ -550,6 +578,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
                                struct tcphdr *tcp = tcp_hdr(skb);
                                key->ipv6.tp.src = tcp->source;
                                key->ipv6.tp.dst = tcp->dest;
+                               key->ipv6.tp.flags = TCP_FLAGS_BE16(tcp);
                        }
                } else if (key->ip.proto == NEXTHDR_UDP) {
                        if (udphdr_ok(skb)) {