datapath: Convert odp_flow_key to use Netlink attributes instead.
[sliver-openvswitch.git] / datapath / tunnel.c
index c78e7dd..af0df46 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 2010, 2011 Nicira Networks.
  * Distributed under the terms of the GNU GPL version 2.
  *
  * Significant portions of this file may be copied from parts of the Linux
@@ -910,15 +910,15 @@ static struct tnl_cache *build_cache(struct vport *vport,
 #endif
 
        if (is_internal_dev(rt_dst(rt).dev)) {
-               struct odp_flow_key flow_key;
+               struct sw_flow_key flow_key;
                struct tbl_node *flow_node;
-               struct vport *vport;
+               struct vport *dst_vport;
                struct sk_buff *skb;
                bool is_frag;
                int err;
 
-               vport = internal_dev_get_vport(rt_dst(rt).dev);
-               if (!vport)
+               dst_vport = internal_dev_get_vport(rt_dst(rt).dev);
+               if (!dst_vport)
                        goto done;
 
                skb = alloc_skb(cache->len, GFP_ATOMIC);
@@ -928,13 +928,13 @@ static struct tnl_cache *build_cache(struct vport *vport,
                __skb_put(skb, cache->len);
                memcpy(skb->data, get_cached_header(cache), cache->len);
 
-               err = flow_extract(skb, vport->port_no, &flow_key, &is_frag);
+               err = flow_extract(skb, dst_vport->port_no, &flow_key, &is_frag);
 
                kfree_skb(skb);
                if (err || is_frag)
                        goto done;
 
-               flow_node = tbl_lookup(rcu_dereference(vport->dp->table),
+               flow_node = tbl_lookup(rcu_dereference(dst_vport->dp->table),
                                       &flow_key, flow_hash(&flow_key),
                                       flow_cmp);
                if (flow_node) {
@@ -1323,9 +1323,9 @@ out:
        return sent_len;
 }
 
-static int set_config(const void *config, const struct tnl_ops *tnl_ops,
-                     const struct vport *cur_vport,
-                     struct tnl_mutable_config *mutable)
+static int tnl_set_config(const void *config, const struct tnl_ops *tnl_ops,
+                         const struct vport *cur_vport,
+                         struct tnl_mutable_config *mutable)
 {
        const struct vport *old_vport;
        const struct tnl_mutable_config *old_mutable;
@@ -1372,6 +1372,7 @@ struct vport *tnl_create(const struct vport_parms *parms,
 {
        struct vport *vport;
        struct tnl_vport *tnl_vport;
+       struct tnl_mutable_config *mutable;
        int initial_frag_id;
        int err;
 
@@ -1386,19 +1387,19 @@ struct vport *tnl_create(const struct vport_parms *parms,
        strcpy(tnl_vport->name, parms->name);
        tnl_vport->tnl_ops = tnl_ops;
 
-       tnl_vport->mutable = kzalloc(sizeof(struct tnl_mutable_config), GFP_KERNEL);
-       if (!tnl_vport->mutable) {
+       mutable = kzalloc(sizeof(struct tnl_mutable_config), GFP_KERNEL);
+       if (!mutable) {
                err = -ENOMEM;
                goto error_free_vport;
        }
 
-       vport_gen_rand_ether_addr(tnl_vport->mutable->eth_addr);
-       tnl_vport->mutable->mtu = ETH_DATA_LEN;
+       vport_gen_rand_ether_addr(mutable->eth_addr);
+       mutable->mtu = ETH_DATA_LEN;
 
        get_random_bytes(&initial_frag_id, sizeof(int));
        atomic_set(&tnl_vport->frag_id, initial_frag_id);
 
-       err = set_config(parms->config, tnl_ops, NULL, tnl_vport->mutable);
+       err = tnl_set_config(parms->config, tnl_ops, NULL, mutable);
        if (err)
                goto error_free_mutable;
 
@@ -1406,9 +1407,11 @@ struct vport *tnl_create(const struct vport_parms *parms,
 
 #ifdef NEED_CACHE_TIMEOUT
        tnl_vport->cache_exp_interval = MAX_CACHE_EXP -
-                                       (net_random() % (MAX_CACHE_EXP / 2));
+                                      (net_random() % (MAX_CACHE_EXP / 2));
 #endif
 
+       rcu_assign_pointer(tnl_vport->mutable, mutable);
+
        err = add_port(vport);
        if (err)
                goto error_free_mutable;
@@ -1416,7 +1419,7 @@ struct vport *tnl_create(const struct vport_parms *parms,
        return vport;
 
 error_free_mutable:
-       kfree(tnl_vport->mutable);
+       kfree(mutable);
 error_free_vport:
        vport_free(vport);
 error:
@@ -1429,13 +1432,14 @@ int tnl_modify(struct vport *vport, struct odp_port *port)
        struct tnl_mutable_config *mutable;
        int err;
 
-       mutable = kmemdup(tnl_vport->mutable, sizeof(struct tnl_mutable_config), GFP_KERNEL);
+       mutable = kmemdup(rtnl_dereference(tnl_vport->mutable),
+                         sizeof(struct tnl_mutable_config), GFP_KERNEL);
        if (!mutable) {
                err = -ENOMEM;
                goto error;
        }
 
-       err = set_config(port->config, tnl_vport->tnl_ops, vport, mutable);
+       err = tnl_set_config(port->config, tnl_vport->tnl_ops, vport, mutable);
        if (err)
                goto error_free;
 
@@ -1455,26 +1459,24 @@ error:
 
 static void free_port_rcu(struct rcu_head *rcu)
 {
-       struct tnl_vport *tnl_vport = container_of(rcu, struct tnl_vport, rcu);
-
-       spin_lock_bh(&tnl_vport->cache_lock);
-       free_cache(tnl_vport->cache);
-       spin_unlock_bh(&tnl_vport->cache_lock);
+       struct tnl_vport *tnl_vport = container_of(rcu,
+                                                  struct tnl_vport, rcu);
 
-       kfree(tnl_vport->mutable);
+       free_cache((struct tnl_cache __force *)tnl_vport->cache);
+       kfree((struct tnl_mutable __force *)tnl_vport->mutable);
        vport_free(tnl_vport_to_vport(tnl_vport));
 }
 
 int tnl_destroy(struct vport *vport)
 {
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
-       const struct tnl_mutable_config *old_mutable;
+       const struct tnl_mutable_config *mutable, *old_mutable;
+
+       mutable = rtnl_dereference(tnl_vport->mutable);
 
-       if (vport == tnl_find_port(tnl_vport->mutable->port_config.saddr,
-           tnl_vport->mutable->port_config.daddr,
-           tnl_vport->mutable->port_config.in_key,
-           tnl_vport->mutable->tunnel_type,
-           &old_mutable))
+       if (vport == tnl_find_port(mutable->port_config.saddr,
+           mutable->port_config.daddr, mutable->port_config.in_key,
+           mutable->tunnel_type, &old_mutable))
                del_port(vport);
 
        call_rcu(&tnl_vport->rcu, free_port_rcu);
@@ -1487,7 +1489,8 @@ int tnl_set_mtu(struct vport *vport, int mtu)
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
        struct tnl_mutable_config *mutable;
 
-       mutable = kmemdup(tnl_vport->mutable, sizeof(struct tnl_mutable_config), GFP_KERNEL);
+       mutable = kmemdup(rtnl_dereference(tnl_vport->mutable),
+                         sizeof(struct tnl_mutable_config), GFP_KERNEL);
        if (!mutable)
                return -ENOMEM;
 
@@ -1502,7 +1505,8 @@ int tnl_set_addr(struct vport *vport, const unsigned char *addr)
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
        struct tnl_mutable_config *mutable;
 
-       mutable = kmemdup(tnl_vport->mutable, sizeof(struct tnl_mutable_config), GFP_KERNEL);
+       mutable = kmemdup(rtnl_dereference(tnl_vport->mutable),
+                         sizeof(struct tnl_mutable_config), GFP_KERNEL);
        if (!mutable)
                return -ENOMEM;
 
@@ -1524,6 +1528,15 @@ const unsigned char *tnl_get_addr(const struct vport *vport)
        return rcu_dereference_rtnl(tnl_vport->mutable)->eth_addr;
 }
 
+void tnl_get_config(const struct vport *vport, void *config)
+{
+       const struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
+       struct tnl_port_config *port_config;
+       
+       port_config = &rcu_dereference_rtnl(tnl_vport->mutable)->port_config;
+       memcpy(config, port_config, sizeof(*port_config));
+}
+
 int tnl_get_mtu(const struct vport *vport)
 {
        const struct tnl_vport *tnl_vport = tnl_vport_priv(vport);