vswitchd: Remove iface_get_carrier().
[openvswitch] / datapath / tunnel.c
index 25aea24676ea8b1186c8a58ddaf50598c02e940a..38004e9e50d717fad18207c77f4345548bfd4d0f 100644 (file)
@@ -160,61 +160,23 @@ static void assign_cache_rcu(struct vport *vport, struct tnl_cache *new_cache)
 static unsigned int *find_port_pool(const struct tnl_mutable_config *mutable)
 {
        if (mutable->flags & TNL_F_IN_KEY_MATCH) {
-               if (mutable->saddr)
+               if (mutable->key.saddr)
                        return &local_remote_ports;
                else
                        return &remote_ports;
        } else {
-               if (mutable->saddr)
+               if (mutable->key.saddr)
                        return &key_local_remote_ports;
                else
                        return &key_remote_ports;
        }
 }
 
-struct port_lookup_key {
-       const struct tnl_mutable_config *mutable;
-       __be64 key;
-       u32 tunnel_type;
-       __be32 saddr;
-       __be32 daddr;
-};
-
-/*
- * Modifies 'target' to store the rcu_dereferenced pointer that was used to do
- * the comparision.
- */
-static int port_cmp(const struct tnl_vport *tnl_vport,
-                    struct port_lookup_key *lookup)
-{
-       lookup->mutable = rcu_dereference_rtnl(tnl_vport->mutable);
-
-       return (lookup->mutable->tunnel_type == lookup->tunnel_type &&
-               lookup->mutable->daddr == lookup->daddr &&
-               lookup->mutable->in_key == lookup->key &&
-               lookup->mutable->saddr == lookup->saddr);
-}
-
-static u32 port_hash(struct port_lookup_key *k)
+static u32 port_hash(const struct port_lookup_key *key)
 {
-       u32 x = jhash_3words((__force u32)k->saddr, (__force u32)k->daddr,
-                            k->tunnel_type, 0);
-       return jhash_2words((__force u64)k->key >> 32, (__force u32)k->key, x);
+       return jhash2((u32*)key, (PORT_KEY_LEN / sizeof(u32)), 0);
 }
 
