X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Fflow.c;h=8be380182dbd963ea19c7ec67b5162995acb84dd;hb=6d7d2ace1494936d11b8cabcec26c7e4d0fdda68;hp=510bb878577f1561a50d8f59dad64ce41520a422;hpb=a66733a8bc1c42d92f498108d7e27987989dc206;p=sliver-openvswitch.git diff --git a/datapath/flow.c b/datapath/flow.c index 510bb8785..8be380182 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -64,9 +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; + if (!flow->stats.is_percpu) + stats = flow->stats.stat; + else + stats = this_cpu_ptr(flow->stats.cpu_stats); + if ((flow->key.eth.type == htons(ETH_P_IP) || flow->key.eth.type == htons(ETH_P_IPV6)) && flow->key.ip.proto == IPPROTO_TCP && @@ -82,56 +87,88 @@ 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]; + if (!flow->stats.is_percpu) { + stats_read(flow->stats.stat, true, ovs_stats, used, tcp_flags); + } else { + cur_cpu = get_cpu(); - if (cpu == cur_cpu) - local_bh_disable(); + for_each_possible_cpu(cpu) { + struct flow_stats *stats; + bool lock_bh; + + stats = per_cpu_ptr(flow->stats.cpu_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) { int cpu, cur_cpu; - cur_cpu = get_cpu(); - for_each_possible_cpu(cpu) { - struct sw_flow_stats *stats = &flow->stats[cpu]; + if (!flow->stats.is_percpu) { + stats_reset(flow->stats.stat, true); + } else { + cur_cpu = get_cpu(); - if (cpu == cur_cpu) - local_bh_disable(); + for_each_possible_cpu(cpu) { + bool lock_bh; - spin_lock(&stats->lock); - stats->used = 0; - stats->packet_count = 0; - stats->byte_count = 0; - stats->tcp_flags = 0; - spin_unlock(&stats->lock); - - if (cpu == cur_cpu) - local_bh_enable(); + lock_bh = (cpu == cur_cpu); + stats_reset(per_cpu_ptr(flow->stats.cpu_stats, cpu), lock_bh); + } + put_cpu(); } - put_cpu(); } static int check_header(struct sk_buff *skb, int len) @@ -482,6 +519,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 +588,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)) {