X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fvport.c;h=cdf615a47b8b135c631988ba6d52e9666391bab3;hb=33ef7695b71a71f2d0bb0e00aab46855afb8c2a6;hp=2438590105c28b85d497159faa955f83dbf8b8c5;hpb=cc98976af50fec5643a372aa9c7a4c4e565e939e;p=openvswitch diff --git a/datapath/vport.c b/datapath/vport.c index 24385901..cdf615a4 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -35,17 +35,6 @@ static int n_vport_types; static struct hlist_head *dev_table; #define VPORT_HASH_BUCKETS 1024 -/* We limit the number of times that we pass through vport_send() to - * avoid blowing out the stack in the event that we have a loop. There is - * a separate counter for each CPU for both interrupt and non-interrupt - * context in order to keep the limit deterministic for a given packet. */ -struct percpu_loop_counter { - int count[2]; -}; - -static DEFINE_PER_CPU(struct percpu_loop_counter, vport_loop_counter); -#define VPORT_MAX_LOOPS 5 - /* Both RTNL lock and vport_mutex need to be held when updating dev_table. * * If you use vport_locate and then perform some operations, you need to hold @@ -1063,12 +1052,20 @@ int vport_get_stats(struct vport *vport, struct odp_vport_stats *stats) for_each_possible_cpu(i) { const struct vport_percpu_stats *percpu_stats; + struct vport_percpu_stats local_stats; + unsigned seqcount; percpu_stats = per_cpu_ptr(vport->percpu_stats, i); - stats->rx_bytes += percpu_stats->rx_bytes; - stats->rx_packets += percpu_stats->rx_packets; - stats->tx_bytes += percpu_stats->tx_bytes; - stats->tx_packets += percpu_stats->tx_packets; + + do { + seqcount = read_seqcount_begin(&percpu_stats->seqlock); + local_stats = *percpu_stats; + } while (read_seqcount_retry(&percpu_stats->seqlock, seqcount)); + + stats->rx_bytes += local_stats.rx_bytes; + stats->rx_packets += local_stats.rx_packets; + stats->tx_bytes += local_stats.tx_bytes; + stats->tx_packets += local_stats.tx_packets; } err = 0; @@ -1203,10 +1200,12 @@ void vport_receive(struct vport *vport, struct sk_buff *skb) struct vport_percpu_stats *stats; local_bh_disable(); - stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id()); + + write_seqcount_begin(&stats->seqlock); stats->rx_packets++; stats->rx_bytes += skb->len; + write_seqcount_end(&stats->seqlock); local_bh_enable(); } @@ -1238,20 +1237,9 @@ static inline unsigned packet_length(const struct sk_buff *skb) */ int vport_send(struct vport *vport, struct sk_buff *skb) { - int *loop_count; int mtu; int sent; - loop_count = &get_cpu_var(vport_loop_counter).count[!!in_interrupt()]; - (*loop_count)++; - - if (unlikely(*loop_count > VPORT_MAX_LOOPS)) { - if (net_ratelimit()) - printk(KERN_WARNING "%s: dropping packet that has looped more than %d times\n", - dp_name(vport_get_dp_port(vport)->dp), VPORT_MAX_LOOPS); - goto error; - } - mtu = vport_get_mtu(vport); if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) { if (net_ratelimit()) @@ -1266,25 +1254,22 @@ int vport_send(struct vport *vport, struct sk_buff *skb) struct vport_percpu_stats *stats; local_bh_disable(); - stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id()); + + write_seqcount_begin(&stats->seqlock); stats->tx_packets++; stats->tx_bytes += sent; + write_seqcount_end(&stats->seqlock); local_bh_enable(); } - goto out; + return sent; error: - sent = 0; kfree_skb(skb); vport_record_error(vport, VPORT_E_TX_DROPPED); -out: - (*loop_count)--; - put_cpu_var(vport_loop_counter); - - return sent; + return 0; } /**