]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'batman-adv/next' of git://git.open-mesh.org/linux-merge
authorDavid S. Miller <davem@davemloft.net>
Tue, 13 Dec 2011 00:26:07 +0000 (19:26 -0500)
committerDavid S. Miller <davem@davemloft.net>
Tue, 13 Dec 2011 00:26:07 +0000 (19:26 -0500)
Documentation/networking/batman-adv.txt
net/batman-adv/gateway_client.c
net/batman-adv/icmp_socket.c
net/batman-adv/routing.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/batman-adv/types.h
net/batman-adv/vis.c

index c86d03f18a5be6c70c97f2fadacd0cb93f66f800..221ad0cdf11f2fb729b1fe2bc624b30e53d996be 100644 (file)
@@ -200,15 +200,16 @@ abled  during run time. Following log_levels are defined:
 
 0 - All  debug  output  disabled
 1 - Enable messages related to routing / flooding / broadcasting
-2 - Enable route or tt entry added / changed / deleted
-3 - Enable all messages
+2 - Enable messages related to route added / changed / deleted
+4 - Enable messages related to translation table operations
+7 - Enable all messages
 
 The debug output can be changed at runtime  using  the  file
 /sys/class/net/bat0/mesh/log_level. e.g.
 
 # echo 2 > /sys/class/net/bat0/mesh/log_level
 
-will enable debug messages for when routes or TTs change.
+will enable debug messages for when routes change.
 
 
 BATCTL
index 9373a143c6d4e15b678666b5b476debfb466a612..24403a7350f75fb5767e8855041c31b8d166fea9 100644 (file)
@@ -695,7 +695,7 @@ bool gw_out_of_range(struct bat_priv *bat_priv,
        }
 
        neigh_old = find_router(bat_priv, orig_dst_node, NULL);
-       if (!!neigh_old)
+       if (!neigh_old)
                goto out;
 
        if (curr_tq_avg - neigh_old->tq_avg > GW_THRESHOLD)
index ac3520e057c0079d97943433a8df648ac1cc402c..d9c1e7bb7fbfa4ba6d5d579bfe1b266cbab65052 100644 (file)
@@ -136,10 +136,9 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf,
 
        spin_unlock_bh(&socket_client->lock);
 
-       error = __copy_to_user(buf, &socket_packet->icmp_packet,
-                              socket_packet->icmp_len);
+       packet_len = min(count, socket_packet->icmp_len);
+       error = copy_to_user(buf, &socket_packet->icmp_packet, packet_len);
 
-       packet_len = socket_packet->icmp_len;
        kfree(socket_packet);
 
        if (error)
@@ -187,12 +186,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
        skb_reserve(skb, sizeof(struct ethhdr));
        icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
 
-       if (!access_ok(VERIFY_READ, buff, packet_len)) {
-               len = -EFAULT;
-               goto free_skb;
-       }
-
-       if (__copy_from_user(icmp_packet, buff, packet_len)) {
+       if (copy_from_user(icmp_packet, buff, packet_len)) {
                len = -EFAULT;
                goto free_skb;
        }
@@ -217,7 +211,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
 
        if (icmp_packet->version != COMPAT_VERSION) {
                icmp_packet->msg_type = PARAMETER_PROBLEM;
-               icmp_packet->ttl = COMPAT_VERSION;
+               icmp_packet->version = COMPAT_VERSION;
                bat_socket_add_packet(socket_client, icmp_packet, packet_len);
                goto free_skb;
        }
index ef24a7205f65beaf3737da6a5389798a5f2f6836..773e606f9702bfcc04b7c41ddf2234790fb205c0 100644 (file)
@@ -627,8 +627,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
 
                        /* Ensure we have all the claimed data */
                        if (unlikely(skb_headlen(skb) <
-                                       sizeof(struct tt_query_packet) +
-                                       tt_len))
+                                    sizeof(struct tt_query_packet) + tt_len))
                                goto out;
 
                        handle_tt_response(bat_priv, tt_query);
index 45297c84309243f4d10eebad667478c19f77c503..987c75a775f9c034c5f6648fc13f05203f1419dc 100644 (file)
@@ -874,7 +874,7 @@ unreg_debugfs:
 unreg_sysfs:
        sysfs_del_meshif(soft_iface);
 unreg_soft_iface:
-       unregister_netdev(soft_iface);
+       unregister_netdevice(soft_iface);
        return NULL;
 
 free_soft_iface:
