datapath: use this_cpu_ptr per-cpu helper
[openvswitch] / datapath / vport.c
index e9ccdbde329d72f147ab6b852bfe555221ac1eb5..4934ac1f57f3e663af0a789c26700d43d9940958 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2011 Nicira Networks.
+ * Copyright (c) 2007-2012 Nicira, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
  * 02110-1301, USA
  */
 
-#include <linux/dcache.h>
 #include <linux/etherdevice.h>
 #include <linux/if.h>
 #include <linux/if_vlan.h>
+#include <linux/jhash.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -28,7 +28,9 @@
 #include <linux/rtnetlink.h>
 #include <linux/compat.h>
 #include <linux/version.h>
+#include <net/net_namespace.h>
 
+#include "datapath.h"
 #include "vport.h"
 #include "vport-internal_dev.h"
 
@@ -39,6 +41,8 @@ static const struct vport_ops *base_vport_ops_list[] = {
        &ovs_internal_vport_ops,
        &ovs_patch_vport_ops,
        &ovs_gre_vport_ops,
+       &ovs_gre_ft_vport_ops,
+       &ovs_gre64_vport_ops,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
        &ovs_capwap_vport_ops,
 #endif
@@ -119,9 +123,9 @@ void ovs_vport_exit(void)
        kfree(dev_table);
 }
 
-static struct hlist_head *hash_bucket(const char *name)
+static struct hlist_head *hash_bucket(struct net *net, const char *name)
 {
-       unsigned int hash = full_name_hash(name, strlen(name));
+       unsigned int hash = jhash(name, strlen(name), (unsigned long) net);
        return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)];
 }
 
@@ -132,14 +136,15 @@ static struct hlist_head *hash_bucket(const char *name)
  *
  * Must be called with RTNL or RCU read lock.
  */
-struct vport *ovs_vport_locate(const char *name)
+struct vport *ovs_vport_locate(struct net *net, const char *name)
 {
-       struct hlist_head *bucket = hash_bucket(name);
+       struct hlist_head *bucket = hash_bucket(net, name);
        struct vport *vport;
        struct hlist_node *node;
 
        hlist_for_each_entry_rcu(vport, node, bucket, hash_node)
-               if (!strcmp(name, vport->ops->get_name(vport)))
+               if (!strcmp(name, vport->ops->get_name(vport)) &&
+                   net_eq(ovs_dp_get_net(vport->dp), net))
                        return vport;
 
        return NULL;
@@ -189,6 +194,7 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
        vport->port_no = parms->port_no;
        vport->upcall_pid = parms->upcall_pid;
        vport->ops = ops;
+       INIT_HLIST_NODE(&vport->dp_hash_node);
 
        /* Initialize kobject for bridge.  This will be added as
         * /sys/class/net/<devname>/brport later, if sysfs is enabled. */
@@ -241,14 +247,17 @@ struct vport *ovs_vport_add(const struct vport_parms *parms)
 
        for (i = 0; i < n_vport_types; i++) {
                if (vport_ops_list[i]->type == parms->type) {
+                       struct hlist_head *bucket;
+
                        vport = vport_ops_list[i]->create(parms);
                        if (IS_ERR(vport)) {
                                err = PTR_ERR(vport);
                                goto out;
                        }
 
-                       hlist_add_head_rcu(&vport->hash_node,
-                                          hash_bucket(vport->ops->get_name(vport)));
+                       bucket = hash_bucket(ovs_dp_get_net(vport->dp),
+                                            vport->ops->get_name(vport));
+                       hlist_add_head_rcu(&vport->hash_node, bucket);
                        return vport;
                }
        }
@@ -444,8 +453,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
 {
        struct vport_percpu_stats *stats;
 
-       stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
-
+       stats = this_cpu_ptr(vport->percpu_stats);
        u64_stats_update_begin(&stats->sync);
        stats->rx_packets++;
        stats->rx_bytes += skb->len;
@@ -455,7 +463,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
                OVS_CB(skb)->flow = NULL;
 
        if (!(vport->ops->flags & VPORT_F_TUN_ID))
-               OVS_CB(skb)->tun_id = 0;
+               OVS_CB(skb)->tun_key = NULL;
 
        ovs_dp_process_received_packet(vport, skb);
 }
@@ -476,7 +484,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
        if (likely(sent)) {
                struct vport_percpu_stats *stats;
 
-               stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
+               stats = this_cpu_ptr(vport->percpu_stats);
 
                u64_stats_update_begin(&stats->sync);
                stats->tx_packets++;
@@ -515,7 +523,7 @@ void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type)
        case VPORT_E_TX_ERROR:
                vport->err_stats.tx_errors++;
                break;
-       };
+       }
 
        spin_unlock(&vport->stats_lock);
 }