-static u32 mutable_hash(const struct tnl_mutable_config *mutable)
-{
-       struct port_lookup_key lookup;
-
-       lookup.saddr = mutable->saddr;
-       lookup.daddr = mutable->daddr;
-       lookup.key = mutable->in_key;
-       lookup.tunnel_type = mutable->tunnel_type;
-
-       return port_hash(&lookup);
-}
-
-
 static inline struct hlist_head *find_bucket(u32 hash)
 {
        return &port_table[(hash & (PORT_TABLE_SIZE - 1))];
@@ -223,11 +185,14 @@ static inline struct hlist_head *find_bucket(u32 hash)
 static void port_table_add_port(struct vport *vport)
 {
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
-       u32 hash = mutable_hash(rtnl_dereference(tnl_vport->mutable));
+       const struct tnl_mutable_config *mutable;
+       u32 hash;
 
        if (port_table_count == 0)
                schedule_cache_cleaner();
 
+       mutable = rtnl_dereference(tnl_vport->mutable);
+       hash = port_hash(&mutable->key);
        hlist_add_head_rcu(&tnl_vport->hash_node, find_bucket(hash));
        port_table_count++;
 
@@ -240,7 +205,7 @@ static void port_table_move_port(struct vport *vport,
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
        u32 hash;
 
-       hash = mutable_hash(new_mutable);
+       hash = port_hash(&new_mutable->key);
        hlist_del_init_rcu(&tnl_vport->hash_node);
        hlist_add_head_rcu(&tnl_vport->hash_node, find_bucket(hash));
 
@@ -262,18 +227,24 @@ static void port_table_remove_port(struct vport *vport)
        (*find_port_pool(rtnl_dereference(tnl_vport->mutable)))--;
 }
 
-static struct tnl_vport *port_table_lookup(struct port_lookup_key *lookup)
+static struct vport *port_table_lookup(struct port_lookup_key *key,
+                                      const struct tnl_mutable_config **pmutable)
 {
        struct hlist_node *n;
        struct hlist_head *bucket;
-       u32 hash = port_hash(lookup);
+       u32 hash = port_hash(key);
        struct tnl_vport * tnl_vport;
 
        bucket = find_bucket(hash);
 
        hlist_for_each_entry_rcu(tnl_vport, n, bucket, hash_node) {
-               if (!port_cmp(tnl_vport, lookup))
-                       return tnl_vport;
+               struct tnl_mutable_config *mutable;
+
+               mutable = rcu_dereference_rtnl(tnl_vport->mutable);
+               if (!memcmp(&mutable->key, key, PORT_KEY_LEN)) {
+                       *pmutable = mutable;
+                       return tnl_vport_to_vport(tnl_vport);
+               }
        }
 
        return NULL;
@@ -284,54 +255,44 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
                            const struct tnl_mutable_config **mutable)
 {
        struct port_lookup_key lookup;
-       struct tnl_vport * tnl_vport;
+       struct vport *vport;
 
        lookup.saddr = saddr;
        lookup.daddr = daddr;
 
-       if (tunnel_type & TNL_T_KEY_EXACT) {
-               lookup.key = key;
-               lookup.tunnel_type = tunnel_type & ~TNL_T_KEY_MATCH;
-
-               if (key_local_remote_ports) {
-                       tnl_vport = port_table_lookup(&lookup);
-                       if (tnl_vport)
-                               goto found;
-               }
-
-               if (key_remote_ports) {
-                       lookup.saddr = 0;
-                       tnl_vport = port_table_lookup(&lookup);
-                       if (tnl_vport)
-                               goto found;
-
-                       lookup.saddr = saddr;
-               }
+       /* First try for exact match on in_key. */
+       lookup.in_key = key;
+       lookup.tunnel_type = tunnel_type | TNL_T_KEY_EXACT;
+       if (key_local_remote_ports) {
+               vport = port_table_lookup(&lookup, mutable);
+               if (vport)
+                       return vport;
        }
+       if (key_remote_ports) {
+               lookup.saddr = 0;
+               vport = port_table_lookup(&lookup, mutable);
+               if (vport)
+                       return vport;
 
-       if (tunnel_type & TNL_T_KEY_MATCH) {
-               lookup.key = 0;
-               lookup.tunnel_type = tunnel_type & ~TNL_T_KEY_EXACT;
-
-               if (local_remote_ports) {
-                       tnl_vport = port_table_lookup(&lookup);
-                       if (tnl_vport)
-                               goto found;
-               }
+               lookup.saddr = saddr;
+       }
 
-               if (remote_ports) {
-                       lookup.saddr = 0;
-                       tnl_vport = port_table_lookup(&lookup);
-                       if (tnl_vport)
-                               goto found;
-               }
+       /* Then try matches that wildcard in_key. */
+       lookup.in_key = 0;
+       lookup.tunnel_type = tunnel_type | TNL_T_KEY_MATCH;
+       if (local_remote_ports) {
+               vport = port_table_lookup(&lookup, mutable);
+               if (vport)
+                       return vport;
+       }
+       if (remote_ports) {
+               lookup.saddr = 0;
+               vport = port_table_lookup(&lookup, mutable);
+               if (vport)
+                       return vport;
        }
 
        return NULL;
-
-found:
-       *mutable = lookup.mutable;
-       return tnl_vport_to_vport(tnl_vport);
 }
 
 static void ecn_decapsulate(struct sk_buff *skb, u8 tos)
@@ -846,9 +807,9 @@ static inline void create_eth_hdr(struct tnl_cache *cache,
 
        cache->hh_seq = hh_seq;
 #else
-       read_lock_bh(&rt_dst(rt).hh->hh_lock);
+       read_lock(&rt_dst(rt).hh->hh_lock);
        memcpy(cache_data, (void *)rt_dst(rt).hh->hh_data + hh_off, hh_len);
-       read_unlock_bh(&rt_dst(rt).hh->hh_lock);
+       read_unlock(&rt_dst(rt).hh->hh_lock);
 #endif
 }
 
@@ -875,7 +836,7 @@ static struct tnl_cache *build_cache(struct vport *vport,
         * If lock is contended fall back to directly building the header.
         * We're not going to help performance by sitting here spinning.
         */
-       if (!spin_trylock_bh(&tnl_vport->cache_lock))
+       if (!spin_trylock(&tnl_vport->cache_lock))
                return NULL;
 
        cache = cache_dereference(tnl_vport);
@@ -943,7 +904,7 @@ done:
        assign_cache_rcu(vport, cache);
 
 unlock:
-       spin_unlock_bh(&tnl_vport->cache_lock);
+       spin_unlock(&tnl_vport->cache_lock);
 
        return cache;
 }
@@ -965,16 +926,16 @@ static struct rtable *find_route(struct vport *vport,
                struct rtable *rt;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
                struct flowi fl = { .nl_u = { .ip4_u =
-                                             { .daddr = mutable->daddr,
-                                               .saddr = mutable->saddr,
+                                             { .daddr = mutable->key.daddr,
+                                               .saddr = mutable->key.saddr,
                                                .tos = tos } },
                                    .proto = tnl_vport->tnl_ops->ipproto };
 
                if (unlikely(ip_route_output_key(&init_net, &rt, &fl)))
                        return NULL;
 #else
-               struct flowi4 fl = { .daddr = mutable->daddr,
-                                    .saddr = mutable->saddr,
+               struct flowi4 fl = { .daddr = mutable->key.daddr,
+                                    .saddr = mutable->key.saddr,
                                     .flowi4_tos = tos,
                                     .flowi4_proto = tnl_vport->tnl_ops->ipproto };
 
@@ -1327,8 +1288,8 @@ static int tnl_set_config(struct nlattr *options, const struct tnl_ops *tnl_ops,
        mutable->flags = nla_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_PUBLIC;
 
        if (a[OVS_TUNNEL_ATTR_SRC_IPV4])
-               mutable->saddr = nla_get_be32(a[OVS_TUNNEL_ATTR_SRC_IPV4]);
-       mutable->daddr = nla_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
+               mutable->key.saddr = nla_get_be32(a[OVS_TUNNEL_ATTR_SRC_IPV4]);
+       mutable->key.daddr = nla_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
 
        if (a[OVS_TUNNEL_ATTR_TOS]) {
                mutable->tos = nla_get_u8(a[OVS_TUNNEL_ATTR_TOS]);
@@ -1339,13 +1300,13 @@ static int tnl_set_config(struct nlattr *options, const struct tnl_ops *tnl_ops,
        if (a[OVS_TUNNEL_ATTR_TTL])
                mutable->ttl = nla_get_u8(a[OVS_TUNNEL_ATTR_TTL]);
 
-       mutable->tunnel_type = tnl_ops->tunnel_type;
+       mutable->key.tunnel_type = tnl_ops->tunnel_type;
        if (!a[OVS_TUNNEL_ATTR_IN_KEY]) {
-               mutable->tunnel_type |= TNL_T_KEY_MATCH;
+               mutable->key.tunnel_type |= TNL_T_KEY_MATCH;
                mutable->flags |= TNL_F_IN_KEY_MATCH;
        } else {
-               mutable->tunnel_type |= TNL_T_KEY_EXACT;
-               mutable->in_key = nla_get_be64(a[OVS_TUNNEL_ATTR_IN_KEY]);
+               mutable->key.tunnel_type |= TNL_T_KEY_EXACT;
+               mutable->key.in_key = nla_get_be64(a[OVS_TUNNEL_ATTR_IN_KEY]);
        }
 
        if (!a[OVS_TUNNEL_ATTR_OUT_KEY])
@@ -1359,10 +1320,7 @@ static int tnl_set_config(struct nlattr *options, const struct tnl_ops *tnl_ops,
 
        mutable->tunnel_hlen += sizeof(struct iphdr);
 
-       old_vport = tnl_find_port(mutable->saddr, mutable->daddr,
-                                 mutable->in_key, mutable->tunnel_type,
-                                 &old_mutable);
-
+       old_vport = port_table_lookup(&mutable->key, &old_mutable);
        if (old_vport && old_vport != cur_vport)
                return -EEXIST;
 
@@ -1448,7 +1406,7 @@ int tnl_set_options(struct vport *vport, struct nlattr *options)
        if (err)
                goto error_free;
 
-       if (mutable_hash(mutable) != mutable_hash(old_mutable))
+       if (port_hash(&mutable->key) != port_hash(&old_mutable->key))
                port_table_move_port(vport, mutable);
 
        return 0;
@@ -1465,14 +1423,14 @@ int tnl_get_options(const struct vport *vport, struct sk_buff *skb)
        const struct tnl_mutable_config *mutable = rcu_dereference_rtnl(tnl_vport->mutable);
 
        NLA_PUT_U32(skb, OVS_TUNNEL_ATTR_FLAGS, mutable->flags & TNL_F_PUBLIC);
-       NLA_PUT_BE32(skb, OVS_TUNNEL_ATTR_DST_IPV4, mutable->daddr);
+       NLA_PUT_BE32(skb, OVS_TUNNEL_ATTR_DST_IPV4, mutable->key.daddr);
 
        if (!(mutable->flags & TNL_F_IN_KEY_MATCH))
-               NLA_PUT_BE64(skb, OVS_TUNNEL_ATTR_IN_KEY, mutable->in_key);
+               NLA_PUT_BE64(skb, OVS_TUNNEL_ATTR_IN_KEY, mutable->key.in_key);
        if (!(mutable->flags & TNL_F_OUT_KEY_ACTION))
                NLA_PUT_BE64(skb, OVS_TUNNEL_ATTR_OUT_KEY, mutable->out_key);
-       if (mutable->saddr)
-               NLA_PUT_BE32(skb, OVS_TUNNEL_ATTR_SRC_IPV4, mutable->saddr);
+       if (mutable->key.saddr)
+               NLA_PUT_BE32(skb, OVS_TUNNEL_ATTR_SRC_IPV4, mutable->key.saddr);
        if (mutable->tos)
                NLA_PUT_U8(skb, OVS_TUNNEL_ATTR_TOS, mutable->tos);
        if (mutable->ttl)