index 78b9528bfc2a5143dcc35b391b9bdfcd38f71ea3..cc87acf0243106dd5e110ad920c8e17d4640760b 100644 (file)
@@ -36,18 +36,9 @@ static void _tt_global_del(struct bat_priv *bat_priv,
 static void tt_purge(struct work_struct *work);
 
 /* returns 1 if they are the same mac addr */
-static int compare_ltt(const struct hlist_node *node, const void *data2)
+static int compare_tt(const struct hlist_node *node, const void *data2)
 {
-       const void *data1 = container_of(node, struct tt_local_entry,
-                                        hash_entry);
-
-       return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
-}
-
-/* returns 1 if they are the same mac addr */
-static int compare_gtt(const struct hlist_node *node, const void *data2)
-{
-       const void *data1 = container_of(node, struct tt_global_entry,
+       const void *data1 = container_of(node, struct tt_common_entry,
                                         hash_entry);
 
        return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
@@ -60,13 +51,12 @@ static void tt_start_timer(struct bat_priv *bat_priv)
                           msecs_to_jiffies(5000));
 }
 
-static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
-                                                const void *data)
+static struct tt_common_entry *tt_hash_find(struct hashtable_t *hash,
+                                           const void *data)
 {
-       struct hashtable_t *hash = bat_priv->tt_local_hash;
        struct hlist_head *head;
        struct hlist_node *node;
-       struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL;
+       struct tt_common_entry *tt_common_entry, *tt_common_entry_tmp = NULL;
        uint32_t index;
 
        if (!hash)
@@ -76,51 +66,46 @@ static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
        head = &hash->table[index];
 
        rcu_read_lock();
-       hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) {
-               if (!compare_eth(tt_local_entry, data))
+       hlist_for_each_entry_rcu(tt_common_entry, node, head, hash_entry) {
+               if (!compare_eth(tt_common_entry, data))
                        continue;
 
-               if (!atomic_inc_not_zero(&tt_local_entry->refcount))
+               if (!atomic_inc_not_zero(&tt_common_entry->refcount))
                        continue;
 
-               tt_local_entry_tmp = tt_local_entry;
+               tt_common_entry_tmp = tt_common_entry;
                break;
        }
        rcu_read_unlock();
 
-       return tt_local_entry_tmp;
+       return tt_common_entry_tmp;
 }
 
-static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
-                                                  const void *data)
+static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
+                                                const void *data)
 {
-       struct hashtable_t *hash = bat_priv->tt_global_hash;
-       struct hlist_head *head;
-       struct hlist_node *node;
-       struct tt_global_entry *tt_global_entry;
-       struct tt_global_entry *tt_global_entry_tmp = NULL;
-       uint32_t index;
-
-       if (!hash)
-               return NULL;
-
-       index = choose_orig(data, hash->size);
-       head = &hash->table[index];
+       struct tt_common_entry *tt_common_entry;
+       struct tt_local_entry *tt_local_entry = NULL;
 
-       rcu_read_lock();
-       hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) {
-               if (!compare_eth(tt_global_entry, data))
-                       continue;
+       tt_common_entry = tt_hash_find(bat_priv->tt_local_hash, data);
+       if (tt_common_entry)
+               tt_local_entry = container_of(tt_common_entry,
+                                             struct tt_local_entry, common);
+       return tt_local_entry;
+}
 
-               if (!atomic_inc_not_zero(&tt_global_entry->refcount))
-                       continue;
+static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
+                                                  const void *data)
+{
+       struct tt_common_entry *tt_common_entry;
+       struct tt_global_entry *tt_global_entry = NULL;
 
-               tt_global_entry_tmp = tt_global_entry;
-               break;
-       }
-       rcu_read_unlock();
+       tt_common_entry = tt_hash_find(bat_priv->tt_global_hash, data);
+       if (tt_common_entry)
+               tt_global_entry = container_of(tt_common_entry,
+                                              struct tt_global_entry, common);
+       return tt_global_entry;
 
-       return tt_global_entry_tmp;
 }
 
 static bool is_out_of_time(unsigned long starting_time, unsigned long timeout)
@@ -133,15 +118,18 @@ static bool is_out_of_time(unsigned long starting_time, unsigned long timeout)
 
 static void tt_local_entry_free_ref(struct tt_local_entry *tt_local_entry)
 {
-       if (atomic_dec_and_test(&tt_local_entry->refcount))
-               kfree_rcu(tt_local_entry, rcu);
+       if (atomic_dec_and_test(&tt_local_entry->common.refcount))
+               kfree_rcu(tt_local_entry, common.rcu);
 }
 
 static void tt_global_entry_free_rcu(struct rcu_head *rcu)
 {
+       struct tt_common_entry *tt_common_entry;
        struct tt_global_entry *tt_global_entry;
 
-       tt_global_entry = container_of(rcu, struct tt_global_entry, rcu);
+       tt_common_entry = container_of(rcu, struct tt_common_entry, rcu);
+       tt_global_entry = container_of(tt_common_entry, struct tt_global_entry,
+                                      common);
 
        if (tt_global_entry->orig_node)
                orig_node_free_ref(tt_global_entry->orig_node);
@@ -151,8 +139,9 @@ static void tt_global_entry_free_rcu(struct rcu_head *rcu)
 
 static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry)
 {
-       if (atomic_dec_and_test(&tt_global_entry->refcount))
-               call_rcu(&tt_global_entry->rcu, tt_global_entry_free_rcu);
+       if (atomic_dec_and_test(&tt_global_entry->common.refcount))
+               call_rcu(&tt_global_entry->common.rcu,
+                        tt_global_entry_free_rcu);
 }
 
 static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr,
