X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fvport.c;h=37d6d8ab058477dea0c74b36801256a0a96b21cc;hb=cd10ed7fb4fb5b1e3ed8e3fae1fd115c7ae96e77;hp=2438590105c28b85d497159faa955f83dbf8b8c5;hpb=cc98976af50fec5643a372aa9c7a4c4e565e939e;p=openvswitch diff --git a/datapath/vport.c b/datapath/vport.c index 24385901..37d6d8ab 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -6,6 +6,8 @@ * kernel, by Linus Torvalds and others. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -16,6 +18,7 @@ #include #include #include +#include #include "vport.h" #include "vport-internal_dev.h" @@ -27,6 +30,9 @@ static struct vport_ops *base_vport_ops_list[] = { &internal_vport_ops, &patch_vport_ops, &gre_vport_ops, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + &capwap_vport_ops, +#endif }; static const struct vport_ops **vport_ops_list; @@ -35,17 +41,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 @@ -83,13 +78,14 @@ void vport_unlock(void) mutex_unlock(&vport_mutex); } -#define ASSERT_VPORT() do { \ - if (unlikely(!mutex_is_locked(&vport_mutex))) { \ - printk(KERN_ERR "openvswitch: vport lock not held at %s (%d)\n", \ - __FILE__, __LINE__); \ - dump_stack(); \ - } \ -} while(0) +#define ASSERT_VPORT() \ +do { \ + if (unlikely(!mutex_is_locked(&vport_mutex))) { \ + pr_err("vport lock not held at %s (%d)\n", \ + __FILE__, __LINE__); \ + dump_stack(); \ + } \ +} while (0) /** * vport_init - initialize vport subsystem @@ -623,7 +619,7 @@ struct vport *vport_locate(const char *name) struct hlist_node *node; if (unlikely(!mutex_is_locked(&vport_mutex) && !rtnl_is_locked())) { - printk(KERN_ERR "openvswitch: neither RTNL nor vport lock held in vport_locate\n"); + pr_err("neither RTNL nor vport lock held in vport_locate\n"); dump_stack(); } @@ -908,13 +904,13 @@ int vport_set_addr(struct vport *vport, const unsigned char *addr) * support setting the stats, in which case the result will always be * -EOPNOTSUPP. RTNL lock must be held. */ -int vport_set_stats(struct vport *vport, struct odp_vport_stats *stats) +int vport_set_stats(struct vport *vport, struct rtnl_link_stats64 *stats) { ASSERT_RTNL(); if (vport->ops->flags & VPORT_F_GEN_STATS) { spin_lock_bh(&vport->stats_lock); - memcpy(&vport->offset_stats, stats, sizeof(struct odp_vport_stats)); + vport->offset_stats = *stats; spin_unlock_bh(&vport->stats_lock); return 0; @@ -1002,10 +998,10 @@ struct kobject *vport_get_kobj(const struct vport *vport) * * Retrieves transmit, receive, and error stats for the given device. */ -int vport_get_stats(struct vport *vport, struct odp_vport_stats *stats) +int vport_get_stats(struct vport *vport, struct rtnl_link_stats64 *stats) { - struct odp_vport_stats dev_stats; - struct odp_vport_stats *dev_statsp = NULL; + struct rtnl_link_stats64 dev_stats; + struct rtnl_link_stats64 *dev_statsp = NULL; int err; if (vport->ops->get_stats) { @@ -1034,7 +1030,7 @@ int vport_get_stats(struct vport *vport, struct odp_vport_stats *stats) spin_lock_bh(&vport->stats_lock); - memcpy(stats, &vport->offset_stats, sizeof(struct odp_vport_stats)); + *stats = vport->offset_stats; stats->rx_errors += vport->err_stats.rx_errors + vport->err_stats.rx_frame_err @@ -1043,32 +1039,55 @@ int vport_get_stats(struct vport *vport, struct odp_vport_stats *stats) stats->tx_errors += vport->err_stats.tx_errors; stats->tx_dropped += vport->err_stats.tx_dropped; stats->rx_dropped += vport->err_stats.rx_dropped; - stats->rx_over_err += vport->err_stats.rx_over_err; - stats->rx_crc_err += vport->err_stats.rx_crc_err; - stats->rx_frame_err += vport->err_stats.rx_frame_err; + stats->rx_over_errors += vport->err_stats.rx_over_err; + stats->rx_crc_errors += vport->err_stats.rx_crc_err; + stats->rx_frame_errors += vport->err_stats.rx_frame_err; stats->collisions += vport->err_stats.collisions; spin_unlock_bh(&vport->stats_lock); if (dev_statsp) { - stats->rx_errors += dev_statsp->rx_errors; - stats->tx_errors += dev_statsp->tx_errors; - stats->rx_dropped += dev_statsp->rx_dropped; - stats->tx_dropped += dev_statsp->tx_dropped; - stats->rx_over_err += dev_statsp->rx_over_err; - stats->rx_crc_err += dev_statsp->rx_crc_err; - stats->rx_frame_err += dev_statsp->rx_frame_err; - stats->collisions += dev_statsp->collisions; + stats->rx_packets += dev_statsp->rx_packets; + stats->tx_packets += dev_statsp->tx_packets; + stats->rx_bytes += dev_statsp->rx_bytes; + stats->tx_bytes += dev_statsp->tx_bytes; + stats->rx_errors += dev_statsp->rx_errors; + stats->tx_errors += dev_statsp->tx_errors; + stats->rx_dropped += dev_statsp->rx_dropped; + stats->tx_dropped += dev_statsp->tx_dropped; + stats->multicast += dev_statsp->multicast; + stats->collisions += dev_statsp->collisions; + stats->rx_length_errors += dev_statsp->rx_length_errors; + stats->rx_over_errors += dev_statsp->rx_over_errors; + stats->rx_crc_errors += dev_statsp->rx_crc_errors; + stats->rx_frame_errors += dev_statsp->rx_frame_errors; + stats->rx_fifo_errors += dev_statsp->rx_fifo_errors; + stats->rx_missed_errors += dev_statsp->rx_missed_errors; + stats->tx_aborted_errors += dev_statsp->tx_aborted_errors; + stats->tx_carrier_errors += dev_statsp->tx_carrier_errors; + stats->tx_fifo_errors += dev_statsp->tx_fifo_errors; + stats->tx_heartbeat_errors += dev_statsp->tx_heartbeat_errors; + stats->tx_window_errors += dev_statsp->tx_window_errors; + stats->rx_compressed += dev_statsp->rx_compressed; + stats->tx_compressed += dev_statsp->tx_compressed; } 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,14 +1222,19 @@ 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(); } + if (!(vport->ops->flags & VPORT_F_FLOW)) + OVS_CB(skb)->flow = NULL; + if (!(vport->ops->flags & VPORT_F_TUN_ID)) OVS_CB(skb)->tun_id = 0; @@ -1238,25 +1262,15 @@ 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()) - printk(KERN_WARNING "%s: dropped over-mtu packet: %d > %d\n", - dp_name(vport_get_dp_port(vport)->dp), packet_length(skb), mtu); + pr_warn("%s: dropped over-mtu packet: %d > %d\n", + dp_name(vport_get_dp_port(vport)->dp), + packet_length(skb), mtu); goto error; } @@ -1266,25 +1280,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; } /**