@@ -201,6 +190,7 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
        struct bat_priv *bat_priv = netdev_priv(soft_iface);
        struct tt_local_entry *tt_local_entry = NULL;
        struct tt_global_entry *tt_global_entry = NULL;
+       int hash_added;
 
        tt_local_entry = tt_local_hash_find(bat_priv, addr);
 
@@ -217,26 +207,33 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
                "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
                (uint8_t)atomic_read(&bat_priv->ttvn));
 
-       memcpy(tt_local_entry->addr, addr, ETH_ALEN);
-       tt_local_entry->last_seen = jiffies;
-       tt_local_entry->flags = NO_FLAGS;
+       memcpy(tt_local_entry->common.addr, addr, ETH_ALEN);
+       tt_local_entry->common.flags = NO_FLAGS;
        if (is_wifi_iface(ifindex))
-               tt_local_entry->flags |= TT_CLIENT_WIFI;
-       atomic_set(&tt_local_entry->refcount, 2);
+               tt_local_entry->common.flags |= TT_CLIENT_WIFI;
+       atomic_set(&tt_local_entry->common.refcount, 2);
+       tt_local_entry->last_seen = jiffies;
 
        /* the batman interface mac address should never be purged */
        if (compare_eth(addr, soft_iface->dev_addr))
-               tt_local_entry->flags |= TT_CLIENT_NOPURGE;
+               tt_local_entry->common.flags |= TT_CLIENT_NOPURGE;
 
-       tt_local_event(bat_priv, addr, tt_local_entry->flags);
+       hash_added = hash_add(bat_priv->tt_local_hash, compare_tt, choose_orig,
+                        &tt_local_entry->common,
+                        &tt_local_entry->common.hash_entry);
+
+       if (unlikely(hash_added != 0)) {
+               /* remove the reference for the hash */
+               tt_local_entry_free_ref(tt_local_entry);
+               goto out;
+       }
+
+       tt_local_event(bat_priv, addr, tt_local_entry->common.flags);
 
        /* The local entry has to be marked as NEW to avoid to send it in
         * a full table response going out before the next ttvn increment
         * (consistency check) */
-       tt_local_entry->flags |= TT_CLIENT_NEW;
-
-       hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig,
-                tt_local_entry, &tt_local_entry->hash_entry);
+       tt_local_entry->common.flags |= TT_CLIENT_NEW;
 
        /* remove address from global hash if present */
        tt_global_entry = tt_global_hash_find(bat_priv, addr);
@@ -247,8 +244,8 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
                tt_global_entry->orig_node->tt_poss_change = true;
                /* The global entry has to be marked as PENDING and has to be
                 * kept for consistency purpose */
-               tt_global_entry->flags |= TT_CLIENT_PENDING;
-               send_roam_adv(bat_priv, tt_global_entry->addr,
+               tt_global_entry->common.flags |= TT_CLIENT_PENDING;
+               send_roam_adv(bat_priv, tt_global_entry->common.addr,
                              tt_global_entry->orig_node);
        }
 out:
@@ -310,7 +307,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
        struct net_device *net_dev = (struct net_device *)seq->private;
        struct bat_priv *bat_priv = netdev_priv(net_dev);
        struct hashtable_t *hash = bat_priv->tt_local_hash;
-       struct tt_local_entry *tt_local_entry;
+       struct tt_common_entry *tt_common_entry;
        struct hard_iface *primary_if;
        struct hlist_node *node;
        struct hlist_head *head;
@@ -340,19 +337,19 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
                head = &hash->table[i];
 
                rcu_read_lock();
-               hlist_for_each_entry_rcu(tt_local_entry, node,
+               hlist_for_each_entry_rcu(tt_common_entry, node,
                                         head, hash_entry) {
                        seq_printf(seq, " * %pM [%c%c%c%c%c]\n",
-                                       tt_local_entry->addr,
-                                       (tt_local_entry->flags &
+                                       tt_common_entry->addr,
+                                       (tt_common_entry->flags &
                                         TT_CLIENT_ROAM ? 'R' : '.'),
-                                       (tt_local_entry->flags &
+                                       (tt_common_entry->flags &
                                         TT_CLIENT_NOPURGE ? 'P' : '.'),
-                                       (tt_local_entry->flags &
+                                       (tt_common_entry->flags &
                                         TT_CLIENT_NEW ? 'N' : '.'),
-                                       (tt_local_entry->flags &
+                                       (tt_common_entry->flags &
                                         TT_CLIENT_PENDING ? 'X' : '.'),
-                                       (tt_local_entry->flags &
+                                       (tt_common_entry->flags &
                                         TT_CLIENT_WIFI ? 'W' : '.'));
                }
                rcu_read_unlock();
@@ -367,13 +364,13 @@ static void tt_local_set_pending(struct bat_priv *bat_priv,
                                 struct tt_local_entry *tt_local_entry,
                                 uint16_t flags)
 {
-       tt_local_event(bat_priv, tt_local_entry->addr,
-                      tt_local_entry->flags | flags);
+       tt_local_event(bat_priv, tt_local_entry->common.addr,
+                      tt_local_entry->common.flags | flags);
 
        /* The local client has to be marked as "pending to be removed" but has
         * to be kept in the table in order to send it in a full table
         * response issued before the net ttvn increment (consistency check) */
-       tt_local_entry->flags |= TT_CLIENT_PENDING;
+       tt_local_entry->common.flags |= TT_CLIENT_PENDING;
 }
 
 void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr,
@@ -389,7 +386,7 @@ void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr,
                             (roaming ? TT_CLIENT_ROAM : NO_FLAGS));
 
        bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) pending to be removed: "
-               "%s\n", tt_local_entry->addr, message);
+               "%s\n", tt_local_entry->common.addr, message);
 out:
        if (tt_local_entry)
                tt_local_entry_free_ref(tt_local_entry);
@@ -399,6 +396,7 @@ static void tt_local_purge(struct bat_priv *bat_priv)
 {
        struct hashtable_t *hash = bat_priv->tt_local_hash;
        struct tt_local_entry *tt_local_entry;
+       struct tt_common_entry *tt_common_entry;
        struct hlist_node *node, *node_tmp;
        struct hlist_head *head;
        spinlock_t *list_lock; /* protects write access to the hash lists */
@@ -409,13 +407,16 @@ static void tt_local_purge(struct bat_priv *bat_priv)
                list_lock = &hash->list_locks[i];
 
                spin_lock_bh(list_lock);
-               hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
+               hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
                                          head, hash_entry) {
-                       if (tt_local_entry->flags & TT_CLIENT_NOPURGE)
+                       tt_local_entry = container_of(tt_common_entry,
+                                                     struct tt_local_entry,
+                                                     common);
+                       if (tt_local_entry->common.flags & TT_CLIENT_NOPURGE)
                                continue;
 
                        /* entry already marked for deletion */
-                       if (tt_local_entry->flags & TT_CLIENT_PENDING)
+                       if (tt_local_entry->common.flags & TT_CLIENT_PENDING)
                                continue;
 
                        if (!is_out_of_time(tt_local_entry->last_seen,
@@ -426,7 +427,7 @@ static void tt_local_purge(struct bat_priv *bat_priv)
                                             TT_CLIENT_DEL);
                        bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) "
                                "pending to be removed: timed out\n",
-                               tt_local_entry->addr);
+                               tt_local_entry->common.addr);
                }
                spin_unlock_bh(list_lock);
        }
@@ -437,6 +438,7 @@ static void tt_local_table_free(struct bat_priv *bat_priv)
 {
        struct hashtable_t *hash;
        spinlock_t *list_lock; /* protects write access to the hash lists */
+       struct tt_common_entry *tt_common_entry;
        struct tt_local_entry *tt_local_entry;
        struct hlist_node *node, *node_tmp;
        struct hlist_head *head;
@@ -452,9 +454,12 @@ static void tt_local_table_free(struct bat_priv *bat_priv)
                list_lock = &hash->list_locks[i];
 
                spin_lock_bh(list_lock);
-               hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
+               hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
                                          head, hash_entry) {
                        hlist_del_rcu(node);
+                       tt_local_entry = container_of(tt_common_entry,
+                                                     struct tt_local_entry,
+                                                     common);
                        tt_local_entry_free_ref(tt_local_entry);
                }
                spin_unlock_bh(list_lock);
@@ -502,6 +507,7 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
        struct tt_global_entry *tt_global_entry;
        struct orig_node *orig_node_tmp;
        int ret = 0;
+       int hash_added;
 
        tt_global_entry = tt_global_hash_find(bat_priv, tt_addr);
 
@@ -512,18 +518,24 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
                if (!tt_global_entry)
                        goto out;
 
-               memcpy(tt_global_entry->addr, tt_addr, ETH_ALEN);
+               memcpy(tt_global_entry->common.addr, tt_addr, ETH_ALEN);
+               tt_global_entry->common.flags = NO_FLAGS;
+               atomic_set(&tt_global_entry->common.refcount, 2);
                /* Assign the new orig_node */
                atomic_inc(&orig_node->refcount);
                tt_global_entry->orig_node = orig_node;
                tt_global_entry->ttvn = ttvn;
-               tt_global_entry->flags = NO_FLAGS;
                tt_global_entry->roam_at = 0;
-               atomic_set(&tt_global_entry->refcount, 2);
 
-               hash_add(bat_priv->tt_global_hash, compare_gtt,
-                        choose_orig, tt_global_entry,
-                        &tt_global_entry->hash_entry);
+               hash_added = hash_add(bat_priv->tt_global_hash, compare_tt,
+                                choose_orig, &tt_global_entry->common,
+                                &tt_global_entry->common.hash_entry);
+
+               if (unlikely(hash_added != 0)) {
+                       /* remove the reference for the hash */
+                       tt_global_entry_free_ref(tt_global_entry);
+                       goto out_remove;
+               }
                atomic_inc(&orig_node->tt_size);
        } else {
                if (tt_global_entry->orig_node != orig_node) {
@@ -534,20 +546,21 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
                        orig_node_free_ref(orig_node_tmp);
                        atomic_inc(&orig_node->tt_size);
                }
+               tt_global_entry->common.flags = NO_FLAGS;
                tt_global_entry->ttvn = ttvn;
-               tt_global_entry->flags = NO_FLAGS;
                tt_global_entry->roam_at = 0;
        }
 
        if (wifi)
-               tt_global_entry->flags |= TT_CLIENT_WIFI;
+               tt_global_entry->common.flags |= TT_CLIENT_WIFI;
 
        bat_dbg(DBG_TT, bat_priv,
                "Creating new global tt entry: %pM (via %pM)\n",
-               tt_global_entry->addr, orig_node->orig);
+               tt_global_entry->common.addr, orig_node->orig);
 
+out_remove:
        /* remove address from local hash if present */
-       tt_local_remove(bat_priv, tt_global_entry->addr,
+       tt_local_remove(bat_priv, tt_global_entry->common.addr,
                        "global tt received", roaming);
        ret = 1;
 out:
@@ -561,6 +574,7 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
        struct net_device *net_dev = (struct net_device *)seq->private;
        struct bat_priv *bat_priv = netdev_priv(net_dev);
        struct hashtable_t *hash = bat_priv->tt_global_hash;
+       struct tt_common_entry *tt_common_entry;
        struct tt_global_entry *tt_global_entry;
        struct hard_iface *primary_if;
        struct hlist_node *node;
@@ -593,20 +607,24 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
                head = &hash->table[i];
 
                rcu_read_lock();
-               hlist_for_each_entry_rcu(tt_global_entry, node,
+               hlist_for_each_entry_rcu(tt_common_entry, node,
                                         head, hash_entry) {
+                       tt_global_entry = container_of(tt_common_entry,
+                                                      struct tt_global_entry,
+                                                      common);
                        seq_printf(seq, " * %pM  (%3u) via %pM     (%3u)   "
-                                       "[%c%c%c]\n", tt_global_entry->addr,
+                                       "[%c%c%c]\n",
+                                       tt_global_entry->common.addr,
                                        tt_global_entry->ttvn,
                                        tt_global_entry->orig_node->orig,
                                        (uint8_t) atomic_read(
                                                &tt_global_entry->orig_node->
                                                last_ttvn),
-                                       (tt_global_entry->flags &
+                                       (tt_global_entry->common.flags &
                                         TT_CLIENT_ROAM ? 'R' : '.'),
-                                       (tt_global_entry->flags &
+                                       (tt_global_entry->common.flags &
                                         TT_CLIENT_PENDING ? 'X' : '.'),
-                                       (tt_global_entry->flags &
+                                       (tt_global_entry->common.flags &
                                         TT_CLIENT_WIFI ? 'W' : '.'));
                }
                rcu_read_unlock();
@@ -626,13 +644,13 @@ static void _tt_global_del(struct bat_priv *bat_priv,
 
        bat_dbg(DBG_TT, bat_priv,
                "Deleting global tt entry %pM (via %pM): %s\n",
-               tt_global_entry->addr, tt_global_entry->orig_node->orig,
+               tt_global_entry->common.addr, tt_global_entry->orig_node->orig,
                message);
 
        atomic_dec(&tt_global_entry->orig_node->tt_size);
 
-       hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig,
-                   tt_global_entry->addr);
+       hash_remove(bat_priv->tt_global_hash, compare_tt, choose_orig,
+                   tt_global_entry->common.addr);
 out:
        if (tt_global_entry)
                tt_global_entry_free_ref(tt_global_entry);
@@ -650,7 +668,7 @@ void tt_global_del(struct bat_priv *bat_priv,
 
        if (tt_global_entry->orig_node == orig_node) {
                if (roaming) {
-                       tt_global_entry->flags |= TT_CLIENT_ROAM;
+                       tt_global_entry->common.flags |= TT_CLIENT_ROAM;
                        tt_global_entry->roam_at = jiffies;
                        goto out;
                }
@@ -665,6 +683,7 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
                        struct orig_node *orig_node, const char *message)
 {
        struct tt_global_entry *tt_global_entry;
+       struct tt_common_entry *tt_common_entry;
        uint32_t i;
        struct hashtable_t *hash = bat_priv->tt_global_hash;
        struct hlist_node *node, *safe;
@@ -679,13 +698,16 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
                list_lock = &hash->list_locks[i];
 
                spin_lock_bh(list_lock);
-               hlist_for_each_entry_safe(tt_global_entry, node, safe,
+               hlist_for_each_entry_safe(tt_common_entry, node, safe,
                                         head, hash_entry) {
+                       tt_global_entry = container_of(tt_common_entry,
+                                                      struct tt_global_entry,
+                                                      common);
                        if (tt_global_entry->orig_node == orig_node) {
                                bat_dbg(DBG_TT, bat_priv,
                                        "Deleting global tt entry %pM "
                                        "(via %pM): %s\n",
-                                       tt_global_entry->addr,
+                                       tt_global_entry->common.addr,
                                        tt_global_entry->orig_node->orig,
                                        message);
                                hlist_del_rcu(node);
@@ -700,6 +722,7 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
 static void tt_global_roam_purge(struct bat_priv *bat_priv)
 {
        struct hashtable_t *hash = bat_priv->tt_global_hash;
+       struct tt_common_entry *tt_common_entry;
        struct tt_global_entry *tt_global_entry;
        struct hlist_node *node, *node_tmp;
        struct hlist_head *head;
@@ -711,9 +734,12 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv)
                list_lock = &hash->list_locks[i];
 
                spin_lock_bh(list_lock);
-               hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
+               hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
                                          head, hash_entry) {
-                       if (!(tt_global_entry->flags & TT_CLIENT_ROAM))
+                       tt_global_entry = container_of(tt_common_entry,
+                                                      struct tt_global_entry,
+                                                      common);
+                       if (!(tt_global_entry->common.flags & TT_CLIENT_ROAM))
                                continue;
                        if (!is_out_of_time(tt_global_entry->roam_at,
                                            TT_CLIENT_ROAM_TIMEOUT * 1000))
@@ -721,7 +747,7 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv)
 
                        bat_dbg(DBG_TT, bat_priv, "Deleting global "
                                "tt entry (%pM): Roaming timeout\n",
-                               tt_global_entry->addr);
+                               tt_global_entry->common.addr);
                        atomic_dec(&tt_global_entry->orig_node->tt_size);
                        hlist_del_rcu(node);
                        tt_global_entry_free_ref(tt_global_entry);
@@ -735,6 +761,7 @@ static void tt_global_table_free(struct bat_priv *bat_priv)
 {
        struct hashtable_t *hash;
        spinlock_t *list_lock; /* protects write access to the hash lists */
+       struct tt_common_entry *tt_common_entry;
        struct tt_global_entry *tt_global_entry;
        struct hlist_node *node, *node_tmp;
        struct hlist_head *head;
@@ -750,9 +777,12 @@ static void tt_global_table_free(struct bat_priv *bat_priv)
                list_lock = &hash->list_locks[i];
 
                spin_lock_bh(list_lock);
-               hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
+               hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
                                          head, hash_entry) {
                        hlist_del_rcu(node);
+                       tt_global_entry = container_of(tt_common_entry,
+                                                      struct tt_global_entry,
+                                                      common);
                        tt_global_entry_free_ref(tt_global_entry);
                }
                spin_unlock_bh(list_lock);
@@ -768,8 +798,8 @@ static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry,
 {
        bool ret = false;
 
-       if (tt_local_entry->flags & TT_CLIENT_WIFI &&
-           tt_global_entry->flags & TT_CLIENT_WIFI)
+       if (tt_local_entry->common.flags & TT_CLIENT_WIFI &&
+           tt_global_entry->common.flags & TT_CLIENT_WIFI)
                ret = true;
 
        return ret;
@@ -802,7 +832,7 @@ struct orig_node *transtable_search(struct bat_priv *bat_priv,
 
        /* A global client marked as PENDING has already moved from that
         * originator */
-       if (tt_global_entry->flags & TT_CLIENT_PENDING)
+       if (tt_global_entry->common.flags & TT_CLIENT_PENDING)
                goto out;
 
        orig_node = tt_global_entry->orig_node;
@@ -821,6 +851,7 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node)
 {
        uint16_t total = 0, total_one;
        struct hashtable_t *hash = bat_priv->tt_global_hash;
+       struct tt_common_entry *tt_common_entry;
        struct tt_global_entry *tt_global_entry;
        struct hlist_node *node;
        struct hlist_head *head;
@@ -831,20 +862,23 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node)
                head = &hash->table[i];
 
                rcu_read_lock();
-               hlist_for_each_entry_rcu(tt_global_entry, node,
+               hlist_for_each_entry_rcu(tt_common_entry, node,
                                         head, hash_entry) {
+                       tt_global_entry = container_of(tt_common_entry,
+                                                      struct tt_global_entry,
+                                                      common);
                        if (compare_eth(tt_global_entry->orig_node,
                                        orig_node)) {
                                /* Roaming clients are in the global table for
                                 * consistency only. They don't have to be
                                 * taken into account while computing the
                                 * global crc */
-                               if (tt_global_entry->flags & TT_CLIENT_ROAM)
+                               if (tt_common_entry->flags & TT_CLIENT_ROAM)
                                        continue;
                                total_one = 0;
                                for (j = 0; j < ETH_ALEN; j++)
                                        total_one = crc16_byte(total_one,
-                                               tt_global_entry->addr[j]);
+                                               tt_common_entry->addr[j]);
                                total ^= total_one;
                        }
                }
@@ -859,7 +893,7 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv)
 {
        uint16_t total = 0, total_one;
        struct hashtable_t *hash = bat_priv->tt_local_hash;
-       struct tt_local_entry *tt_local_entry;
+       struct tt_common_entry *tt_common_entry;
        struct hlist_node *node;
        struct hlist_head *head;
        uint32_t i;
@@ -869,16 +903,16 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv)
                head = &hash->table[i];
 
                rcu_read_lock();
-               hlist_for_each_entry_rcu(tt_local_entry, node,
+               hlist_for_each_entry_rcu(tt_common_entry, node,
                                         head, hash_entry) {
                        /* not yet committed clients have not to be taken into
                         * account while computing the CRC */
-                       if (tt_local_entry->flags & TT_CLIENT_NEW)
+                       if (tt_common_entry->flags & TT_CLIENT_NEW)
                                continue;
                        total_one = 0;
                        for (j = 0; j < ETH_ALEN; j++)
                                total_one = crc16_byte(total_one,
-                                                  tt_local_entry->addr[j]);
+                                                  tt_common_entry->addr[j]);
                        total ^= total_one;
                }
                rcu_read_unlock();
@@ -967,21 +1001,25 @@ unlock:
 /* data_ptr is useless here, but has to be kept to respect the prototype */
 static int tt_local_valid_entry(const void *entry_ptr, const void *data_ptr)
 {
-       const struct tt_local_entry *tt_local_entry = entry_ptr;
+       const struct tt_common_entry *tt_common_entry = entry_ptr;
 
-       if (tt_local_entry->flags & TT_CLIENT_NEW)
+       if (tt_common_entry->flags & TT_CLIENT_NEW)
                return 0;
        return 1;
 }
 
 static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr)
 {
-       const struct tt_global_entry *tt_global_entry = entry_ptr;
+       const struct tt_common_entry *tt_common_entry = entry_ptr;
+       const struct tt_global_entry *tt_global_entry;
        const struct orig_node *orig_node = data_ptr;
 
-       if (tt_global_entry->flags & TT_CLIENT_ROAM)
+       if (tt_common_entry->flags & TT_CLIENT_ROAM)
                return 0;
 
+       tt_global_entry = container_of(tt_common_entry, struct tt_global_entry,
+                                      common);
+
        return (tt_global_entry->orig_node == orig_node);
 }
 
@@ -992,7 +1030,7 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
                                                              const void *),
                                              void *cb_data)
 {
-       struct tt_local_entry *tt_local_entry;
+       struct tt_common_entry *tt_common_entry;
        struct tt_query_packet *tt_response;
        struct tt_change *tt_change;
        struct hlist_node *node;
@@ -1024,15 +1062,16 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
        for (i = 0; i < hash->size; i++) {
                head = &hash->table[i];
 
-               hlist_for_each_entry_rcu(tt_local_entry, node,
+               hlist_for_each_entry_rcu(tt_common_entry, node,
                                         head, hash_entry) {
                        if (tt_count == tt_tot)
                                break;
 
-                       if ((valid_cb) && (!valid_cb(tt_local_entry, cb_data)))
+                       if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
                                continue;
 
-                       memcpy(tt_change->addr, tt_local_entry->addr, ETH_ALEN);
+                       memcpy(tt_change->addr, tt_common_entry->addr,
+                              ETH_ALEN);
                        tt_change->flags = NO_FLAGS;
 
                        tt_count++;
@@ -1449,7 +1488,7 @@ bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr)
                goto out;
        /* Check if the client has been logically deleted (but is kept for
         * consistency purpose) */
-       if (tt_local_entry->flags & TT_CLIENT_PENDING)
+       if (tt_local_entry->common.flags & TT_CLIENT_PENDING)
                goto out;
        ret = true;
 out:
@@ -1672,40 +1711,48 @@ void tt_free(struct bat_priv *bat_priv)
        kfree(bat_priv->tt_buff);
 }
 
-/* This function will reset the specified flags from all the entries in
- * the given hash table and will increment num_local_tt for each involved
- * entry */
-static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags)
+/* This function will enable or disable the specified flags for all the entries
+ * in the given hash table and returns the number of modified entries */
+static uint16_t tt_set_flags(struct hashtable_t *hash, uint16_t flags,
+                            bool enable)
 {
        uint32_t i;
-       struct hashtable_t *hash = bat_priv->tt_local_hash;
+       uint16_t changed_num = 0;
        struct hlist_head *head;
        struct hlist_node *node;
-       struct tt_local_entry *tt_local_entry;
+       struct tt_common_entry *tt_common_entry;
 
        if (!hash)
-               return;
+               goto out;
 
        for (i = 0; i < hash->size; i++) {
                head = &hash->table[i];
 
                rcu_read_lock();
-               hlist_for_each_entry_rcu(tt_local_entry, node,
+               hlist_for_each_entry_rcu(tt_common_entry, node,
                                         head, hash_entry) {
-                       if (!(tt_local_entry->flags & flags))
-                               continue;
-                       tt_local_entry->flags &= ~flags;
-                       atomic_inc(&bat_priv->num_local_tt);
+                       if (enable) {
+                               if ((tt_common_entry->flags & flags) == flags)
+                                       continue;
+                               tt_common_entry->flags |= flags;
+                       } else {
+                               if (!(tt_common_entry->flags & flags))
+                                       continue;
+                               tt_common_entry->flags &= ~flags;
+                       }
+                       changed_num++;
                }
                rcu_read_unlock();
        }
-
+out:
+       return changed_num;
 }
 
 /* Purge out all the tt local entries marked with TT_CLIENT_PENDING */
 static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
 {
        struct hashtable_t *hash = bat_priv->tt_local_hash;
+       struct tt_common_entry *tt_common_entry;
        struct tt_local_entry *tt_local_entry;
        struct hlist_node *node, *node_tmp;
        struct hlist_head *head;
@@ -1720,16 +1767,19 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
                list_lock = &hash->list_locks[i];
 
                spin_lock_bh(list_lock);
-               hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
+               hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
                                          head, hash_entry) {
-                       if (!(tt_local_entry->flags & TT_CLIENT_PENDING))
+                       if (!(tt_common_entry->flags & TT_CLIENT_PENDING))
                                continue;
 
                        bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry "
-                               "(%pM): pending\n", tt_local_entry->addr);
+                               "(%pM): pending\n", tt_common_entry->addr);
 
                        atomic_dec(&bat_priv->num_local_tt);
                        hlist_del_rcu(node);
+                       tt_local_entry = container_of(tt_common_entry,
+                                                     struct tt_local_entry,
+                                                     common);
                        tt_local_entry_free_ref(tt_local_entry);
                }
                spin_unlock_bh(list_lock);
@@ -1739,7 +1789,11 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
 
 void tt_commit_changes(struct bat_priv *bat_priv)
 {
-       tt_local_reset_flags(bat_priv, TT_CLIENT_NEW);
+       uint16_t changed_num = tt_set_flags(bat_priv->tt_local_hash,
+                                           TT_CLIENT_NEW, false);
+       /* all the reset entries have now to be effectively counted as local
+        * entries */
+       atomic_add(changed_num, &bat_priv->num_local_tt);
        tt_local_purge_pending_clients(bat_priv);
 
        /* Increment the TTVN only once per OGM interval */
index ab8d0fe6df5a4ed6c16092705e79e23675838d0c..e9eb043719ace347b1ac29142879cf15d218f8f4 100644 (file)
@@ -222,24 +222,24 @@ struct socket_packet {
        struct icmp_packet_rr icmp_packet;
 };
 
-struct tt_local_entry {
+struct tt_common_entry {
        uint8_t addr[ETH_ALEN];
        struct hlist_node hash_entry;
-       unsigned long last_seen;
        uint16_t flags;
        atomic_t refcount;
        struct rcu_head rcu;
 };
 
+struct tt_local_entry {
+       struct tt_common_entry common;
+       unsigned long last_seen;
+};
+
 struct tt_global_entry {
-       uint8_t addr[ETH_ALEN];
-       struct hlist_node hash_entry; /* entry in the global table */
+       struct tt_common_entry common;
        struct orig_node *orig_node;
        uint8_t ttvn;
-       uint16_t flags; /* only TT_GLOBAL_ROAM is used */
        unsigned long roam_at; /* time at which TT_GLOBAL_ROAM was set */
-       atomic_t refcount;
-       struct rcu_head rcu;
 };
 
 struct tt_change_node {
index 7445413253cabf82976943c02dcd0d9be4cb3126..cc3b9f2f3b5dde8f524f05d8089fa9adf2384292 100644 (file)
@@ -609,7 +609,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
        struct vis_info *info = bat_priv->my_vis_info;
        struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data;
        struct vis_info_entry *entry;
-       struct tt_local_entry *tt_local_entry;
+       struct tt_common_entry *tt_common_entry;
        int best_tq = -1;
        uint32_t i;
 
@@ -672,13 +672,13 @@ next:
                head = &hash->table[i];
 
                rcu_read_lock();
-               hlist_for_each_entry_rcu(tt_local_entry, node, head,
+               hlist_for_each_entry_rcu(tt_common_entry, node, head,
                                         hash_entry) {
                        entry = (struct vis_info_entry *)
                                        skb_put(info->skb_packet,
                                                sizeof(*entry));
                        memset(entry->src, 0, ETH_ALEN);
-                       memcpy(entry->dest, tt_local_entry->addr, ETH_ALEN);
+                       memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN);
                        entry->quality = 0; /* 0 means TT */
                        packet->entries++;